From 1a94f94b50f6d829b1e8fba08a3002a5db4f00d5 Mon Sep 17 00:00:00 2001 From: Ladislav Zezula Date: Fri, 17 Dec 2021 14:51:35 +0100 Subject: Support for protected SCX files --- StormLib_vs19.vcxproj | 2 +- StormLib_vs19_dll.vcxproj | 8 +- StormLib_vs19_test.vcxproj | 8 +- make-msvc.bat | 16 +-- src/SBaseCommon.cpp | 5 +- src/SBaseFileTable.cpp | 12 +- src/SFileAddFile.cpp | 2 +- src/SFileCreateArchive.cpp | 29 ++--- src/SFileFindFile.cpp | 4 +- src/SFileOpenArchive.cpp | 32 +++-- src/SFileReadFile.cpp | 10 +- src/StormCommon.h | 1 + src/StormLib.h | 11 +- test/StormTest.cpp | 292 +++++++++++++++++++++++---------------------- test/TLogHelper.cpp | 2 +- 15 files changed, 233 insertions(+), 201 deletions(-) diff --git a/StormLib_vs19.vcxproj b/StormLib_vs19.vcxproj index ffcf960..e0c83f9 100644 --- a/StormLib_vs19.vcxproj +++ b/StormLib_vs19.vcxproj @@ -73,7 +73,7 @@ false 10.0.17134.0 StaticLibrary - v141 + v141_xp false diff --git a/StormLib_vs19_dll.vcxproj b/StormLib_vs19_dll.vcxproj index 712b427..1dbbce8 100644 --- a/StormLib_vs19_dll.vcxproj +++ b/StormLib_vs19_dll.vcxproj @@ -28,24 +28,24 @@ DynamicLibrary - v141 + v141_xp Unicode true DynamicLibrary - v141 + v141_xp Unicode DynamicLibrary - v141 + v141_xp Unicode true DynamicLibrary - v141 + v141_xp Unicode diff --git a/StormLib_vs19_test.vcxproj b/StormLib_vs19_test.vcxproj index 3bd8248..9f91ade 100644 --- a/StormLib_vs19_test.vcxproj +++ b/StormLib_vs19_test.vcxproj @@ -28,24 +28,24 @@ Application - v141 + v141_xp Unicode true Application - v141 + v141_xp Unicode Application - v141 + v141_xp Unicode true Application - v141 + v141_xp Unicode diff --git a/make-msvc.bat b/make-msvc.bat index 9a2ea8e..8b9a559 100644 --- a/make-msvc.bat +++ b/make-msvc.bat @@ -42,14 +42,14 @@ goto:eof call %1 %2 if "%2" == "x86" set SLN_TRG=Win32 if "%2" == "x64" set SLN_TRG=x64 -devenv.com %3 /project "%LIB_NAME%" /rebuild "DebugAD|%SLN_TRG%" -devenv.com %3 /project "%LIB_NAME%" /rebuild "DebugAS|%SLN_TRG%" -devenv.com %3 /project "%LIB_NAME%" /rebuild "DebugUD|%SLN_TRG%" -devenv.com %3 /project "%LIB_NAME%" /rebuild "DebugUS|%SLN_TRG%" -devenv.com %3 /project "%LIB_NAME%" /rebuild "ReleaseAD|%SLN_TRG%" -devenv.com %3 /project "%LIB_NAME%" /rebuild "ReleaseAS|%SLN_TRG%" -devenv.com %3 /project "%LIB_NAME%" /rebuild "ReleaseUD|%SLN_TRG%" -devenv.com %3 /project "%LIB_NAME%" /rebuild "ReleaseUS|%SLN_TRG%" +devenv.com %3 /project "%LIB_NAME%" /build "DebugAD|%SLN_TRG%" +devenv.com %3 /project "%LIB_NAME%" /build "DebugAS|%SLN_TRG%" +devenv.com %3 /project "%LIB_NAME%" /build "DebugUD|%SLN_TRG%" +devenv.com %3 /project "%LIB_NAME%" /build "DebugUS|%SLN_TRG%" +devenv.com %3 /project "%LIB_NAME%" /build "ReleaseAD|%SLN_TRG%" +devenv.com %3 /project "%LIB_NAME%" /build "ReleaseAS|%SLN_TRG%" +devenv.com %3 /project "%LIB_NAME%" /build "ReleaseUD|%SLN_TRG%" +devenv.com %3 /project "%LIB_NAME%" /build "ReleaseUS|%SLN_TRG%" :: Restore environment variables to the old level set INCLUDE=%SAVE_INCLUDE% diff --git a/src/SBaseCommon.cpp b/src/SBaseCommon.cpp index a1aa78e..98d541a 100644 --- a/src/SBaseCommon.cpp +++ b/src/SBaseCommon.cpp @@ -1334,11 +1334,12 @@ DWORD AllocateSectorOffsets(TMPQFile * hf, bool bLoadFromFile) // They are mostly empty on WoW release MPQs, but on MPQs from PTR, // they contain random non-zero data. Their meaning is unknown. // - // These extra values are, however, include in the dwCmpSize in the file + // These extra values are, however, included in the dwCmpSize in the file // table. We cannot ignore them, because compacting archive would fail // - if(hf->SectorOffsets[0] > dwSectorOffsLen) + // Clear the lower 2 bits in order to make sure that the value is aligned to 4 bytes + if((hf->SectorOffsets[0] & 0xFFFFFFFC) > dwSectorOffsLen) { // MPQ protectors put some ridiculous values there. We must limit the extra bytes if(hf->SectorOffsets[0] > (dwSectorOffsLen + 0x400)) diff --git a/src/SBaseFileTable.cpp b/src/SBaseFileTable.cpp index 7d52f7c..97fa3a2 100644 --- a/src/SBaseFileTable.cpp +++ b/src/SBaseFileTable.cpp @@ -893,15 +893,11 @@ static DWORD BuildFileTableFromBlockTable( TMPQHash * pHash; LPDWORD DefragmentTable = NULL; DWORD dwItemCount = 0; - DWORD dwFlagMask; // Sanity checks assert(ha->pFileTable != NULL); assert(ha->dwFileTableSize >= ha->dwMaxFileCount); - // MPQs for Warcraft III doesn't know some flags, namely MPQ_FILE_SINGLE_UNIT and MPQ_FILE_PATCH_FILE - dwFlagMask = (ha->dwFlags & MPQ_FLAG_WAR3_MAP) ? MPQ_FILE_VALID_FLAGS_W3X : MPQ_FILE_VALID_FLAGS; - // Defragment the hash table, if needed if(ha->dwFlags & MPQ_FLAG_HASH_TABLE_CUT) { @@ -976,10 +972,12 @@ static DWORD BuildFileTableFromBlockTable( if(pFileEntry->ByteOffset == 0 && pBlock->dwFSize == 0) pFileEntry->ByteOffset = ha->pHeader->dwHeaderSize; + // Clear file flags that are unknown to this type of map. + pFileEntry->dwFlags = pBlock->dwFlags & ha->dwValidFileFlags; + // Fill the rest of the file entry - pFileEntry->dwFileSize = pBlock->dwFSize; - pFileEntry->dwCmpSize = pBlock->dwCSize; - pFileEntry->dwFlags = pBlock->dwFlags & dwFlagMask; + pFileEntry->dwFileSize = pBlock->dwFSize; + pFileEntry->dwCmpSize = pBlock->dwCSize; } } diff --git a/src/SFileAddFile.cpp b/src/SFileAddFile.cpp index 7b88c12..9c7331b 100644 --- a/src/SFileAddFile.cpp +++ b/src/SFileAddFile.cpp @@ -795,7 +795,7 @@ bool WINAPI SFileCreateFile( if(dwErrCode == ERROR_SUCCESS) { // Mask all unsupported flags out - dwFlags &= (ha->dwFlags & MPQ_FLAG_WAR3_MAP) ? MPQ_FILE_VALID_FLAGS_W3X : MPQ_FILE_VALID_FLAGS; + dwFlags &= ha->dwValidFileFlags; // Check for valid flag combinations if((dwFlags & (MPQ_FILE_IMPLODE | MPQ_FILE_COMPRESS)) == (MPQ_FILE_IMPLODE | MPQ_FILE_COMPRESS)) diff --git a/src/SFileCreateArchive.cpp b/src/SFileCreateArchive.cpp index 742b829..4266070 100644 --- a/src/SFileCreateArchive.cpp +++ b/src/SFileCreateArchive.cpp @@ -202,20 +202,21 @@ bool WINAPI SFileCreateArchive2(const TCHAR * szMpqName, PSFILE_CREATE_MPQ pCrea if(dwErrCode == ERROR_SUCCESS) { memset(ha, 0, sizeof(TMPQArchive)); - ha->pfnHashString = HashStringSlash; - ha->pStream = pStream; - ha->dwSectorSize = pCreateInfo->dwSectorSize; - ha->UserDataPos = MpqPos; - ha->MpqPos = MpqPos; - ha->pHeader = pHeader = (TMPQHeader *)ha->HeaderData; - ha->dwMaxFileCount = dwHashTableSize; - ha->dwFileTableSize = 0; - ha->dwReservedFiles = dwReservedFiles; - ha->dwFileFlags1 = pCreateInfo->dwFileFlags1; - ha->dwFileFlags2 = pCreateInfo->dwFileFlags2; - ha->dwFileFlags3 = pCreateInfo->dwFileFlags3 ? MPQ_FILE_EXISTS : 0; - ha->dwAttrFlags = pCreateInfo->dwAttrFlags; - ha->dwFlags = dwMpqFlags | MPQ_FLAG_CHANGED; + ha->pfnHashString = HashStringSlash; + ha->pStream = pStream; + ha->dwSectorSize = pCreateInfo->dwSectorSize; + ha->UserDataPos = MpqPos; + ha->MpqPos = MpqPos; + ha->pHeader = pHeader = (TMPQHeader *)ha->HeaderData; + ha->dwMaxFileCount = dwHashTableSize; + ha->dwFileTableSize = 0; + ha->dwReservedFiles = dwReservedFiles; + ha->dwValidFileFlags = (pCreateInfo->dwMpqVersion > 1) ? MPQ_FILE_VALID_FLAGS : MPQ_FILE_VALID_FLAGS_W3X; + ha->dwFileFlags1 = pCreateInfo->dwFileFlags1; + ha->dwFileFlags2 = pCreateInfo->dwFileFlags2; + ha->dwFileFlags3 = pCreateInfo->dwFileFlags3 ? MPQ_FILE_EXISTS : 0; + ha->dwAttrFlags = pCreateInfo->dwAttrFlags; + ha->dwFlags = dwMpqFlags | MPQ_FLAG_CHANGED; pStream = NULL; // Fill the MPQ header diff --git a/src/SFileFindFile.cpp b/src/SFileFindFile.cpp index ef8b834..223e194 100644 --- a/src/SFileFindFile.cpp +++ b/src/SFileFindFile.cpp @@ -221,7 +221,7 @@ static bool DoMPQSearch_FileEntry( if((pFileEntry->dwFlags & hs->dwFlagMask) == MPQ_FILE_EXISTS) { // Ignore fake files which are not compressed but have size higher than the archive - if ((pFileEntry->dwFlags & MPQ_FILE_COMPRESS_MASK) == 0 && (pFileEntry->dwFileSize > ha->FileSize)) + if((pFileEntry->dwFlags & MPQ_FILE_COMPRESS_MASK) == 0 && (pFileEntry->dwFileSize > ha->FileSize)) return false; // Now we have to check if this file was not enumerated before @@ -236,8 +236,6 @@ 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/SFileOpenArchive.cpp b/src/SFileOpenArchive.cpp index ea29850..dcc7e18 100644 --- a/src/SFileOpenArchive.cpp +++ b/src/SFileOpenArchive.cpp @@ -18,6 +18,7 @@ #include "StormCommon.h" #define HEADER_SEARCH_BUFFER_SIZE 0x1000 +#define MINIMUM_MPQ_SIZE 0x0C //----------------------------------------------------------------------------- // Local functions @@ -35,21 +36,28 @@ static MTYPE CheckMapType(LPCTSTR szFileName, LPBYTE pbHeaderBuffer, size_t cbHe DWORD DwordValue2 = BSWAP_INT32_UNSIGNED(HeaderInt32[2]); DWORD DwordValue3 = BSWAP_INT32_UNSIGNED(HeaderInt32[3]); - // Test for AVI files (Warcraft III cinematics) - 'RIFF', 'AVI ' or 'LIST' - if(DwordValue0 == 0x46464952 && DwordValue2 == 0x20495641 && DwordValue3 == 0x5453494C) - return MapTypeAviFile; - - // Check for Starcraft II maps + // Check maps by extension (Starcraft, Starcraft II). We must do this before + // checking actual data, because the "NP_Protect" protector places + // fake Warcraft III header into the Starcraft II maps if((szExtension = _tcsrchr(szFileName, _T('.'))) != NULL) { - // The "NP_Protect" protector places fake Warcraft III header - // into the Starcraft II maps, whilst SC2 maps have no other header but MPQ v4 + // Check for Starcraft II maps by extension if(!_tcsicmp(szExtension, _T(".s2ma")) || !_tcsicmp(szExtension, _T(".SC2Map")) || !_tcsicmp(szExtension, _T(".SC2Mod"))) { return MapTypeStarcraft2; } + + // Check for Starcraft I maps by extension + if(!_tcsicmp(szExtension, _T(".scm")) || !_tcsicmp(szExtension, _T(".scx"))) + { + return MapTypeStarcraft; + } } + // Test for AVI files (Warcraft III cinematics) - 'RIFF', 'AVI ' or 'LIST' + if(DwordValue0 == 0x46464952 && DwordValue2 == 0x20495641 && DwordValue3 == 0x5453494C) + return MapTypeAviFile; + // Check for Warcraft III maps if(DwordValue0 == 0x57334D48 && DwordValue1 == 0x00000000) return MapTypeWarcraft3; @@ -271,6 +279,7 @@ bool WINAPI SFileOpenArchive( bool bSearchComplete = false; memset(ha, 0, sizeof(TMPQArchive)); + ha->dwValidFileFlags = MPQ_FILE_VALID_FLAGS; ha->pfnHashString = HashStringSlash; ha->pStream = pStream; pStream = NULL; @@ -288,6 +297,8 @@ bool WINAPI SFileOpenArchive( // Limit the header searching to about 130 MB of data if(EndOfSearch > 0x08000000) EndOfSearch = 0x08000000; + if(FileSize < HEADER_SEARCH_BUFFER_SIZE) + memset(pbHeaderBuffer, 0, HEADER_SEARCH_BUFFER_SIZE); // Find the offset of MPQ header within the file while(bSearchComplete == false && ByteOffset < EndOfSearch) @@ -438,7 +449,14 @@ bool WINAPI SFileOpenArchive( // Remember whether whis is a map for Warcraft III if(MapType == MapTypeWarcraft3) + { + ha->dwValidFileFlags = MPQ_FILE_VALID_FLAGS_W3X; ha->dwFlags |= MPQ_FLAG_WAR3_MAP; + } + + // If this is starcraft map, set the flag mask + if(MapType == MapTypeStarcraft) + ha->dwValidFileFlags = MPQ_FILE_VALID_FLAGS_SCX; // Set the size of file sector ha->dwSectorSize = (0x200 << ha->pHeader->wSectorSize); diff --git a/src/SFileReadFile.cpp b/src/SFileReadFile.cpp index 34edc06..1703748 100644 --- a/src/SFileReadFile.cpp +++ b/src/SFileReadFile.cpp @@ -663,7 +663,8 @@ static DWORD ReadMpqFileLocalFile(TMPQFile * hf, void * pvBuffer, DWORD dwFilePo bool WINAPI SFileReadFile(HANDLE hFile, void * pvBuffer, DWORD dwToRead, LPDWORD pdwRead, LPOVERLAPPED lpOverlapped) { - TMPQFile * hf = (TMPQFile *)hFile; + TFileEntry * pFileEntry; + TMPQFile * hf; DWORD dwBytesRead = 0; // Number of bytes read DWORD dwErrCode = ERROR_SUCCESS; @@ -673,7 +674,7 @@ bool WINAPI SFileReadFile(HANDLE hFile, void * pvBuffer, DWORD dwToRead, LPDWORD lpOverlapped = lpOverlapped; // Check valid parameters - if(!IsValidFileHandle(hFile)) + if((hf = IsValidFileHandle(hFile)) == NULL) { SetLastError(ERROR_INVALID_HANDLE); return false; @@ -697,6 +698,7 @@ bool WINAPI SFileReadFile(HANDLE hFile, void * pvBuffer, DWORD dwToRead, LPDWORD } // Clear the last used compression + pFileEntry = hf->pFileEntry; hf->dwCompression0 = 0; // If the file is local file, read the data directly from the stream @@ -706,7 +708,7 @@ bool WINAPI SFileReadFile(HANDLE hFile, void * pvBuffer, DWORD dwToRead, LPDWORD } // If the file is a patch file, we have to read it special way - else if(hf->hfPatch != NULL && (hf->pFileEntry->dwFlags & MPQ_FILE_PATCH_FILE) == 0) + else if(hf->hfPatch != NULL && (pFileEntry->dwFlags & MPQ_FILE_PATCH_FILE) == 0) { dwErrCode = ReadMpqFilePatchFile(hf, pvBuffer, hf->dwFilePos, dwToRead, &dwBytesRead); } @@ -718,7 +720,7 @@ bool WINAPI SFileReadFile(HANDLE hFile, void * pvBuffer, DWORD dwToRead, LPDWORD } // If the file is single unit file, redirect it to read file - else if(hf->pFileEntry->dwFlags & MPQ_FILE_SINGLE_UNIT) + else if(pFileEntry->dwFlags & MPQ_FILE_SINGLE_UNIT) { dwErrCode = ReadMpqFileSingleUnit(hf, pvBuffer, hf->dwFilePos, dwToRead, &dwBytesRead); } diff --git a/src/StormCommon.h b/src/StormCommon.h index e9187f9..f452112 100644 --- a/src/StormCommon.h +++ b/src/StormCommon.h @@ -81,6 +81,7 @@ typedef enum _MTYPE MapTypeNotChecked, // The map type was not checked yet MapTypeNotRecognized, // The file does not seems to be a map MapTypeAviFile, // The file is actually an AVI file (Warcraft III cinematics) + MapTypeStarcraft, // The file is a Starcraft map MapTypeWarcraft3, // The file is a Warcraft III map MapTypeStarcraft2 // The file is a Starcraft II map } MTYPE, *PMTYPE; diff --git a/src/StormLib.h b/src/StormLib.h index f7279e6..1335f0e 100644 --- a/src/StormLib.h +++ b/src/StormLib.h @@ -25,7 +25,7 @@ /* hash table */ /* 08.12.03 4.11 DCH Fixed bug in reading file sector larger than 0x1000 */ /* on certain files. */ -/* Fixed bug in AddFile with MPQ_FILE_REPLACE_EXISTING */ +/* Fixed bug in AddFile with MPQ_FILE_REPLACEEXISTING */ /* (Thanx Daniel Chiamarello, dchiamarello@madvawes.com)*/ /* 21.12.03 4.50 Lad Completed port for Mac */ /* Fixed bug in compacting (if fsize is mul of 0x1000) */ @@ -193,7 +193,7 @@ extern "C" { #define MPQ_FLAG_CHECK_SECTOR_CRC 0x00000020 // Checking sector CRC when reading files #define MPQ_FLAG_SAVING_TABLES 0x00000040 // If set, we are saving MPQ internal files and MPQ tables #define MPQ_FLAG_PATCH 0x00000080 // If set, this MPQ is a patch archive -#define MPQ_FLAG_WAR3_MAP 0x00000100 // If set, this MPQ is a map for Warcraft III +#define MPQ_FLAG_WAR3_MAP 0x00000100 // If set, this MPQ is a Warcraft III map #define MPQ_FLAG_LISTFILE_NONE 0x00000200 // Set when no (listfile) was found in InvalidateInternalFiles #define MPQ_FLAG_LISTFILE_NEW 0x00000400 // Set when (listfile) invalidated by InvalidateInternalFiles #define MPQ_FLAG_LISTFILE_FORCE 0x00000800 // Save updated listfile on exit @@ -250,6 +250,12 @@ extern "C" { MPQ_FILE_SIGNATURE | \ MPQ_FILE_EXISTS) +#define MPQ_FILE_VALID_FLAGS_SCX (MPQ_FILE_IMPLODE | \ + MPQ_FILE_COMPRESS | \ + MPQ_FILE_ENCRYPTED | \ + MPQ_FILE_FIX_KEY | \ + MPQ_FILE_EXISTS) + // We need to mask out the upper 4 bits of the block table index. // This is because it gets shifted out when calculating block table offset // BlockTableOffset = pHash->dwBlockIndex << 0x04 @@ -839,6 +845,7 @@ typedef struct _TMPQArchive DWORD dwFileFlags2; // Flags for (attributes) DWORD dwFileFlags3; // Flags for (signature) DWORD dwAttrFlags; // Flags for the (attributes) file, see MPQ_ATTRIBUTE_XXX + DWORD dwValidFileFlags; // Valid flags for the current MPQ DWORD dwFlags; // See MPQ_FLAG_XXXXX DWORD dwSubType; // See MPQ_SUBTYPE_XXX diff --git a/test/StormTest.cpp b/test/StormTest.cpp index 3ba9b1e..123ec43 100644 --- a/test/StormTest.cpp +++ b/test/StormTest.cpp @@ -35,8 +35,9 @@ //------------------------------------------------------------------------------ // Local structures -#define TEST_FLAG_PROTECTED 0x01000000 -#define TEST_FLAG_FILE_COUNT 0x00FFFFFF +#define TFLG_COUNT_HASH 0x01000000 // There is file count in the lower 24-bits, then hash +#define TFLG_COUNT_MASK 0x00FFFFFF // Mask for file count +#define TEST_DATA(hash, num) (num | TFLG_COUNT_HASH), hash typedef struct _TEST_INFO { @@ -80,6 +81,8 @@ static const TCHAR szListFileDir[] = { '1', '9', '9', '5', ' ', '-', ' ', 'T', ' // Global for the work MPQ static LPCTSTR szMpqSubDir = _T("1995 - Test MPQs"); static LPCTSTR szMpqPatchDir = _T("1995 - Test MPQs\\patches"); +static LPCSTR IntToHexChar = "0123456789abcdef"; + typedef DWORD (*FIND_FILE_CALLBACK)(LPCTSTR szFullPath); @@ -353,23 +356,27 @@ static bool IsMpqExtension(LPCTSTR szFileName) return false; } -static void BinaryFromString(LPCSTR szBinary, LPBYTE pbBuffer, DWORD cbBuffer) +// Converts binary array to string. +// The caller must ensure that the buffer has at least ((cbBinary * 2) + 1) characters +template +xchar * StringFromBinary(LPBYTE pbBinary, size_t cbBinary, xchar * szBuffer) { - LPBYTE pbBufferEnd = pbBuffer + cbBuffer; - char * szTemp; - char szHexaDigit[4]; + xchar * szSaveBuffer = szBuffer; - while(szBinary[0] != 0 && pbBuffer < pbBufferEnd) + // Verify the binary pointer + if(pbBinary && cbBinary) { - // Get the 2-byte chunk - szHexaDigit[0] = szBinary[0]; - szHexaDigit[1] = szBinary[1]; - szHexaDigit[2] = 0; - - // Convert to integer - *pbBuffer++ = (BYTE)strtoul(szHexaDigit, &szTemp, 16); - szBinary += 2; + // Convert the bytes to string array + for(size_t i = 0; i < cbBinary; i++) + { + *szBuffer++ = IntToHexChar[pbBinary[i] >> 0x04]; + *szBuffer++ = IntToHexChar[pbBinary[i] & 0x0F]; + } } + + // Terminate the string + *szBuffer = 0; + return szSaveBuffer; } static void AddStringBeforeExtension(char * szBuffer, LPCSTR szFileName, LPCSTR szExtraString) @@ -2452,12 +2459,12 @@ static DWORD TestArchive( LPCTSTR szPlainName, // Plain name of the MPQ LPCTSTR szListFile, // Listfile name (NULL if none) DWORD dwFlags, // Flags - LPCSTR szFileName1, - LPCSTR szFileName2) + LPCSTR szParam1, + LPCSTR szParam2) { - TFileData * pFileData1 = NULL; - TFileData * pFileData2 = NULL; + TFileData * FileDataList[2] = {NULL}; TLogHelper Logger("TestMpq", szPlainName); + LPCSTR FileNameList[2] = {NULL}; LPCSTR szExpectedMD5 = NULL; HANDLE hMpq = NULL; DWORD dwFileCount = 0; @@ -2467,8 +2474,7 @@ static DWORD TestArchive( DWORD dwExpectedFileCount = 0; DWORD dwMpqFlags = 0; TCHAR szFullName[MAX_PATH]; - BYTE ExpectedMD5[MD5_DIGEST_SIZE]; - BYTE OverallMD5[MD5_DIGEST_SIZE]; + BYTE ObtainedMD5[MD5_DIGEST_SIZE] = {0}; bool bIgnoreOpedwErrCodes = false; // If the file is a partial MPQ, don't load all files @@ -2476,14 +2482,18 @@ static DWORD TestArchive( dwSearchFlags |= SEARCH_FLAG_LOAD_FILES; // If the MPQ is a protected MPQ, do different tests - if(dwFlags & TEST_FLAG_PROTECTED) + if(dwFlags & TFLG_COUNT_HASH) { - dwExpectedFileCount = (dwFlags & TEST_FLAG_FILE_COUNT); - if((szExpectedMD5 = szFileName1) != NULL) + if((szExpectedMD5 = szParam1) != NULL) dwSearchFlags |= SEARCH_FLAG_HASH_FILES; - szFileName2 = szFileName1 = NULL; + dwExpectedFileCount = (dwFlags & TFLG_COUNT_MASK); + szParam1 = NULL; } + // Put all file names into list + FileNameList[0] = szParam1; + FileNameList[1] = szParam2; + // Copy the archive so we won't fuck up the original one dwErrCode = OpenExistingArchiveWithCopy(&Logger, szPlainName, NULL, &hMpq); while(dwErrCode == ERROR_SUCCESS) @@ -2510,49 +2520,43 @@ static DWORD TestArchive( if(dwErrCode != ERROR_SUCCESS) break; - // If szFileName1 was given, load it and check its CRC - if(szFileName1 && szFileName1[0]) + // For every file name given, load it and check its CRC + for(size_t i = 0; i < _countof(FileNameList); i++) { - // Test setting position - dwErrCode = TestArchive_SetPos(hMpq, szFileName1); - if(dwErrCode != ERROR_SUCCESS) - break; + TFileData * pFileData; + LPCSTR szFileName = FileNameList[i]; - // Load the entire file 1 - pFileData1 = LoadMpqFile(&Logger, hMpq, szFileName1); - if(pFileData1 == NULL) + if(szFileName && szFileName[0]) { - dwErrCode = Logger.PrintError("Failed to load the file %s", szFileName1); - break; - } + // Test setting position + dwErrCode = TestArchive_SetPos(hMpq, szFileName); + if(dwErrCode != ERROR_SUCCESS) + break; - // 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); - } - } + // Load the entire file 1 + FileDataList[i] = pFileData = LoadMpqFile(&Logger, hMpq, szFileName); + if(pFileData == NULL) + { + dwErrCode = Logger.PrintError("Failed to load the file %s", szFileName); + break; + } - // If szFileName2 was given, load it - if(szFileName2 && szFileName2[0]) - { - // Load the entire file 2 - pFileData2 = LoadMpqFile(&Logger, hMpq, szFileName2); - if(pFileData2 == NULL) - { - dwErrCode = Logger.PrintError("Failed to load the file %s", szFileName2); - break; + // Check the CRC of file1, if available + if(pFileData->dwCrc32) + { + // 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", szFileName); + } } } // If two files were given, compare them - if(pFileData1 && pFileData2) + if(FileDataList[0] && FileDataList[1]) { // Compare both files - if(!CompareTwoFiles(&Logger, pFileData1, pFileData2)) + if(!CompareTwoFiles(&Logger, FileDataList[0], FileDataList[1])) { dwErrCode = Logger.PrintError("The file has different size/content of files"); break; @@ -2560,38 +2564,38 @@ static DWORD TestArchive( } // Search the archive - dwErrCode = SearchArchive(&Logger, hMpq, dwSearchFlags, &dwFileCount, OverallMD5); + dwErrCode = SearchArchive(&Logger, hMpq, dwSearchFlags, &dwFileCount, ObtainedMD5); // Shall we check the file count and overall MD5? - if(dwExpectedFileCount != 0) + if(dwFlags & TFLG_COUNT_HASH) { if(dwFileCount != dwExpectedFileCount) { - Logger.PrintMessage("File count mismatch(expected: %u, found:%u)", dwExpectedFileCount, dwFileCount); + Logger.PrintMessage("File count mismatch(expected: %u, found: %u)", dwExpectedFileCount, dwFileCount); dwErrCode = ERROR_CAN_NOT_COMPLETE; - break; } } // Shall we check overall MD5? if(szExpectedMD5 && szExpectedMD5[0]) { - BinaryFromString(szExpectedMD5, ExpectedMD5, MD5_DIGEST_SIZE); - if(memcmp(ExpectedMD5, OverallMD5, MD5_DIGEST_SIZE)) + char szObtainedMD5[0x40]; + + StringFromBinary(ObtainedMD5, MD5_DIGEST_SIZE, szObtainedMD5); + if(_stricmp(szObtainedMD5, szExpectedMD5)) { - Logger.PrintMessage("Extracted files MD5 mismatch"); + Logger.PrintMessage("Extracted files MD5 mismatch (expected: %s, obtained: %s)", szExpectedMD5, szObtainedMD5); dwErrCode = ERROR_CAN_NOT_COMPLETE; - break; } } break; } // Common cleanup - if(pFileData2 != NULL) - STORM_FREE(pFileData2); - if(pFileData1 != NULL) - STORM_FREE(pFileData1); + if(FileDataList[1] != NULL) + STORM_FREE(FileDataList[1]); + if(FileDataList[0] != NULL) + STORM_FREE(FileDataList[0]); if(hMpq != NULL) SFileCloseArchive(hMpq); return dwErrCode; @@ -4198,6 +4202,9 @@ static DWORD TestModifyArchive_ReplaceFile(LPCTSTR szMpqPlainName, LPCTSTR szFil //----------------------------------------------------------------------------- // Tables +static LPCTSTR szBliz = _T("ListFile_Blizzard.txt"); +static LPCTSTR szWotI = _T("ListFile_WarOfTheImmortals.txt"); + static const TEST_INFO TestList_StreamOps[] = { {_T("MPQ_2013_v4_alternate-original.MPQ"), NULL, 0}, @@ -4223,54 +4230,54 @@ static const TEST_INFO TestList_MasterMirror[] = static const TEST_INFO Test_Mpqs[] = { - // 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 + {_T("MPQ_1997_v1_Diablo1_DIABDAT.MPQ"), NULL, 0, "music\\dintro.wav", "File00000023.xxx"}, + {_T("MPQ_2016_v1_D2XP_IX86_1xx_114a.mpq"), NULL, TEST_DATA("255d87a62f3c9518f72cf723a1818946", 221), "waitingroombkgd.dc6"}, // Update MPQ from Diablo II (patch 2016) + {_T("MPQ_2018_v1_icon_error.w3m"), NULL, TEST_DATA("fcefa25fb50c391e8714f2562d1e10ff", 19), "file00000002.blp"}, + {_T("MPQ_1997_v1_Diablo1_STANDARD.SNP"), szBliz, TEST_DATA("5ef18ef9a26b5704d8d46a344d976c89", 2)}, // File whose archive's (signature) file has flags = 0x90000000 + {_T("MPQ_2012_v2_EmptyMpq.MPQ"), NULL, TEST_DATA("00000000000000000000000000000000", 0)}, // Empty archive (found in WoW cache - it's just a header) + {_T("MPQ_2013_v4_EmptyMpq.MPQ"), NULL, TEST_DATA("00000000000000000000000000000000", 0)}, // Empty archive (created artificially - it's just a header) + {_T("MPQ_2013_v4_patch-base-16357.MPQ"), NULL, TEST_DATA("d41d8cd98f00b204e9800998ecf8427e", 1)}, // Empty archive (found in WoW cache - it's just a header) + {_T("MPQ_2011_v4_InvalidHetEntryCount.MPQ"), NULL, TEST_DATA("be4b49ecc3942d1957249f9da0021659", 6)}, // Empty archive (with invalid HET entry count) + {_T("MPQ_2002_v1_BlockTableCut.MPQ"), NULL, TEST_DATA("a9499ab74d939303d8cda7c397c36275", 287)}, // Truncated archive + {_T("MPQ_2010_v2_HasUserData.s2ma"), NULL, TEST_DATA("feff9e2c86db716b6ff5ffc906181200", 52)}, // MPQ that actually has user data + {_T("MPQ_2014_v1_AttributesOneEntryLess.w3x"), NULL, TEST_DATA("90451b7052eb0f1d6f4bf69b2daff7f5", 116)}, // Warcraft III map whose "(attributes)" file has (BlockTableSize-1) entries + {_T("MPQ_2020_v1_AHF04patch.mix"), NULL, TEST_DATA("d3c6aac48bc12813ef5ce4ad113e58bf", 2891)}, // MIX file + {_T("MPQ_2010_v3_expansion-locale-frFR.MPQ"), NULL, TEST_DATA("0c8fc921466f07421a281a05fad08b01", 53)}, // MPQ archive v 3.0 (the only one I know) + {_T("mpqe-file://MPQ_2011_v2_EncryptedMpq.MPQE"), NULL, TEST_DATA("10e4dcdbe95b7ad731c563ec6b71bc16", 82)}, // Encrypted archive from Starcraft II installer + {_T("MPx_2013_v1_LongwuOnline.mpk"), NULL, TEST_DATA("548f7db88284097f7e94c95a08c5bc24", 469)}, // MPK archive from Longwu online + {_T("MPx_2013_v1_WarOfTheImmortals.sqp"), szWotI, TEST_DATA("a048f37f7c6162a96253d8081722b6d9", 9396)}, // SQP archive from War of the Immortals + {_T("part-file://MPQ_2010_v2_HashTableCompressed.MPQ.part"),0, TEST_DATA("d41d8cd98f00b204e9800998ecf8427e", 14263)}, // Partial MPQ with compressed hash table + {_T("blk4-file://streaming/model.MPQ.0"), NULL, TEST_DATA("e06b00efb2fc7e7469dd8b3b859ae15d", 39914)}, // Archive that is merged with multiple files // 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"}, + {_T("MPQ_2002_v1_ProtectedMap_InvalidUserData.w3x"), NULL, TEST_DATA("b900364cc134a51ddeca21a13697c3ca", 79)}, + {_T("MPQ_2002_v1_ProtectedMap_InvalidMpqFormat.w3x"), NULL, TEST_DATA("db67e894da9de618a1cdf86d02d315ff", 117)}, + {_T("MPQ_2002_v1_ProtectedMap_Spazzler.w3x"), NULL, TEST_DATA("72d7963aa799a7fb4117c55b7beabaf9", 470)}, // Warcraft III map locked by the Spazzler protector + {_T("MPQ_2014_v1_ProtectedMap_Spazzler2.w3x"), NULL, TEST_DATA("72d7963aa799a7fb4117c55b7beabaf9", 470)}, // Warcraft III map locked by the Spazzler protector + {_T("MPQ_2014_v1_ProtectedMap_Spazzler3.w3x"), NULL, TEST_DATA("e55aad2dd33cf68b372ca8e30dcb78a7", 130)}, // Warcraft III map locked by the Spazzler protector + {_T("MPQ_2002_v1_ProtectedMap_BOBA.w3m"), NULL, TEST_DATA("7b725d87e07a2173c42fe2314b95fa6c", 17)}, // Warcraft III map locked by the BOBA protector + {_T("MPQ_2015_v1_ProtectedMap_KangTooJee.w3x"), NULL, TEST_DATA("c7ca4d2d0b1e58db5c784f522506c897", 1578)}, + {_T("MPQ_2015_v1_ProtectedMap_Somj2hM16.w3x"), NULL, TEST_DATA("b411f9a51a6e9a9a509150c8d66ba359", 92)}, + {_T("MPQ_2015_v1_ProtectedMap_Spazy.w3x"), NULL, TEST_DATA("6e491bd055511435dcb4d9c8baed0516", 4089)}, // Warcraft III map locked by Spazy protector + {_T("MPQ_2015_v1_MessListFile.mpq"), NULL, TEST_DATA("15e25d5be124d8ad71519f967997efc2", 8)}, + {_T("MPQ_2016_v1_ProtectedMap_TableSizeOverflow.w3x"), NULL, TEST_DATA("ad81b43cbd37bbfa27e4bed4c17e6a81", 176)}, + {_T("MPQ_2016_v1_ProtectedMap_HashOffsIsZero.w3x"), NULL, TEST_DATA("d6e712c275a26dc51f16b3a02f6187df", 228)}, + {_T("MPQ_2016_v1_ProtectedMap_Somj2.w3x"), NULL, TEST_DATA("457cdbf97a9ca41cfe8ea130dafaa0bb", 21)}, // Something like Somj 2.0 + {_T("MPQ_2016_v1_WME4_4.w3x"), NULL, TEST_DATA("e85e1c0ccb4465a30ffd07cae3260254", 382)}, // Protector from China (2016-05-27) + {_T("MPQ_2016_v1_SP_(4)Adrenaline.w3x"), NULL, TEST_DATA("b6f6d56f4f8aaef04c2c4b1f08881a8b", 16)}, + {_T("MPQ_2016_v1_ProtectedMap_1.4.w3x"), NULL, TEST_DATA("3c7908b29d3feac9ec952282390a242d", 5027)}, + {_T("MPQ_2016_v1_KoreanFile.w3m"), NULL, TEST_DATA("805d1f75712472a81c6df27b2a71f946", 18)}, + {_T("MPQ_2017_v1_Eden_RPG_S2_2.5J.w3x"), NULL, TEST_DATA("7a7f0749b47b5f05a8b63ecba2488a3e", 16300)}, // Protected by PG1.11.973 + {_T("MPQ_2017_v1_BigDummyFiles.w3x"), NULL, TEST_DATA("f4d2ee9d85d2c4107e0b2d00ff302dd7", 9086)}, + {_T("MPQ_2017_v1_TildeInFileName.mpq"), NULL, TEST_DATA("f203e3979247a4dbf7f3828695ac810c", 5)}, + {_T("MPQ_2018_v1_EWIX_v8_7.w3x"), NULL, TEST_DATA("12c0f4e15c7361b7c13acd37a181d83b", 857), "BlueCrystal.mdx"}, + {_T("MPQ_2020_v4_FakeMpqHeaders.SC2Mod"), NULL, TEST_DATA("f45392f6523250c943990a017c230b41", 24)}, // Archive that has two fake headers before the real one + {_T("MPQ_2020_v4_NP_Protect_1.s2ma"), NULL, TEST_DATA("1a1ea40ac1165bcdb4f2e434edfc7636", 21)}, // SC2 map that is protected by the NP_Protect + {_T("MPQ_2020_v4_NP_Protect_2.s2ma"), NULL, TEST_DATA("7d1a379da8bd966da1f4fa6e4646049b", 55)}, // SC2 map that is protected by the NP_Protect + {_T("MPQ_2015_v1_flem1.w3x"), NULL, TEST_DATA("1c4c13e627658c473e84d94371e31f37", 20)}, + {_T("MPQ_2002_v1_ProtectedMap_HashTable_FakeValid.w3x"), NULL, TEST_DATA("5250975ed917375fc6540d7be436d4de", 114)}, + {_T("MPQ_2021_v1_CantExtractCHK.scx"), NULL, TEST_DATA("c9a7ded9f93d883b9419a52bec6087f7", 28)}, }; //----------------------------------------------------------------------------- @@ -4302,50 +4309,49 @@ int _tmain(int argc, TCHAR * argv[]) // Open all files from the command line // - TestArchive(_T("e:\\Other.sqp"), NULL, 0, "replay.game.events", NULL); - for(int i = 1; i < argc; i++) - { - TestOpenArchive_CompactArchive(argv[i], _T("TestArchiveCopy.mpq"), false); - } + //for(int i = 1; i < argc; i++) + //{ + // TestArchive(_T("MPQ_2021_v1_CantExtractCHK.scx"), _T("Listfile_Blizzard.txt"), TEST_FLAG_FILE_COUNT, NULL, NULL); + //} // // Search all testing archives and verify their SHA1 hash // - if(dwErrCode == ERROR_SUCCESS) - { - dwErrCode = FindFiles(ForEachFile_VerifyFileChecksum, szMpqSubDir); - } + //if(dwErrCode == ERROR_SUCCESS) + //{ + // dwErrCode = FindFiles(ForEachFile_VerifyFileChecksum, szMpqSubDir); + //} // // Test file stream operations // - 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; - } - } + //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; + // } + //} // // Test master-mirror reading operations // - 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) + //{ + // 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; + // } + //} // // Test opening various archives - correct, damaged, protected diff --git a/test/TLogHelper.cpp b/test/TLogHelper.cpp index cd10a3c..8a4fc41 100644 --- a/test/TLogHelper.cpp +++ b/test/TLogHelper.cpp @@ -402,7 +402,7 @@ char * TLogHelper::CopyFormatCharacter(char * szBuffer, const char *& szFormat) // String format if(szFormat[0] == '%') { - if(szFormat[1] == 's' && szFormat[2] != ')') + if(szFormat[1] == 's') { strcpy(szBuffer, szStringFormat); szFormat += 2; -- cgit v1.2.3 From 4f4f926c1a3347f7ecd18f549c4be0a1e62413ba Mon Sep 17 00:00:00 2001 From: Ladislav Zezula Date: Fri, 17 Dec 2021 14:51:35 +0100 Subject: Support for protected SCX files --- StormLib_vs19.vcxproj | 2 +- StormLib_vs19_dll.vcxproj | 8 +++---- StormLib_vs19_test.vcxproj | 8 +++---- make-msvc.bat | 16 +++++++------- src/SBaseCommon.cpp | 5 +++-- src/SBaseFileTable.cpp | 12 +++++----- src/SFileAddFile.cpp | 2 +- src/SFileCreateArchive.cpp | 29 ++++++++++++------------ src/SFileFindFile.cpp | 4 +--- src/SFileOpenArchive.cpp | 32 +++++++++++++++++++++------ src/SFileReadFile.cpp | 10 +++++---- src/StormCommon.h | 1 + src/StormLib.h | 11 ++++++++-- test/StormTest.cpp | 55 ++++++++++++++++++++++++++-------------------- test/TLogHelper.cpp | 2 +- 15 files changed, 115 insertions(+), 82 deletions(-) diff --git a/StormLib_vs19.vcxproj b/StormLib_vs19.vcxproj index ffcf960..e0c83f9 100644 --- a/StormLib_vs19.vcxproj +++ b/StormLib_vs19.vcxproj @@ -73,7 +73,7 @@ false 10.0.17134.0 StaticLibrary - v141 + v141_xp false diff --git a/StormLib_vs19_dll.vcxproj b/StormLib_vs19_dll.vcxproj index 712b427..1dbbce8 100644 --- a/StormLib_vs19_dll.vcxproj +++ b/StormLib_vs19_dll.vcxproj @@ -28,24 +28,24 @@ DynamicLibrary - v141 + v141_xp Unicode true DynamicLibrary - v141 + v141_xp Unicode DynamicLibrary - v141 + v141_xp Unicode true DynamicLibrary - v141 + v141_xp Unicode diff --git a/StormLib_vs19_test.vcxproj b/StormLib_vs19_test.vcxproj index 3bd8248..9f91ade 100644 --- a/StormLib_vs19_test.vcxproj +++ b/StormLib_vs19_test.vcxproj @@ -28,24 +28,24 @@ Application - v141 + v141_xp Unicode true Application - v141 + v141_xp Unicode Application - v141 + v141_xp Unicode true Application - v141 + v141_xp Unicode diff --git a/make-msvc.bat b/make-msvc.bat index 9a2ea8e..8b9a559 100644 --- a/make-msvc.bat +++ b/make-msvc.bat @@ -42,14 +42,14 @@ goto:eof call %1 %2 if "%2" == "x86" set SLN_TRG=Win32 if "%2" == "x64" set SLN_TRG=x64 -devenv.com %3 /project "%LIB_NAME%" /rebuild "DebugAD|%SLN_TRG%" -devenv.com %3 /project "%LIB_NAME%" /rebuild "DebugAS|%SLN_TRG%" -devenv.com %3 /project "%LIB_NAME%" /rebuild "DebugUD|%SLN_TRG%" -devenv.com %3 /project "%LIB_NAME%" /rebuild "DebugUS|%SLN_TRG%" -devenv.com %3 /project "%LIB_NAME%" /rebuild "ReleaseAD|%SLN_TRG%" -devenv.com %3 /project "%LIB_NAME%" /rebuild "ReleaseAS|%SLN_TRG%" -devenv.com %3 /project "%LIB_NAME%" /rebuild "ReleaseUD|%SLN_TRG%" -devenv.com %3 /project "%LIB_NAME%" /rebuild "ReleaseUS|%SLN_TRG%" +devenv.com %3 /project "%LIB_NAME%" /build "DebugAD|%SLN_TRG%" +devenv.com %3 /project "%LIB_NAME%" /build "DebugAS|%SLN_TRG%" +devenv.com %3 /project "%LIB_NAME%" /build "DebugUD|%SLN_TRG%" +devenv.com %3 /project "%LIB_NAME%" /build "DebugUS|%SLN_TRG%" +devenv.com %3 /project "%LIB_NAME%" /build "ReleaseAD|%SLN_TRG%" +devenv.com %3 /project "%LIB_NAME%" /build "ReleaseAS|%SLN_TRG%" +devenv.com %3 /project "%LIB_NAME%" /build "ReleaseUD|%SLN_TRG%" +devenv.com %3 /project "%LIB_NAME%" /build "ReleaseUS|%SLN_TRG%" :: Restore environment variables to the old level set INCLUDE=%SAVE_INCLUDE% diff --git a/src/SBaseCommon.cpp b/src/SBaseCommon.cpp index a1aa78e..98d541a 100644 --- a/src/SBaseCommon.cpp +++ b/src/SBaseCommon.cpp @@ -1334,11 +1334,12 @@ DWORD AllocateSectorOffsets(TMPQFile * hf, bool bLoadFromFile) // They are mostly empty on WoW release MPQs, but on MPQs from PTR, // they contain random non-zero data. Their meaning is unknown. // - // These extra values are, however, include in the dwCmpSize in the file + // These extra values are, however, included in the dwCmpSize in the file // table. We cannot ignore them, because compacting archive would fail // - if(hf->SectorOffsets[0] > dwSectorOffsLen) + // Clear the lower 2 bits in order to make sure that the value is aligned to 4 bytes + if((hf->SectorOffsets[0] & 0xFFFFFFFC) > dwSectorOffsLen) { // MPQ protectors put some ridiculous values there. We must limit the extra bytes if(hf->SectorOffsets[0] > (dwSectorOffsLen + 0x400)) diff --git a/src/SBaseFileTable.cpp b/src/SBaseFileTable.cpp index 7d52f7c..97fa3a2 100644 --- a/src/SBaseFileTable.cpp +++ b/src/SBaseFileTable.cpp @@ -893,15 +893,11 @@ static DWORD BuildFileTableFromBlockTable( TMPQHash * pHash; LPDWORD DefragmentTable = NULL; DWORD dwItemCount = 0; - DWORD dwFlagMask; // Sanity checks assert(ha->pFileTable != NULL); assert(ha->dwFileTableSize >= ha->dwMaxFileCount); - // MPQs for Warcraft III doesn't know some flags, namely MPQ_FILE_SINGLE_UNIT and MPQ_FILE_PATCH_FILE - dwFlagMask = (ha->dwFlags & MPQ_FLAG_WAR3_MAP) ? MPQ_FILE_VALID_FLAGS_W3X : MPQ_FILE_VALID_FLAGS; - // Defragment the hash table, if needed if(ha->dwFlags & MPQ_FLAG_HASH_TABLE_CUT) { @@ -976,10 +972,12 @@ static DWORD BuildFileTableFromBlockTable( if(pFileEntry->ByteOffset == 0 && pBlock->dwFSize == 0) pFileEntry->ByteOffset = ha->pHeader->dwHeaderSize; + // Clear file flags that are unknown to this type of map. + pFileEntry->dwFlags = pBlock->dwFlags & ha->dwValidFileFlags; + // Fill the rest of the file entry - pFileEntry->dwFileSize = pBlock->dwFSize; - pFileEntry->dwCmpSize = pBlock->dwCSize; - pFileEntry->dwFlags = pBlock->dwFlags & dwFlagMask; + pFileEntry->dwFileSize = pBlock->dwFSize; + pFileEntry->dwCmpSize = pBlock->dwCSize; } } diff --git a/src/SFileAddFile.cpp b/src/SFileAddFile.cpp index 7b88c12..9c7331b 100644 --- a/src/SFileAddFile.cpp +++ b/src/SFileAddFile.cpp @@ -795,7 +795,7 @@ bool WINAPI SFileCreateFile( if(dwErrCode == ERROR_SUCCESS) { // Mask all unsupported flags out - dwFlags &= (ha->dwFlags & MPQ_FLAG_WAR3_MAP) ? MPQ_FILE_VALID_FLAGS_W3X : MPQ_FILE_VALID_FLAGS; + dwFlags &= ha->dwValidFileFlags; // Check for valid flag combinations if((dwFlags & (MPQ_FILE_IMPLODE | MPQ_FILE_COMPRESS)) == (MPQ_FILE_IMPLODE | MPQ_FILE_COMPRESS)) diff --git a/src/SFileCreateArchive.cpp b/src/SFileCreateArchive.cpp index 742b829..4266070 100644 --- a/src/SFileCreateArchive.cpp +++ b/src/SFileCreateArchive.cpp @@ -202,20 +202,21 @@ bool WINAPI SFileCreateArchive2(const TCHAR * szMpqName, PSFILE_CREATE_MPQ pCrea if(dwErrCode == ERROR_SUCCESS) { memset(ha, 0, sizeof(TMPQArchive)); - ha->pfnHashString = HashStringSlash; - ha->pStream = pStream; - ha->dwSectorSize = pCreateInfo->dwSectorSize; - ha->UserDataPos = MpqPos; - ha->MpqPos = MpqPos; - ha->pHeader = pHeader = (TMPQHeader *)ha->HeaderData; - ha->dwMaxFileCount = dwHashTableSize; - ha->dwFileTableSize = 0; - ha->dwReservedFiles = dwReservedFiles; - ha->dwFileFlags1 = pCreateInfo->dwFileFlags1; - ha->dwFileFlags2 = pCreateInfo->dwFileFlags2; - ha->dwFileFlags3 = pCreateInfo->dwFileFlags3 ? MPQ_FILE_EXISTS : 0; - ha->dwAttrFlags = pCreateInfo->dwAttrFlags; - ha->dwFlags = dwMpqFlags | MPQ_FLAG_CHANGED; + ha->pfnHashString = HashStringSlash; + ha->pStream = pStream; + ha->dwSectorSize = pCreateInfo->dwSectorSize; + ha->UserDataPos = MpqPos; + ha->MpqPos = MpqPos; + ha->pHeader = pHeader = (TMPQHeader *)ha->HeaderData; + ha->dwMaxFileCount = dwHashTableSize; + ha->dwFileTableSize = 0; + ha->dwReservedFiles = dwReservedFiles; + ha->dwValidFileFlags = (pCreateInfo->dwMpqVersion > 1) ? MPQ_FILE_VALID_FLAGS : MPQ_FILE_VALID_FLAGS_W3X; + ha->dwFileFlags1 = pCreateInfo->dwFileFlags1; + ha->dwFileFlags2 = pCreateInfo->dwFileFlags2; + ha->dwFileFlags3 = pCreateInfo->dwFileFlags3 ? MPQ_FILE_EXISTS : 0; + ha->dwAttrFlags = pCreateInfo->dwAttrFlags; + ha->dwFlags = dwMpqFlags | MPQ_FLAG_CHANGED; pStream = NULL; // Fill the MPQ header diff --git a/src/SFileFindFile.cpp b/src/SFileFindFile.cpp index ef8b834..223e194 100644 --- a/src/SFileFindFile.cpp +++ b/src/SFileFindFile.cpp @@ -221,7 +221,7 @@ static bool DoMPQSearch_FileEntry( if((pFileEntry->dwFlags & hs->dwFlagMask) == MPQ_FILE_EXISTS) { // Ignore fake files which are not compressed but have size higher than the archive - if ((pFileEntry->dwFlags & MPQ_FILE_COMPRESS_MASK) == 0 && (pFileEntry->dwFileSize > ha->FileSize)) + if((pFileEntry->dwFlags & MPQ_FILE_COMPRESS_MASK) == 0 && (pFileEntry->dwFileSize > ha->FileSize)) return false; // Now we have to check if this file was not enumerated before @@ -236,8 +236,6 @@ 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/SFileOpenArchive.cpp b/src/SFileOpenArchive.cpp index ea29850..dcc7e18 100644 --- a/src/SFileOpenArchive.cpp +++ b/src/SFileOpenArchive.cpp @@ -18,6 +18,7 @@ #include "StormCommon.h" #define HEADER_SEARCH_BUFFER_SIZE 0x1000 +#define MINIMUM_MPQ_SIZE 0x0C //----------------------------------------------------------------------------- // Local functions @@ -35,21 +36,28 @@ static MTYPE CheckMapType(LPCTSTR szFileName, LPBYTE pbHeaderBuffer, size_t cbHe DWORD DwordValue2 = BSWAP_INT32_UNSIGNED(HeaderInt32[2]); DWORD DwordValue3 = BSWAP_INT32_UNSIGNED(HeaderInt32[3]); - // Test for AVI files (Warcraft III cinematics) - 'RIFF', 'AVI ' or 'LIST' - if(DwordValue0 == 0x46464952 && DwordValue2 == 0x20495641 && DwordValue3 == 0x5453494C) - return MapTypeAviFile; - - // Check for Starcraft II maps + // Check maps by extension (Starcraft, Starcraft II). We must do this before + // checking actual data, because the "NP_Protect" protector places + // fake Warcraft III header into the Starcraft II maps if((szExtension = _tcsrchr(szFileName, _T('.'))) != NULL) { - // The "NP_Protect" protector places fake Warcraft III header - // into the Starcraft II maps, whilst SC2 maps have no other header but MPQ v4 + // Check for Starcraft II maps by extension if(!_tcsicmp(szExtension, _T(".s2ma")) || !_tcsicmp(szExtension, _T(".SC2Map")) || !_tcsicmp(szExtension, _T(".SC2Mod"))) { return MapTypeStarcraft2; } + + // Check for Starcraft I maps by extension + if(!_tcsicmp(szExtension, _T(".scm")) || !_tcsicmp(szExtension, _T(".scx"))) + { + return MapTypeStarcraft; + } } + // Test for AVI files (Warcraft III cinematics) - 'RIFF', 'AVI ' or 'LIST' + if(DwordValue0 == 0x46464952 && DwordValue2 == 0x20495641 && DwordValue3 == 0x5453494C) + return MapTypeAviFile; + // Check for Warcraft III maps if(DwordValue0 == 0x57334D48 && DwordValue1 == 0x00000000) return MapTypeWarcraft3; @@ -271,6 +279,7 @@ bool WINAPI SFileOpenArchive( bool bSearchComplete = false; memset(ha, 0, sizeof(TMPQArchive)); + ha->dwValidFileFlags = MPQ_FILE_VALID_FLAGS; ha->pfnHashString = HashStringSlash; ha->pStream = pStream; pStream = NULL; @@ -288,6 +297,8 @@ bool WINAPI SFileOpenArchive( // Limit the header searching to about 130 MB of data if(EndOfSearch > 0x08000000) EndOfSearch = 0x08000000; + if(FileSize < HEADER_SEARCH_BUFFER_SIZE) + memset(pbHeaderBuffer, 0, HEADER_SEARCH_BUFFER_SIZE); // Find the offset of MPQ header within the file while(bSearchComplete == false && ByteOffset < EndOfSearch) @@ -438,7 +449,14 @@ bool WINAPI SFileOpenArchive( // Remember whether whis is a map for Warcraft III if(MapType == MapTypeWarcraft3) + { + ha->dwValidFileFlags = MPQ_FILE_VALID_FLAGS_W3X; ha->dwFlags |= MPQ_FLAG_WAR3_MAP; + } + + // If this is starcraft map, set the flag mask + if(MapType == MapTypeStarcraft) + ha->dwValidFileFlags = MPQ_FILE_VALID_FLAGS_SCX; // Set the size of file sector ha->dwSectorSize = (0x200 << ha->pHeader->wSectorSize); diff --git a/src/SFileReadFile.cpp b/src/SFileReadFile.cpp index 34edc06..1703748 100644 --- a/src/SFileReadFile.cpp +++ b/src/SFileReadFile.cpp @@ -663,7 +663,8 @@ static DWORD ReadMpqFileLocalFile(TMPQFile * hf, void * pvBuffer, DWORD dwFilePo bool WINAPI SFileReadFile(HANDLE hFile, void * pvBuffer, DWORD dwToRead, LPDWORD pdwRead, LPOVERLAPPED lpOverlapped) { - TMPQFile * hf = (TMPQFile *)hFile; + TFileEntry * pFileEntry; + TMPQFile * hf; DWORD dwBytesRead = 0; // Number of bytes read DWORD dwErrCode = ERROR_SUCCESS; @@ -673,7 +674,7 @@ bool WINAPI SFileReadFile(HANDLE hFile, void * pvBuffer, DWORD dwToRead, LPDWORD lpOverlapped = lpOverlapped; // Check valid parameters - if(!IsValidFileHandle(hFile)) + if((hf = IsValidFileHandle(hFile)) == NULL) { SetLastError(ERROR_INVALID_HANDLE); return false; @@ -697,6 +698,7 @@ bool WINAPI SFileReadFile(HANDLE hFile, void * pvBuffer, DWORD dwToRead, LPDWORD } // Clear the last used compression + pFileEntry = hf->pFileEntry; hf->dwCompression0 = 0; // If the file is local file, read the data directly from the stream @@ -706,7 +708,7 @@ bool WINAPI SFileReadFile(HANDLE hFile, void * pvBuffer, DWORD dwToRead, LPDWORD } // If the file is a patch file, we have to read it special way - else if(hf->hfPatch != NULL && (hf->pFileEntry->dwFlags & MPQ_FILE_PATCH_FILE) == 0) + else if(hf->hfPatch != NULL && (pFileEntry->dwFlags & MPQ_FILE_PATCH_FILE) == 0) { dwErrCode = ReadMpqFilePatchFile(hf, pvBuffer, hf->dwFilePos, dwToRead, &dwBytesRead); } @@ -718,7 +720,7 @@ bool WINAPI SFileReadFile(HANDLE hFile, void * pvBuffer, DWORD dwToRead, LPDWORD } // If the file is single unit file, redirect it to read file - else if(hf->pFileEntry->dwFlags & MPQ_FILE_SINGLE_UNIT) + else if(pFileEntry->dwFlags & MPQ_FILE_SINGLE_UNIT) { dwErrCode = ReadMpqFileSingleUnit(hf, pvBuffer, hf->dwFilePos, dwToRead, &dwBytesRead); } diff --git a/src/StormCommon.h b/src/StormCommon.h index e9187f9..f452112 100644 --- a/src/StormCommon.h +++ b/src/StormCommon.h @@ -81,6 +81,7 @@ typedef enum _MTYPE MapTypeNotChecked, // The map type was not checked yet MapTypeNotRecognized, // The file does not seems to be a map MapTypeAviFile, // The file is actually an AVI file (Warcraft III cinematics) + MapTypeStarcraft, // The file is a Starcraft map MapTypeWarcraft3, // The file is a Warcraft III map MapTypeStarcraft2 // The file is a Starcraft II map } MTYPE, *PMTYPE; diff --git a/src/StormLib.h b/src/StormLib.h index f7279e6..1335f0e 100644 --- a/src/StormLib.h +++ b/src/StormLib.h @@ -25,7 +25,7 @@ /* hash table */ /* 08.12.03 4.11 DCH Fixed bug in reading file sector larger than 0x1000 */ /* on certain files. */ -/* Fixed bug in AddFile with MPQ_FILE_REPLACE_EXISTING */ +/* Fixed bug in AddFile with MPQ_FILE_REPLACEEXISTING */ /* (Thanx Daniel Chiamarello, dchiamarello@madvawes.com)*/ /* 21.12.03 4.50 Lad Completed port for Mac */ /* Fixed bug in compacting (if fsize is mul of 0x1000) */ @@ -193,7 +193,7 @@ extern "C" { #define MPQ_FLAG_CHECK_SECTOR_CRC 0x00000020 // Checking sector CRC when reading files #define MPQ_FLAG_SAVING_TABLES 0x00000040 // If set, we are saving MPQ internal files and MPQ tables #define MPQ_FLAG_PATCH 0x00000080 // If set, this MPQ is a patch archive -#define MPQ_FLAG_WAR3_MAP 0x00000100 // If set, this MPQ is a map for Warcraft III +#define MPQ_FLAG_WAR3_MAP 0x00000100 // If set, this MPQ is a Warcraft III map #define MPQ_FLAG_LISTFILE_NONE 0x00000200 // Set when no (listfile) was found in InvalidateInternalFiles #define MPQ_FLAG_LISTFILE_NEW 0x00000400 // Set when (listfile) invalidated by InvalidateInternalFiles #define MPQ_FLAG_LISTFILE_FORCE 0x00000800 // Save updated listfile on exit @@ -250,6 +250,12 @@ extern "C" { MPQ_FILE_SIGNATURE | \ MPQ_FILE_EXISTS) +#define MPQ_FILE_VALID_FLAGS_SCX (MPQ_FILE_IMPLODE | \ + MPQ_FILE_COMPRESS | \ + MPQ_FILE_ENCRYPTED | \ + MPQ_FILE_FIX_KEY | \ + MPQ_FILE_EXISTS) + // We need to mask out the upper 4 bits of the block table index. // This is because it gets shifted out when calculating block table offset // BlockTableOffset = pHash->dwBlockIndex << 0x04 @@ -839,6 +845,7 @@ typedef struct _TMPQArchive DWORD dwFileFlags2; // Flags for (attributes) DWORD dwFileFlags3; // Flags for (signature) DWORD dwAttrFlags; // Flags for the (attributes) file, see MPQ_ATTRIBUTE_XXX + DWORD dwValidFileFlags; // Valid flags for the current MPQ DWORD dwFlags; // See MPQ_FLAG_XXXXX DWORD dwSubType; // See MPQ_SUBTYPE_XXX diff --git a/test/StormTest.cpp b/test/StormTest.cpp index 13b0ace..3d783aa 100644 --- a/test/StormTest.cpp +++ b/test/StormTest.cpp @@ -4327,49 +4327,56 @@ int _tmain(int argc, TCHAR * argv[]) // Open all files from the command line // +<<<<<<< HEAD for(int i = 1; i < argc; i++) { TestArchive(_T("MPQ_2021_v1_CantExtractCHK.scx"), _T("Listfile_Blizzard.txt"), 0, NULL, NULL); } +======= + //for(int i = 1; i < argc; i++) + //{ + // TestArchive(_T("MPQ_2021_v1_CantExtractCHK.scx"), _T("Listfile_Blizzard.txt"), TEST_FLAG_FILE_COUNT, NULL, NULL); + //} +>>>>>>> 1a94f94 (Support for protected SCX files) // // Search all testing archives and verify their SHA1 hash // - if(dwErrCode == ERROR_SUCCESS) - { - dwErrCode = FindFiles(ForEachFile_VerifyFileChecksum, szMpqSubDir); - } + //if(dwErrCode == ERROR_SUCCESS) + //{ + // dwErrCode = FindFiles(ForEachFile_VerifyFileChecksum, szMpqSubDir); + //} // // Test file stream operations // - 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; - } - } + //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; + // } + //} // // Test master-mirror reading operations // - 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) + //{ + // 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; + // } + //} // // Test opening various archives - correct, damaged, protected diff --git a/test/TLogHelper.cpp b/test/TLogHelper.cpp index 3d09823..f277e64 100644 --- a/test/TLogHelper.cpp +++ b/test/TLogHelper.cpp @@ -423,7 +423,7 @@ char * TLogHelper::CopyFormatCharacter(char * szBuffer, const char *& szFormat) // String format if(szFormat[0] == '%') { - if(szFormat[1] == 's' && szFormat[2] != ')') + if(szFormat[1] == 's') { strcpy(szBuffer, szStringFormat); szFormat += 2; -- cgit v1.2.3 From 3424ac8ba449b6036d49fd28725f6a2d7c4548e9 Mon Sep 17 00:00:00 2001 From: Ladislav Zezula Date: Fri, 17 Dec 2021 23:42:52 +0100 Subject: Finalizing --- PostBuild.bat | 34 ------------------------ StormLib_vs08.vcproj | 32 +++++++++++------------ StormLib_vs19.vcxproj | 64 ++++++++++++++++++++++++++++++++++------------ StormLib_vs19_dll.vcxproj | 4 +++ StormLib_vs19_test.vcxproj | 4 +++ make-msvc.bat | 33 ++++++++++++++++-------- make.bat | 8 +++--- test/StormTest.cpp | 55 +++++++++++++++++---------------------- test/TLogHelper.cpp | 2 +- 9 files changed, 123 insertions(+), 113 deletions(-) delete mode 100644 PostBuild.bat diff --git a/PostBuild.bat b/PostBuild.bat deleted file mode 100644 index c2d2534..0000000 --- a/PostBuild.bat +++ /dev/null @@ -1,34 +0,0 @@ -@echo off -rem Post-build batch for StormLib project -rem Called as PostBuild.bat $(ProjectName) $(PlatformName) $(ConfigurationName) [vs2008] -rem Example: PostBuild.bat StormLib_dll x64 Debug vs2008 - -rem Select build type -if "%1" == "StormLib_dll" goto PostBuild_DLL -if "%1" == "StormLib" goto PostBuild_LIB -goto:eof - -:PostBuild_DLL - -rem Build steps for the DLL. On 32-bit Release version, increment the build number -if not "x%2" == "xWin32" goto:eof -if not "x%3" == "xRelease" goto:eof -PostBuild.exe .\src\DllMain.rc -goto:eof - -:PostBuild_LIB - -rem Set target folders -if "x%2" == "xWin32" set TARGET_DIR_LEVEL2=lib32 -if "x%2" == "xx64" set TARGET_DIR_LEVEL2=lib64 -if "x%4" == "xvs2008" set TARGET_DIR_LEVEL3=vs2008 - -rem Check & create target folder structure -if not exist ..\aaa goto:eof -if not exist ..\aaa\%TARGET_DIR_LEVEL2% md ..\aaa\%TARGET_DIR_LEVEL2% -if not exist ..\aaa\%TARGET_DIR_LEVEL2%\%TARGET_DIR_LEVEL3% md ..\aaa\%TARGET_DIR_LEVEL2%\%TARGET_DIR_LEVEL3% - -rem Copy include and LIB files to the target folder -copy /Y .\src\StormLib.h ..\aaa\inc >nul -copy /Y .\src\StormPort.h ..\aaa\inc >nul -copy /Y .\bin\%1\%2\%3\StormLib???.lib ..\aaa\%TARGET_DIR_LEVEL2%\%TARGET_DIR_LEVEL3% >nul diff --git a/StormLib_vs08.vcproj b/StormLib_vs08.vcproj index 0c02e13..4f59a1b 100644 --- a/StormLib_vs08.vcproj +++ b/StormLib_vs08.vcproj @@ -80,7 +80,7 @@ /> diff --git a/StormLib_vs19.vcxproj b/StormLib_vs19.vcxproj index e0c83f9..eba3ea2 100644 --- a/StormLib_vs19.vcxproj +++ b/StormLib_vs19.vcxproj @@ -269,12 +269,14 @@ Level1 ProgramDatabase + true ./bin/$(ProjectName)/$(Platform)/$(Configuration)/$(TargetName).lib - PostBuild.bat $(ProjectName) $(Platform) $(Configuration) + + @@ -289,12 +291,14 @@ Level1 ProgramDatabase + true ./bin/$(ProjectName)/$(Platform)/$(Configuration)/$(TargetName).lib - PostBuild.bat $(ProjectName) $(Platform) $(Configuration) + + @@ -306,12 +310,14 @@ Level1 ProgramDatabase + true ./bin/$(ProjectName)/$(Platform)/$(Configuration)/$(TargetName).lib - PostBuild.bat $(ProjectName) $(Platform) $(Configuration) + + @@ -326,12 +332,14 @@ Level1 ProgramDatabase + true ./bin/$(ProjectName)/$(Platform)/$(Configuration)/$(TargetName).lib - PostBuild.bat $(ProjectName) $(Platform) $(Configuration) + + @@ -342,12 +350,14 @@ Level1 ProgramDatabase + true ./bin/$(ProjectName)/$(Platform)/$(Configuration)/$(TargetName).lib - PostBuild.bat $(ProjectName) $(Platform) $(Configuration) + + @@ -361,12 +371,14 @@ Level1 ProgramDatabase + true ./bin/$(ProjectName)/$(Platform)/$(Configuration)/$(TargetName).lib - PostBuild.bat $(ProjectName) $(Platform) $(Configuration) + + @@ -377,12 +389,14 @@ Level1 ProgramDatabase + true ./bin/$(ProjectName)/$(Platform)/$(Configuration)/$(TargetName).lib - PostBuild.bat $(ProjectName) $(Platform) $(Configuration) + + @@ -396,12 +410,14 @@ Level1 ProgramDatabase + true ./bin/$(ProjectName)/$(Platform)/$(Configuration)/$(TargetName).lib - PostBuild.bat $(ProjectName) $(Platform) $(Configuration) + + @@ -413,12 +429,14 @@ Level1 ProgramDatabase + true ./bin/$(ProjectName)/$(Platform)/$(Configuration)/$(TargetName).lib - PostBuild.bat $(ProjectName) $(Platform) $(Configuration) + + @@ -433,12 +451,14 @@ Level1 ProgramDatabase + true ./bin/$(ProjectName)/$(Platform)/$(Configuration)/$(TargetName).lib - PostBuild.bat $(ProjectName) $(Platform) $(Configuration) + + @@ -450,12 +470,14 @@ Level1 ProgramDatabase + true ./bin/$(ProjectName)/$(Platform)/$(Configuration)/$(TargetName).lib - PostBuild.bat $(ProjectName) $(Platform) $(Configuration) + + @@ -470,12 +492,14 @@ Level1 ProgramDatabase + true ./bin/$(ProjectName)/$(Platform)/$(Configuration)/$(TargetName).lib - PostBuild.bat $(ProjectName) $(Platform) $(Configuration) + + @@ -486,12 +510,14 @@ Level1 ProgramDatabase + true ./bin/$(ProjectName)/$(Platform)/$(Configuration)/$(TargetName).lib - PostBuild.bat $(ProjectName) $(Platform) $(Configuration) + + @@ -505,12 +531,14 @@ Level1 ProgramDatabase + true ./bin/$(ProjectName)/$(Platform)/$(Configuration)/$(TargetName).lib - PostBuild.bat $(ProjectName) $(Platform) $(Configuration) + + @@ -521,12 +549,14 @@ Level1 ProgramDatabase + true ./bin/$(ProjectName)/$(Platform)/$(Configuration)/$(TargetName).lib - PostBuild.bat $(ProjectName) $(Platform) $(Configuration) + + @@ -540,12 +570,14 @@ Level1 ProgramDatabase + true ./bin/$(ProjectName)/$(Platform)/$(Configuration)/$(TargetName).lib - PostBuild.bat $(ProjectName) $(Platform) $(Configuration) + + diff --git a/StormLib_vs19_dll.vcxproj b/StormLib_vs19_dll.vcxproj index 1dbbce8..ba888e9 100644 --- a/StormLib_vs19_dll.vcxproj +++ b/StormLib_vs19_dll.vcxproj @@ -100,6 +100,7 @@ Level1 ProgramDatabase + true $(OutDir)StormLib.dll @@ -123,6 +124,7 @@ Level1 ProgramDatabase + true $(OutDir)StormLib.dll @@ -141,6 +143,7 @@ Level1 ProgramDatabase + true $(OutDir)StormLib.dll @@ -164,6 +167,7 @@ Level1 ProgramDatabase + true $(OutDir)StormLib.dll diff --git a/StormLib_vs19_test.vcxproj b/StormLib_vs19_test.vcxproj index 9f91ade..d293549 100644 --- a/StormLib_vs19_test.vcxproj +++ b/StormLib_vs19_test.vcxproj @@ -98,6 +98,7 @@ Level1 EditAndContinue Default + true true @@ -121,6 +122,7 @@ Level1 ProgramDatabase Default + true true @@ -138,6 +140,7 @@ Level1 ProgramDatabase + true true @@ -160,6 +163,7 @@ Level1 ProgramDatabase + true true diff --git a/make-msvc.bat b/make-msvc.bat index 8b9a559..d8097d1 100644 --- a/make-msvc.bat +++ b/make-msvc.bat @@ -21,8 +21,8 @@ if exist "%PROGRAM_FILES_DIR%\Microsoft Visual Studio\2019\Professional\VC\Auxil if exist "%PROGRAM_FILES_DIR%\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" set VCVARS_2019=%PROGRAM_FILES_DIR%\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvarsall.bat ::Build all libraries using Visual Studio 2008 and 2017 -call :BuildLibs "%VCVARS_2008%" x86 %LIB_NAME%_vs08.sln -call :BuildLibs "%VCVARS_2008%" x64 %LIB_NAME%_vs08.sln +call :BuildLibs "%VCVARS_2008%" x86 %LIB_NAME%_vs08.sln \vs2008 +call :BuildLibs "%VCVARS_2008%" x64 %LIB_NAME%_vs08.sln \vs2008 call :BuildLibs "%VCVARS_2019%" x86 %LIB_NAME%_vs19.sln call :BuildLibs "%VCVARS_2019%" x64 %LIB_NAME%_vs19.sln goto:eof @@ -35,21 +35,31 @@ goto:eof :: %1 Full path to the VCVARS.BAT file :: %2 Target build platform (x86 or x64) :: %3 Plain name of the /sln solution file +:: %4 Subdirectory for the target folder of the library ("\vs2008" or "") :: :BuildLibs -::set VSCMD_DEBUG=1 call %1 %2 if "%2" == "x86" set SLN_TRG=Win32 +if "%2" == "x86" set LIB_TRG=lib32 if "%2" == "x64" set SLN_TRG=x64 -devenv.com %3 /project "%LIB_NAME%" /build "DebugAD|%SLN_TRG%" -devenv.com %3 /project "%LIB_NAME%" /build "DebugAS|%SLN_TRG%" -devenv.com %3 /project "%LIB_NAME%" /build "DebugUD|%SLN_TRG%" -devenv.com %3 /project "%LIB_NAME%" /build "DebugUS|%SLN_TRG%" -devenv.com %3 /project "%LIB_NAME%" /build "ReleaseAD|%SLN_TRG%" -devenv.com %3 /project "%LIB_NAME%" /build "ReleaseAS|%SLN_TRG%" -devenv.com %3 /project "%LIB_NAME%" /build "ReleaseUD|%SLN_TRG%" -devenv.com %3 /project "%LIB_NAME%" /build "ReleaseUS|%SLN_TRG%" +if "%2" == "x64" set LIB_TRG=lib64 +devenv.com %3 /project "%LIB_NAME%" /rebuild "DebugAD|%SLN_TRG%" +xcopy.exe /Y /D .\bin\StormLib\%SLN_TRG%\DebugAD\*.lib ..\aaa\%LIB_TRG%%4 +devenv.com %3 /project "%LIB_NAME%" /rebuild "DebugAS|%SLN_TRG%" +xcopy.exe /Y /D .\bin\StormLib\%SLN_TRG%\DebugAS\*.lib ..\aaa\%LIB_TRG%%4 +devenv.com %3 /project "%LIB_NAME%" /rebuild "DebugUD|%SLN_TRG%" +xcopy.exe /Y /D .\bin\StormLib\%SLN_TRG%\DebugUD\*.lib ..\aaa\%LIB_TRG%%4 +devenv.com %3 /project "%LIB_NAME%" /rebuild "DebugUS|%SLN_TRG%" +xcopy.exe /Y /D .\bin\StormLib\%SLN_TRG%\DebugUS\*.lib ..\aaa\%LIB_TRG%%4 +devenv.com %3 /project "%LIB_NAME%" /rebuild "ReleaseAD|%SLN_TRG%" +xcopy.exe /Y /D .\bin\StormLib\%SLN_TRG%\ReleaseAD\*.lib ..\aaa\%LIB_TRG%%4 +devenv.com %3 /project "%LIB_NAME%" /rebuild "ReleaseAS|%SLN_TRG%" +xcopy.exe /Y /D .\bin\StormLib\%SLN_TRG%\ReleaseAS\*.lib ..\aaa\%LIB_TRG%%4 +devenv.com %3 /project "%LIB_NAME%" /rebuild "ReleaseUD|%SLN_TRG%" +xcopy.exe /Y /D .\bin\StormLib\%SLN_TRG%\ReleaseUD\*.lib ..\aaa\%LIB_TRG%%4 +devenv.com %3 /project "%LIB_NAME%" /rebuild "ReleaseUS|%SLN_TRG%" +xcopy.exe /Y /D .\bin\StormLib\%SLN_TRG%\ReleaseUS\*.lib ..\aaa\%LIB_TRG%%4 :: Restore environment variables to the old level set INCLUDE=%SAVE_INCLUDE% @@ -58,3 +68,4 @@ set PATH=%SAVE_PATH% set VSINSTALLDIR= set VCINSTALLDIR= set DevEnvDir= +goto:eof diff --git a/make.bat b/make.bat index 8765eb5..7b29207 100644 --- a/make.bat +++ b/make.bat @@ -35,10 +35,10 @@ del buildfre_wlh_amd64.log echo. :COPY_LIBS -copy /Y .\objfre_wlh_amd64\amd64\%LIBRARY_NAME%.lib ..\aaa\lib64\%LIBRARY_NAME%.lib >nul -copy /Y .\objfre_w2k_x86\i386\%LIBRARY_NAME%.lib ..\aaa\lib32\%LIBRARY_NAME%.lib >nul -copy /Y .\src\StormPort.h ..\aaa\inc >nul -copy /Y .\src\StormLib.h ..\aaa\inc >nul +xcopy /Y /D .\src\StormLib.h ..\aaa\inc >nul +xcopy /Y /D .\src\StormPort.h ..\aaa\inc >nul +xcopy /Y /D .\objfre_w2k_x86\i386\%LIBRARY_NAME%.lib ..\aaa\lib32\%LIBRARY_NAME%.lib >nul +xcopy /Y /D .\objfre_wlh_amd64\amd64\%LIBRARY_NAME%.lib ..\aaa\lib64\%LIBRARY_NAME%.lib >nul :CLEANUP if exist sources-cpp.cpp del sources-cpp.cpp diff --git a/test/StormTest.cpp b/test/StormTest.cpp index 3d783aa..13b0ace 100644 --- a/test/StormTest.cpp +++ b/test/StormTest.cpp @@ -4327,56 +4327,49 @@ int _tmain(int argc, TCHAR * argv[]) // Open all files from the command line // -<<<<<<< HEAD for(int i = 1; i < argc; i++) { TestArchive(_T("MPQ_2021_v1_CantExtractCHK.scx"), _T("Listfile_Blizzard.txt"), 0, NULL, NULL); } -======= - //for(int i = 1; i < argc; i++) - //{ - // TestArchive(_T("MPQ_2021_v1_CantExtractCHK.scx"), _T("Listfile_Blizzard.txt"), TEST_FLAG_FILE_COUNT, NULL, NULL); - //} ->>>>>>> 1a94f94 (Support for protected SCX files) // // Search all testing archives and verify their SHA1 hash // - //if(dwErrCode == ERROR_SUCCESS) - //{ - // dwErrCode = FindFiles(ForEachFile_VerifyFileChecksum, szMpqSubDir); - //} + if(dwErrCode == ERROR_SUCCESS) + { + dwErrCode = FindFiles(ForEachFile_VerifyFileChecksum, szMpqSubDir); + } // // Test file stream operations // - //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; - // } - //} + 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; + } + } // // Test master-mirror reading operations // - //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) + { + 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; + } + } // // Test opening various archives - correct, damaged, protected diff --git a/test/TLogHelper.cpp b/test/TLogHelper.cpp index f277e64..3d09823 100644 --- a/test/TLogHelper.cpp +++ b/test/TLogHelper.cpp @@ -423,7 +423,7 @@ char * TLogHelper::CopyFormatCharacter(char * szBuffer, const char *& szFormat) // String format if(szFormat[0] == '%') { - if(szFormat[1] == 's') + if(szFormat[1] == 's' && szFormat[2] != ')') { strcpy(szBuffer, szStringFormat); szFormat += 2; -- cgit v1.2.3 From f0a2aaa7e2a407b0661da55460833e1190a99207 Mon Sep 17 00:00:00 2001 From: Ladislav Zezula Date: Sat, 18 Dec 2021 07:18:51 +0100 Subject: Bug fixes --- make-msvc.bat | 22 +++++++++++----------- test/StormTest.cpp | 2 +- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/make-msvc.bat b/make-msvc.bat index 007254e..099fc19 100644 --- a/make-msvc.bat +++ b/make-msvc.bat @@ -43,34 +43,34 @@ call %1 %2 if "%2" == "x86" set SLN_TRG=Win32 if "%2" == "x86" set LIB_TRG=lib32 if "%2" == "x64" set SLN_TRG=x64 -<<<<<<< HEAD if "%2" == "x64" set LIB_TRG=lib64 + +xcopy.exe /Y /D .\src\StormLib.h ..\aaa\inc +xcopy.exe /Y /D .\src\StormPort.h ..\aaa\inc + devenv.com %3 /project "%LIB_NAME%" /rebuild "DebugAD|%SLN_TRG%" xcopy.exe /Y /D .\bin\StormLib\%SLN_TRG%\DebugAD\*.lib ..\aaa\%LIB_TRG%%4 + devenv.com %3 /project "%LIB_NAME%" /rebuild "DebugAS|%SLN_TRG%" xcopy.exe /Y /D .\bin\StormLib\%SLN_TRG%\DebugAS\*.lib ..\aaa\%LIB_TRG%%4 + devenv.com %3 /project "%LIB_NAME%" /rebuild "DebugUD|%SLN_TRG%" xcopy.exe /Y /D .\bin\StormLib\%SLN_TRG%\DebugUD\*.lib ..\aaa\%LIB_TRG%%4 + devenv.com %3 /project "%LIB_NAME%" /rebuild "DebugUS|%SLN_TRG%" xcopy.exe /Y /D .\bin\StormLib\%SLN_TRG%\DebugUS\*.lib ..\aaa\%LIB_TRG%%4 + devenv.com %3 /project "%LIB_NAME%" /rebuild "ReleaseAD|%SLN_TRG%" xcopy.exe /Y /D .\bin\StormLib\%SLN_TRG%\ReleaseAD\*.lib ..\aaa\%LIB_TRG%%4 + devenv.com %3 /project "%LIB_NAME%" /rebuild "ReleaseAS|%SLN_TRG%" xcopy.exe /Y /D .\bin\StormLib\%SLN_TRG%\ReleaseAS\*.lib ..\aaa\%LIB_TRG%%4 + devenv.com %3 /project "%LIB_NAME%" /rebuild "ReleaseUD|%SLN_TRG%" xcopy.exe /Y /D .\bin\StormLib\%SLN_TRG%\ReleaseUD\*.lib ..\aaa\%LIB_TRG%%4 + devenv.com %3 /project "%LIB_NAME%" /rebuild "ReleaseUS|%SLN_TRG%" xcopy.exe /Y /D .\bin\StormLib\%SLN_TRG%\ReleaseUS\*.lib ..\aaa\%LIB_TRG%%4 -======= -devenv.com %3 /project "%LIB_NAME%" /build "DebugAD|%SLN_TRG%" -devenv.com %3 /project "%LIB_NAME%" /build "DebugAS|%SLN_TRG%" -devenv.com %3 /project "%LIB_NAME%" /build "DebugUD|%SLN_TRG%" -devenv.com %3 /project "%LIB_NAME%" /build "DebugUS|%SLN_TRG%" -devenv.com %3 /project "%LIB_NAME%" /build "ReleaseAD|%SLN_TRG%" -devenv.com %3 /project "%LIB_NAME%" /build "ReleaseAS|%SLN_TRG%" -devenv.com %3 /project "%LIB_NAME%" /build "ReleaseUD|%SLN_TRG%" -devenv.com %3 /project "%LIB_NAME%" /build "ReleaseUS|%SLN_TRG%" ->>>>>>> 1a94f94b50f6d829b1e8fba08a3002a5db4f00d5 :: Restore environment variables to the old level set INCLUDE=%SAVE_INCLUDE% diff --git a/test/StormTest.cpp b/test/StormTest.cpp index 1f8a334..4342e10 100644 --- a/test/StormTest.cpp +++ b/test/StormTest.cpp @@ -2646,7 +2646,7 @@ static DWORD TestOpenArchive_Corrupt(LPCTSTR szPlainName) // Opens a patched MPQ archive static DWORD TestArchive_Patched(LPCTSTR PatchList[], LPCSTR szPatchedFile, DWORD dwFlags) { - TLogHelper Logger("OpenPatchedMpqTest", PatchList[0]); + TLogHelper Logger("PatchedMPQ", PatchList[0]); HANDLE hMpq; HANDLE hFile; BYTE Buffer[0x100]; -- cgit v1.2.3 From e7af34bcfb5cba3c1ff6ac1b2ebd8c4ba47f1df4 Mon Sep 17 00:00:00 2001 From: Ladislav Zezula Date: Sat, 18 Dec 2021 07:23:40 +0100 Subject: Cosmetics --- src/SFileOpenArchive.cpp | 1 - test/TLogHelper.cpp | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/SFileOpenArchive.cpp b/src/SFileOpenArchive.cpp index dcc7e18..52e1a39 100644 --- a/src/SFileOpenArchive.cpp +++ b/src/SFileOpenArchive.cpp @@ -18,7 +18,6 @@ #include "StormCommon.h" #define HEADER_SEARCH_BUFFER_SIZE 0x1000 -#define MINIMUM_MPQ_SIZE 0x0C //----------------------------------------------------------------------------- // Local functions diff --git a/test/TLogHelper.cpp b/test/TLogHelper.cpp index 7129b63..3a82368 100644 --- a/test/TLogHelper.cpp +++ b/test/TLogHelper.cpp @@ -120,7 +120,7 @@ TLogHelper::~TLogHelper() #if defined(_MSC_VER) && defined(_DEBUG) if(_CrtDumpMemoryLeaks()) { - PrintMessage(_T("Memory leak(s) detected after.\n")); + PrintMessage(_T("Memory leak(s) detected.\n")); } #endif // _MSC_VER } -- cgit v1.2.3