From 809005c7f025bcc55bfa4ede78cb4cc45d3c0e6c Mon Sep 17 00:00:00 2001 From: Ladislav Zezula Date: Sat, 21 Nov 2020 04:27:09 +0100 Subject: * Release 9.23 * Fixed regressions * Fixed test program --- src/SBaseDumpData.cpp | 50 ++- src/SBaseFileTable.cpp | 6 +- src/SFileAddFile.cpp | 20 +- src/SFileFindFile.cpp | 2 + src/SFileGetFileInfo.cpp | 887 +++++++++++++---------------------------------- src/SFileListFile.cpp | 8 +- src/SFileOpenArchive.cpp | 2 +- src/SFileReadFile.cpp | 2 +- src/StormLib.h | 4 +- src/huffman/huff.cpp | 61 ++-- src/huffman/huff.h | 2 +- 11 files changed, 328 insertions(+), 716 deletions(-) (limited to 'src') diff --git a/src/SBaseDumpData.cpp b/src/SBaseDumpData.cpp index 334561b..2454f22 100644 --- a/src/SBaseDumpData.cpp +++ b/src/SBaseDumpData.cpp @@ -111,39 +111,33 @@ void DumpHetAndBetTable(TMPQHetTable * pHetTable, TMPQBetTable * pBetTable) DWORD dwFlags = 0; DWORD dwBetIndex = 0; - GetBits(pHetTable->pBetIndexes, i * pHetTable->dwIndexSizeTotal, - pHetTable->dwIndexSize, - &dwBetIndex, - 4); + GetMPQBits(pHetTable->pBetIndexes, i * pHetTable->dwIndexSizeTotal, + pHetTable->dwIndexSize, + &dwBetIndex, 4); if(dwBetIndex < pHetTable->dwTotalCount) { DWORD dwEntryIndex = pBetTable->dwTableEntrySize * dwBetIndex; - GetBits(pBetTable->pNameHashes, dwBetIndex * pBetTable->dwBitTotal_NameHash2, - pBetTable->dwBitCount_NameHash2, - &BetHash, - 8); - - GetBits(pBetTable->pFileTable, dwEntryIndex + pBetTable->dwBitIndex_FilePos, - pBetTable->dwBitCount_FilePos, - &ByteOffset, - 8); - - GetBits(pBetTable->pFileTable, dwEntryIndex + pBetTable->dwBitIndex_FileSize, - pBetTable->dwBitCount_FileSize, - &dwFileSize, - 4); - - GetBits(pBetTable->pFileTable, dwEntryIndex + pBetTable->dwBitIndex_CmpSize, - pBetTable->dwBitCount_CmpSize, - &dwCmpSize, - 4); - - GetBits(pBetTable->pFileTable, dwEntryIndex + pBetTable->dwBitIndex_FlagIndex, - pBetTable->dwBitCount_FlagIndex, - &dwFlagIndex, - 4); + GetMPQBits(pBetTable->pNameHashes, dwBetIndex * pBetTable->dwBitTotal_NameHash2, + pBetTable->dwBitCount_NameHash2, + &BetHash, 8); + + GetMPQBits(pBetTable->pFileTable, dwEntryIndex + pBetTable->dwBitIndex_FilePos, + pBetTable->dwBitCount_FilePos, + &ByteOffset, 8); + + GetMPQBits(pBetTable->pFileTable, dwEntryIndex + pBetTable->dwBitIndex_FileSize, + pBetTable->dwBitCount_FileSize, + &dwFileSize, 4); + + GetMPQBits(pBetTable->pFileTable, dwEntryIndex + pBetTable->dwBitIndex_CmpSize, + pBetTable->dwBitCount_CmpSize, + &dwCmpSize, 4); + + GetMPQBits(pBetTable->pFileTable, dwEntryIndex + pBetTable->dwBitIndex_FlagIndex, + pBetTable->dwBitCount_FlagIndex, + &dwFlagIndex, 4); dwFlags = pBetTable->pFileFlags[dwFlagIndex]; } diff --git a/src/SBaseFileTable.cpp b/src/SBaseFileTable.cpp index af8d290..7fe1042 100644 --- a/src/SBaseFileTable.cpp +++ b/src/SBaseFileTable.cpp @@ -432,9 +432,9 @@ int ConvertMpqHeaderToFormat4( // If version 1.0 is forced, then the format version is forced to be 1.0 // Reason: Storm.dll in Warcraft III ignores format version value - if((dwFlags & MPQ_OPEN_FORCE_MPQ_V1) || (MapType == MapTypeWarcraft3)) + if((MapType == MapTypeWarcraft3) || (dwFlags & MPQ_OPEN_FORCE_MPQ_V1)) wFormatVersion = MPQ_FORMAT_VERSION_1; - if(MapType == MapTypeStarcraft2) + if((MapType == MapTypeStarcraft2) && (pHeader->wFormatVersion > MPQ_FORMAT_VERSION_4)) wFormatVersion = MPQ_FORMAT_VERSION_4; // Format-specific fixes @@ -647,7 +647,7 @@ int ConvertMpqHeaderToFormat4( return ERROR_FAKE_MPQ_HEADER; // Check for malformed MPQs - if(pHeader->wFormatVersion != MPQ_FORMAT_VERSION_4 || (ha->MpqPos + pHeader->ArchiveSize64) != FileSize || (ha->MpqPos + pHeader->HiBlockTablePos64) >= FileSize) + if(pHeader->wFormatVersion != MPQ_FORMAT_VERSION_4 || (MpqOffset + pHeader->ArchiveSize64) != FileSize || (MpqOffset + pHeader->HiBlockTablePos64) >= FileSize) { pHeader->wFormatVersion = MPQ_FORMAT_VERSION_4; pHeader->dwHeaderSize = MPQ_HEADER_SIZE_V4; diff --git a/src/SFileAddFile.cpp b/src/SFileAddFile.cpp index 7dd583f..e756781 100644 --- a/src/SFileAddFile.cpp +++ b/src/SFileAddFile.cpp @@ -236,7 +236,7 @@ static int WriteDataToMpqFile( // We have to calculate sector CRC, if enabled if(hf->SectorChksums != NULL) hf->SectorChksums[dwSectorIndex] = adler32(0, pbCompressed, nOutBuffer); - } + } // Encrypt the sector, if necessary if(pFileEntry->dwFlags & MPQ_FILE_ENCRYPTED) @@ -592,7 +592,7 @@ int SFileAddFile_Write(TMPQFile * hf, const void * pvData, DWORD dwSize, DWORD d if(hf->pPatchInfo == NULL && IsIncrementalPatchFile(pvData, dwSize, &hf->dwPatchedFileSize)) { // Set the MPQ_FILE_PATCH_FILE flag - hf->pFileEntry->dwFlags |= MPQ_FILE_PATCH_FILE; + pFileEntry->dwFlags |= MPQ_FILE_PATCH_FILE; // Allocate the patch info hf->nAddFileError = nError = AllocatePatchInfo(hf, false); @@ -659,10 +659,10 @@ int SFileAddFile_Write(TMPQFile * hf, const void * pvData, DWORD dwSize, DWORD d if(hf->dwFilePos >= pFileEntry->dwFileSize) { // Finish calculating CRC32 - hf->pFileEntry->dwCrc32 = hf->dwCrc32; + pFileEntry->dwCrc32 = hf->dwCrc32; // Finish calculating MD5 - md5_done((hash_state *)hf->hctx, hf->pFileEntry->md5); + md5_done((hash_state *)hf->hctx, pFileEntry->md5); // If we also have sector checksums, write them to the file if(hf->SectorChksums != NULL) @@ -673,9 +673,9 @@ int SFileAddFile_Write(TMPQFile * hf, const void * pvData, DWORD dwSize, DWORD d // Now write patch info if(hf->pPatchInfo != NULL) { - memcpy(hf->pPatchInfo->md5, hf->pFileEntry->md5, MD5_DIGEST_SIZE); - hf->pPatchInfo->dwDataSize = hf->pFileEntry->dwFileSize; - hf->pFileEntry->dwFileSize = hf->dwPatchedFileSize; + memcpy(hf->pPatchInfo->md5, pFileEntry->md5, MD5_DIGEST_SIZE); + hf->pPatchInfo->dwDataSize = pFileEntry->dwFileSize; + pFileEntry->dwFileSize = hf->dwPatchedFileSize; nError = WritePatchInfo(hf); } @@ -689,13 +689,17 @@ int SFileAddFile_Write(TMPQFile * hf, const void * pvData, DWORD dwSize, DWORD d if(ha->pHeader->dwRawChunkSize != 0) { nError = WriteMpqDataMD5(ha->pStream, - ha->MpqPos + hf->pFileEntry->ByteOffset, + ha->MpqPos + pFileEntry->ByteOffset, hf->pFileEntry->dwCmpSize, ha->pHeader->dwRawChunkSize); } } } + // Update the archive size + if((ha->MpqPos + pFileEntry->ByteOffset + pFileEntry->dwCmpSize) > ha->FileSize) + ha->FileSize = ha->MpqPos + pFileEntry->ByteOffset + pFileEntry->dwCmpSize; + // Store the error code from the Write File operation hf->nAddFileError = nError; return nError; diff --git a/src/SFileFindFile.cpp b/src/SFileFindFile.cpp index 7e8502b..6a4cecd 100644 --- a/src/SFileFindFile.cpp +++ b/src/SFileFindFile.cpp @@ -238,6 +238,8 @@ static bool DoMPQSearch_FileEntry( // Prepare the block index dwBlockIndex = (DWORD)(pFileEntry - ha->pFileTable); + if(dwBlockIndex == 569) + szNameBuff[0] = 'F'; // Get the file name. If it's not known, we will create pseudo-name szFileName = pFileEntry->szFileName; diff --git a/src/SFileGetFileInfo.cpp b/src/SFileGetFileInfo.cpp index c57b3b7..4ec05e2 100644 --- a/src/SFileGetFileInfo.cpp +++ b/src/SFileGetFileInfo.cpp @@ -12,36 +12,9 @@ #include "StormLib.h" #include "StormCommon.h" -//----------------------------------------------------------------------------- -// Local defines - -// Information types for SFileGetFileInfo -#define SFILE_INFO_TYPE_INVALID_HANDLE 0 -#define SFILE_INFO_TYPE_NOT_FOUND 1 -#define SFILE_INFO_TYPE_DIRECT_POINTER 2 -#define SFILE_INFO_TYPE_ALLOCATED 3 -#define SFILE_INFO_TYPE_READ_FROM_FILE 4 -#define SFILE_INFO_TYPE_TABLE_POINTER 5 -#define SFILE_INFO_TYPE_FILE_ENTRY 6 - //----------------------------------------------------------------------------- // Local functions -static void ConvertFileEntryToSelfRelative(TFileEntry * pFileEntry, TFileEntry * pSrcFileEntry) -{ - // Copy the file entry itself - memcpy(pFileEntry, pSrcFileEntry, sizeof(TFileEntry)); - - // If source is NULL, leave it NULL - if(pSrcFileEntry->szFileName != NULL) - { - // Set the file name pointer after the file entry - pFileEntry->szFileName = (char *)(pFileEntry + 1); - strcpy(pFileEntry->szFileName, pSrcFileEntry->szFileName); - } -} - - static DWORD GetMpqFileCount(TMPQArchive * ha) { TFileEntry * pFileTableEnd; @@ -69,56 +42,138 @@ static DWORD GetMpqFileCount(TMPQArchive * ha) return dwFileCount; } -static bool GetFilePatchChain(TMPQFile * hf, void * pvFileInfo, DWORD cbFileInfo, DWORD * pcbLengthNeeded) +static bool GetInfo_ReturnError(DWORD dwErrCode) +{ + SetLastError(dwErrCode); + return false; +} + +static bool GetInfo_BufferCheck(void * pvFileInfo, DWORD cbFileInfo, DWORD cbData, LPDWORD pcbLengthNeeded) +{ + // Give the length needed to store the info + if(pcbLengthNeeded != NULL) + pcbLengthNeeded[0] = cbData; + + // Check for sufficient buffer + if(cbData > cbFileInfo) + return GetInfo_ReturnError(ERROR_INSUFFICIENT_BUFFER); + + // If the buffer size is sufficient, check for valid user buffer + if(pvFileInfo == NULL) + return GetInfo_ReturnError(ERROR_INVALID_PARAMETER); + + // Buffers and sizes are OK, we are ready to proceed file copying + return true; +} + +static bool GetInfo(void * pvFileInfo, DWORD cbFileInfo, const void * pvData, DWORD cbData, LPDWORD pcbLengthNeeded) +{ + // Verify buffer pointer and buffer size + if(!GetInfo_BufferCheck(pvFileInfo, cbFileInfo, cbData, pcbLengthNeeded)) + return false; + + // Copy the data to the caller-supplied buffer + memcpy(pvFileInfo, pvData, cbData); + return true; +} + +static bool GetInfo_Allocated(void * pvFileInfo, DWORD cbFileInfo, void * pvData, DWORD cbData, LPDWORD pcbLengthNeeded) +{ + bool bResult; + + // Verify buffer pointer and buffer size + if((bResult = GetInfo_BufferCheck(pvFileInfo, cbFileInfo, cbData, pcbLengthNeeded)) != false) + memcpy(pvFileInfo, pvData, cbData); + + // Copy the data to the user buffer + STORM_FREE(pvData); + return bResult; +} + +static bool GetInfo_TablePointer(void * pvFileInfo, DWORD cbFileInfo, void * pvTablePointer, SFileInfoClass InfoClass, LPDWORD pcbLengthNeeded) +{ + // Verify buffer pointer and buffer size + if(!GetInfo_BufferCheck(pvFileInfo, cbFileInfo, sizeof(void *), pcbLengthNeeded)) + { + SFileFreeFileInfo(pvTablePointer, InfoClass); + return false; + } + + // The user buffer receives pointer to the table. + // When done, the caller needs to call SFileFreeFileInfo on it + *(void **)pvFileInfo = pvTablePointer; + return true; +} + +static bool GetInfo_ReadFromFile(void * pvFileInfo, DWORD cbFileInfo, TFileStream * pStream, ULONGLONG ByteOffset, DWORD cbData, LPDWORD pcbLengthNeeded) +{ + // Verify buffer pointer and buffer size + if(!GetInfo_BufferCheck(pvFileInfo, cbFileInfo, cbData, pcbLengthNeeded)) + return false; + + return FileStream_Read(pStream, &ByteOffset, pvFileInfo, cbData); +} + +static bool GetInfo_FileEntry(void * pvFileInfo, DWORD cbFileInfo, TFileEntry * pFileEntry, LPDWORD pcbLengthNeeded) +{ + LPBYTE pbFileInfo = (LPBYTE)pvFileInfo; + DWORD cbSrcFileInfo = sizeof(TFileEntry); + DWORD cbFileName = 1; + + // The file name belongs to the file entry + if(pFileEntry->szFileName) + cbFileName = (DWORD)strlen(pFileEntry->szFileName) + 1; + cbSrcFileInfo += cbFileName; + + // Verify buffer pointer and buffer size + if(!GetInfo_BufferCheck(pvFileInfo, cbFileInfo, cbSrcFileInfo, pcbLengthNeeded)) + return false; + + // Copy the file entry + memcpy(pbFileInfo, pFileEntry, sizeof(TFileEntry)); + pbFileInfo += sizeof(TFileEntry); + pbFileInfo[0] = 0; + + // Copy the file name + if(pFileEntry->szFileName) + memcpy(pbFileInfo, pFileEntry->szFileName, cbFileName); + return true; +} + +static bool GetInfo_PatchChain(TMPQFile * hf, void * pvFileInfo, DWORD cbFileInfo, LPDWORD pcbLengthNeeded) { TMPQFile * hfTemp; - TCHAR * szFileInfo = (TCHAR *)pvFileInfo; + LPCTSTR szPatchName; + LPTSTR szFileInfo = (LPTSTR)pvFileInfo; size_t cchCharsNeeded = 1; - size_t cchFileInfo = (cbFileInfo / sizeof(TCHAR)); size_t nLength; - // Patch chain is only supported on MPQ files. + // Patch chain is only supported on MPQ files. Local files are not supported. if(hf->pStream != NULL) - { - SetLastError(ERROR_INVALID_PARAMETER); - return false; - } + return GetInfo_ReturnError(ERROR_INVALID_PARAMETER); // Calculate the necessary length of the multi-string for(hfTemp = hf; hfTemp != NULL; hfTemp = hfTemp->hfPatch) cchCharsNeeded += _tcslen(FileStream_GetFileName(hfTemp->ha->pStream)) + 1; - // Give the caller the needed length - if(pcbLengthNeeded != NULL) - pcbLengthNeeded[0] = (DWORD)(cchCharsNeeded * sizeof(TCHAR)); + // Verify whether the caller gave us valid buffer with enough size + if(!GetInfo_BufferCheck(pvFileInfo, cbFileInfo, (DWORD)(cchCharsNeeded * sizeof(TCHAR)), pcbLengthNeeded)) + return false; - // If the caller gave both buffer pointer and data length, - // try to copy the patch chain - if(szFileInfo != NULL && cchFileInfo != 0) + // Copy each patch name + for(hfTemp = hf; hfTemp != NULL; hfTemp = hfTemp->hfPatch) { - // If there is enough space in the buffer, copy the patch chain - if(cchCharsNeeded > cchFileInfo) - { - SetLastError(ERROR_INSUFFICIENT_BUFFER); - return false; - } + // Get the file name and its length + szPatchName = FileStream_GetFileName(hfTemp->ha->pStream); + nLength = _tcslen(szPatchName) + 1; - // Copy each patch - for(hfTemp = hf; hfTemp != NULL; hfTemp = hfTemp->hfPatch) - { - // Get the file name and its length - const TCHAR * szFileName = FileStream_GetFileName(hfTemp->ha->pStream); - nLength = _tcslen(szFileName) + 1; - - // Copy the file name - memcpy(szFileInfo, szFileName, nLength * sizeof(TCHAR)); - szFileInfo += nLength; - } - - // Make it multi-string - szFileInfo[0] = 0; + // Copy the file name + memcpy(szFileInfo, szPatchName, nLength * sizeof(TCHAR)); + szFileInfo += nLength; } + // Make it multi-string + szFileInfo[0] = 0; return true; } @@ -139,719 +194,253 @@ bool WINAPI SFileGetFileInfo( LPDWORD pcbLengthNeeded) { MPQ_SIGNATURE_INFO SignatureInfo; + const TCHAR * szSrcFileInfo; TMPQArchive * ha = NULL; TFileEntry * pFileEntry = NULL; + TMPQHeader * pHeader = NULL; ULONGLONG Int64Value = 0; - ULONGLONG ByteOffset = 0; TMPQFile * hf = NULL; void * pvSrcFileInfo = NULL; DWORD cbSrcFileInfo = 0; DWORD dwInt32Value = 0; - int nInfoType = SFILE_INFO_TYPE_INVALID_HANDLE; - int nError = ERROR_SUCCESS; + // Validate archive/file handle + if((int)InfoClass <= (int)SFileMpqFlags) + { + if((ha = IsValidMpqHandle(hMpqOrFile)) == NULL) + return GetInfo_ReturnError(ERROR_INVALID_HANDLE); + pHeader = ha->pHeader; + } + else + { + if((hf = IsValidFileHandle(hMpqOrFile)) == NULL) + return GetInfo_ReturnError(ERROR_INVALID_HANDLE); + pFileEntry = hf->pFileEntry; + } + + // Return info-class-specific data switch(InfoClass) { case SFileMpqFileName: - ha = IsValidMpqHandle(hMpqOrFile); - if(ha != NULL) - { - pvSrcFileInfo = (void *)FileStream_GetFileName(ha->pStream); - cbSrcFileInfo = (DWORD)(_tcslen((TCHAR *)pvSrcFileInfo) + 1) * sizeof(TCHAR); - nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER; - } - break; + szSrcFileInfo = FileStream_GetFileName(ha->pStream); + cbSrcFileInfo = (DWORD)((_tcslen(szSrcFileInfo) + 1) * sizeof(TCHAR)); + return GetInfo(pvFileInfo, cbFileInfo, szSrcFileInfo, cbSrcFileInfo, pcbLengthNeeded); case SFileMpqStreamBitmap: - ha = IsValidMpqHandle(hMpqOrFile); - if(ha != NULL) - return FileStream_GetBitmap(ha->pStream, pvFileInfo, cbFileInfo, pcbLengthNeeded); - break; + return FileStream_GetBitmap(ha->pStream, pvFileInfo, cbFileInfo, pcbLengthNeeded); case SFileMpqUserDataOffset: - ha = IsValidMpqHandle(hMpqOrFile); - if(ha != NULL) - { - nInfoType = SFILE_INFO_TYPE_NOT_FOUND; - if(ha->pUserData != NULL) - { - pvSrcFileInfo = &ha->UserDataPos; - cbSrcFileInfo = sizeof(ULONGLONG); - nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER; - } - } - break; + return GetInfo(pvFileInfo, cbFileInfo, &ha->UserDataPos, sizeof(ULONGLONG), pcbLengthNeeded); case SFileMpqUserDataHeader: - ha = IsValidMpqHandle(hMpqOrFile); - if(ha != NULL) - { - nInfoType = SFILE_INFO_TYPE_NOT_FOUND; - if(ha->pUserData != NULL) - { - ByteOffset = ha->UserDataPos; - cbSrcFileInfo = sizeof(TMPQUserData); - nInfoType = SFILE_INFO_TYPE_READ_FROM_FILE; - } - } - break; + return GetInfo_ReadFromFile(pvFileInfo, cbFileInfo, ha->pStream, ha->UserDataPos, sizeof(TMPQUserData), pcbLengthNeeded); case SFileMpqUserData: - ha = IsValidMpqHandle(hMpqOrFile); - if(ha != NULL) - { - nInfoType = SFILE_INFO_TYPE_NOT_FOUND; - if(ha->pUserData != NULL) - { - ByteOffset = ha->UserDataPos + sizeof(TMPQUserData); - cbSrcFileInfo = ha->pUserData->dwHeaderOffs - sizeof(TMPQUserData); - nInfoType = SFILE_INFO_TYPE_READ_FROM_FILE; - } - } - break; + return GetInfo_ReadFromFile(pvFileInfo, cbFileInfo, ha->pStream, ha->UserDataPos + sizeof(TMPQUserData), ha->pUserData->dwHeaderOffs - sizeof(TMPQUserData), pcbLengthNeeded); case SFileMpqHeaderOffset: - ha = IsValidMpqHandle(hMpqOrFile); - if(ha != NULL) - { - pvSrcFileInfo = &ha->MpqPos; - cbSrcFileInfo = sizeof(ULONGLONG); - nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER; - } - break; + return GetInfo(pvFileInfo, cbFileInfo, &ha->MpqPos, sizeof(ULONGLONG), pcbLengthNeeded); case SFileMpqHeaderSize: - ha = IsValidMpqHandle(hMpqOrFile); - if(ha != NULL) - { - pvSrcFileInfo = &ha->pHeader->dwHeaderSize; - cbSrcFileInfo = sizeof(DWORD); - nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER; - } - break; + return GetInfo(pvFileInfo, cbFileInfo, &pHeader->dwHeaderSize, sizeof(DWORD), pcbLengthNeeded); case SFileMpqHeader: - ha = IsValidMpqHandle(hMpqOrFile); - if(ha != NULL) - { - ByteOffset = ha->MpqPos; - cbSrcFileInfo = ha->pHeader->dwHeaderSize; - nInfoType = SFILE_INFO_TYPE_READ_FROM_FILE; - } - break; + return GetInfo_ReadFromFile(pvFileInfo, cbFileInfo, ha->pStream, ha->MpqPos, pHeader->dwHeaderSize, pcbLengthNeeded); case SFileMpqHetTableOffset: - ha = IsValidMpqHandle(hMpqOrFile); - if(ha != NULL) - { - pvSrcFileInfo = &ha->pHeader->HetTablePos64; - cbSrcFileInfo = sizeof(ULONGLONG); - nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER; - } - break; + return GetInfo(pvFileInfo, cbFileInfo, &pHeader->HetTablePos64, sizeof(ULONGLONG), pcbLengthNeeded); case SFileMpqHetTableSize: - ha = IsValidMpqHandle(hMpqOrFile); - if(ha != NULL) - { - pvSrcFileInfo = &ha->pHeader->HetTableSize64; - cbSrcFileInfo = sizeof(ULONGLONG); - nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER; - } - break; + return GetInfo(pvFileInfo, cbFileInfo, &pHeader->HetTableSize64, sizeof(ULONGLONG), pcbLengthNeeded); case SFileMpqHetHeader: - ha = IsValidMpqHandle(hMpqOrFile); - if(ha != NULL) - { - nInfoType = SFILE_INFO_TYPE_NOT_FOUND; - pvSrcFileInfo = LoadExtTable(ha, ha->pHeader->HetTablePos64, (size_t)ha->pHeader->HetTableSize64, HET_TABLE_SIGNATURE, MPQ_KEY_HASH_TABLE); - if(pvSrcFileInfo != NULL) - { - cbSrcFileInfo = sizeof(TMPQHetHeader); - nInfoType = SFILE_INFO_TYPE_ALLOCATED; - } - } - break; + pvSrcFileInfo = LoadExtTable(ha, pHeader->HetTablePos64, (size_t)pHeader->HetTableSize64, HET_TABLE_SIGNATURE, MPQ_KEY_HASH_TABLE); + if(pvSrcFileInfo == NULL) + return GetInfo_ReturnError(ERROR_FILE_NOT_FOUND); + return GetInfo_Allocated(pvFileInfo, cbFileInfo, pvSrcFileInfo, sizeof(TMPQHetHeader), pcbLengthNeeded); case SFileMpqHetTable: - ha = IsValidMpqHandle(hMpqOrFile); - if(ha != NULL) - { - nInfoType = SFILE_INFO_TYPE_NOT_FOUND; - pvSrcFileInfo = LoadHetTable(ha); - if(pvSrcFileInfo != NULL) - { - cbSrcFileInfo = sizeof(void *); - nInfoType = SFILE_INFO_TYPE_TABLE_POINTER; - } - } - break; + if((pvSrcFileInfo = LoadHetTable(ha)) == NULL) + return GetInfo_ReturnError(ERROR_NOT_ENOUGH_MEMORY); + return GetInfo_TablePointer(pvFileInfo, cbFileInfo, pvSrcFileInfo, InfoClass, pcbLengthNeeded); case SFileMpqBetTableOffset: - ha = IsValidMpqHandle(hMpqOrFile); - if(ha != NULL) - { - pvSrcFileInfo = &ha->pHeader->BetTablePos64; - cbSrcFileInfo = sizeof(ULONGLONG); - nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER; - } - break; + return GetInfo(pvFileInfo, cbFileInfo, &pHeader->BetTablePos64, sizeof(ULONGLONG), pcbLengthNeeded); case SFileMpqBetTableSize: - ha = IsValidMpqHandle(hMpqOrFile); - if(ha != NULL) - { - pvSrcFileInfo = &ha->pHeader->BetTableSize64; - cbSrcFileInfo = sizeof(ULONGLONG); - nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER; - } - break; + return GetInfo(pvFileInfo, cbFileInfo, &pHeader->BetTableSize64, sizeof(ULONGLONG), pcbLengthNeeded); case SFileMpqBetHeader: - ha = IsValidMpqHandle(hMpqOrFile); - if(ha != NULL) - { - nInfoType = SFILE_INFO_TYPE_NOT_FOUND; - pvSrcFileInfo = LoadExtTable(ha, ha->pHeader->BetTablePos64, (size_t)ha->pHeader->BetTableSize64, BET_TABLE_SIGNATURE, MPQ_KEY_BLOCK_TABLE); - if(pvSrcFileInfo != NULL) - { - // It is allowed for the caller to only require BET header. - cbSrcFileInfo = sizeof(TMPQBetHeader) + ((TMPQBetHeader *)pvSrcFileInfo)->dwFlagCount * sizeof(DWORD); - if(cbFileInfo == sizeof(TMPQBetHeader)) - cbSrcFileInfo = sizeof(TMPQBetHeader); - nInfoType = SFILE_INFO_TYPE_ALLOCATED; - } - } - break; + + // Retrieve the table and its size + pvSrcFileInfo = LoadExtTable(ha, pHeader->BetTablePos64, (size_t)pHeader->BetTableSize64, BET_TABLE_SIGNATURE, MPQ_KEY_BLOCK_TABLE); + if(pvSrcFileInfo == NULL) + return GetInfo_ReturnError(ERROR_FILE_NOT_FOUND); + cbSrcFileInfo = sizeof(TMPQBetHeader) + ((TMPQBetHeader *)pvSrcFileInfo)->dwFlagCount * sizeof(DWORD); + + // It is allowed for the caller to only require BET header + if(cbFileInfo == sizeof(TMPQBetHeader)) + cbSrcFileInfo = sizeof(TMPQBetHeader); + return GetInfo_Allocated(pvFileInfo, cbFileInfo, pvSrcFileInfo, cbSrcFileInfo, pcbLengthNeeded); case SFileMpqBetTable: - ha = IsValidMpqHandle(hMpqOrFile); - if(ha != NULL) - { - nInfoType = SFILE_INFO_TYPE_NOT_FOUND; - pvSrcFileInfo = LoadBetTable(ha); - if(pvSrcFileInfo != NULL) - { - cbSrcFileInfo = sizeof(void *); - nInfoType = SFILE_INFO_TYPE_TABLE_POINTER; - } - } - break; + if((pvSrcFileInfo = LoadBetTable(ha)) == NULL) + return GetInfo_ReturnError(ERROR_NOT_ENOUGH_MEMORY); + return GetInfo_TablePointer(pvFileInfo, cbFileInfo, pvSrcFileInfo, InfoClass, pcbLengthNeeded); case SFileMpqHashTableOffset: - ha = IsValidMpqHandle(hMpqOrFile); - if(ha != NULL) - { - Int64Value = MAKE_OFFSET64(ha->pHeader->wHashTablePosHi, ha->pHeader->dwHashTablePos); - pvSrcFileInfo = &Int64Value; - cbSrcFileInfo = sizeof(ULONGLONG); - nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER; - } - break; + Int64Value = MAKE_OFFSET64(pHeader->wHashTablePosHi, pHeader->dwHashTablePos); + return GetInfo(pvFileInfo, cbFileInfo, &Int64Value, sizeof(ULONGLONG), pcbLengthNeeded); case SFileMpqHashTableSize64: - ha = IsValidMpqHandle(hMpqOrFile); - if(ha != NULL) - { - pvSrcFileInfo = &ha->pHeader->HashTableSize64; - cbSrcFileInfo = sizeof(ULONGLONG); - nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER; - } - break; + return GetInfo(pvFileInfo, cbFileInfo, &pHeader->HashTableSize64, sizeof(ULONGLONG), pcbLengthNeeded); case SFileMpqHashTableSize: - ha = IsValidMpqHandle(hMpqOrFile); - if(ha != NULL) - { - pvSrcFileInfo = &ha->pHeader->dwHashTableSize; - cbSrcFileInfo = sizeof(DWORD); - nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER; - } - break; + return GetInfo(pvFileInfo, cbFileInfo, &pHeader->dwHashTableSize, sizeof(DWORD), pcbLengthNeeded); case SFileMpqHashTable: - ha = IsValidMpqHandle(hMpqOrFile); - if(ha != NULL && ha->pHashTable != NULL) - { - pvSrcFileInfo = ha->pHashTable; - cbSrcFileInfo = ha->pHeader->dwHashTableSize * sizeof(TMPQHash); - nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER; - } - break; + cbSrcFileInfo = pHeader->dwHashTableSize * sizeof(TMPQHash); + return GetInfo(pvFileInfo, cbFileInfo, ha->pHashTable, cbSrcFileInfo, pcbLengthNeeded); case SFileMpqBlockTableOffset: - ha = IsValidMpqHandle(hMpqOrFile); - if(ha != NULL) - { - Int64Value = MAKE_OFFSET64(ha->pHeader->wBlockTablePosHi, ha->pHeader->dwBlockTablePos); - pvSrcFileInfo = &Int64Value; - cbSrcFileInfo = sizeof(ULONGLONG); - nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER; - } - break; + Int64Value = MAKE_OFFSET64(pHeader->wBlockTablePosHi, pHeader->dwBlockTablePos); + return GetInfo(pvFileInfo, cbFileInfo, &Int64Value, sizeof(ULONGLONG), pcbLengthNeeded); case SFileMpqBlockTableSize64: - ha = IsValidMpqHandle(hMpqOrFile); - if(ha != NULL) - { - pvSrcFileInfo = &ha->pHeader->BlockTableSize64; - cbSrcFileInfo = sizeof(ULONGLONG); - nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER; - } - break; + return GetInfo(pvFileInfo, cbFileInfo, &pHeader->BlockTableSize64, sizeof(ULONGLONG), pcbLengthNeeded); case SFileMpqBlockTableSize: - ha = IsValidMpqHandle(hMpqOrFile); - if(ha != NULL) - { - pvSrcFileInfo = &ha->pHeader->dwBlockTableSize; - cbSrcFileInfo = sizeof(DWORD); - nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER; - } - break; + return GetInfo(pvFileInfo, cbFileInfo, &pHeader->dwBlockTableSize, sizeof(DWORD), pcbLengthNeeded); case SFileMpqBlockTable: - ha = IsValidMpqHandle(hMpqOrFile); - if(ha != NULL) - { - nInfoType = SFILE_INFO_TYPE_NOT_FOUND; - if(MAKE_OFFSET64(ha->pHeader->wBlockTablePosHi, ha->pHeader->dwBlockTablePos) < ha->FileSize) - { - cbSrcFileInfo = ha->pHeader->dwBlockTableSize * sizeof(TMPQBlock); - if(cbFileInfo >= cbSrcFileInfo) - pvSrcFileInfo = LoadBlockTable(ha, true); - nInfoType = SFILE_INFO_TYPE_ALLOCATED; - } - } - break; + if(MAKE_OFFSET64(pHeader->wBlockTablePosHi, pHeader->dwBlockTablePos) >= ha->FileSize) + return GetInfo_ReturnError(ERROR_FILE_NOT_FOUND); + cbSrcFileInfo = pHeader->dwBlockTableSize * sizeof(TMPQBlock); + pvSrcFileInfo = LoadBlockTable(ha, true); + return GetInfo_Allocated(pvFileInfo, cbFileInfo, pvSrcFileInfo, cbSrcFileInfo, pcbLengthNeeded); case SFileMpqHiBlockTableOffset: - ha = IsValidMpqHandle(hMpqOrFile); - if(ha != NULL) - { - pvSrcFileInfo = &ha->pHeader->HiBlockTablePos64; - cbSrcFileInfo = sizeof(ULONGLONG); - nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER; - } - break; + return GetInfo(pvFileInfo, cbFileInfo, &pHeader->HiBlockTablePos64, sizeof(ULONGLONG), pcbLengthNeeded); case SFileMpqHiBlockTableSize64: - ha = IsValidMpqHandle(hMpqOrFile); - if(ha != NULL) - { - pvSrcFileInfo = &ha->pHeader->HiBlockTableSize64; - cbSrcFileInfo = sizeof(ULONGLONG); - nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER; - } - break; + return GetInfo(pvFileInfo, cbFileInfo, &pHeader->HiBlockTableSize64, sizeof(ULONGLONG), pcbLengthNeeded); case SFileMpqHiBlockTable: - ha = IsValidMpqHandle(hMpqOrFile); - if(ha != NULL) - { - nInfoType = SFILE_INFO_TYPE_NOT_FOUND; - if(ha->pHeader->HiBlockTablePos64 && ha->pHeader->HiBlockTableSize64) - { - assert(false); - } - } - break; + return GetInfo_ReturnError(ERROR_FILE_NOT_FOUND); case SFileMpqSignatures: - ha = IsValidMpqHandle(hMpqOrFile); - if(ha != NULL && QueryMpqSignatureInfo(ha, &SignatureInfo)) - { - pvSrcFileInfo = &SignatureInfo.SignatureTypes; - cbSrcFileInfo = sizeof(DWORD); - nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER; - } - break; + if(!QueryMpqSignatureInfo(ha, &SignatureInfo)) + return GetInfo_ReturnError(ERROR_FILE_NOT_FOUND); + return GetInfo(pvFileInfo, cbFileInfo, &SignatureInfo.SignatureTypes, sizeof(DWORD), pcbLengthNeeded); case SFileMpqStrongSignatureOffset: - ha = IsValidMpqHandle(hMpqOrFile); - if(ha != NULL) - { - nInfoType = SFILE_INFO_TYPE_NOT_FOUND; - if(QueryMpqSignatureInfo(ha, &SignatureInfo) && (SignatureInfo.SignatureTypes & SIGNATURE_TYPE_STRONG)) - { - pvSrcFileInfo = &SignatureInfo.EndMpqData; - cbSrcFileInfo = sizeof(ULONGLONG); - nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER; - } - } - break; + if(QueryMpqSignatureInfo(ha, &SignatureInfo) == false || (SignatureInfo.SignatureTypes & SIGNATURE_TYPE_STRONG) == 0) + return GetInfo_ReturnError(ERROR_FILE_NOT_FOUND); + return GetInfo(pvFileInfo, cbFileInfo, &SignatureInfo.EndMpqData, sizeof(ULONGLONG), pcbLengthNeeded); case SFileMpqStrongSignatureSize: - ha = IsValidMpqHandle(hMpqOrFile); - if(ha != NULL) - { - nInfoType = SFILE_INFO_TYPE_NOT_FOUND; - if(QueryMpqSignatureInfo(ha, &SignatureInfo) && (SignatureInfo.SignatureTypes & SIGNATURE_TYPE_STRONG)) - { - dwInt32Value = MPQ_STRONG_SIGNATURE_SIZE + 4; - pvSrcFileInfo = &dwInt32Value; - cbSrcFileInfo = sizeof(DWORD); - nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER; - } - } - break; + if(QueryMpqSignatureInfo(ha, &SignatureInfo) == false || (SignatureInfo.SignatureTypes & SIGNATURE_TYPE_STRONG) == 0) + return GetInfo_ReturnError(ERROR_FILE_NOT_FOUND); + dwInt32Value = MPQ_STRONG_SIGNATURE_SIZE + 4; + return GetInfo(pvFileInfo, cbFileInfo, &dwInt32Value, sizeof(DWORD), pcbLengthNeeded); case SFileMpqStrongSignature: - ha = IsValidMpqHandle(hMpqOrFile); - if(ha != NULL) - { - nInfoType = SFILE_INFO_TYPE_NOT_FOUND; - if(QueryMpqSignatureInfo(ha, &SignatureInfo) && (SignatureInfo.SignatureTypes & SIGNATURE_TYPE_STRONG)) - { - pvSrcFileInfo = SignatureInfo.Signature; - cbSrcFileInfo = MPQ_STRONG_SIGNATURE_SIZE + 4; - nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER; - } - } - break; + if(QueryMpqSignatureInfo(ha, &SignatureInfo) == false || (SignatureInfo.SignatureTypes & SIGNATURE_TYPE_STRONG) == 0) + return GetInfo_ReturnError(ERROR_FILE_NOT_FOUND); + return GetInfo(pvFileInfo, cbFileInfo, SignatureInfo.Signature, MPQ_STRONG_SIGNATURE_SIZE + 4, pcbLengthNeeded); case SFileMpqArchiveSize64: - ha = IsValidMpqHandle(hMpqOrFile); - if(ha != NULL) - { - pvSrcFileInfo = &ha->pHeader->ArchiveSize64; - cbSrcFileInfo = sizeof(DWORD); - nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER; - } - break; + return GetInfo(pvFileInfo, cbFileInfo, &pHeader->ArchiveSize64, sizeof(ULONGLONG), pcbLengthNeeded); case SFileMpqArchiveSize: - ha = IsValidMpqHandle(hMpqOrFile); - if(ha != NULL) - { - pvSrcFileInfo = &ha->pHeader->dwArchiveSize; - cbSrcFileInfo = sizeof(DWORD); - nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER; - } - break; + return GetInfo(pvFileInfo, cbFileInfo, &pHeader->dwArchiveSize, sizeof(DWORD), pcbLengthNeeded); case SFileMpqMaxFileCount: - ha = IsValidMpqHandle(hMpqOrFile); - if(ha != NULL) - { - pvSrcFileInfo = &ha->dwMaxFileCount; - cbSrcFileInfo = sizeof(DWORD); - nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER; - } - break; + return GetInfo(pvFileInfo, cbFileInfo, &ha->dwMaxFileCount, sizeof(DWORD), pcbLengthNeeded); case SFileMpqFileTableSize: - ha = IsValidMpqHandle(hMpqOrFile); - if(ha != NULL) - { - pvSrcFileInfo = &ha->dwFileTableSize; - cbSrcFileInfo = sizeof(DWORD); - nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER; - } - break; + return GetInfo(pvFileInfo, cbFileInfo, &ha->dwFileTableSize, sizeof(DWORD), pcbLengthNeeded); case SFileMpqSectorSize: - ha = IsValidMpqHandle(hMpqOrFile); - if(ha != NULL) - { - pvSrcFileInfo = &ha->dwSectorSize; - cbSrcFileInfo = sizeof(DWORD); - nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER; - } - break; + return GetInfo(pvFileInfo, cbFileInfo, &ha->dwSectorSize, sizeof(DWORD), pcbLengthNeeded); case SFileMpqNumberOfFiles: - ha = IsValidMpqHandle(hMpqOrFile); - if(ha != NULL) - { - pvSrcFileInfo = &dwInt32Value; - cbSrcFileInfo = sizeof(DWORD); - dwInt32Value = GetMpqFileCount(ha); - nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER; - } - break; + dwInt32Value = GetMpqFileCount(ha); + return GetInfo(pvFileInfo, cbFileInfo, &dwInt32Value, sizeof(DWORD), pcbLengthNeeded); case SFileMpqRawChunkSize: - ha = IsValidMpqHandle(hMpqOrFile); - if(ha != NULL) - { - nInfoType = SFILE_INFO_TYPE_NOT_FOUND; - if(ha->pHeader->dwRawChunkSize != 0) - { - pvSrcFileInfo = &ha->pHeader->dwRawChunkSize; - cbSrcFileInfo = sizeof(DWORD); - nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER; - } - } - break; + if(pHeader->dwRawChunkSize == 0) + return GetInfo_ReturnError(ERROR_FILE_NOT_FOUND); + return GetInfo(pvFileInfo, cbFileInfo, &pHeader->dwRawChunkSize, sizeof(DWORD), pcbLengthNeeded); case SFileMpqStreamFlags: - ha = IsValidMpqHandle(hMpqOrFile); - if(ha != NULL) - { - FileStream_GetFlags(ha->pStream, &dwInt32Value); - pvSrcFileInfo = &dwInt32Value; - cbSrcFileInfo = sizeof(DWORD); - nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER; - } - break; + FileStream_GetFlags(ha->pStream, &dwInt32Value); + return GetInfo(pvFileInfo, cbFileInfo, &dwInt32Value, sizeof(DWORD), pcbLengthNeeded); case SFileMpqFlags: - ha = IsValidMpqHandle(hMpqOrFile); - if(ha != NULL) - { - dwInt32Value = ha->dwFlags; - pvSrcFileInfo = &dwInt32Value; - cbSrcFileInfo = sizeof(DWORD); - nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER; - } - break; + return GetInfo(pvFileInfo, cbFileInfo, &ha->dwFlags, sizeof(DWORD), pcbLengthNeeded); case SFileInfoPatchChain: - hf = IsValidFileHandle(hMpqOrFile); - if(hf != NULL) - return GetFilePatchChain(hf, pvFileInfo, cbFileInfo, pcbLengthNeeded); - break; + return GetInfo_PatchChain(hf, pvFileInfo, cbFileInfo, pcbLengthNeeded); case SFileInfoFileEntry: - hf = IsValidFileHandle(hMpqOrFile); - if(hf != NULL && hf->pFileEntry != NULL) - { - pvSrcFileInfo = pFileEntry = hf->pFileEntry; - cbSrcFileInfo = sizeof(TFileEntry); - if(pFileEntry->szFileName != NULL) - cbSrcFileInfo += (DWORD)strlen(pFileEntry->szFileName) + 1; - nInfoType = SFILE_INFO_TYPE_FILE_ENTRY; - } - break; + if(pFileEntry == NULL) + return GetInfo_ReturnError(ERROR_FILE_NOT_FOUND); + return GetInfo_FileEntry(pvFileInfo, cbFileInfo, pFileEntry, pcbLengthNeeded); case SFileInfoHashEntry: - hf = IsValidFileHandle(hMpqOrFile); - if(hf != NULL && hf->pHashEntry != NULL) - { - pvSrcFileInfo = hf->pHashEntry; - cbSrcFileInfo = sizeof(TMPQHash); - nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER; - } - break; + return GetInfo(pvFileInfo, cbFileInfo, hf->pHashEntry, sizeof(TMPQHash), pcbLengthNeeded); case SFileInfoHashIndex: - hf = IsValidFileHandle(hMpqOrFile); - if(hf != NULL && hf->pHashEntry != NULL) - { - pvSrcFileInfo = &hf->dwHashIndex; - cbSrcFileInfo = sizeof(DWORD); - nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER; - } - break; + return GetInfo(pvFileInfo, cbFileInfo, &hf->dwHashIndex, sizeof(DWORD), pcbLengthNeeded); case SFileInfoNameHash1: - hf = IsValidFileHandle(hMpqOrFile); - if(hf != NULL && hf->pHashEntry != NULL) - { - dwInt32Value = hf->pHashEntry->dwName1; - pvSrcFileInfo = &dwInt32Value; - cbSrcFileInfo = sizeof(DWORD); - nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER; - } - break; + return GetInfo(pvFileInfo, cbFileInfo, &hf->pHashEntry->dwName1, sizeof(DWORD), pcbLengthNeeded); case SFileInfoNameHash2: - hf = IsValidFileHandle(hMpqOrFile); - if(hf != NULL && hf->pHashEntry != NULL) - { - dwInt32Value = hf->pHashEntry->dwName2; - pvSrcFileInfo = &dwInt32Value; - cbSrcFileInfo = sizeof(DWORD); - nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER; - } - break; + return GetInfo(pvFileInfo, cbFileInfo, &hf->pHashEntry->dwName2, sizeof(DWORD), pcbLengthNeeded); case SFileInfoNameHash3: - hf = IsValidFileHandle(hMpqOrFile); - if(hf != NULL && hf->pFileEntry != NULL) - { - pvSrcFileInfo = &hf->pFileEntry->FileNameHash; - cbSrcFileInfo = sizeof(ULONGLONG); - nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER; - } - break; + return GetInfo(pvFileInfo, cbFileInfo, &pFileEntry->FileNameHash, sizeof(ULONGLONG), pcbLengthNeeded); case SFileInfoLocale: - hf = IsValidFileHandle(hMpqOrFile); - if(hf != NULL && hf->pHashEntry != NULL) - { - dwInt32Value = hf->pHashEntry->lcLocale; - pvSrcFileInfo = &dwInt32Value; - cbSrcFileInfo = sizeof(DWORD); - nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER; - } - break; + dwInt32Value = hf->pHashEntry->lcLocale; + return GetInfo(pvFileInfo, cbFileInfo, &dwInt32Value, sizeof(DWORD), pcbLengthNeeded); case SFileInfoFileIndex: - hf = IsValidFileHandle(hMpqOrFile); - if(hf != NULL && hf->ha != NULL && hf->pFileEntry != NULL) - { - dwInt32Value = (DWORD)(hf->pFileEntry - hf->ha->pFileTable); - pvSrcFileInfo = &dwInt32Value; - cbSrcFileInfo = sizeof(DWORD); - nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER; - } - break; + dwInt32Value = (DWORD)(pFileEntry - hf->ha->pFileTable); + return GetInfo(pvFileInfo, cbFileInfo, &dwInt32Value, sizeof(DWORD), pcbLengthNeeded); case SFileInfoByteOffset: - hf = IsValidFileHandle(hMpqOrFile); - if(hf != NULL && hf->pFileEntry != NULL) - { - pvSrcFileInfo = &hf->pFileEntry->ByteOffset; - cbSrcFileInfo = sizeof(ULONGLONG); - nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER; - } - break; + return GetInfo(pvFileInfo, cbFileInfo, &pFileEntry->ByteOffset, sizeof(ULONGLONG), pcbLengthNeeded); case SFileInfoFileTime: - hf = IsValidFileHandle(hMpqOrFile); - if(hf != NULL && hf->pFileEntry != NULL) - { - pvSrcFileInfo = &hf->pFileEntry->FileTime; - cbSrcFileInfo = sizeof(ULONGLONG); - nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER; - } - break; + return GetInfo(pvFileInfo, cbFileInfo, &pFileEntry->FileTime, sizeof(ULONGLONG), pcbLengthNeeded); case SFileInfoFileSize: - hf = IsValidFileHandle(hMpqOrFile); - if(hf != NULL && hf->pFileEntry != NULL) - { - pvSrcFileInfo = &hf->pFileEntry->dwFileSize; - cbSrcFileInfo = sizeof(DWORD); - nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER; - } - break; + return GetInfo(pvFileInfo, cbFileInfo, &pFileEntry->dwFileSize, sizeof(DWORD), pcbLengthNeeded); case SFileInfoCompressedSize: - hf = IsValidFileHandle(hMpqOrFile); - if(hf != NULL && hf->pFileEntry != NULL) - { - pvSrcFileInfo = &hf->pFileEntry->dwCmpSize; - cbSrcFileInfo = sizeof(DWORD); - nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER; - } - break; + return GetInfo(pvFileInfo, cbFileInfo, &pFileEntry->dwCmpSize, sizeof(DWORD), pcbLengthNeeded); case SFileInfoFlags: - hf = IsValidFileHandle(hMpqOrFile); - if(hf != NULL && hf->pFileEntry != NULL) - { - pvSrcFileInfo = &hf->pFileEntry->dwFlags; - cbSrcFileInfo = sizeof(DWORD); - nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER; - } - break; + return GetInfo(pvFileInfo, cbFileInfo, &pFileEntry->dwFlags, sizeof(DWORD), pcbLengthNeeded); case SFileInfoEncryptionKey: - hf = IsValidFileHandle(hMpqOrFile); - if(hf != NULL) - { - pvSrcFileInfo = &hf->dwFileKey; - cbSrcFileInfo = sizeof(DWORD); - nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER; - } - break; + return GetInfo(pvFileInfo, cbFileInfo, &hf->dwFileKey, sizeof(DWORD), pcbLengthNeeded); case SFileInfoEncryptionKeyRaw: - hf = IsValidFileHandle(hMpqOrFile); - if(hf != NULL && hf->pFileEntry != NULL) - { - dwInt32Value = hf->dwFileKey; - if(hf->pFileEntry->dwFlags & MPQ_FILE_FIX_KEY) - dwInt32Value = (dwInt32Value ^ hf->pFileEntry->dwFileSize) - (DWORD)hf->MpqFilePos; - pvSrcFileInfo = &dwInt32Value; - cbSrcFileInfo = sizeof(DWORD); - nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER; - } - break; + dwInt32Value = hf->dwFileKey; + if(pFileEntry->dwFlags & MPQ_FILE_FIX_KEY) + dwInt32Value = (dwInt32Value ^ pFileEntry->dwFileSize) - (DWORD)hf->MpqFilePos; + return GetInfo(pvFileInfo, cbFileInfo, &dwInt32Value, sizeof(DWORD), pcbLengthNeeded); case SFileInfoCRC32: - hf = IsValidFileHandle(hMpqOrFile); - if(hf != NULL && hf->pFileEntry != NULL) - { - dwInt32Value = hf->pFileEntry->dwCrc32; - pvSrcFileInfo = &dwInt32Value; - cbSrcFileInfo = sizeof(DWORD); - nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER; - } - break; - - default: // Invalid info class - SetLastError(ERROR_INVALID_PARAMETER); - return false; - } - - // If we validated the handle and info class, give as much info as possible - if(nInfoType >= SFILE_INFO_TYPE_DIRECT_POINTER) - { - // Give the length needed, if wanted - if(pcbLengthNeeded != NULL) - pcbLengthNeeded[0] = cbSrcFileInfo; - - // If the caller entered an output buffer, the output size must also be entered - if(pvFileInfo != NULL && cbFileInfo != 0) - { - // Check if there is enough space in the output buffer - if(cbSrcFileInfo <= cbFileInfo) - { - switch(nInfoType) - { - case SFILE_INFO_TYPE_DIRECT_POINTER: - case SFILE_INFO_TYPE_ALLOCATED: - assert(pvSrcFileInfo != NULL); - memcpy(pvFileInfo, pvSrcFileInfo, cbSrcFileInfo); - break; - - case SFILE_INFO_TYPE_READ_FROM_FILE: - if(!FileStream_Read(ha->pStream, &ByteOffset, pvFileInfo, cbSrcFileInfo)) - nError = GetLastError(); - break; - - case SFILE_INFO_TYPE_TABLE_POINTER: - assert(pvSrcFileInfo != NULL); - *(void **)pvFileInfo = pvSrcFileInfo; - pvSrcFileInfo = NULL; - break; - - case SFILE_INFO_TYPE_FILE_ENTRY: - assert(pFileEntry != NULL); - ConvertFileEntryToSelfRelative((TFileEntry *)pvFileInfo, pFileEntry); - break; - } - } - else - { - nError = ERROR_INSUFFICIENT_BUFFER; - } - } - - // Free the file info if needed - if(nInfoType == SFILE_INFO_TYPE_ALLOCATED && pvSrcFileInfo != NULL) - STORM_FREE(pvSrcFileInfo); - if(nInfoType == SFILE_INFO_TYPE_TABLE_POINTER && pvSrcFileInfo != NULL) - SFileFreeFileInfo(pvSrcFileInfo, InfoClass); - } - else - { - // Handle error cases - if(nInfoType == SFILE_INFO_TYPE_INVALID_HANDLE) - nError = ERROR_INVALID_HANDLE; - if(nInfoType == SFILE_INFO_TYPE_NOT_FOUND) - nError = ERROR_FILE_NOT_FOUND; + return GetInfo(pvFileInfo, cbFileInfo, &hf->pFileEntry->dwCrc32, sizeof(DWORD), pcbLengthNeeded); } - // Set the last error value, if needed - if(nError != ERROR_SUCCESS) - SetLastError(nError); - return (nError == ERROR_SUCCESS); + // Invalid info class + return GetInfo_ReturnError(ERROR_INVALID_PARAMETER); } bool WINAPI SFileFreeFileInfo(void * pvFileInfo, SFileInfoClass InfoClass) diff --git a/src/SFileListFile.cpp b/src/SFileListFile.cpp index aa8969c..fe9bc69 100644 --- a/src/SFileListFile.cpp +++ b/src/SFileListFile.cpp @@ -17,7 +17,7 @@ // Listfile entry structure #define CACHE_BUFFER_SIZE 0x1000 // Size of the cache buffer -#define MAX_LISTFILE_SIZE 0x04000000 // Maximum accepted listfile size is about 68 MB +#define MAX_LISTFILE_SIZE 0x8000000 // Maximum accepted listfile size is 128 MB union TListFileHandle { @@ -148,6 +148,10 @@ static TListFileCache * CreateListFileCache( TListFileCache * pCache = NULL; TListFileHandle ListHandle = {NULL}; + // Put default value to dwMaxSize + if(dwMaxSize == 0) + dwMaxSize = MAX_LISTFILE_SIZE; + // Internal listfile: hMPQ must be non NULL and szListFile must be NULL. // We load the MPQ::(listfile) file if(hMpq != NULL && szListFile == NULL) @@ -181,7 +185,7 @@ static TListFileCache * CreateListFileCache( { // Verify the file size FileStream_GetSize(ListHandle.pStream, &FileSize); - if(0 < FileSize && FileSize < MAX_LISTFILE_SIZE) + if(0 < FileSize && FileSize < dwMaxSize) { pCache = CreateListFileCache(LoadListFile_Stream, &ListHandle, szWildCard, (DWORD)FileSize, dwMaxSize, dwFlags); } diff --git a/src/SFileOpenArchive.cpp b/src/SFileOpenArchive.cpp index d1cc4d6..3e333a9 100644 --- a/src/SFileOpenArchive.cpp +++ b/src/SFileOpenArchive.cpp @@ -9,7 +9,7 @@ /*---------------------------------------------------------------------------*/ /* Date Ver Who Comment */ /* -------- ---- --- ------- */ -/* xx.xx.xx 1.00 Lad The first version of SFileOpenArchive.cpp */ +/* xx.xx.xx 1.00 Lad Created */ /* 19.11.03 1.01 Dan Big endian handling */ /*****************************************************************************/ diff --git a/src/SFileReadFile.cpp b/src/SFileReadFile.cpp index a693e70..0320677 100644 --- a/src/SFileReadFile.cpp +++ b/src/SFileReadFile.cpp @@ -725,7 +725,7 @@ bool WINAPI SFileReadFile(HANDLE hFile, void * pvBuffer, DWORD dwToRead, LPDWORD // Otherwise read it as sector based MPQ file else - { + { nError = ReadMpqFileSectorFile(hf, pvBuffer, hf->dwFilePos, dwToRead, &dwBytesRead); } diff --git a/src/StormLib.h b/src/StormLib.h index d913a54..f254290 100644 --- a/src/StormLib.h +++ b/src/StormLib.h @@ -142,8 +142,8 @@ extern "C" { //----------------------------------------------------------------------------- // Defines -#define STORMLIB_VERSION 0x0916 // Current version of StormLib (9.21) -#define STORMLIB_VERSION_STRING "9.22" // String version of StormLib version +#define STORMLIB_VERSION 0x0917 // Current version of StormLib (9.23) +#define STORMLIB_VERSION_STRING "9.23" // String version of StormLib version #define ID_MPQ 0x1A51504D // MPQ archive header ID ('MPQ\x1A') #define ID_MPQ_USERDATA 0x1B51504D // MPQ userdata entry ('MPQ\x1B') diff --git a/src/huffman/huff.cpp b/src/huffman/huff.cpp index 9de5acb..fa0964d 100644 --- a/src/huffman/huff.cpp +++ b/src/huffman/huff.cpp @@ -478,19 +478,24 @@ THTreeItem * THuffmannTree::FindHigherOrEqualItem(THTreeItem * pItem, unsigned i THTreeItem * THuffmannTree::CreateNewItem(unsigned int DecompressedValue, unsigned int Weight, TInsertPoint InsertPoint) { - THTreeItem * pNewItem; + THTreeItem * pNewItem = NULL; - // Allocate new item from the item pool - pNewItem = &ItemBuffer[ItemsUsed++]; + // Don't let the item buffer run out of space + if(ItemsUsed < HUFF_ITEM_COUNT) + { + // Allocate new item from the item pool + pNewItem = &ItemBuffer[ItemsUsed++]; - // Insert this item to the top of the tree - InsertItem(pNewItem, InsertPoint, NULL); + // Insert this item to the top of the tree + InsertItem(pNewItem, InsertPoint, NULL); - // Fill the rest of the item - pNewItem->DecompressedValue = DecompressedValue; - pNewItem->Weight = Weight; - pNewItem->pParent = NULL; - pNewItem->pChildLo = NULL; + // Fill the rest of the item + pNewItem->DecompressedValue = DecompressedValue; + pNewItem->Weight = Weight; + pNewItem->pParent = NULL; + pNewItem->pChildLo = NULL; + } + return pNewItem; } @@ -567,6 +572,8 @@ bool THuffmannTree::BuildTree(unsigned int CompressionType) // Create new parent item for the children pNewItem = CreateNewItem(0, pChildHi->Weight + pChildLo->Weight, InsertAfter); + if(pNewItem == NULL) + return false; // Link both child items to their new parent pChildLo->pParent = pNewItem; @@ -631,7 +638,7 @@ void THuffmannTree::IncWeightsAndRebalance(THTreeItem * pItem) } } -void THuffmannTree::InsertNewBranchAndRebalance(unsigned int Value1, unsigned int Value2) +bool THuffmannTree::InsertNewBranchAndRebalance(unsigned int Value1, unsigned int Value2) { THTreeItem * pLastItem = pLast; THTreeItem * pChildHi; @@ -639,16 +646,26 @@ void THuffmannTree::InsertNewBranchAndRebalance(unsigned int Value1, unsigned in // Create higher-weight child pChildHi = CreateNewItem(Value1, pLastItem->Weight, InsertBefore); - pChildHi->pParent = pLastItem; - ItemsByByte[Value1] = pChildHi; + if(pChildHi != NULL) + { + pChildHi->pParent = pLastItem; + ItemsByByte[Value1] = pChildHi; - // Create lower-weight child - pChildLo = CreateNewItem(Value2, 0, InsertBefore); - pChildLo->pParent = pLastItem; - pLastItem->pChildLo = pChildLo; - ItemsByByte[Value2] = pChildLo; + // Create lower-weight child + pChildLo = CreateNewItem(Value2, 0, InsertBefore); + if(pChildLo != NULL) + { + pChildLo->pParent = pLastItem; + pLastItem->pChildLo = pChildLo; + ItemsByByte[Value2] = pChildLo; + + IncWeightsAndRebalance(pChildLo); + return true; + } + } - IncWeightsAndRebalance(pChildLo); + // No more space in the tree buffer + return false; } void THuffmannTree::EncodeOneByte(TOutputStream * os, THTreeItem * pItem) @@ -789,7 +806,8 @@ unsigned int THuffmannTree::Compress(TOutputStream * os, void * pvInBuffer, int // Store the loaded byte into output stream os->PutBits(InputByte, 8); - InsertNewBranchAndRebalance(pLast->DecompressedValue, InputByte); + if(!InsertNewBranchAndRebalance(pLast->DecompressedValue, InputByte)) + return 0; if(bIsCmp0) { @@ -851,7 +869,8 @@ unsigned int THuffmannTree::Decompress(void * pvOutBuffer, unsigned int cbOutLen // The decompressed byte is stored in the next 8 bits DecompressedValue = is->Get8Bits(); - InsertNewBranchAndRebalance(pLast->DecompressedValue, DecompressedValue); + if(!InsertNewBranchAndRebalance(pLast->DecompressedValue, DecompressedValue)) + return 0; if(bIsCmp0 == 0) IncWeightsAndRebalance(ItemsByByte[DecompressedValue]); diff --git a/src/huffman/huff.h b/src/huffman/huff.h index 89993fd..d2c3e3e 100644 --- a/src/huffman/huff.h +++ b/src/huffman/huff.h @@ -118,7 +118,7 @@ class THuffmannTree bool BuildTree(unsigned int CompressionType); void IncWeightsAndRebalance(THTreeItem * pItem); - void InsertNewBranchAndRebalance(unsigned int Value1, unsigned int Value2); + bool InsertNewBranchAndRebalance(unsigned int Value1, unsigned int Value2); void EncodeOneByte(TOutputStream * os, THTreeItem * pItem); unsigned int DecodeOneByte(TInputStream * is); -- cgit v1.2.3