summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLadislav Zezula <zezula@volny.cz>2020-11-21 04:27:09 +0100
committerLadislav Zezula <zezula@volny.cz>2020-11-21 04:27:09 +0100
commit809005c7f025bcc55bfa4ede78cb4cc45d3c0e6c (patch)
treee5d10b093dd215147f3e7128b11f96cc6afed04a
parentaea84bea149020385eadcd3df348d8e6fcbab733 (diff)
* Release 9.23v9.23
* Fixed regressions * Fixed test program
-rw-r--r--CMakeLists.txt6
-rw-r--r--StormLib_vs08_test.vcproj2
-rw-r--r--StormLib_vs19_test.vcxproj2
-rw-r--r--src/SBaseDumpData.cpp50
-rw-r--r--src/SBaseFileTable.cpp6
-rw-r--r--src/SFileAddFile.cpp20
-rw-r--r--src/SFileFindFile.cpp2
-rw-r--r--src/SFileGetFileInfo.cpp887
-rw-r--r--src/SFileListFile.cpp8
-rw-r--r--src/SFileOpenArchive.cpp2
-rw-r--r--src/SFileReadFile.cpp2
-rw-r--r--src/StormLib.h4
-rw-r--r--src/huffman/huff.cpp61
-rw-r--r--src/huffman/huff.h2
-rw-r--r--test/StormTest.cpp1108
-rw-r--r--test/TLogHelper.cpp30
16 files changed, 761 insertions, 1431 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 6d9ec5a..bd8d336 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -367,8 +367,8 @@ if (NOT STORM_SKIP_INSTALL)
endif()
if(STORM_BUILD_TESTS)
- add_executable(storm_test ${TEST_SRC_FILES})
- target_link_libraries(storm_test ${LIBRARY_NAME})
- install(TARGETS storm_test RUNTIME DESTINATION bin)
+ add_executable(StormLib_test ${TEST_SRC_FILES})
+ target_link_libraries(StormLib_test ${LIBRARY_NAME})
+ install(TARGETS StormLib_test RUNTIME DESTINATION bin)
endif()
diff --git a/StormLib_vs08_test.vcproj b/StormLib_vs08_test.vcproj
index 7e9e485..2f03a0b 100644
--- a/StormLib_vs08_test.vcproj
+++ b/StormLib_vs08_test.vcproj
@@ -50,7 +50,7 @@
<Tool
Name="VCCLCompilerTool"
Optimization="0"
- PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;__STORMLIB_TEST__;__STORMLIB_DUMP_DATA__"
+ PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;__STORMLIB_TEST__"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="1"
diff --git a/StormLib_vs19_test.vcxproj b/StormLib_vs19_test.vcxproj
index 96d1546..15f9a6b 100644
--- a/StormLib_vs19_test.vcxproj
+++ b/StormLib_vs19_test.vcxproj
@@ -91,7 +91,7 @@
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<Optimization>Disabled</Optimization>
- <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;__STORMLIB_TEST__;__STORMLIB_DUMP_DATA__;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;__STORMLIB_TEST__;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<PrecompiledHeader />
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
@@ -13,35 +13,8 @@
#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);
diff --git a/test/StormTest.cpp b/test/StormTest.cpp
index 47a8cb5..8f9cd71 100644
--- a/test/StormTest.cpp
+++ b/test/StormTest.cpp
@@ -35,12 +35,8 @@
//------------------------------------------------------------------------------
// Local structures
-#define TEST_OPEN_MPQ 0x00000000
-#define TEST_LOAD_FILE_CHECK_CRC 0x00010000
-#define TEST_OPEN_COMPARE_TWO_FILES 0x00020000
-#define TEST_MASK 0xFFFF0000
-
-#define TEST_SETPOS 0x00000001
+#define TEST_FLAG_PROTECTED 0x01000000
+#define TEST_FLAG_FILE_COUNT 0x00FFFFFF
typedef struct _TEST_INFO
{
@@ -60,7 +56,7 @@ static const TCHAR szListFileDir[] = { '1', '9', '9', '5', ' ', '-', ' ', 'T', '
#endif
#ifdef STORMLIB_LINUX
-#define WORK_PATH_ROOT "/home/ladik/StormLib/test"
+#define WORK_PATH_ROOT "/media/ladik/MPQs"
static const TCHAR szListFileDir[] = { '1', '9', '9', '5', ' ', '-', ' ', 'T', 'e', 's', 't', ' ', 'M', 'P', 'Q', 's', '\\', 'l', 'i', 's', 't', 'f', 'i', 'l', 'e', 's', '-', (TCHAR)0xe6, (TCHAR)0x96, (TCHAR)0xB0, (TCHAR)0xE5, (TCHAR)0xBB, (TCHAR)0xBA, (TCHAR)0xE6, (TCHAR)0x96, (TCHAR)0x87, (TCHAR)0xE4, (TCHAR)0xBB, (TCHAR)0xB6, (TCHAR)0xE5, (TCHAR)0xA4, (TCHAR)0xB9, 0 };
#endif
@@ -486,62 +482,6 @@ static bool CopyStringAndVerifyConversion(
return (_tcsicmp(szBufferT, szFoundFile) == 0) ? true : false;
}
-static void CalculateRelativePath(LPCSTR szFullPath1, LPCSTR szFullPath2, char * szBuffer)
-{
- LPCSTR szPathPart1 = szFullPath1;
- LPCSTR szPathPart2 = szFullPath2;
- LPCSTR szNextPart1;
- LPCSTR szNextPart2;
- int nEqualParts = 0;
- int nStepsUp = 0;
-
- // Parse both paths and find all path parts that are equal
- for(;;)
- {
- // Find the next part of the first path
- szNextPart1 = FindNextPathPart(szPathPart1, 1);
- if(szNextPart1 == szPathPart1)
- break;
-
- szNextPart2 = FindNextPathPart(szPathPart2, 1);
- if(szNextPart2 == szPathPart2)
- break;
-
- // Are these equal?
- if((szNextPart2 - szPathPart2) != (szNextPart1 - szPathPart1))
- break;
- if(_strnicmp(szPathPart1, szPathPart2, (szNextPart1 - szPathPart1 - 1)))
- break;
-
- // Increment the number of path parts that are equal
- szPathPart1 = szNextPart1;
- szPathPart2 = szNextPart2;
- nEqualParts++;
- }
-
- // If we found at least one equal part, we can create relative path
- if(nEqualParts != 0)
- {
- // Calculate how many steps up we need to go
- nStepsUp = GetPathSeparatorCount(szPathPart2);
-
- // Append "../" nStepsUp-times
- for(int i = 0; i < nStepsUp; i++)
- {
- *szBuffer++ = '.';
- *szBuffer++ = '.';
- *szBuffer++ = '/';
- }
-
- // Append the rest of the path. Also change DOS backslashes to slashes
- CopyPathPart(szBuffer, szPathPart1);
- return;
- }
-
- // Failed. Just copy the source path as it is
- strcpy(szBuffer, szFullPath1);
-}
-
static size_t ConvertSha1ToText(const unsigned char * sha1_digest, TCHAR * szSha1Text)
{
LPCSTR szTable = "0123456789abcdef";
@@ -864,19 +804,23 @@ static int InitializeMpqDirectory(TCHAR * argv[], int argc)
TLogHelper Logger("InitWorkDir");
TFileStream * pStream;
TCHAR szFullPath[MAX_PATH];
- LPCTSTR szWhereFrom = NULL;
- LPCTSTR szDirName;
+ LPCTSTR szWhereFrom = _T("default");
+ LPCTSTR szDirName = WORK_PATH_ROOT;
- // Retrieve the name of the MPQ directory
+ // Retrieve the first argument
if(argc > 1 && argv[1] != NULL)
{
- szWhereFrom = _T("command line");
- szDirName = argv[1];
- }
- else
- {
- szWhereFrom = _T("default");
- szDirName = WORK_PATH_ROOT;
+ // Check if it's a directory
+ pStream = FileStream_OpenFile(argv[1], STREAM_FLAG_READ_ONLY);
+ if(pStream == NULL)
+ {
+ szWhereFrom = _T("command line");
+ szDirName = argv[1];
+ }
+ else
+ {
+ FileStream_Close(pStream);
+ }
}
// Copy the name of the MPQ directory.
@@ -912,33 +856,33 @@ static int InitializeMpqDirectory(TCHAR * argv[], int argc)
return ERROR_SUCCESS;
}
-static int GetFilePatchCount(TLogHelper * pLogger, HANDLE hMpq, LPCSTR szFileName)
+static DWORD GetFilePatchCount(TLogHelper * pLogger, HANDLE hMpq, LPCSTR szFileName)
{
TCHAR * szPatchName;
HANDLE hFile;
TCHAR szPatchChain[0x400];
+ DWORD dwErrCode = ERROR_SUCCESS;
int nPatchCount = 0;
- int nError = ERROR_SUCCESS;
// Open the MPQ file
if(SFileOpenFileEx(hMpq, szFileName, 0, &hFile))
{
// Notify the user
- pLogger->PrintProgress(_T("Verifying patch chain for %s ..."), GetShortPlainName(szFileName));
+ pLogger->PrintProgress("Verifying patch chain for %s ...", GetShortPlainName(szFileName));
// Query the patch chain
if(!SFileGetFileInfo(hFile, SFileInfoPatchChain, szPatchChain, sizeof(szPatchChain), NULL))
- nError = pLogger->PrintError("Failed to retrieve the patch chain on %s", szFileName);
+ dwErrCode = pLogger->PrintError("Failed to retrieve the patch chain on %s", szFileName);
// Is there anything at all in the patch chain?
- if(nError == ERROR_SUCCESS && szPatchChain[0] == 0)
+ if(dwErrCode == ERROR_SUCCESS && szPatchChain[0] == 0)
{
pLogger->PrintError("The patch chain for %s is empty", szFileName);
- nError = ERROR_FILE_CORRUPT;
+ dwErrCode = ERROR_FILE_CORRUPT;
}
// Now calculate the number of patches
- if(nError == ERROR_SUCCESS)
+ if(dwErrCode == ERROR_SUCCESS)
{
// Get the pointer to the patch
szPatchName = szPatchChain;
@@ -966,7 +910,7 @@ static int GetFilePatchCount(TLogHelper * pLogger, HANDLE hMpq, LPCSTR szFileNam
return nPatchCount;
}
-static int VerifyFilePatchCount(TLogHelper * pLogger, HANDLE hMpq, LPCSTR szFileName, int nExpectedPatchCount)
+static DWORD VerifyFilePatchCount(TLogHelper * pLogger, HANDLE hMpq, LPCSTR szFileName, int nExpectedPatchCount)
{
int nPatchCount = 0;
@@ -977,21 +921,21 @@ static int VerifyFilePatchCount(TLogHelper * pLogger, HANDLE hMpq, LPCSTR szFile
// Check if there are any patches at all
if(nExpectedPatchCount != 0 && nPatchCount == 0)
{
- pLogger->PrintMessage(_T("There are no patches for %s"), szFileName);
+ pLogger->PrintMessage("There are no patches for %s", szFileName);
return ERROR_FILE_CORRUPT;
}
// Check if the number of patches fits
if(nPatchCount != nExpectedPatchCount)
{
- pLogger->PrintMessage(_T("Unexpected number of patches for %s"), szFileName);
+ pLogger->PrintMessage("Unexpected number of patches for %s", szFileName);
return ERROR_FILE_CORRUPT;
}
return ERROR_SUCCESS;
}
-static int CreateEmptyFile(TLogHelper * pLogger, LPCTSTR szPlainName, ULONGLONG FileSize, TCHAR * szBuffer)
+static DWORD CreateEmptyFile(TLogHelper * pLogger, LPCTSTR szPlainName, ULONGLONG FileSize, TCHAR * szBuffer)
{
TFileStream * pStream;
TCHAR szFullPath[MAX_PATH];
@@ -1015,13 +959,13 @@ static int CreateEmptyFile(TLogHelper * pLogger, LPCTSTR szPlainName, ULONGLONG
return ERROR_SUCCESS;
}
-static int VerifyFilePosition(
+static DWORD VerifyFilePosition(
TLogHelper * pLogger,
TFileStream * pStream,
ULONGLONG ExpectedPosition)
{
ULONGLONG ByteOffset = 0;
- int nError = ERROR_SUCCESS;
+ DWORD dwErrCode = ERROR_SUCCESS;
// Retrieve the file position
if(FileStream_GetPos(pStream, &ByteOffset))
@@ -1029,15 +973,15 @@ static int VerifyFilePosition(
if(ByteOffset != ExpectedPosition)
{
pLogger->PrintMessage(_T("The file position is different than expected (expected: ") I64u_t _T(", current: ") I64u_t, ExpectedPosition, ByteOffset);
- nError = ERROR_FILE_CORRUPT;
+ dwErrCode = ERROR_FILE_CORRUPT;
}
}
else
{
- nError = pLogger->PrintError(_T("Failed to retrieve the file offset"));
+ dwErrCode = pLogger->PrintError(_T("Failed to retrieve the file offset"));
}
- return nError;
+ return dwErrCode;
}
static int VerifyFileMpqHeader(TLogHelper * pLogger, TFileStream * pStream, ULONGLONG * pByteOffset)
@@ -1341,10 +1285,11 @@ static void WINAPI CompactCallback(void * pvUserData, DWORD dwWork, ULONGLONG By
//-----------------------------------------------------------------------------
// MPQ file utilities
-#define TEST_FLAG_LOAD_FILES 0x00000001 // Test function should load all files in the MPQ
-#define TEST_FLAG_HASH_FILES 0x00000002 // Test function should load all files in the MPQ
-#define TEST_FLAG_PLAY_WAVES 0x00000004 // Play extracted WAVE files
-#define TEST_FLAG_MOST_PATCHED 0x00000008 // Find the most patched file
+#define SEARCH_FLAG_LOAD_FILES 0x00000001 // Test function should load all files in the MPQ
+#define SEARCH_FLAG_HASH_FILES 0x00000002 // Test function should load all files in the MPQ
+#define SEARCH_FLAG_PLAY_WAVES 0x00000004 // Play extracted WAVE files
+#define SEARCH_FLAG_MOST_PATCHED 0x00000008 // Find the most patched file
+#define SEARCH_FLAG_IGNORE_ERRORS 0x00000010 // Ignore files that failed to open
struct TFileData
{
@@ -1496,7 +1441,7 @@ static int CompareTwoLocalFilesRR(
return nError;
}
-static TFileData * LoadMpqFile(TLogHelper * pLogger, HANDLE hMpq, LPCSTR szFileName, LCID lcLocale = 0)
+static TFileData * LoadMpqFile(TLogHelper * pLogger, HANDLE hMpq, LPCSTR szFileName, LCID lcLocale = 0, bool bIgnoreOpenErrors = false)
{
TFileData * pFileData = NULL;
HANDLE hFile;
@@ -1518,74 +1463,81 @@ static TFileData * LoadMpqFile(TLogHelper * pLogger, HANDLE hMpq, LPCSTR szFileN
SFileSetLocale(lcLocale);
// Open the file from MPQ
- if(!SFileOpenFileEx(hMpq, szFileName, 0, &hFile))
- dwErrCode = pLogger->PrintError("Open failed: %s", szFileName);
+ if(SFileOpenFileEx(hMpq, szFileName, 0, &hFile))
+ {
+ // Get the CRC32 of the file
+ SFileGetFileInfo(hFile, SFileInfoCRC32, &dwCrc32, sizeof(dwCrc32), NULL);
- // Get the CRC32 of the file
- SFileGetFileInfo(hFile, SFileInfoCRC32, &dwCrc32, sizeof(dwCrc32), NULL);
+ // Get the size of the file
+ if(dwErrCode == ERROR_SUCCESS)
+ {
+ dwFileSizeLo = SFileGetFileSize(hFile, &dwFileSizeHi);
+ if(dwFileSizeLo == SFILE_INVALID_SIZE || dwFileSizeHi != 0)
+ dwErrCode = pLogger->PrintError("Failed to query the file size");
+ }
- // Get the size of the file
- if(dwErrCode == ERROR_SUCCESS)
- {
- dwFileSizeLo = SFileGetFileSize(hFile, &dwFileSizeHi);
- if(dwFileSizeLo == SFILE_INVALID_SIZE || dwFileSizeHi != 0)
- dwErrCode = pLogger->PrintError("Failed to query the file size");
- }
+ // Spazzler protector: Creates fake files with size of 0x7FFFE7CA
+ if(dwErrCode == ERROR_SUCCESS)
+ {
+ if(dwFileSizeLo > 0x1FFFFFFF)
+ dwErrCode = ERROR_FILE_CORRUPT;
+ }
- // Spazzler protector: Creates fake files with size of 0x7FFFE7CA
- if(dwErrCode == ERROR_SUCCESS)
- {
- if(dwFileSizeLo > 0x1FFFFFFF)
- dwErrCode = ERROR_FILE_CORRUPT;
- }
+ // Allocate buffer for the file content
+ if(dwErrCode == ERROR_SUCCESS)
+ {
+ pFileData = (TFileData *)STORM_ALLOC(BYTE, sizeof(TFileData) + dwFileSizeLo);
+ if(pFileData == NULL)
+ {
+ pLogger->PrintError("Failed to allocate buffer for the file content");
+ dwErrCode = ERROR_NOT_ENOUGH_MEMORY;
+ }
+ }
- // Allocate buffer for the file content
- if(dwErrCode == ERROR_SUCCESS)
- {
- pFileData = (TFileData *)STORM_ALLOC(BYTE, sizeof(TFileData) + dwFileSizeLo);
- if(pFileData == NULL)
+ // get the file index of the MPQ file
+ if(dwErrCode == ERROR_SUCCESS)
{
- pLogger->PrintError("Failed to allocate buffer for the file content");
- dwErrCode = ERROR_NOT_ENOUGH_MEMORY;
+ // Store the file size
+ memset(pFileData, 0, sizeof(TFileData) + dwFileSizeLo);
+ pFileData->dwFileSize = dwFileSizeLo;
+ pFileData->dwCrc32 = dwCrc32;
+
+ // Retrieve the block index and file flags
+ if(!SFileGetFileInfo(hFile, SFileInfoFileIndex, &pFileData->dwBlockIndex, sizeof(DWORD), NULL))
+ dwErrCode = pLogger->PrintError("Failed retrieve the file index of %s", szFileName);
+ if(!SFileGetFileInfo(hFile, SFileInfoFlags, &pFileData->dwFlags, sizeof(DWORD), NULL))
+ dwErrCode = pLogger->PrintError("Failed retrieve the file flags of %s", szFileName);
}
- }
- // get the file index of the MPQ file
- if(dwErrCode == ERROR_SUCCESS)
- {
- // Store the file size
- memset(pFileData, 0, sizeof(TFileData) + dwFileSizeLo);
- pFileData->dwFileSize = dwFileSizeLo;
- pFileData->dwCrc32 = dwCrc32;
+ // Load the entire file
+ if(dwErrCode == ERROR_SUCCESS)
+ {
+ // Read the file data
+ SFileReadFile(hFile, pFileData->FileData, dwFileSizeLo, &dwBytesRead, NULL);
+ if(dwBytesRead != dwFileSizeLo)
+ dwErrCode = ERROR_FILE_CORRUPT;
+ }
- // Retrieve the block index and file flags
- if(!SFileGetFileInfo(hFile, SFileInfoFileIndex, &pFileData->dwBlockIndex, sizeof(DWORD), NULL))
- dwErrCode = pLogger->PrintError("Failed retrieve the file index of %s", szFileName);
- if(!SFileGetFileInfo(hFile, SFileInfoFlags, &pFileData->dwFlags, sizeof(DWORD), NULL))
- dwErrCode = pLogger->PrintError("Failed retrieve the file flags of %s", szFileName);
- }
+ // If failed, free the buffer
+ if(dwErrCode != ERROR_SUCCESS)
+ {
+ SetLastError(dwErrCode);
+ if(pFileData != NULL)
+ STORM_FREE(pFileData);
+ pFileData = NULL;
+ }
- // Load the entire file
- if(dwErrCode == ERROR_SUCCESS)
- {
- // Read the file data
- SFileReadFile(hFile, pFileData->FileData, dwFileSizeLo, &dwBytesRead, NULL);
- if(dwBytesRead != dwFileSizeLo)
-// dwErrCode = pLogger->PrintError("Read failed: %s", szFileName);
- dwErrCode = ERROR_FILE_CORRUPT;
+ SFileCloseFile(hFile);
}
-
- // If failed, free the buffer
- if(dwErrCode != ERROR_SUCCESS)
+ else
{
- STORM_FREE(pFileData);
- SetLastError(dwErrCode);
- pFileData = NULL;
+ if(bIgnoreOpenErrors == false)
+ {
+ dwErrCode = pLogger->PrintError("Open failed: %s", szFileName);
+ }
}
- // Close the file and return what we got
- if(hFile != NULL)
- SFileCloseFile(hFile);
+ // Return what we got
return pFileData;
}
@@ -1617,7 +1569,7 @@ static bool CompareTwoFiles(TLogHelper * pLogger, TFileData * pFileData1, TFileD
static DWORD SearchArchive(
TLogHelper * pLogger,
HANDLE hMpq,
- DWORD dwTestFlags = 0,
+ DWORD dwSearchFlags = 0,
DWORD * pdwFileCount = NULL,
LPBYTE pbFileHash = NULL)
{
@@ -1629,6 +1581,7 @@ static DWORD SearchArchive(
TCHAR szListFile[MAX_PATH] = _T("");
char szMostPatched[MAX_PATH] = "";
DWORD dwErrCode = ERROR_SUCCESS;
+ bool bIgnoreOpenErrors = (dwSearchFlags & SEARCH_FLAG_IGNORE_ERRORS) ? true : false;
bool bFound = true;
int nMaxPatchCount = 0;
int nPatchCount = 0;
@@ -1640,7 +1593,7 @@ static DWORD SearchArchive(
md5_init(&md5state);
// Initiate the MPQ search
- pLogger->PrintProgress("Searching the archive ...");
+ pLogger->PrintProgress("Searching the archive (initializing) ...");
hFind = SFileFindFirstFile(hMpq, "*", &sf, szListFile);
if(hFind == NULL)
{
@@ -1650,6 +1603,7 @@ static DWORD SearchArchive(
}
// Perform the search
+ pLogger->PrintProgress("Searching the archive ...");
while(bFound == true)
{
// Increment number of files
@@ -1658,7 +1612,7 @@ static DWORD SearchArchive(
// if(!_stricmp(sf.cFileName, "war3map.j"))
// DebugBreak();
- if(dwTestFlags & TEST_FLAG_MOST_PATCHED)
+ if(dwSearchFlags & SEARCH_FLAG_MOST_PATCHED)
{
// Load the patch count
nPatchCount = GetFilePatchCount(pLogger, hMpq, sf.cFileName);
@@ -1672,18 +1626,18 @@ static DWORD SearchArchive(
}
// Load the file to memory, if required
- if(dwTestFlags & TEST_FLAG_LOAD_FILES)
+ if(dwSearchFlags & SEARCH_FLAG_LOAD_FILES)
{
// Load the entire file to the MPQ
- pFileData = LoadMpqFile(pLogger, hMpq, sf.cFileName, sf.lcLocale);
+ pFileData = LoadMpqFile(pLogger, hMpq, sf.cFileName, sf.lcLocale, bIgnoreOpenErrors);
if(pFileData != NULL)
{
// Hash the file data, if needed
- if((dwTestFlags & TEST_FLAG_HASH_FILES) && !IsInternalMpqFileName(sf.cFileName))
+ if((dwSearchFlags & SEARCH_FLAG_HASH_FILES) && !IsInternalMpqFileName(sf.cFileName))
md5_process(&md5state, pFileData->FileData, pFileData->dwFileSize);
// Play sound files, if required
- if((dwTestFlags & TEST_FLAG_PLAY_WAVES) && strstr(sf.cFileName, ".wav") != NULL)
+ if((dwSearchFlags & SEARCH_FLAG_PLAY_WAVES) && strstr(sf.cFileName, ".wav") != NULL)
{
#ifdef _MSC_VER
pLogger->PrintProgress("Playing sound %s", sf.cFileName);
@@ -1704,7 +1658,7 @@ static DWORD SearchArchive(
pdwFileCount[0] = dwFileCount;
// Give the hash, if required
- if(pbFileHash != NULL && (dwTestFlags & TEST_FLAG_HASH_FILES))
+ if(pbFileHash != NULL && (dwSearchFlags & SEARCH_FLAG_HASH_FILES))
md5_done(&md5state, pbFileHash);
return dwErrCode;
@@ -2132,35 +2086,42 @@ static void TestGetFileInfo(
DWORD cbFileInfo,
DWORD * pcbLengthNeeded,
bool bExpectedResult,
- int nExpectedError)
+ DWORD dwExpectedErrCode)
{
+ DWORD dwErrCode = ERROR_SUCCESS;
bool bResult;
- int nError = ERROR_SUCCESS;
// Call the get file info
bResult = SFileGetFileInfo(hMpqOrFile, InfoClass, pvFileInfo, cbFileInfo, pcbLengthNeeded);
if(!bResult)
- nError = GetLastError();
+ dwErrCode = GetLastError();
if(bResult != bExpectedResult)
pLogger->PrintMessage("Different result of SFileGetFileInfo.");
- if(nError != nExpectedError)
- pLogger->PrintMessage("Different error from SFileGetFileInfo (expected %u, returned %u)", nExpectedError, nError);
+ if(dwErrCode != dwExpectedErrCode)
+ pLogger->PrintMessage("Different error from SFileGetFileInfo (expected %u, returned %u)", dwExpectedErrCode, dwErrCode);
}
// StormLib is able to open local files (as well as the original Storm.dll)
// I want to keep this for occasional use
-static int TestOpenLocalFile(LPCTSTR szPlainName)
+static DWORD TestOnLocalListFile(LPCTSTR szPlainName)
{
- TLogHelper Logger("OpenLocalFile", szPlainName);
+ TLogHelper Logger("LocalListFile", szPlainName);
+ SFILE_FIND_DATA sf;
HANDLE hFile;
+ HANDLE hFind;
DWORD dwFileSizeHi = 0;
DWORD dwFileSizeLo = 0;
+ TCHAR szFullPath[MAX_PATH];
char szFileName1[MAX_PATH];
char szFileName2[MAX_PATH];
- char szFileLine[0x40];
+ char szFileLine[0x40] = {0};
+ int nFileCount = 0;
+ // Get the full name of the local file
CreateFullPathName(szFileName1, _countof(szFileName1), szMpqSubDir, szPlainName);
+
+ // Test opening the local file
if(SFileOpenFileEx(NULL, szFileName1, SFILE_OPEN_LOCAL_FILE, &hFile))
{
// Retrieve the file name. It must match the name under which the file was open
@@ -2170,30 +2131,23 @@ static int TestOpenLocalFile(LPCTSTR szPlainName)
// Retrieve the file size
dwFileSizeLo = SFileGetFileSize(hFile, &dwFileSizeHi);
- if(dwFileSizeHi != 0 || dwFileSizeLo != 3904784)
+ if(dwFileSizeHi != 0 || dwFileSizeLo != 0x04385a4e)
Logger.PrintMessage("Local file size mismatch");
// Read the first line
- memset(szFileLine, 0, sizeof(szFileLine));
SFileReadFile(hFile, szFileLine, 18, NULL, NULL);
- if(strcmp(szFileLine, "(1)Enslavers01.scm"))
+ if(strcmp(szFileLine, "accountbilling.url"))
Logger.PrintMessage("Content of the listfile does not match");
SFileCloseFile(hFile);
}
+ else
+ return Logger.PrintError("Failed to open local listfile");
- return ERROR_SUCCESS;
-}
+ // We need unicode listfile name
+ StringCopy(szFullPath, _countof(szFullPath), szFileName1);
-static int TestSearchListFile(LPCTSTR szPlainName)
-{
- SFILE_FIND_DATA sf;
- TLogHelper Logger("SearchListFile", szPlainName);
- TCHAR szFullPath[MAX_PATH];
- HANDLE hFind;
- int nFileCount = 0;
-
- CreateFullPathName(szFullPath, _countof(szFullPath), szMpqSubDir, szPlainName);
+ // Start searching in the listfile
hFind = SListFileFindFirstFile(NULL, szFullPath, "*", &sf);
if(hFind != NULL)
{
@@ -2206,6 +2160,9 @@ static int TestSearchListFile(LPCTSTR szPlainName)
SListFileFindClose(hFind);
}
+ else
+ return Logger.PrintError("Failed to search local listfile");
+
return ERROR_SUCCESS;
}
@@ -2391,28 +2348,29 @@ static int TestFileStreamOperations(LPCTSTR szPlainName, DWORD dwStreamFlags)
return nError;
}
-static DWORD TestArchive_LoadFiles(TLogHelper * pLogger, HANDLE hMpq, ...)
+static DWORD TestArchive_LoadFiles(TLogHelper * pLogger, HANDLE hMpq, bool bIgnoreOpenErrors, ...)
{
TFileData * pFileData;
const char * szFileName;
va_list argList;
DWORD dwErrCode = ERROR_SUCCESS;
- va_start(argList, hMpq);
+ va_start(argList, bIgnoreOpenErrors);
while((szFileName = va_arg(argList, const char *)) != NULL)
{
if(SFileHasFile(hMpq, szFileName))
{
pFileData = LoadMpqFile(pLogger, hMpq, szFileName);
- if(pFileData != NULL)
+ if(pFileData == NULL && bIgnoreOpenErrors == false)
{
- STORM_FREE(pFileData);
- pFileData = NULL;
+ pLogger->PrintError("Error loading the file %s", szFileName);
+ dwErrCode = ERROR_FILE_CORRUPT;
+ break;
}
else
{
- dwErrCode = pLogger->PrintError("Error loading the file %s", szFileName);
- break;
+ STORM_FREE(pFileData);
+ pFileData = NULL;
}
}
}
@@ -2445,27 +2403,51 @@ static DWORD TestArchive_SetPos(HANDLE hMpq, const char * szFileName)
static DWORD TestArchive(
LPCTSTR szPlainName, // Plain name of the MPQ
LPCTSTR szListFile, // Listfile name (NULL if none)
- DWORD dwWhatToDo, // Flags what to do
+ DWORD dwFlags, // Flags
LPCSTR szFileName1,
LPCSTR szFileName2)
{
+ TFileData * pFileData1 = NULL;
TFileData * pFileData2 = NULL;
- TFileData * pFileData = NULL;
TLogHelper Logger("TestMpq", szPlainName);
-// HANDLE hFile = NULL;
+ LPCSTR szExpectedMD5 = NULL;
HANDLE hMpq = NULL;
DWORD dwFileCount = 0;
+ DWORD dwSearchFlags = 0;
DWORD dwErrCode;
DWORD dwCrc32 = 0;
+ DWORD dwExpectedFileCount = 0;
+ DWORD dwMpqFlags = 0;
TCHAR szFullName[MAX_PATH];
+ BYTE ExpectedMD5[MD5_DIGEST_SIZE];
+ BYTE OverallMD5[MD5_DIGEST_SIZE];
+ bool bIgnoreOpenErrors = false;
// If the file is a partial MPQ, don't load all files
- bool bIsPartialMpq = (_tcsstr(szPlainName, _T(".MPQ.part")) != NULL);
+ if(_tcsstr(szPlainName, _T(".MPQ.part")) == NULL)
+ dwSearchFlags |= SEARCH_FLAG_LOAD_FILES;
+
+ // If the MPQ is a protected MPQ, do different tests
+ if(dwFlags & TEST_FLAG_PROTECTED)
+ {
+ dwExpectedFileCount = (dwFlags & TEST_FLAG_FILE_COUNT);
+ if((szExpectedMD5 = szFileName1) != NULL)
+ dwSearchFlags |= SEARCH_FLAG_HASH_FILES;
+ szFileName2 = szFileName1 = NULL;
+ }
// Copy the archive so we won't fuck up the original one
dwErrCode = OpenExistingArchiveWithCopy(&Logger, szPlainName, NULL, &hMpq);
- if(dwErrCode == ERROR_SUCCESS)
+ while(dwErrCode == ERROR_SUCCESS)
{
+ // Check for malformed MPQs
+ SFileGetFileInfo(hMpq, SFileMpqFlags, &dwMpqFlags, sizeof(dwMpqFlags), NULL);
+ if(dwMpqFlags & MPQ_FLAG_MALFORMED)
+ {
+ dwSearchFlags |= SEARCH_FLAG_IGNORE_ERRORS;
+ bIgnoreOpenErrors = true;
+ }
+
// If the listfile was given, add it to the MPQ
if(szListFile && szListFile[0])
{
@@ -2475,256 +2457,96 @@ static DWORD TestArchive(
Logger.PrintMessage("Failed to add the listfile to the MPQ");
}
- // Perform work-specific duty
- switch(dwWhatToDo & TEST_MASK)
- {
- case TEST_LOAD_FILE_CHECK_CRC:
-
- // Load the entire file
- pFileData = LoadMpqFile(&Logger, hMpq, szFileName1);
- if(pFileData == NULL)
- {
- dwErrCode = Logger.PrintError("Failed to load the file %s", szFileName1);
- break;
- }
-
- // Compare the CRC32, if available
- dwCrc32 = crc32(0, (Bytef *)pFileData->FileData, (uInt)pFileData->dwFileSize);
- if(dwCrc32 != pFileData->dwCrc32)
- Logger.PrintError("Warning: CRC32 error on %s", szFileName1);
- break;
-
- case TEST_OPEN_COMPARE_TWO_FILES:
-
- // Load the first file
- pFileData = LoadMpqFile(&Logger, hMpq, szFileName1);
- if(pFileData == NULL)
- {
- dwErrCode = Logger.PrintError("Failed to load the file %s", "File00000023.xxx");
- break;
- }
-
- // Load the second file
- pFileData2 = LoadMpqFile(&Logger, hMpq, szFileName2);
- if(pFileData2 == NULL)
- {
- dwErrCode = Logger.PrintError("Failed to load the file %s", "music\\dintro.wav");
- break;
- }
+ // Attempt to open the (listfile), (attributes), (signature)
+ dwErrCode = TestArchive_LoadFiles(&Logger, hMpq, bIgnoreOpenErrors, LISTFILE_NAME, ATTRIBUTES_NAME, SIGNATURE_NAME, NULL);
+ if(dwErrCode != ERROR_SUCCESS)
+ break;
- // Compare both files
- if(!CompareTwoFiles(&Logger, pFileData, pFileData2))
- dwErrCode = Logger.PrintError("The file has different size/content when open without name");
+ // If szFileName1 was given, load it and check its CRC
+ if(szFileName1 && szFileName1[0])
+ {
+ // Test setting position
+ dwErrCode = TestArchive_SetPos(hMpq, szFileName1);
+ if(dwErrCode != ERROR_SUCCESS)
break;
- case TEST_OPEN_MPQ:
-
- // Attempt to open the (listfile), (attributes), (signature)
- dwErrCode = TestArchive_LoadFiles(&Logger, hMpq, LISTFILE_NAME, ATTRIBUTES_NAME, SIGNATURE_NAME, NULL);
- if(dwErrCode != ERROR_SUCCESS)
- break;
-
- // Test setting position
- if((dwWhatToDo & TEST_SETPOS) && (szFileName1 != NULL))
- {
- dwErrCode = TestArchive_SetPos(hMpq, szFileName1);
- if(dwErrCode != ERROR_SUCCESS)
- break;
- }
-
- // Search the archive
- dwErrCode = SearchArchive(&Logger, hMpq, (bIsPartialMpq ? 0 : TEST_FLAG_LOAD_FILES), &dwFileCount);
+ // Load the entire file 1
+ pFileData1 = LoadMpqFile(&Logger, hMpq, szFileName1);
+ if(pFileData1 == NULL)
+ {
+ dwErrCode = Logger.PrintError("Failed to load the file %s", szFileName1);
break;
- }
- }
-
- // Common cleanup
- if(pFileData2 != NULL)
- STORM_FREE(pFileData2);
- if(pFileData != NULL)
- STORM_FREE(pFileData);
- if(hMpq != NULL)
- SFileCloseArchive(hMpq);
- return dwErrCode;
-}
-
-static int TestOpenArchive(LPCTSTR szPlainName, LPCTSTR szListFile = NULL, LPCSTR szFileName = NULL, bool bDontCopyArchive = false)
-{
- TLogHelper Logger("OpenMpqTest", szPlainName);
- TFileData * pFileData;
- LPCTSTR szCopyName = (bDontCopyArchive) ? NULL : szPlainName;
- HANDLE hMpq;
- HANDLE hFile;
- DWORD dwFileCount = 0;
- DWORD dwTestFlags;
- TCHAR szListFileBuff[MAX_PATH];
- bool bIsPartialMpq = false;
- int nError;
-
- // If the file is a partial MPQ, don't load all files
- bIsPartialMpq = (_tcsstr(szPlainName, _T(".MPQ.part")) != NULL);
-
- // Copy the archive so we won't fuck up the original one
- nError = OpenExistingArchiveWithCopy(&Logger, szPlainName, szCopyName, &hMpq);
- if(nError == ERROR_SUCCESS)
- {
- // If the listfile was given, add it to the MPQ
- if(szListFile != NULL)
- {
- Logger.PrintProgress(_T("Adding listfile %s ..."), szListFile);
- CreateFullPathName(szListFileBuff, _countof(szListFileBuff), szListFileDir, szListFile);
- nError = SFileAddListFile(hMpq, szListFileBuff);
- if(nError != ERROR_SUCCESS)
- Logger.PrintMessage("Failed to add the listfile to the MPQ");
- }
+ }
- // Attempt to open the (listfile)
- if(SFileHasFile(hMpq, LISTFILE_NAME))
- {
- pFileData = LoadMpqFile(&Logger, hMpq, LISTFILE_NAME);
- if(pFileData != NULL)
- STORM_FREE(pFileData);
+ // Check the CRC of file1, if available
+ if(pFileData1->dwCrc32)
+ {
+ // Compare the CRC32, if available
+ dwCrc32 = crc32(0, (Bytef *)pFileData1->FileData, (uInt)pFileData1->dwFileSize);
+ if(dwCrc32 != pFileData1->dwCrc32)
+ Logger.PrintError("Warning: CRC32 error on %s", szFileName1);
+ }
}
- // Attempt to open the (attributes)
- if(SFileHasFile(hMpq, ATTRIBUTES_NAME))
+ // If szFileName2 was given, load it
+ if(szFileName2 && szFileName2[0])
{
- pFileData = LoadMpqFile(&Logger, hMpq, ATTRIBUTES_NAME);
- if(pFileData != NULL)
- STORM_FREE(pFileData);
+ // Load the entire file 2
+ pFileData2 = LoadMpqFile(&Logger, hMpq, szFileName2);
+ if(pFileData2 == NULL)
+ {
+ dwErrCode = Logger.PrintError("Failed to load the file %s", szFileName2);
+ break;
+ }
}
- // Attempt to open the (signature)
- if(SFileHasFile(hMpq, SIGNATURE_NAME))
+ // If two files were given, compare them
+ if(pFileData1 && pFileData2)
{
- pFileData = LoadMpqFile(&Logger, hMpq, SIGNATURE_NAME);
- if(pFileData != NULL)
- STORM_FREE(pFileData);
+ // Compare both files
+ if(!CompareTwoFiles(&Logger, pFileData1, pFileData2))
+ {
+ dwErrCode = Logger.PrintError("The file has different size/content of files");
+ break;
+ }
}
- // Attempt to open an arbitrary file
- if(szFileName != NULL && szFileName[0] != 0)
+ // Search the archive
+ dwErrCode = SearchArchive(&Logger, hMpq, dwSearchFlags, &dwFileCount, OverallMD5);
+
+ // Shall we check the file count and overall MD5?
+ if(dwExpectedFileCount != 0)
{
- if(SFileOpenFileEx(hMpq, "1.blp", 0, &hFile))
+ if(dwFileCount != dwExpectedFileCount)
{
- DWORD dwFileSize;
- DWORD dwBytesRead = 0;
- BYTE Buffer[0x10];
-
- dwFileSize = SFileGetFileSize(hFile, NULL);
- if(dwFileSize > sizeof(Buffer))
- {
- SFileSetFilePointer(hFile, dwFileSize - sizeof(Buffer), NULL, FILE_BEGIN);
- SFileReadFile(hFile, Buffer, sizeof(Buffer), &dwBytesRead, NULL);
- }
-
- SFileCloseFile(hFile);
+ Logger.PrintMessage("File count mismatch(expected: %u, found:%u)", dwExpectedFileCount, dwFileCount);
+ dwErrCode = ERROR_CAN_NOT_COMPLETE;
+ break;
}
}
- // Search the archive and load every file
- dwTestFlags = bIsPartialMpq ? 0 : TEST_FLAG_LOAD_FILES;
- nError = SearchArchive(&Logger, hMpq, dwTestFlags, &dwFileCount);
- SFileCloseArchive(hMpq);
- }
-
- return nError;
-}
-
-static int TestOpenArchive_SetPos(LPCTSTR szPlainName, LPCSTR szFileName)
-{
- TLogHelper Logger("SetPosTest", szPlainName);
- HANDLE hFile = NULL;
- HANDLE hMpq = NULL;
- TCHAR szMpqName[MAX_PATH];
- char szFullPath[MAX_PATH];
- int nError = ERROR_SUCCESS;
-
- // Create the full path name for the archive
- CreateFullPathName(szFullPath, _countof(szFullPath), szMpqSubDir, szPlainName);
- StringCopy(szMpqName, _countof(szMpqName), szFullPath);
-
- // Try to open the archive. It is expected to fail
- Logger.PrintProgress("Opening archive %s", szPlainName);
- if(SFileOpenArchive(szMpqName, 0, MPQ_OPEN_READ_ONLY, &hMpq))
- {
- if(SFileOpenFileEx(hMpq, szFileName, 0, &hFile))
+ // Shall we check overall MD5?
+ if(szExpectedMD5 && szExpectedMD5[0])
{
- // First, use the SFileSetFilePointer WITHOUT the high-dword position
- if(nError == ERROR_SUCCESS)
- nError = TestSetFilePointers(hFile, false);
-
- // First, use the SFileSetFilePointer WITH the high-dword position
- if(nError == ERROR_SUCCESS)
- nError = TestSetFilePointers(hFile, true);
-
- // Close the file
- SFileCloseFile(hFile);
+ BinaryFromString(szExpectedMD5, ExpectedMD5, MD5_DIGEST_SIZE);
+ if(memcmp(ExpectedMD5, OverallMD5, MD5_DIGEST_SIZE))
+ {
+ Logger.PrintMessage("Extracted files MD5 mismatch");
+ dwErrCode = ERROR_CAN_NOT_COMPLETE;
+ break;
+ }
}
- else
- nError = GetLastError();
-
- // Close the archive
- SFileCloseArchive(hMpq);
+ break;
}
- else
- nError = GetLastError();
-
- return nError;
-}
-
-static int TestOpenArchive_ProtectedMap(LPCTSTR szPlainName, LPCTSTR szListFile = NULL, DWORD dwExpectedFileCount = 0, LPCSTR szExpectedMD5 = NULL)
-{
- TLogHelper Logger("ProtectedMapTest", szPlainName);
- HANDLE hMpq;
- DWORD dwTestFlags = TEST_FLAG_LOAD_FILES | TEST_FLAG_HASH_FILES;
- DWORD dwFileCount = 0;
- BYTE ExpectedMD5[MD5_DIGEST_SIZE];
- BYTE OverallMD5[MD5_DIGEST_SIZE];
- TCHAR szListFileBuff[MAX_PATH];
- int nError;
-
- // Copy the archive so we won't fuck up the original one
- nError = OpenExistingArchiveWithCopy(&Logger, szPlainName, szPlainName, &hMpq);
- if(nError == ERROR_SUCCESS)
- {
- // If the listfile was given, add it to the MPQ
- if(szListFile != NULL)
- {
- Logger.PrintProgress(_T("Adding listfile %s ..."), szListFile);
- CreateFullPathName(szListFileBuff, _countof(szListFileBuff), szMpqSubDir, szListFile);
- nError = SFileAddListFile(hMpq, szListFileBuff);
- if(nError != ERROR_SUCCESS)
- Logger.PrintMessage("Failed to add the listfile to the MPQ");
- }
- // Search the archive and load every file
- nError = SearchArchive(&Logger, hMpq, dwTestFlags, &dwFileCount, OverallMD5);
+ // Common cleanup
+ if(pFileData2 != NULL)
+ STORM_FREE(pFileData2);
+ if(pFileData1 != NULL)
+ STORM_FREE(pFileData1);
+ if(hMpq != NULL)
SFileCloseArchive(hMpq);
- }
-
- // Check the file count and hash, if required
- if(nError == ERROR_SUCCESS && dwExpectedFileCount != 0)
- {
- if(dwFileCount != dwExpectedFileCount)
- {
- Logger.PrintMessage("File count mismatch(expected: %u, found:%u)", dwExpectedFileCount, dwFileCount);
- nError = ERROR_CAN_NOT_COMPLETE;
- }
- }
-
- // Check the overall hash, if required
- if(nError == ERROR_SUCCESS && szExpectedMD5 != NULL && szExpectedMD5[0] != 0)
- {
- BinaryFromString(szExpectedMD5, ExpectedMD5, MD5_DIGEST_SIZE);
- if(memcmp(ExpectedMD5, OverallMD5, MD5_DIGEST_SIZE))
- {
- Logger.PrintMessage("Extracted files MD5 mismatch");
- nError = ERROR_CAN_NOT_COMPLETE;
- }
- }
-
- return nError;
+ return dwErrCode;
}
// Open an empty archive (found in WoW cache - it's just a header)
@@ -2769,7 +2591,7 @@ static int TestOpenArchive_Corrupt(LPCTSTR szPlainName)
// Opens a patched MPQ archive
-static int TestOpenArchive_Patched(LPCTSTR PatchList[], LPCSTR szPatchedFile, int nExpectedPatchCount, bool bExpectedToFail = false)
+static DWORD TestOpenArchive_Patched(LPCTSTR PatchList[], LPCSTR szPatchedFile, int nExpectedPatchCount, bool bExpectedToFail = false)
{
TLogHelper Logger("OpenPatchedMpqTest", PatchList[0]);
HANDLE hMpq;
@@ -2777,18 +2599,18 @@ static int TestOpenArchive_Patched(LPCTSTR PatchList[], LPCSTR szPatchedFile, in
BYTE Buffer[0x100];
DWORD dwFileCount = 0;
DWORD BytesRead = 0;
- int nError;
+ DWORD dwErrCode;
// Open a patched MPQ archive
- nError = OpenPatchedArchive(&Logger, &hMpq, PatchList);
- if(nError == ERROR_SUCCESS)
+ dwErrCode = OpenPatchedArchive(&Logger, &hMpq, PatchList);
+ if(dwErrCode == ERROR_SUCCESS)
{
// Check patch count
if(szPatchedFile != NULL)
- nError = VerifyFilePatchCount(&Logger, hMpq, szPatchedFile, nExpectedPatchCount);
+ dwErrCode = VerifyFilePatchCount(&Logger, hMpq, szPatchedFile, nExpectedPatchCount);
// Try to open and read the file
- if(nError == ERROR_SUCCESS)
+ if(dwErrCode == ERROR_SUCCESS)
{
if(SFileOpenFileEx(hMpq, szPatchedFile, 0, &hFile))
{
@@ -2798,17 +2620,17 @@ static int TestOpenArchive_Patched(LPCTSTR PatchList[], LPCSTR szPatchedFile, in
}
// Search the archive and load every file
- if(nError == ERROR_SUCCESS)
- nError = SearchArchive(&Logger, hMpq, TEST_FLAG_LOAD_FILES, &dwFileCount);
+ if(dwErrCode == ERROR_SUCCESS)
+ dwErrCode = SearchArchive(&Logger, hMpq, SEARCH_FLAG_LOAD_FILES | SEARCH_FLAG_IGNORE_ERRORS, &dwFileCount);
// Close the archive
SFileCloseArchive(hMpq);
}
// Clear the error if patch prefix was not found
- if(nError == ERROR_CANT_FIND_PATCH_PREFIX && bExpectedToFail)
- nError = ERROR_SUCCESS;
- return nError;
+ if(dwErrCode == ERROR_CANT_FIND_PATCH_PREFIX && bExpectedToFail)
+ dwErrCode = ERROR_SUCCESS;
+ return dwErrCode;
}
// Open an archive for read-only access
@@ -2877,21 +2699,21 @@ static int TestOpenArchive_GetFileInfo(LPCTSTR szPlainName1, LPCTSTR szPlainName
TestGetFileInfo(&Logger, NULL, SFileMpqBetHeader, NULL, 0, NULL, false, ERROR_INVALID_HANDLE);
// Valid handle but invalid value of file info class (false, ERROR_INVALID_PARAMETER)
- TestGetFileInfo(&Logger, NULL, (SFileInfoClass)0xFFF, NULL, 0, NULL, false, ERROR_INVALID_PARAMETER);
+ TestGetFileInfo(&Logger, NULL, (SFileInfoClass)0xFFF, NULL, 0, NULL, false, ERROR_INVALID_HANDLE);
- // Valid archive handle but file info class is for file (false, ERROR_INVALID_HANDLE)
+ // Invalid archive handle and file info class is for file (false, ERROR_INVALID_HANDLE)
TestGetFileInfo(&Logger, NULL, SFileInfoNameHash1, NULL, 0, NULL, false, ERROR_INVALID_HANDLE);
// Valid handle and all parameters NULL
- // Returns (true, ERROR_SUCCESS), if BET table is present, otherwise (false, ERROR_CAN_NOT_COMPLETE)
+ // Returns (true, ERROR_SUCCESS), if BET table is present, otherwise (false, ERROR_FILE_NOT_FOUND)
TestGetFileInfo(&Logger, hMpq1, SFileMpqBetHeader, NULL, 0, NULL, false, ERROR_FILE_NOT_FOUND);
- TestGetFileInfo(&Logger, hMpq4, SFileMpqBetHeader, NULL, 0, NULL, true, ERROR_SUCCESS);
+ TestGetFileInfo(&Logger, hMpq4, SFileMpqBetHeader, NULL, 0, NULL, false, ERROR_INSUFFICIENT_BUFFER);
// Now try to retrieve the required size of the BET table header
- TestGetFileInfo(&Logger, hMpq4, SFileMpqBetHeader, NULL, 0, &cbLength, true, ERROR_SUCCESS);
+ TestGetFileInfo(&Logger, hMpq4, SFileMpqBetHeader, NULL, 0, &cbLength, false, ERROR_INSUFFICIENT_BUFFER);
// When we call SFileInfo with buffer = NULL and nonzero buffer size, it is ignored
- TestGetFileInfo(&Logger, hMpq4, SFileMpqBetHeader, NULL, 3, &cbLength, true, ERROR_SUCCESS);
+ TestGetFileInfo(&Logger, hMpq4, SFileMpqBetHeader, NULL, 3, &cbLength, false, ERROR_INSUFFICIENT_BUFFER);
// When we call SFileInfo with buffer != NULL and nonzero buffer size, it should return error
TestGetFileInfo(&Logger, hMpq4, SFileMpqBetHeader, DataBuff, 3, &cbLength, false, ERROR_INSUFFICIENT_BUFFER);
@@ -2903,11 +2725,11 @@ static int TestOpenArchive_GetFileInfo(LPCTSTR szPlainName1, LPCTSTR szPlainName
TestGetFileInfo(&Logger, hMpq4, SFileMpqBetHeader, DataBuff, sizeof(DataBuff), &cbLength, true, ERROR_SUCCESS);
// Try to retrieve strong signature from the MPQ
- TestGetFileInfo(&Logger, hMpq1, SFileMpqStrongSignature, NULL, 0, NULL, true, ERROR_SUCCESS);
+ TestGetFileInfo(&Logger, hMpq1, SFileMpqStrongSignature, NULL, 0, NULL, false, ERROR_INSUFFICIENT_BUFFER);
TestGetFileInfo(&Logger, hMpq4, SFileMpqStrongSignature, NULL, 0, NULL, false, ERROR_FILE_NOT_FOUND);
// Strong signature is returned including the signature ID
- TestGetFileInfo(&Logger, hMpq1, SFileMpqStrongSignature, NULL, 0, &cbLength, true, ERROR_SUCCESS);
+ TestGetFileInfo(&Logger, hMpq1, SFileMpqStrongSignature, NULL, 0, &cbLength, false, ERROR_INSUFFICIENT_BUFFER);
assert(cbLength == MPQ_STRONG_SIGNATURE_SIZE + 4);
// Retrieve the signature
@@ -3137,8 +2959,7 @@ static int TestOpenArchive_SignExisting(LPCTSTR szPlainName)
return nError;
}
-// Open an empty archive (found in WoW cache - it's just a header)
-static int TestOpenArchive_CompactArchive(LPCTSTR szPlainName, LPCTSTR szCopyName, bool bAddUserData)
+static DWORD TestOpenArchive_CompactArchive(LPCTSTR szPlainName, LPCTSTR szCopyName, bool bAddUserData)
{
TLogHelper Logger("CompactMpqTest", szPlainName);
ULONGLONG PreMpqDataSize = (bAddUserData) ? 0x400 : 0;
@@ -3149,64 +2970,64 @@ static int TestOpenArchive_CompactArchive(LPCTSTR szPlainName, LPCTSTR szCopyNam
TCHAR szFullPath[MAX_PATH];
BYTE FileHash1[MD5_DIGEST_SIZE];
BYTE FileHash2[MD5_DIGEST_SIZE];
- int nError;
+ DWORD dwErrCode;
// Create copy of the archive, with interleaving some user data
- nError = CreateFileCopy(&Logger, szPlainName, szCopyName, szFullPath, _countof(szFullPath), PreMpqDataSize, UserDataSize);
+ dwErrCode = CreateFileCopy(&Logger, szPlainName, szCopyName, szFullPath, _countof(szFullPath), PreMpqDataSize, UserDataSize);
// Open the archive and load some files
- if(nError == ERROR_SUCCESS)
+ if(dwErrCode == ERROR_SUCCESS)
{
// Open the archive
- nError = OpenExistingArchive(&Logger, szFullPath, 0, &hMpq);
- if(nError != ERROR_SUCCESS)
- return nError;
+ dwErrCode = OpenExistingArchive(&Logger, szFullPath, 0, &hMpq);
+ if(dwErrCode != ERROR_SUCCESS)
+ return dwErrCode;
// Verify presence of (listfile) and (attributes)
CheckIfFileIsPresent(&Logger, hMpq, LISTFILE_NAME, true);
CheckIfFileIsPresent(&Logger, hMpq, ATTRIBUTES_NAME, true);
// Search the archive and load every file
- nError = SearchArchive(&Logger, hMpq, TEST_FLAG_LOAD_FILES | TEST_FLAG_HASH_FILES, &dwFileCount1, FileHash1);
+ dwErrCode = SearchArchive(&Logger, hMpq, SEARCH_FLAG_LOAD_FILES | SEARCH_FLAG_HASH_FILES, &dwFileCount1, FileHash1);
SFileCloseArchive(hMpq);
}
// Try to compact the MPQ
- if(nError == ERROR_SUCCESS)
+ if(dwErrCode == ERROR_SUCCESS)
{
// Open the archive again
- nError = OpenExistingArchive(&Logger, szFullPath, 0, &hMpq);
- if(nError != ERROR_SUCCESS)
- return nError;
+ dwErrCode = OpenExistingArchive(&Logger, szFullPath, 0, &hMpq);
+ if(dwErrCode != ERROR_SUCCESS)
+ return dwErrCode;
// Compact the archive
Logger.PrintProgress("Compacting archive %s ...", GetShortPlainName(szFullPath));
if(!SFileSetCompactCallback(hMpq, CompactCallback, &Logger))
- nError = Logger.PrintError(_T("Failed to compact archive %s"), szFullPath);
+ dwErrCode = Logger.PrintError(_T("Failed to compact archive %s"), szFullPath);
SFileCompactArchive(hMpq, NULL, false);
SFileCloseArchive(hMpq);
}
// Open the archive and load some files
- if(nError == ERROR_SUCCESS)
+ if(dwErrCode == ERROR_SUCCESS)
{
// Open the archive
- nError = OpenExistingArchive(&Logger, szFullPath, 0, &hMpq);
- if(nError != ERROR_SUCCESS)
- return nError;
+ dwErrCode = OpenExistingArchive(&Logger, szFullPath, 0, &hMpq);
+ if(dwErrCode != ERROR_SUCCESS)
+ return dwErrCode;
// Verify presence of (listfile) and (attributes)
CheckIfFileIsPresent(&Logger, hMpq, LISTFILE_NAME, true);
CheckIfFileIsPresent(&Logger, hMpq, ATTRIBUTES_NAME, true);
// Search the archive and load every file
- nError = SearchArchive(&Logger, hMpq, TEST_FLAG_LOAD_FILES | TEST_FLAG_HASH_FILES, &dwFileCount2, FileHash2);
+ dwErrCode = SearchArchive(&Logger, hMpq, SEARCH_FLAG_LOAD_FILES | SEARCH_FLAG_HASH_FILES, &dwFileCount2, FileHash2);
SFileCloseArchive(hMpq);
}
// Compare the file counts and their hashes
- if(nError == ERROR_SUCCESS)
+ if(dwErrCode == ERROR_SUCCESS)
{
if(dwFileCount2 != dwFileCount1)
Logger.PrintMessage("Different file count after compacting archive: %u vs %u", dwFileCount2, dwFileCount1);
@@ -3215,7 +3036,7 @@ static int TestOpenArchive_CompactArchive(LPCTSTR szPlainName, LPCTSTR szCopyNam
Logger.PrintMessage("Different file hash after compacting archive");
}
- return nError;
+ return dwErrCode;
}
static int ForEachFile_VerifyFileChecksum(LPCTSTR szFullPath)
@@ -3403,7 +3224,7 @@ static int TestCreateArchive_Deprotect(LPCSTR szPlainName)
BYTE FileHash2[MD5_DIGEST_SIZE];
DWORD dwFileCount1 = 0;
DWORD dwFileCount2 = 0;
- DWORD dwTestFlags = TEST_FLAG_LOAD_FILES | TEST_FLAG_HASH_FILES;
+ DWORD dwTestFlags = SEARCH_FLAG_LOAD_FILES | SEARCH_FLAG_HASH_FILES;
int nError = ERROR_SUCCESS;
// First copy: The original (untouched) file
@@ -3898,7 +3719,7 @@ static int TestCreateArchive_UnicodeNames()
return nError;
}
-static int TestCreateArchive_FileFlagTest(LPCTSTR szPlainName)
+static DWORD TestCreateArchive_FileFlagTest(LPCTSTR szPlainName)
{
TLogHelper Logger("FileFlagTest", szPlainName);
HANDLE hMpq = NULL; // Handle of created archive
@@ -3910,29 +3731,28 @@ static int TestCreateArchive_FileFlagTest(LPCTSTR szPlainName)
char szArchivedName[MAX_PATH];
DWORD dwMaxFileCount = 0;
DWORD dwFileCount = 0;
- size_t i;
- int nError;
+ DWORD dwErrCode;
// Create paths for local file to be added
CreateFullPathName(szFileName1, _countof(szFileName1), szMpqSubDir, _T("AddFile.exe"));
CreateFullPathName(szFileName2, _countof(szFileName2), szMpqSubDir, _T("AddFile.bin"));
// Create an empty file that will serve as holder for the MPQ
- nError = CreateEmptyFile(&Logger, szPlainName, 0x100000, szFullPath);
+ dwErrCode = CreateEmptyFile(&Logger, szPlainName, 0x100000, szFullPath);
// Create new MPQ archive over that file
- if(nError == ERROR_SUCCESS)
- nError = CreateNewArchive(&Logger, szPlainName, MPQ_CREATE_ARCHIVE_V1 | MPQ_CREATE_LISTFILE | MPQ_CREATE_ATTRIBUTES, 17, &hMpq);
+ if(dwErrCode == ERROR_SUCCESS)
+ dwErrCode = CreateNewArchive(&Logger, szPlainName, MPQ_CREATE_ARCHIVE_V1 | MPQ_CREATE_LISTFILE | MPQ_CREATE_ATTRIBUTES, 17, &hMpq);
// Add the same file multiple times
- if(nError == ERROR_SUCCESS)
+ if(dwErrCode == ERROR_SUCCESS)
{
dwMaxFileCount = SFileGetMaxFileCount(hMpq);
- for(i = 0; AddFlags[i] != 0xFFFFFFFF; i++)
+ for(size_t i = 0; AddFlags[i] != 0xFFFFFFFF; i++)
{
sprintf(szArchivedName, "FileTest_%02u.exe", (unsigned int)i);
- nError = AddLocalFileToMpq(&Logger, hMpq, szArchivedName, szFileName1, AddFlags[i], 0);
- if(nError != ERROR_SUCCESS)
+ dwErrCode = AddLocalFileToMpq(&Logger, hMpq, szArchivedName, szFileName1, AddFlags[i], 0);
+ if(dwErrCode != ERROR_SUCCESS)
break;
dwFileCount++;
@@ -3940,41 +3760,41 @@ static int TestCreateArchive_FileFlagTest(LPCTSTR szPlainName)
}
// Delete a file in the middle of the file table
- if(nError == ERROR_SUCCESS)
+ if(dwErrCode == ERROR_SUCCESS)
{
Logger.PrintProgress("Removing file %s ...", szMiddleFile);
- nError = RemoveMpqFile(&Logger, hMpq, szMiddleFile, ERROR_SUCCESS);
+ dwErrCode = RemoveMpqFile(&Logger, hMpq, szMiddleFile, ERROR_SUCCESS);
dwFileCount--;
}
// Add one more file
- if(nError == ERROR_SUCCESS)
+ if(dwErrCode == ERROR_SUCCESS)
{
- nError = AddLocalFileToMpq(&Logger, hMpq, "FileTest_xx.exe", szFileName1);
+ dwErrCode = AddLocalFileToMpq(&Logger, hMpq, "FileTest_xx.exe", szFileName1);
dwFileCount++;
}
// Try to decrement max file count. This must succeed
- if(nError == ERROR_SUCCESS)
+ if(dwErrCode == ERROR_SUCCESS)
{
Logger.PrintProgress("Attempting to decrement max file count ...");
if(SFileSetMaxFileCount(hMpq, 5))
- nError = Logger.PrintError("Max file count decremented, even if it should fail");
+ dwErrCode = Logger.PrintError("Max file count decremented, even if it should fail");
}
// Add ZeroSize.txt several times under a different locale
- if(nError == ERROR_SUCCESS)
+ if(dwErrCode == ERROR_SUCCESS)
{
- for(i = 0; LocaleIDs[i] != 0xFFFF; i++)
+ for(size_t i = 0; LocaleIDs[i] != 0xFFFF; i++)
{
bool bMustSucceed = ((dwFileCount + 2) < dwMaxFileCount);
SFileSetLocale(LocaleIDs[i]);
- nError = AddLocalFileToMpq(&Logger, hMpq, "ZeroSize_1.txt", szFileName2);
- if(nError != ERROR_SUCCESS)
+ dwErrCode = AddLocalFileToMpq(&Logger, hMpq, "ZeroSize_1.txt", szFileName2);
+ if(dwErrCode != ERROR_SUCCESS)
{
if(bMustSucceed == false)
- nError = ERROR_SUCCESS;
+ dwErrCode = ERROR_SUCCESS;
break;
}
@@ -3983,18 +3803,18 @@ static int TestCreateArchive_FileFlagTest(LPCTSTR szPlainName)
}
// Add ZeroSize.txt again several times under a different locale
- if(nError == ERROR_SUCCESS)
+ if(dwErrCode == ERROR_SUCCESS)
{
- for(i = 0; LocaleIDs[i] != 0xFFFF; i++)
+ for(size_t i = 0; LocaleIDs[i] != 0xFFFF; i++)
{
bool bMustSucceed = ((dwFileCount + 2) < dwMaxFileCount);
SFileSetLocale(LocaleIDs[i]);
- nError = AddLocalFileToMpq(&Logger, hMpq, "ZeroSize_2.txt", szFileName2, 0, 0, bMustSucceed);
- if(nError != ERROR_SUCCESS)
+ dwErrCode = AddLocalFileToMpq(&Logger, hMpq, "ZeroSize_2.txt", szFileName2, 0, 0, bMustSucceed);
+ if(dwErrCode != ERROR_SUCCESS)
{
if(bMustSucceed == false)
- nError = ERROR_SUCCESS;
+ dwErrCode = ERROR_SUCCESS;
break;
}
@@ -4003,45 +3823,45 @@ static int TestCreateArchive_FileFlagTest(LPCTSTR szPlainName)
}
// Verify how many files did we add to the MPQ
- if(nError == ERROR_SUCCESS)
+ if(dwErrCode == ERROR_SUCCESS)
{
if(dwFileCount + 2 != dwMaxFileCount)
{
Logger.PrintErrorVa("Number of files added to MPQ was unexpected (expected %u, added %u)", dwFileCount, dwMaxFileCount - 2);
- nError = ERROR_FILE_CORRUPT;
+ dwErrCode = ERROR_FILE_CORRUPT;
}
}
// Test rename function
- if(nError == ERROR_SUCCESS)
+ if(dwErrCode == ERROR_SUCCESS)
{
Logger.PrintProgress("Testing rename files ...");
SFileSetLocale(LANG_NEUTRAL);
if(!SFileRenameFile(hMpq, "FileTest_08.exe", "FileTest_08a.exe"))
- nError = Logger.PrintError("Failed to rename the file");
+ dwErrCode = Logger.PrintError("Failed to rename the file");
}
- if(nError == ERROR_SUCCESS)
+ if(dwErrCode == ERROR_SUCCESS)
{
if(!SFileRenameFile(hMpq, "FileTest_08a.exe", "FileTest_08.exe"))
- nError = Logger.PrintError("Failed to rename the file");
+ dwErrCode = Logger.PrintError("Failed to rename the file");
}
- if(nError == ERROR_SUCCESS)
+ if(dwErrCode == ERROR_SUCCESS)
{
if(SFileRenameFile(hMpq, "FileTest_10.exe", "FileTest_10a.exe"))
{
Logger.PrintError("Rename test succeeded even if it shouldn't");
- nError = ERROR_FILE_CORRUPT;
+ dwErrCode = ERROR_FILE_CORRUPT;
}
}
- if(nError == ERROR_SUCCESS)
+ if(dwErrCode == ERROR_SUCCESS)
{
if(SFileRenameFile(hMpq, "FileTest_10a.exe", "FileTest_10.exe"))
{
Logger.PrintError("Rename test succeeded even if it shouldn't");
- nError = ERROR_FILE_CORRUPT;
+ dwErrCode = ERROR_FILE_CORRUPT;
}
}
@@ -4051,9 +3871,9 @@ static int TestCreateArchive_FileFlagTest(LPCTSTR szPlainName)
hMpq = NULL;
// Try to reopen the archive
- if(nError == ERROR_SUCCESS)
- nError = OpenExistingArchive(&Logger, szFullPath, 0, NULL);
- return nError;
+ if(dwErrCode == ERROR_SUCCESS)
+ dwErrCode = OpenExistingArchive(&Logger, szFullPath, 0, NULL);
+ return dwErrCode;
}
static int TestCreateArchive_WaveCompressionsTest(LPCTSTR szPlainName, LPCTSTR szWaveFile)
@@ -4097,7 +3917,7 @@ static int TestCreateArchive_WaveCompressionsTest(LPCTSTR szPlainName, LPCTSTR s
nError = OpenExistingArchiveWithCopy(&Logger, NULL, szPlainName, &hMpq);
if(nError == ERROR_SUCCESS)
{
- SearchArchive(&Logger, hMpq, TEST_FLAG_LOAD_FILES | TEST_FLAG_PLAY_WAVES, &dwFoundFiles, NULL);
+ SearchArchive(&Logger, hMpq, SEARCH_FLAG_LOAD_FILES | SEARCH_FLAG_PLAY_WAVES, &dwFoundFiles, NULL);
SFileCloseArchive(hMpq);
}
@@ -4263,20 +4083,20 @@ static int TestCreateArchive_BigArchive(LPCTSTR szPlainName)
}
// "MPQ_2014_v4_Heroes_Replay.MPQ", "AddFile-replay.message.events"
-static int TestModifyArchive_ReplaceFile(LPCTSTR szMpqPlainName, LPCTSTR szFileName)
+static DWORD TestModifyArchive_ReplaceFile(LPCTSTR szMpqPlainName, LPCTSTR szFileName)
{
TLogHelper Logger("ModifyTest", szMpqPlainName);
HANDLE hMpq = NULL;
TCHAR szLocalFileName[MAX_PATH];
char szArchivedName[MAX_PATH];
size_t nOffset = 0;
- int nError;
+ DWORD dwErrCode;
// Open an existing archive
- nError = OpenExistingArchiveWithCopy(&Logger, szMpqPlainName, szMpqPlainName, &hMpq);
+ dwErrCode = OpenExistingArchiveWithCopy(&Logger, szMpqPlainName, szMpqPlainName, &hMpq);
// Add the given file
- if(nError == ERROR_SUCCESS)
+ if(dwErrCode == ERROR_SUCCESS)
{
// Get the name of archived file
if(!_tcsnicmp(szFileName, _T("AddFile-"), 8))
@@ -4287,38 +4107,38 @@ static int TestModifyArchive_ReplaceFile(LPCTSTR szMpqPlainName, LPCTSTR szFileN
CreateFullPathName(szLocalFileName, _countof(szLocalFileName), szMpqSubDir, szFileName);
// Add the file to MPQ
- nError = AddLocalFileToMpq(&Logger, hMpq,
- szArchivedName,
- szLocalFileName,
- MPQ_FILE_REPLACEEXISTING | MPQ_FILE_COMPRESS | MPQ_FILE_SINGLE_UNIT,
- MPQ_COMPRESSION_ZLIB,
- true);
+ dwErrCode = AddLocalFileToMpq(&Logger, hMpq,
+ szArchivedName,
+ szLocalFileName,
+ MPQ_FILE_REPLACEEXISTING | MPQ_FILE_COMPRESS | MPQ_FILE_SINGLE_UNIT,
+ MPQ_COMPRESSION_ZLIB,
+ true);
}
// Reopen the MPQ and compact it
- if(nError == ERROR_SUCCESS)
+ if(dwErrCode == ERROR_SUCCESS)
{
// Compact the archive
Logger.PrintProgress("Compacting archive %s ...", szMpqPlainName);
if(!SFileSetCompactCallback(hMpq, CompactCallback, &Logger))
- nError = Logger.PrintError(_T("Failed to compact archive %s"), szMpqPlainName);
+ dwErrCode = Logger.PrintError(_T("Failed to compact archive %s"), szMpqPlainName);
if(!SFileCompactArchive(hMpq, NULL, 0))
- nError = GetLastError();
+ dwErrCode = GetLastError();
SFileCloseArchive(hMpq);
}
// Try to open the archive again
- if(nError == ERROR_SUCCESS)
+ if(dwErrCode == ERROR_SUCCESS)
{
CreateFullPathName(szLocalFileName, _countof(szLocalFileName), NULL, szMpqPlainName);
- nError = OpenExistingArchive(&Logger, szLocalFileName, 0, &hMpq);
- if(nError == ERROR_SUCCESS)
+ dwErrCode = OpenExistingArchive(&Logger, szLocalFileName, 0, &hMpq);
+ if(dwErrCode == ERROR_SUCCESS)
SFileCloseArchive(hMpq);
}
- return nError;
+ return dwErrCode;
}
//-----------------------------------------------------------------------------
@@ -4349,28 +4169,53 @@ static const TEST_INFO TestList_MasterMirror[] =
static const TEST_INFO Test_Mpqs[] =
{
- {_T("MPQ_1997_v1_Diablo1_DIABDAT.MPQ"), NULL, TEST_OPEN_COMPARE_TWO_FILES, "music\\dintro.wav", "File00000023.xxx"},
- {_T("MPQ_2016_v1_D2XP_IX86_1xx_114a.mpq"), NULL, TEST_LOAD_FILE_CHECK_CRC, "waitingroombkgd.dc6" }, // The update MPQ from Diablo II (patch 2016)
- {_T("MPQ_2018_v1_icon_error.w3m"), NULL, TEST_LOAD_FILE_CHECK_CRC, "file00000002.blp" },
-
- {_T("MPQ_1997_v1_Diablo1_STANDARD.SNP"), _T("ListFile_Blizzard.txt"), TEST_OPEN_MPQ }, // Open a file whose archive's (signature) file has flags = 0x90000000
- {_T("MPQ_1997_v1_Diablo1_DIABDAT.MPQ"), NULL, TEST_OPEN_MPQ | TEST_SETPOS, "music\\dtowne.wav" }, // Test the SFileSetFilePointer operations
- {_T("MPQ_2012_v2_EmptyMpq.MPQ") }, // Open an empty archive (found in WoW cache - it's just a header)
- {_T("MPQ_2013_v4_EmptyMpq.MPQ") }, // Open an empty archive (created artificially - it's just a header)
- {_T("MPQ_2013_v4_patch-base-16357.MPQ") }, // Open an empty archive (found in WoW cache - it's just a header)
- {_T("MPQ_2011_v4_InvalidHetEntryCount.MPQ") }, // Open an empty archive (A buggy MPQ with invalid HET entry count)
- {_T("MPQ_2002_v1_BlockTableCut.MPQ") }, // Open a truncated archive
-
- // TODO: Doesn't work anymore
- //{_T("MPQ_2010_v2_HasUserData.s2ma") }, // Open a MPQ that actually has user data
-
- {_T("MPQ_2014_v1_AttributesOneEntryLess.w3x") }, // Open an Warcraft III map whose "(attributes)" file has (BlockTableSize-1) entries
- {_T("MPQ_2020_v1_AHF04patch.mix") }, // Open a MIX file
- {_T("MPQ_2010_v3_expansion-locale-frFR.MPQ") }, // Open a MPQ archive v 3.0
- {_T("mpqe-file://MPQ_2011_v2_EncryptedMpq.MPQE") }, // Open an encrypted archive from Starcraft II installer
- {_T("MPx_2013_v1_LongwuOnline.mpk") }, // Open a MPK archive from Longwu online
- {_T("MPx_2013_v1_WarOfTheImmortals.sqp"), _T("ListFile_WarOfTheImmortals.txt") }, // Open a SQP archive from War of the Immortals
- {_T("part-file://MPQ_2010_v2_HashTableCompressed.MPQ.part") }, // Open a partial MPQ with compressed hash table
+ // Correct or damaged archives
+ {_T("MPQ_1997_v1_Diablo1_DIABDAT.MPQ"), NULL, 0, "music\\dintro.wav", "File00000023.xxx"},
+ {_T("MPQ_2016_v1_D2XP_IX86_1xx_114a.mpq"), NULL, 0, "waitingroombkgd.dc6"}, // Update MPQ from Diablo II (patch 2016)
+ {_T("MPQ_2018_v1_icon_error.w3m"), NULL, 0, "file00000002.blp"},
+ {_T("MPQ_1997_v1_Diablo1_STANDARD.SNP"), _T("ListFile_Blizzard.txt")}, // File whose archive's (signature) file has flags = 0x90000000
+ {_T("MPQ_2012_v2_EmptyMpq.MPQ") }, // Empty archive (found in WoW cache - it's just a header)
+ {_T("MPQ_2013_v4_EmptyMpq.MPQ") }, // Empty archive (created artificially - it's just a header)
+ {_T("MPQ_2013_v4_patch-base-16357.MPQ") }, // Empty archive (found in WoW cache - it's just a header)
+ {_T("MPQ_2011_v4_InvalidHetEntryCount.MPQ") }, // Empty archive (A buggy MPQ with invalid HET entry count)
+ {_T("MPQ_2002_v1_BlockTableCut.MPQ") }, // Truncated archive
+ {_T("MPQ_2010_v2_HasUserData.s2ma") }, // MPQ that actually has user data
+ {_T("MPQ_2014_v1_AttributesOneEntryLess.w3x") }, // Warcraft III map whose "(attributes)" file has (BlockTableSize-1) entries
+ {_T("MPQ_2020_v1_AHF04patch.mix") }, // MIX file
+ {_T("MPQ_2010_v3_expansion-locale-frFR.MPQ") }, // MPQ archive v 3.0
+ {_T("mpqe-file://MPQ_2011_v2_EncryptedMpq.MPQE") }, // Encrypted archive from Starcraft II installer
+ {_T("MPx_2013_v1_LongwuOnline.mpk") }, // MPK archive from Longwu online
+ {_T("MPx_2013_v1_WarOfTheImmortals.sqp"), _T("ListFile_WarOfTheImmortals.txt") }, // SQP archive from War of the Immortals
+ {_T("part-file://MPQ_2010_v2_HashTableCompressed.MPQ.part") }, // Partial MPQ with compressed hash table
+ {_T("blk4-file://streaming/model.MPQ.0")}, // Archive that is merged with multiple files
+ {_T("MPQ_2002_v1_ProtectedMap_InvalidUserData.w3x")},
+ {_T("MPQ_2002_v1_ProtectedMap_InvalidMpqFormat.w3x")},
+ {_T("MPQ_2002_v1_ProtectedMap_Spazzler.w3x")}, // Warcraft III map locked by the Spazzler protector
+ {_T("MPQ_2014_v1_ProtectedMap_Spazzler2.w3x")}, // Warcraft III map locked by the Spazzler protector
+ {_T("MPQ_2014_v1_ProtectedMap_Spazzler3.w3x")}, // Warcraft III map locked by the Spazzler protector
+ {_T("MPQ_2002_v1_ProtectedMap_BOBA.w3m")}, // Warcraft III map locked by the BOBA protector
+ {_T("MPQ_2015_v1_ProtectedMap_KangTooJee.w3x")},
+ {_T("MPQ_2015_v1_ProtectedMap_Somj2hM16.w3x")},
+ {_T("MPQ_2015_v1_ProtectedMap_Spazy.w3x")}, // Warcraft III map locked by Spazy protector
+ {_T("MPQ_2015_v1_MessListFile.mpq")},
+ {_T("MPQ_2016_v1_ProtectedMap_TableSizeOverflow.w3x")},
+ {_T("MPQ_2016_v1_ProtectedMap_HashOffsIsZero.w3x")},
+ {_T("MPQ_2016_v1_ProtectedMap_Somj2.w3x")}, // Something like Somj 2.0
+ {_T("MPQ_2016_v1_WME4_4.w3x")}, // Protector from China (2016-05-27)
+ {_T("MPQ_2016_v1_SP_(4)Adrenaline.w3x")},
+ {_T("MPQ_2016_v1_ProtectedMap_1.4.w3x")},
+ {_T("MPQ_2016_v1_KoreanFile.w3m")},
+ {_T("MPQ_2017_v1_Eden_RPG_S2_2.5J.w3x")}, // Load map protected by PG1.11.973
+ {_T("MPQ_2017_v1_BigDummyFiles.w3x")},
+ {_T("MPQ_2017_v1_TildeInFileName.mpq")},
+ {_T("MPQ_2018_v1_EWIX_v8_7.w3x"), NULL, 0, "BlueCrystal.mdx"},
+ {_T("MPQ_2020_v4_FakeMpqHeaders.SC2Mod")}, // Archive that has two fake headers before the real one
+ {_T("MPQ_2020_v4_NP_Protect_1.s2ma")}, // SC2 map that is protected by the NP_Protect
+ {_T("MPQ_2020_v4_NP_Protect_2.s2ma")}, // SC2 map that is protected by the NP_Protect
+
+ // Protected archives
+ {_T("MPQ_2015_v1_flem1.w3x"), NULL, TEST_FLAG_PROTECTED | 20, "1c4c13e627658c473e84d94371e31f37"},
+ {_T("MPQ_2002_v1_ProtectedMap_HashTable_FakeValid.w3x"), NULL, TEST_FLAG_PROTECTED | 114, "5250975ed917375fc6540d7be436d4de"},
};
//-----------------------------------------------------------------------------
@@ -4389,89 +4234,60 @@ int _tmain(int argc, TCHAR * argv[])
dwErrCode = InitializeMpqDirectory(argv, argc);
//
- // Open all files from the command line
+ // Tests on a local listfile
//
- for(int i = 1; i < argc; i++)
+ if(dwErrCode == ERROR_SUCCESS)
{
- //SFILE_FIND_DATA sf;
- HANDLE hFile = NULL;
- HANDLE hMpq = NULL;
- BYTE Buffer[0x40];
-
- if(SFileOpenArchive(argv[i], 0, 0, &hMpq))
- {
- if(SFileOpenFileEx(hMpq, "koKR.SC2Data\\LocalizedData\\ObjectStrings.txt", 0, &hFile))
- {
- SFileReadFile(hFile, Buffer, sizeof(Buffer), NULL, NULL);
- SFileCloseFile(hFile);
- }
-
- //if((hFind = SFileFindFirstFile(hMpq, "*", &sf, NULL)) != NULL)
- //{
- // SFileFindNextFile(hFind, &sf);
- // SFileFindClose(hFind);
- //}
-
- SFileCloseArchive(hMpq);
- }
+ dwErrCode = TestOnLocalListFile(_T("ListFile_Blizzard.txt"));
}
//
- // Search all testing archives and verify their SHA1 hash
- //
-
- //if(dwErrCode == ERROR_SUCCESS)
- //{
- // dwErrCode = FindFiles(ForEachFile_VerifyFileChecksum, szMpqSubDir);
- //}
-
- //
- // Test file stream operations
+ // Open all files from the command line
//
- //if(dwErrCode == ERROR_SUCCESS)
- //{
- // for(size_t i = 0; i < _countof(TestList_StreamOps); i++)
- // {
- // dwErrCode = TestFileStreamOperations(TestList_StreamOps[i].szMpqName1, TestList_StreamOps[i].dwFlags);
- // if(dwErrCode != ERROR_SUCCESS)
- // break;
- // }
- //}
+ for(int i = 1; i < argc; i++)
+ {
+ ForEachFile_OpenArchive(argv[i]);
+ }
//
- // Test master-mirror reading operations
+ // Search all testing archives and verify their SHA1 hash
//
- //if(dwErrCode == ERROR_SUCCESS)
- //{
- // for(size_t i = 0; i < _countof(TestList_MasterMirror); i++)
- // {
- // dwErrCode = TestReadFile_MasterMirror(TestList_MasterMirror[i].szMpqName1,
- // TestList_MasterMirror[i].szMpqName2,
- // TestList_MasterMirror[i].dwFlags != 0);
- // if(dwErrCode != ERROR_SUCCESS)
- // break;
- // }
- //}
+ if(dwErrCode == ERROR_SUCCESS)
+ {
+ dwErrCode = FindFiles(ForEachFile_VerifyFileChecksum, szMpqSubDir);
+ }
//
- // Search in listfile
+ // Test file stream operations
//
if(dwErrCode == ERROR_SUCCESS)
{
- dwErrCode = TestSearchListFile(_T("ListFile_Blizzard.txt"));
+ for(size_t i = 0; i < _countof(TestList_StreamOps); i++)
+ {
+ dwErrCode = TestFileStreamOperations(TestList_StreamOps[i].szMpqName1, TestList_StreamOps[i].dwFlags);
+ if(dwErrCode != ERROR_SUCCESS)
+ break;
+ }
}
//
- // Test opening local file with SFileOpenFileEx
+ // Test master-mirror reading operations
//
if(dwErrCode == ERROR_SUCCESS)
{
- dwErrCode = TestOpenLocalFile(_T("ListFile_Blizzard.txt"));
+ for(size_t i = 0; i < _countof(TestList_MasterMirror); i++)
+ {
+ dwErrCode = TestReadFile_MasterMirror(TestList_MasterMirror[i].szMpqName1,
+ TestList_MasterMirror[i].szMpqName2,
+ TestList_MasterMirror[i].dwFlags != 0);
+ if(dwErrCode != ERROR_SUCCESS)
+ break;
+ }
}
//
@@ -4492,96 +4308,10 @@ int _tmain(int argc, TCHAR * argv[])
}
}
- // Open an protected map
- if(dwErrCode == ERROR_SUCCESS)
- dwErrCode = TestOpenArchive_ProtectedMap(_T("MPQ_2015_v1_flem1.w3x"), NULL, 20, "1c4c13e627658c473e84d94371e31f37");
-
- if(dwErrCode == ERROR_SUCCESS)
- dwErrCode = TestOpenArchive_ProtectedMap(_T("MPQ_2002_v1_ProtectedMap_HashTable_FakeValid.w3x"), NULL, 114, "5250975ed917375fc6540d7be436d4de");
-
- if(dwErrCode == ERROR_SUCCESS)
- dwErrCode = TestOpenArchive(_T("MPQ_2002_v1_ProtectedMap_InvalidUserData.w3x"));
-
- if(dwErrCode == ERROR_SUCCESS)
- dwErrCode = TestOpenArchive(_T("MPQ_2002_v1_ProtectedMap_InvalidMpqFormat.w3x"));
-
- // Open an Warcraft III map locked by the Spazzler protector
- if(dwErrCode == ERROR_SUCCESS)
- dwErrCode = TestOpenArchive(_T("MPQ_2002_v1_ProtectedMap_Spazzler.w3x"));
-
- if(dwErrCode == ERROR_SUCCESS)
- dwErrCode = TestOpenArchive(_T("MPQ_2014_v1_ProtectedMap_Spazzler2.w3x"));
-
- if(dwErrCode == ERROR_SUCCESS)
- dwErrCode = TestOpenArchive(_T("MPQ_2014_v1_ProtectedMap_Spazzler3.w3x"));
-
- // Open an Warcraft III map locked by the BOBA protector
- if(dwErrCode == ERROR_SUCCESS)
- dwErrCode = TestOpenArchive(_T("MPQ_2002_v1_ProtectedMap_BOBA.w3m"));
-
- // Open an Warcraft III map locked by a protector
- if(dwErrCode == ERROR_SUCCESS)
- dwErrCode = TestOpenArchive(_T("MPQ_2015_v1_ProtectedMap_KangTooJee.w3x"));
-
- // Open an Warcraft III map locked by a protector
- if(dwErrCode == ERROR_SUCCESS)
- dwErrCode = TestOpenArchive(_T("MPQ_2015_v1_ProtectedMap_Somj2hM16.w3x"));
-
- // Open an Warcraft III map locked by Spazy protector
- if(dwErrCode == ERROR_SUCCESS)
- dwErrCode = TestOpenArchive(_T("MPQ_2015_v1_ProtectedMap_Spazy.w3x"));
-
- // Open an Warcraft III map locked by Spazy protector
- if(dwErrCode == ERROR_SUCCESS)
- dwErrCode = TestOpenArchive(_T("MPQ_2015_v1_MessListFile.mpq"));
-
- // Open another protected map
- if(dwErrCode == ERROR_SUCCESS)
- dwErrCode = TestOpenArchive(_T("MPQ_2016_v1_ProtectedMap_TableSizeOverflow.w3x"));
-
- // Open another protected map
- if(dwErrCode == ERROR_SUCCESS)
- dwErrCode = TestOpenArchive(_T("MPQ_2016_v1_ProtectedMap_HashOffsIsZero.w3x"));
-
- // Something like Somj 2.0
- if(dwErrCode == ERROR_SUCCESS)
- dwErrCode = TestOpenArchive(_T("MPQ_2016_v1_ProtectedMap_Somj2.w3x"));
-
- // Protector from China (2016-05-27)
- if(dwErrCode == ERROR_SUCCESS)
- dwErrCode = TestOpenArchive(_T("MPQ_2016_v1_WME4_4.w3x"));
-
- if(dwErrCode == ERROR_SUCCESS)
- dwErrCode = TestOpenArchive(_T("MPQ_2016_v1_SP_(4)Adrenaline.w3x"));
-
- if(dwErrCode == ERROR_SUCCESS)
- dwErrCode = TestOpenArchive(_T("MPQ_2016_v1_ProtectedMap_1.4.w3x"));
-
- if(dwErrCode == ERROR_SUCCESS)
- dwErrCode = TestOpenArchive(_T("MPQ_2016_v1_KoreanFile.w3m"));
-
- // Load map protected by PG1.11.973
- if(dwErrCode == ERROR_SUCCESS)
- dwErrCode = TestOpenArchive(_T("MPQ_2017_v1_Eden_RPG_S2_2.5J.w3x"));
-
- // Load map protected by PG1.11.973
- if(dwErrCode == ERROR_SUCCESS)
- dwErrCode = TestOpenArchive(_T("MPQ_2017_v1_BigDummyFiles.w3x"), NULL, "1.blp");
-
- if(dwErrCode == ERROR_SUCCESS)
- dwErrCode = TestOpenArchive(_T("MPQ_2017_v1_TildeInFileName.mpq"), NULL, "1.blp");
-
- if(dwErrCode == ERROR_SUCCESS)
- dwErrCode = TestOpenArchive(_T("MPQ_2018_v1_EWIX_v8_7.w3x"), NULL, "BlueCrystal.mdx");
-
// Open the multi-file archive with wrong prefix to see how StormLib deals with it
if(dwErrCode == ERROR_SUCCESS)
dwErrCode = TestOpenArchive_WillFail(_T("flat-file://streaming/model.MPQ.0"));
- // Open an archive that is merged with multiple files
- if(dwErrCode == ERROR_SUCCESS)
- dwErrCode = TestOpenArchive(_T("blk4-file://streaming/model.MPQ.0"), NULL, NULL, true);
-
// Open every MPQ that we have in the storage
if(dwErrCode == ERROR_SUCCESS)
dwErrCode = FindFiles(ForEachFile_OpenArchive, NULL);
@@ -4590,18 +4320,6 @@ int _tmain(int argc, TCHAR * argv[])
if(dwErrCode == ERROR_SUCCESS)
dwErrCode = TestOpenArchive_Corrupt(_T("MPQ_2013_vX_Battle.net.MPQ"));
- // Test on an archive that has two fake headers before the real one
- if (dwErrCode == ERROR_SUCCESS)
- dwErrCode = TestOpenArchive(_T("MPQ_2020_v4_FakeMpqHeaders.SC2Mod"));
-
- // Test on an SC2 map that is protected by the NP_Protect
- if (dwErrCode == ERROR_SUCCESS)
- dwErrCode = TestOpenArchive(_T("MPQ_2020_v4_NP_Protect_1.s2ma"));
-
- // Test on an SC2 map that is protected by the NP_Protect
- if (dwErrCode == ERROR_SUCCESS)
- dwErrCode = TestOpenArchive(_T("MPQ_2020_v4_NP_Protect_2.s2ma"));
-
// Open a patched archive
if(dwErrCode == ERROR_SUCCESS)
dwErrCode = TestOpenArchive_Patched(PatchList_StarCraft, "music\\terran1.wav", 0);
@@ -4632,7 +4350,7 @@ int _tmain(int argc, TCHAR * argv[])
// Open a patched archive
if(dwErrCode == ERROR_SUCCESS)
- dwErrCode = TestOpenArchive_Patched(PatchList_SC2_32283_enGB, "LocalizedData\\GameHotkeys.txt", 0, true);
+ dwErrCode = TestOpenArchive_Patched(PatchList_SC2_32283_enGB, "Assets\\Textures\\startupimage.dds", 0, true);
// Open a patched archive where the "StreamingBuckets.txt" in the patch doesn't contain MPQ_FILE_PATCH_FILE
if(dwErrCode == ERROR_SUCCESS)
diff --git a/test/TLogHelper.cpp b/test/TLogHelper.cpp
index 9bf4f6d..fca85ec 100644
--- a/test/TLogHelper.cpp
+++ b/test/TLogHelper.cpp
@@ -30,11 +30,11 @@ class TLogHelper
#endif // defined(UNICODE) || defined(UNICODE)
// ANSI functions
- int PrintWithClreol(const char * szFormat, va_list argList, bool bPrintPrefix, bool bPrintLastError, bool bPrintEndOfLine);
- void PrintProgress(const char * szFormat, ...);
- void PrintMessage(const char * szFormat, ...);
- int PrintErrorVa(const char * szFormat, ...);
- int PrintError(const char * szFormat, const char * szFileName = NULL);
+ DWORD PrintWithClreol(const char * szFormat, va_list argList, bool bPrintPrefix, bool bPrintLastError, bool bPrintEndOfLine);
+ void PrintProgress(const char * szFormat, ...);
+ void PrintMessage(const char * szFormat, ...);
+ DWORD PrintErrorVa(const char * szFormat, ...);
+ DWORD PrintError(const char * szFormat, const char * szFileName = NULL);
const char * UserString;
unsigned int UserCount;
@@ -140,7 +140,7 @@ TLogHelper::~TLogHelper()
#if defined(_MSC_VER) && defined(_DEBUG)
if(_CrtDumpMemoryLeaks())
{
- PrintMessage("Memory leak detected after %s\n.", szSaveMainTitle);
+ PrintMessage(_T("Memory leak(s) detected after %s.\n"), szSaveMainTitle);
}
#endif // _MSC_VER
}
@@ -257,7 +257,7 @@ int TLogHelper::PrintError(const TCHAR * szFormat, const TCHAR * szFileName)
//-----------------------------------------------------------------------------
// ANSI functions
-int TLogHelper::PrintWithClreol(const char * szFormat, va_list argList, bool bPrintPrefix, bool bPrintLastError, bool bPrintEndOfLine)
+DWORD TLogHelper::PrintWithClreol(const char * szFormat, va_list argList, bool bPrintPrefix, bool bPrintLastError, bool bPrintEndOfLine)
{
char szFormatBuff[0x200];
char szMessage[0x200];
@@ -265,7 +265,7 @@ int TLogHelper::PrintWithClreol(const char * szFormat, va_list argList, bool bPr
int nRemainingWidth;
int nConsoleWidth = GetConsoleWidth();
int nLength = 0;
- int nError = GetLastError();
+ DWORD dwErrCode = GetLastError();
// Always start the buffer with '\r'
*szBuffer++ = '\r';
@@ -292,7 +292,7 @@ int TLogHelper::PrintWithClreol(const char * szFormat, va_list argList, bool bPr
// Append the last error
if(bPrintLastError)
{
- nLength = sprintf(szBuffer, " (error code: %u)", nError);
+ nLength = sprintf(szBuffer, " (error code: %u)", dwErrCode);
szBuffer += nLength;
}
@@ -322,7 +322,7 @@ int TLogHelper::PrintWithClreol(const char * szFormat, va_list argList, bool bPr
// Spit out the text in one single printf
printf("%s", szMessage);
- return nError;
+ return dwErrCode;
}
void TLogHelper::PrintProgress(const char * szFormat, ...)
@@ -343,19 +343,19 @@ void TLogHelper::PrintMessage(const char * szFormat, ...)
va_end(argList);
}
-int TLogHelper::PrintErrorVa(const char * szFormat, ...)
+DWORD TLogHelper::PrintErrorVa(const char * szFormat, ...)
{
va_list argList;
- int nResult;
+ DWORD dwErrCode;
va_start(argList, szFormat);
- nResult = PrintWithClreol(szFormat, argList, true, true, true);
+ dwErrCode = PrintWithClreol(szFormat, argList, true, true, true);
va_end(argList);
- return nResult;
+ return dwErrCode;
}
-int TLogHelper::PrintError(const char * szFormat, const char * szFileName)
+DWORD TLogHelper::PrintError(const char * szFormat, const char * szFileName)
{
return PrintErrorVa(szFormat, szFileName);
}