diff options
author | Ladislav Zezula <ladislav.zezula@avast.com> | 2023-01-25 21:49:35 +0100 |
---|---|---|
committer | Ladislav Zezula <ladislav.zezula@avast.com> | 2023-01-25 21:49:35 +0100 |
commit | 50f811e59056488ebf153b86ea8cba1d339246e4 (patch) | |
tree | 814a96fad4402c93530b1bcad66e1b1af839d60e | |
parent | 67d66b45100c0f193b6211f9474f5ad6469b1a94 (diff) |
Refactoring regression tests
-rw-r--r-- | src/StormCommon.h | 5 | ||||
-rw-r--r-- | test/StormTest.cpp | 1321 | ||||
-rw-r--r-- | test/stormlib-test-001.txt | 42 |
3 files changed, 623 insertions, 745 deletions
diff --git a/src/StormCommon.h b/src/StormCommon.h index 48fd86f..39f7524 100644 --- a/src/StormCommon.h +++ b/src/StormCommon.h @@ -73,6 +73,11 @@ // Macro for building 64-bit file offset from two 32-bit
#define MAKE_OFFSET64(hi, lo) (((ULONGLONG)hi << 32) | (ULONGLONG)lo)
+// Macro for checking a valid, non-empty ASCIIZ string
+#ifndef IS_VALID_STRING
+#define IS_VALID_STRING(str) (str && str[0])
+#endif
+
//-----------------------------------------------------------------------------
// MTYPE definition - specifies what kind of MPQ is the map type
diff --git a/test/StormTest.cpp b/test/StormTest.cpp index 688b653..46f8637 100644 --- a/test/StormTest.cpp +++ b/test/StormTest.cpp @@ -36,16 +36,44 @@ //------------------------------------------------------------------------------
// Local structures
-#define TFLG_COUNT_HASH 0x01000000 // There is file count in the lower 24-bits, then hash
-#define TFLG_FILE_LOCALE 0x02000000 // The process is expected to fail
#define TFLG_WILL_FAIL 0x04000000 // The process is expected to fail
#define TFLG_VALUE_MASK 0x00FFFFFF // Mask for integer value
-#define TEST_DATA(hash, num) (num | TFLG_COUNT_HASH), hash
#define ERROR_UNDETERMINED_RESULT 0xC000FFFF
typedef DWORD(*FIND_FILE_CALLBACK)(LPCTSTR szFullPath);
+typedef enum _EXTRA_TYPE
+{
+ NoExtraType = 0,
+ TwoFiles,
+ PatchList,
+} EXTRA_TYPE, *PEXTRA_TYPE;
+
+typedef struct _FILE_DATA
+{
+ DWORD dwBlockIndex;
+ DWORD dwFileSize;
+ DWORD dwFlags;
+ DWORD dwCrc32;
+ BYTE FileData[1];
+} FILE_DATA, *PFILE_DATA;
+
+typedef struct _TEST_EXTRA_TWOFILES
+{
+ EXTRA_TYPE Type; // Must be TwoFiles
+ LPCSTR szFile1; // The first referenced file name
+ LPCSTR szFile2; // The second referenced file name
+} TEST_EXTRA_TWOFILES, *PTEST_EXTRA_TWOFILES;
+
+typedef struct _TEST_EXTRA_PATCHES
+{
+ EXTRA_TYPE Type; // Must be PatchList
+ LPCTSTR szPatchList; // Multi-SZ list of patches
+ LPCSTR szFileName; // Example of patched file
+ DWORD dwPatchCount; // Number of patches
+} TEST_EXTRA_PATCHES, *PTEST_EXTRA_PATCHES;
+
typedef struct _TEST_INFO
{
LPCTSTR szMpqName1;
@@ -55,6 +83,15 @@ typedef struct _TEST_INFO const void * param2;
} TEST_INFO, *PTEST_INFO;
+typedef struct _TEST_INFO2
+{
+ LPCTSTR szName1; // MPQ name
+ LPCTSTR szName2; // ListFile name or NULL if none
+ LPCSTR szDataHash; // Compound name+data hash
+ DWORD dwFlags; // Flags for testing the file. Low 16 bits contains number of files
+ const void * pExtra;
+} TEST_INFO2, *PTEST_INFO2;
+
typedef struct _LINE_INFO
{
LONG nLinePos;
@@ -110,6 +147,11 @@ static LPCSTR IntToHexChar = "0123456789abcdef"; #define MFLAG_OPEN_READ_WRITE 0x00000004 // Open the file as read-write
#define MFLAG_GET_FILE_INFO 0x00000008 // Get the file info
+// Flags for TestOpenArchive_AddFile()
+#define TFLAG_REOPEN 0x00000001 // Reopen the archive
+#define TFLAG_HAS_LISTFILE 0x00000002 // The archive must have (listfile) after reopen
+#define TFLAG_HAS_ATTRIBUTES 0x00000004 // The archive must have (attributes) after reopen
+
static DWORD AddFlags[] =
{
// Compression Encryption Fixed key Single Unit Sector CRC
@@ -179,140 +221,6 @@ static SFILE_MARKERS MpqMarkers[] = {sizeof(SFILE_MARKERS), 'XHSC', "(cash table)", "(clock table)"}
};
-static LPCTSTR PatchList_StarCraft[] =
-{
- _T("MPQ_1998_v1_StarCraft.mpq"),
- _T("s1-1998-BroodWar.mpq"),
- NULL
-};
-
-static LPCTSTR PatchList_WoW_OldWorld13286[] =
-{
- _T("MPQ_2012_v4_OldWorld.MPQ"),
- _T("wow-update-oldworld-13154.MPQ"),
- _T("wow-update-oldworld-13286.MPQ"),
- NULL
-};
-
-static LPCTSTR PatchList_WoW_15050[] =
-{
- _T("MPQ_2013_v4_world.MPQ"),
- _T("wow-update-13164.MPQ"),
- _T("wow-update-13205.MPQ"),
- _T("wow-update-13287.MPQ"),
- _T("wow-update-13329.MPQ"),
- _T("wow-update-13596.MPQ"),
- _T("wow-update-13623.MPQ"),
- _T("wow-update-base-13914.MPQ"),
- _T("wow-update-base-14007.MPQ"),
- _T("wow-update-base-14333.MPQ"),
- _T("wow-update-base-14480.MPQ"),
- _T("wow-update-base-14545.MPQ"),
- _T("wow-update-base-14946.MPQ"),
- _T("wow-update-base-15005.MPQ"),
- _T("wow-update-base-15050.MPQ"),
- NULL
-};
-
-static LPCTSTR PatchList_WoW_16965[] =
-{
- _T("MPQ_2013_v4_locale-enGB.MPQ"),
- _T("wow-update-enGB-16016.MPQ"),
- _T("wow-update-enGB-16048.MPQ"),
- _T("wow-update-enGB-16057.MPQ"),
- _T("wow-update-enGB-16309.MPQ"),
- _T("wow-update-enGB-16357.MPQ"),
- _T("wow-update-enGB-16516.MPQ"),
- _T("wow-update-enGB-16650.MPQ"),
- _T("wow-update-enGB-16844.MPQ"),
- _T("wow-update-enGB-16965.MPQ"),
- NULL
-};
-
-static LPCTSTR PatchList_SC2_32283[] =
-{
- _T("MPQ_2013_v4_Base1.SC2Data"),
- _T("s2-update-base-23258.MPQ"),
- _T("s2-update-base-24540.MPQ"),
- _T("s2-update-base-26147.MPQ"),
- _T("s2-update-base-28522.MPQ"),
- _T("s2-update-base-30508.MPQ"),
- _T("s2-update-base-32283.MPQ"),
- NULL
-};
-
-static LPCTSTR PatchList_SC2_34644[] =
-{
- _T("MPQ_2013_v4_Base1.SC2Data"),
- _T("s2-update-base-23258.MPQ"),
- _T("s2-update-base-24540.MPQ"),
- _T("s2-update-base-26147.MPQ"),
- _T("s2-update-base-28522.MPQ"),
- _T("s2-update-base-32384.MPQ"),
- _T("s2-update-base-34644.MPQ"),
- NULL
-};
-
-static LPCTSTR PatchList_SC2_34644_Maps[] =
-{
- _T("MPQ_2013_v4_Base3.SC2Maps"),
- _T("s2-update-base-23258.MPQ"),
- _T("s2-update-base-24540.MPQ"),
- _T("s2-update-base-26147.MPQ"),
- _T("s2-update-base-28522.MPQ"),
- _T("s2-update-base-32384.MPQ"),
- _T("s2-update-base-34644.MPQ"),
- NULL
-};
-
-static LPCTSTR PatchList_SC2_32283_enGB[] =
-{
- _T("MPQ_2013_v4_Mods#Core.SC2Mod#enGB.SC2Assets"),
- _T("s2-update-enGB-23258.MPQ"),
- _T("s2-update-enGB-24540.MPQ"),
- _T("s2-update-enGB-26147.MPQ"),
- _T("s2-update-enGB-28522.MPQ"),
- _T("s2-update-enGB-30508.MPQ"),
- _T("s2-update-enGB-32283.MPQ"),
- NULL
-};
-
-static LPCTSTR PatchList_SC2_36281_enGB[] =
-{
- _T("MPQ_2013_v4_Mods#Liberty.SC2Mod#enGB.SC2Data"),
- _T("s2-update-enGB-23258.MPQ"),
- _T("s2-update-enGB-24540.MPQ"),
- _T("s2-update-enGB-26147.MPQ"),
- _T("s2-update-enGB-28522.MPQ"),
- _T("s2-update-enGB-32384.MPQ"),
- _T("s2-update-enGB-34644.MPQ"),
- _T("s2-update-enGB-36281.MPQ"),
- NULL
-};
-
-static LPCTSTR PatchList_HS_3604_enGB[] =
-{
- _T("MPQ_2014_v4_base-Win.MPQ"),
- _T("hs-0-3604-Win-final.MPQ"),
- NULL
-};
-
-static LPCTSTR PatchList_HS_6898_enGB[] =
-{
- _T("MPQ_2014_v4_base-Win.MPQ"),
- _T("hs-0-5314-Win-final.MPQ"),
- _T("hs-5314-5435-Win-final.MPQ"),
- _T("hs-5435-5506-Win-final.MPQ"),
- _T("hs-5506-5834-Win-final.MPQ"),
- _T("hs-5834-6024-Win-final.MPQ"),
- _T("hs-6024-6141-Win-final.MPQ"),
- _T("hs-6141-6187-Win-final.MPQ"),
- _T("hs-6187-6284-Win-final.MPQ"),
- _T("hs-6284-6485-Win-final.MPQ"),
- _T("hs-6485-6898-Win-final.MPQ"),
- NULL
-};
-
//-----------------------------------------------------------------------------
// Local file functions
@@ -330,6 +238,18 @@ static const TCHAR PATH_SEPARATOR = '/'; // Path separator for Non-Wi static TCHAR szMpqDirectory[MAX_PATH+1];
size_t cchMpqDirectory = 0;
+static EXTRA_TYPE GetExtraType(const void * pExtra)
+{
+ if(pExtra != NULL)
+ {
+ return *(PEXTRA_TYPE)(pExtra);
+ }
+ else
+ {
+ return NoExtraType;
+ }
+}
+
template <typename XCHAR>
static bool IsFullPath(const XCHAR * szFileName)
{
@@ -418,6 +338,28 @@ static bool CompareBlocks(LPBYTE pbBlock1, LPBYTE pbBlock2, DWORD dwLength, DWOR return true;
}
+static DWORD CompareTwoFiles(TLogHelper & Logger, PFILE_DATA pFileData1, PFILE_DATA pFileData2)
+{
+ DWORD dwDifference = 0;
+
+ // Compare the file sizes
+ if(pFileData1->dwFileSize != pFileData2->dwFileSize)
+ {
+ Logger.PrintMessage("File size mismatch: %u vs %u", pFileData1->dwFileSize, pFileData2->dwFileSize);
+ return ERROR_FILE_CORRUPT;
+ }
+
+ // Compare the file data
+ if(memcmp(pFileData1->FileData, pFileData2->FileData, pFileData1->dwFileSize))
+ {
+ CompareBlocks(pFileData1->FileData, pFileData2->FileData, pFileData1->dwFileSize, &dwDifference);
+ Logger.PrintMessage("File data mismatch at offset %08x", dwDifference);
+ return ERROR_FILE_CORRUPT;
+ }
+
+ return ERROR_SUCCESS;
+}
+
template <typename XCHAR>
static const XCHAR * FindNextPathPart(const XCHAR * szPath, size_t nPartCount)
{
@@ -1282,25 +1224,15 @@ static void WINAPI CompactCallback(void * pvUserData, DWORD dwWork, ULONGLONG By #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
-{
- DWORD dwBlockIndex;
- DWORD dwFileSize;
- DWORD dwFlags;
- DWORD dwCrc32;
- BYTE FileData[1];
-};
+#define SEARCH_FLAG_IGNORE_ERRORS 0x00000008 // Ignore files that failed to open
-static bool CheckIfFileIsPresent(TLogHelper * pLogger, HANDLE hMpq, LPCSTR szFileName, bool bShouldExist)
+static bool CheckIfFileIsPresent(TLogHelper * pLogger, HANDLE hMpq, LPCSTR szFileName, DWORD bShouldExist)
{
HANDLE hFile = NULL;
if(SFileOpenFileEx(hMpq, szFileName, 0, &hFile))
{
- if(bShouldExist == false)
+ if(!bShouldExist)
pLogger->PrintMessage("The file \"%s\" is present, but it should not be", szFileName);
SFileCloseFile(hFile);
return true;
@@ -1313,10 +1245,10 @@ static bool CheckIfFileIsPresent(TLogHelper * pLogger, HANDLE hMpq, LPCSTR szFil }
}
-static TFileData * LoadLocalFile(TLogHelper * pLogger, LPCTSTR szFileName, bool bMustSucceed)
+static PFILE_DATA LoadLocalFile(TLogHelper * pLogger, LPCTSTR szFileName, bool bMustSucceed)
{
TFileStream * pStream;
- TFileData * pFileData = NULL;
+ PFILE_DATA pFileData = NULL;
ULONGLONG FileSize = 0;
size_t nAllocateBytes;
@@ -1338,8 +1270,8 @@ static TFileData * LoadLocalFile(TLogHelper * pLogger, LPCTSTR szFileName, bool if((FileSize >> 0x20) == 0)
{
// Allocate space for the file
- nAllocateBytes = sizeof(TFileData) + (size_t)FileSize;
- pFileData = (TFileData *)STORM_ALLOC(BYTE, nAllocateBytes);
+ nAllocateBytes = sizeof(FILE_DATA) + (size_t)FileSize;
+ pFileData = (PFILE_DATA)STORM_ALLOC(BYTE, nAllocateBytes);
if(pFileData != NULL)
{
// Make sure it;s properly zeroed
@@ -1361,7 +1293,7 @@ static TFileData * LoadLocalFile(TLogHelper * pLogger, LPCTSTR szFileName, bool static DWORD LoadLocalFileMD5(TLogHelper * pLogger, LPCTSTR szFileFullName, LPBYTE md5_file_local)
{
- TFileData * pFileData;
+ PFILE_DATA pFileData;
// Load the local file to memory
if((pFileData = LoadLocalFile(pLogger, szFileFullName, true)) == NULL)
@@ -1375,9 +1307,9 @@ static DWORD LoadLocalFileMD5(TLogHelper * pLogger, LPCTSTR szFileFullName, LPBY return ERROR_SUCCESS;
}
-static TFileData * LoadMpqFile(TLogHelper * pLogger, HANDLE hMpq, LPCSTR szFileName, LCID lcFileLocale = 0, bool bIgnoreOpedwErrCodes = false)
+static DWORD LoadMpqFile(TLogHelper & Logger, HANDLE hMpq, LPCSTR szFileName, LCID lcFileLocale, DWORD dwSearchFlags, PFILE_DATA * ppFileData)
{
- TFileData * pFileData = NULL;
+ PFILE_DATA pFileData = NULL;
HANDLE hFile;
DWORD dwFileSizeHi = 0xCCCCCCCC;
DWORD dwFileSizeLo = 0;
@@ -1385,12 +1317,12 @@ static TFileData * LoadMpqFile(TLogHelper * pLogger, HANDLE hMpq, LPCSTR szFileN DWORD dwCrc32 = 0;
DWORD dwErrCode = ERROR_SUCCESS;
- // Notify the user that we are loading a file from MPQ
- pLogger->PrintProgress("Loading file %s ...", GetShortPlainName(szFileName));
+ // Do nothing if the file name is invalid
+ Logger.PrintProgress("Loading file %s ...", GetShortPlainName(szFileName));
#if defined(_MSC_VER) && defined(_DEBUG)
-// if(!_stricmp(szFileName, "File00000687.xxx"))
-// __debugbreak();
+ // if(!_stricmp(szFileName, "File00000687.xxx"))
+ // __debugbreak();
#endif
// Make sure that we open the proper locale file
@@ -1407,7 +1339,7 @@ static TFileData * LoadMpqFile(TLogHelper * pLogger, HANDLE hMpq, LPCSTR szFileN {
dwFileSizeLo = SFileGetFileSize(hFile, &dwFileSizeHi);
if(dwFileSizeLo == SFILE_INVALID_SIZE || dwFileSizeHi != 0)
- dwErrCode = pLogger->PrintError("Failed to query the file size");
+ dwErrCode = Logger.PrintError("Failed to query the file size");
}
// Spazzler protector: Creates fake files with size of 0x7FFFE7CA
@@ -1419,76 +1351,85 @@ static TFileData * LoadMpqFile(TLogHelper * pLogger, HANDLE hMpq, LPCSTR szFileN // Allocate buffer for the file content
if(dwErrCode == ERROR_SUCCESS)
{
- pFileData = (TFileData *)STORM_ALLOC(BYTE, sizeof(TFileData) + dwFileSizeLo);
+ pFileData = (PFILE_DATA)STORM_ALLOC(BYTE, sizeof(FILE_DATA) + dwFileSizeLo);
if(pFileData == NULL)
{
- pLogger->PrintError("Failed to allocate buffer for the file content");
+ Logger.PrintError("Failed to allocate buffer for the file content");
dwErrCode = ERROR_NOT_ENOUGH_MEMORY;
}
}
- // get the file index of the MPQ file
+ // Get the file index of the MPQ file
if(dwErrCode == ERROR_SUCCESS)
{
// Store the file size
- memset(pFileData, 0, sizeof(TFileData) + dwFileSizeLo);
+ memset(pFileData, 0, sizeof(FILE_DATA) + 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);
+ dwErrCode = Logger.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);
+ dwErrCode = Logger.PrintError("Failed retrieve the file flags of %s", szFileName);
}
// Load the entire file
if(dwErrCode == ERROR_SUCCESS)
{
- //if(!_stricmp(szFileName, "File00000687.xxx"))
- // __debugbreak();
-
// Read the file data
SFileReadFile(hFile, pFileData->FileData, dwFileSizeLo, &dwBytesRead, NULL);
if(dwBytesRead != dwFileSizeLo)
dwErrCode = ERROR_FILE_CORRUPT;
}
- // If failed, free the buffer
- if(dwErrCode != ERROR_SUCCESS)
+ // If succeeded, check the CRC
+ if(dwErrCode == ERROR_SUCCESS && dwCrc32 != 0 && (dwSearchFlags & SEARCH_FLAG_IGNORE_ERRORS) == 0)
{
- SetLastError(dwErrCode);
- if(pFileData != NULL)
- STORM_FREE(pFileData);
- pFileData = NULL;
+ dwCrc32 = crc32(0, (Bytef *)pFileData->FileData, (uInt)pFileData->dwFileSize);
+ if(dwCrc32 != pFileData->dwCrc32)
+ Logger.PrintMessage("Warning: CRC32 error on %s", szFileName);
}
SFileCloseFile(hFile);
}
else
{
- if(bIgnoreOpedwErrCodes == false)
+ if((dwSearchFlags & SEARCH_FLAG_IGNORE_ERRORS) == 0)
{
- dwErrCode = pLogger->PrintError("Open failed: %s", szFileName);
+ dwErrCode = Logger.PrintError("Open failed: %s", szFileName);
}
}
+ // If something failed, free the file data
+ if((dwErrCode != ERROR_SUCCESS) && (pFileData != NULL))
+ {
+ STORM_FREE(pFileData);
+ pFileData = NULL;
+ }
+
// Return what we got
- return pFileData;
+ if(ppFileData != NULL)
+ ppFileData[0] = pFileData;
+ return dwErrCode;
}
-static DWORD LoadMpqFileMD5(TLogHelper * pLogger, HANDLE hMpq, LPCSTR szArchivedName, LPBYTE md5_file_in_mpq1)
+static DWORD LoadMpqFileMD5(TLogHelper & Logger, HANDLE hMpq, LPCSTR szArchivedName, LPBYTE md5_file_in_mpq1)
{
- TFileData * pFileData;
+ PFILE_DATA pFileData = NULL;
+ DWORD dwErrCode;
// Load the MPQ to memory
- if((pFileData = LoadMpqFile(pLogger, hMpq, szArchivedName)) == NULL)
- return pLogger->PrintError("The file \"%s\" is not in the archive", szArchivedName);
+ dwErrCode = LoadMpqFile(Logger, hMpq, szArchivedName, 0, 0, &pFileData);
+ if(dwErrCode == ERROR_SUCCESS && pFileData != NULL)
+ {
+ CalculateDataBlockHash(pFileData->FileData, pFileData->dwFileSize, md5_file_in_mpq1);
+ STORM_FREE(pFileData);
+ return ERROR_SUCCESS;
+ }
- // Calculate hash
- CalculateDataBlockHash(pFileData->FileData, pFileData->dwFileSize, md5_file_in_mpq1);
- STORM_FREE(pFileData);
- return ERROR_SUCCESS;
+ Logger.PrintError("The file \"%s\" is not in the archive", szArchivedName);
+ return dwErrCode;
}
static DWORD CompareTwoLocalFilesRR(
@@ -1567,31 +1508,6 @@ static DWORD CompareTwoLocalFilesRR( return dwErrCode;
}
-static bool CompareTwoFiles(TLogHelper * pLogger, TFileData * pFileData1, TFileData * pFileData2)
-{
- // Compare the file size
- if(pFileData1->dwFileSize != pFileData2->dwFileSize)
- {
- pLogger->PrintErrorVa(_T("The files have different size (%u vs %u)"), pFileData1->dwFileSize, pFileData2->dwFileSize);
- SetLastError(ERROR_FILE_CORRUPT);
- return false;
- }
-
- // Compare the files
- for(DWORD i = 0; i < pFileData1->dwFileSize; i++)
- {
- if(pFileData1->FileData[i] != pFileData2->FileData[i])
- {
- pLogger->PrintErrorVa(_T("Files are different at offset %08X"), i);
- SetLastError(ERROR_FILE_CORRUPT);
- return false;
- }
- }
-
- // The files are identical
- return true;
-}
-
static DWORD SearchArchive(
TLogHelper * pLogger,
HANDLE hMpq,
@@ -1600,17 +1516,14 @@ static DWORD SearchArchive( LPBYTE pbFileHash = NULL)
{
SFILE_FIND_DATA sf;
- TFileData * pFileData;
+ PFILE_DATA pFileData;
HANDLE hFind;
DWORD dwFileCount = 0;
hash_state md5state;
TCHAR szListFile[MAX_PATH] = _T("");
char szMostPatched[MAX_PATH] = "";
DWORD dwErrCode = ERROR_SUCCESS;
- bool bIgnoreOpedwErrCodes = (dwSearchFlags & SEARCH_FLAG_IGNORE_ERRORS) ? true : false;
bool bFound = true;
- int nMaxPatchCount = 0;
- int nPatchCount = 0;
// Construct the full name of the listfile
CreateFullPathName(szListFile, _countof(szListFile), szListFileDir, _T("ListFile_Blizzard.txt"));
@@ -1635,25 +1548,11 @@ static DWORD SearchArchive( // Increment number of files
dwFileCount++;
- if(dwSearchFlags & SEARCH_FLAG_MOST_PATCHED)
- {
- // Load the patch count
- nPatchCount = GetFilePatchCount(pLogger, hMpq, sf.cFileName);
-
- // Check if it's greater than maximum
- if(nPatchCount > nMaxPatchCount)
- {
- strcpy(szMostPatched, sf.cFileName);
- nMaxPatchCount = nPatchCount;
- }
- }
-
// Load the file to memory, if required
if(dwSearchFlags & SEARCH_FLAG_LOAD_FILES)
{
// Load the entire file to the MPQ
- pFileData = LoadMpqFile(pLogger, hMpq, sf.cFileName, sf.lcLocale, bIgnoreOpedwErrCodes);
- if(pFileData != NULL)
+ if(LoadMpqFile(*pLogger, hMpq, sf.cFileName, sf.lcLocale, dwSearchFlags, &pFileData) == ERROR_SUCCESS && pFileData != NULL)
{
// Hash the file data, if needed
if((dwSearchFlags & SEARCH_FLAG_HASH_FILES) && !IsInternalMpqFileName(sf.cFileName))
@@ -1692,6 +1591,44 @@ static DWORD SearchArchive( return dwErrCode;
}
+static DWORD VerifyDataChecksum(TLogHelper & Logger, HANDLE hMpq, DWORD dwSearchFlags, LPCSTR szExpectedHash, DWORD dwExpectedFileCount)
+{
+ DWORD dwErrCode = ERROR_SUCCESS;
+ DWORD dwFileCount = 0;
+ BYTE NameHash[MD5_DIGEST_SIZE] = {0};
+ char szNameHash[0x40];
+
+ // Do nothing if no name hash and no known file count
+ if(IS_VALID_STRING(szNameHash) || (dwExpectedFileCount != 0))
+ {
+ // Search the archive, obtain file count and name hash
+ if((dwErrCode = SearchArchive(&Logger, hMpq, dwSearchFlags, &dwFileCount, NameHash)) != ERROR_SUCCESS)
+ {
+ Logger.PrintMessage("Failed to search the archive");
+ return dwErrCode;
+ }
+
+ // Check the file count, if given
+ if((dwExpectedFileCount != 0) && (dwExpectedFileCount != dwFileCount))
+ {
+ Logger.PrintMessage("File count mismatch(expected: %u, found: %u)", dwExpectedFileCount, dwFileCount);
+ dwErrCode = ERROR_CAN_NOT_COMPLETE;
+ }
+
+ // Check the MD5 hash, if given
+ if(IS_VALID_STRING(szNameHash))
+ {
+ StringFromBinary(NameHash, MD5_DIGEST_SIZE, szNameHash);
+ if(_stricmp(szNameHash, szExpectedHash))
+ {
+ Logger.PrintMessage("Extracted files MD5 mismatch (expected: %s, obtained: %s)", szExpectedHash, szNameHash);
+ dwErrCode = ERROR_CAN_NOT_COMPLETE;
+ }
+ }
+ }
+ return dwErrCode;
+}
+
static DWORD CreateNewArchive(TLogHelper * pLogger, LPCTSTR szPlainName, DWORD dwCreateFlags, DWORD dwMaxFileCount, HANDLE * phMpq)
{
HANDLE hMpq = NULL;
@@ -1840,19 +1777,6 @@ static DWORD OpenExistingArchive(TLogHelper * pLogger, LPCTSTR szFullPath, DWORD return dwErrCode;
}
-static DWORD OpenPatchArchive(TLogHelper * pLogger, HANDLE hMpq, LPCTSTR szFullPath)
-{
- TCHAR szPatchName[MAX_PATH];
- DWORD dwErrCode = ERROR_SUCCESS;
-
- pLogger->PrintProgress(_T("Adding patch %s ..."), GetShortPlainName(szFullPath));
- StringCopy(szPatchName, _countof(szPatchName), szFullPath);
- if(!SFileOpenPatchArchive(hMpq, szPatchName, NULL, 0))
- dwErrCode = pLogger->PrintError(_T("Failed to add patch %s ..."), szFullPath);
-
- return dwErrCode;
-}
-
static DWORD OpenExistingArchiveWithCopy(TLogHelper * pLogger, LPCTSTR szFileName, LPCTSTR szCopyName, HANDLE * phMpq, DWORD dwFlags = 0)
{
DWORD dwErrCode = ERROR_SUCCESS;
@@ -1889,44 +1813,6 @@ static DWORD OpenExistingArchiveWithCopy(TLogHelper * pLogger, LPCTSTR szFileNam return OpenExistingArchive(pLogger, szFullPath, dwFlags, phMpq);
}
-static DWORD OpenPatchedArchive(TLogHelper * pLogger, HANDLE * phMpq, LPCTSTR PatchList[])
-{
- HANDLE hMpq = NULL;
- TCHAR szFullPath[MAX_PATH];
- DWORD dwErrCode = ERROR_SUCCESS;
-
- // The first file is expected to be valid
- assert(PatchList[0] != NULL);
-
- // Open the primary MPQ
- CreateFullPathName(szFullPath, _countof(szFullPath), szMpqSubDir, PatchList[0]);
- dwErrCode = OpenExistingArchive(pLogger, szFullPath, MPQ_OPEN_READ_ONLY, &hMpq);
-
- // Add all patches
- if(dwErrCode == ERROR_SUCCESS)
- {
- for(size_t i = 1; PatchList[i] != NULL; i++)
- {
- CreateFullPathName(szFullPath, _countof(szFullPath), szMpqPatchDir, PatchList[i]);
- dwErrCode = OpenPatchArchive(pLogger, hMpq, szFullPath);
- if(dwErrCode != ERROR_SUCCESS)
- break;
- }
- }
-
- // If anything failed, close the MPQ handle
- if(dwErrCode != ERROR_SUCCESS)
- {
- SFileCloseArchive(hMpq);
- hMpq = NULL;
- }
-
- // Give the archive handle to the caller
- if(phMpq != NULL)
- *phMpq = hMpq;
- return dwErrCode;
-}
-
static DWORD AddFileToMpq(
TLogHelper * pLogger,
HANDLE hMpq,
@@ -2052,71 +1938,9 @@ static DWORD RemoveMpqFile(TLogHelper * pLogger, HANDLE hMpq, LPCSTR szFileName, return ERROR_SUCCESS;
}
-static ULONGLONG SFileGetFilePointer(HANDLE hFile)
-{
- LONG FilePosHi = 0;
- DWORD FilePosLo;
-
- FilePosLo = SFileSetFilePointer(hFile, 0, &FilePosHi, FILE_CURRENT);
- return MAKE_OFFSET64(FilePosHi, FilePosLo);
-}
-
//-----------------------------------------------------------------------------
// Tests
-static DWORD TestSetFilePointer(
- HANDLE hFile,
- LONGLONG DeltaPos,
- ULONGLONG ExpectedPos,
- DWORD dwMoveMethod,
- bool bUseFilePosHigh,
- DWORD dwErrCode)
-{
- ULONGLONG NewPos = 0;
- LONG DeltaPosHi = (LONG)(DeltaPos >> 32);
- LONG DeltaPosLo = (LONG)(DeltaPos);
-
- // If there was an error before, do nothing
- if(dwErrCode == ERROR_SUCCESS)
- {
- SFileSetFilePointer(hFile, DeltaPosLo, bUseFilePosHigh ? &DeltaPosHi : NULL, dwMoveMethod);
- NewPos = SFileGetFilePointer(hFile);
- if(NewPos != ExpectedPos)
- dwErrCode = ERROR_HANDLE_EOF;
- }
-
- return dwErrCode;
-}
-
-static DWORD TestSetFilePointers(HANDLE hFile, bool bUseFilePosHigh)
-{
- LONGLONG FileSize;
- DWORD dwErrCode = ERROR_SUCCESS;
-
- // We expect the file to be at least 2 pages long
- FileSize = SFileGetFileSize(hFile, NULL);
- if(FileSize < 0x2000)
- return ERROR_NOT_SUPPORTED;
-
- // Move 0x20 bytes from the beginning. Expected new pos is 0x20
- dwErrCode = TestSetFilePointer(hFile, 0x20, 0x20, FILE_BEGIN, bUseFilePosHigh, dwErrCode);
-
- // Move 0x20 bytes from the current position. Expected new pos is 0x20
- dwErrCode = TestSetFilePointer(hFile, 0x20, 0x40, FILE_CURRENT, bUseFilePosHigh, dwErrCode);
-
- // Move 0x40 bytes back. Because the offset can't be moved to negative position, it will be zero
- dwErrCode = TestSetFilePointer(hFile, -64, 0x00, FILE_CURRENT, bUseFilePosHigh, dwErrCode);
-
- // Move 0x40 bytes before the end of the file
- dwErrCode = TestSetFilePointer(hFile, -64, FileSize-64, FILE_END, bUseFilePosHigh, dwErrCode);
-
- // Move 0x80 bytes forward. Should be at end of file
- dwErrCode = TestSetFilePointer(hFile, 0x80, FileSize, FILE_CURRENT, bUseFilePosHigh, dwErrCode);
-
- return dwErrCode;
-}
-
-
static void TestGetFileInfo(
TLogHelper * pLogger,
HANDLE hMpqOrFile,
@@ -2421,27 +2245,28 @@ static DWORD TestFileStreamOperations(LPCTSTR szPlainName, DWORD dwStreamFlags) return dwErrCode;
}
-static DWORD TestArchive_LoadFiles(TLogHelper * pLogger, HANDLE hMpq, bool bIgnoreOpedwErrCodes, ...)
+static DWORD TestArchive_LoadFiles(TLogHelper * pLogger, HANDLE hMpq, DWORD bIgnoreOpenErrors, ...)
{
- TFileData * pFileData;
+ PFILE_DATA pFileData;
const char * szFileName;
va_list argList;
+ DWORD dwSearchFlags = (bIgnoreOpenErrors) ? SEARCH_FLAG_IGNORE_ERRORS : 0;
DWORD dwErrCode = ERROR_SUCCESS;
- va_start(argList, bIgnoreOpedwErrCodes);
+ va_start(argList, bIgnoreOpenErrors);
while((szFileName = va_arg(argList, const char *)) != NULL)
{
if(SFileHasFile(hMpq, szFileName))
{
- pFileData = LoadMpqFile(pLogger, hMpq, szFileName);
- if(pFileData == NULL && bIgnoreOpedwErrCodes == false)
+ dwErrCode = LoadMpqFile(*pLogger, hMpq, szFileName, 0, dwSearchFlags, &pFileData);
+ if(dwErrCode != ERROR_SUCCESS && bIgnoreOpenErrors == FALSE)
{
pLogger->PrintError("Error loading the file %s", szFileName);
- dwErrCode = ERROR_FILE_CORRUPT;
break;
}
else
{
+ dwErrCode = ERROR_SUCCESS;
STORM_FREE(pFileData);
pFileData = NULL;
}
@@ -2452,234 +2277,168 @@ static DWORD TestArchive_LoadFiles(TLogHelper * pLogger, HANDLE hMpq, bool bIgno return dwErrCode;
}
-static DWORD TestArchive_SetPos(HANDLE hMpq, const char * szFileName)
+//-----------------------------------------------------------------------------
+// Testing archive operations: Single archive
+
+static DWORD TestArchive_AddListFile(TLogHelper & Logger, HANDLE hMpq, LPCTSTR szListFile)
{
- HANDLE hFile = NULL;
DWORD dwErrCode = ERROR_SUCCESS;
+ TCHAR szFullName[MAX_PATH];
- if(SFileOpenFileEx(hMpq, szFileName, 0, &hFile))
+ if(IS_VALID_STRING(szListFile))
{
- // First, use the SFileSetFilePointer WITHOUT the high-dword position
- dwErrCode = TestSetFilePointers(hFile, false);
+ Logger.PrintProgress(_T("Adding listfile %s ..."), szListFile);
+ CreateFullPathName(szFullName, _countof(szFullName), szListFileDir, szListFile);
+ if((dwErrCode = SFileAddListFile(hMpq, szFullName)) != ERROR_SUCCESS)
+ Logger.PrintMessage("Failed to add the listfile to the MPQ");
+ }
+ return dwErrCode;
+}
- // First, use the SFileSetFilePointer WITH the high-dword position
- if(dwErrCode == ERROR_SUCCESS)
- dwErrCode = TestSetFilePointers(hFile, true);
+static DWORD TestArchive_Extra_TwoFiles(TLogHelper & Logger, HANDLE hMpq, DWORD dwSearchFlags, PTEST_EXTRA_TWOFILES pExtra)
+{
+ PFILE_DATA pFileData1 = NULL;
+ PFILE_DATA pFileData2 = NULL;
+ DWORD dwErrCode = ERROR_SUCCESS;
- // Close the file
- SFileCloseFile(hFile);
+ // Perform actions
+ for(;;)
+ {
+ // Load and verify the first file, if any
+ if(IS_VALID_STRING(pExtra->szFile1))
+ {
+ if((dwErrCode = LoadMpqFile(Logger, hMpq, pExtra->szFile1, 0, dwSearchFlags, &pFileData1)) != ERROR_SUCCESS)
+ break;
+ }
+
+ // Load and verify the second file, if any
+ if(IS_VALID_STRING(pExtra->szFile2))
+ {
+ if((dwErrCode = LoadMpqFile(Logger, hMpq, pExtra->szFile2, 0, dwSearchFlags, &pFileData2)) != ERROR_SUCCESS)
+ break;
+ }
+
+ // If two files were given, they must be equal
+ if(pFileData1 && pFileData2)
+ {
+ dwErrCode = CompareTwoFiles(Logger, pFileData1, pFileData2);
+ }
+ break;
+ }
+
+ // Free buffers and exit
+ if(pFileData2 != NULL)
+ STORM_FREE(pFileData2);
+ if(pFileData1 != NULL)
+ STORM_FREE(pFileData1);
+ return dwErrCode;
+}
+
+static DWORD TestArchive_Extra_Patches(TLogHelper & Logger, HANDLE hMpq, PTEST_EXTRA_PATCHES pExtra)
+{
+ LPCTSTR szPatch;
+ TCHAR szFullPath[MAX_PATH];
+ DWORD dwErrCode = ERROR_SUCCESS;
+
+ // Open all patches that are in the multi-SZ list
+ if(IS_VALID_STRING(pExtra->szPatchList))
+ {
+ for(szPatch = pExtra->szPatchList; szPatch[0] != 0; szPatch = szPatch + _tcslen(szPatch) + 1)
+ {
+ Logger.PrintProgress(_T("Adding patch %s ..."), GetShortPlainName(szPatch));
+ CreateFullPathName(szFullPath, _countof(szFullPath), szMpqPatchDir, szPatch);
+ if(!SFileOpenPatchArchive(hMpq, szFullPath, NULL, 0))
+ return Logger.PrintError(_T("Failed to add patch %s ..."), szFullPath);
+ }
}
+ // Verify the patch count of the given file
+ if(IS_VALID_STRING(pExtra->szFileName))
+ dwErrCode = VerifyFilePatchCount(&Logger, hMpq, pExtra->szFileName, pExtra->dwPatchCount);
return dwErrCode;
}
+static DWORD TestArchive_ExtraType(TLogHelper & Logger, HANDLE hMpq, DWORD dwSearchFlags, const void * pExtra)
+{
+ switch(GetExtraType(pExtra))
+ {
+ case TwoFiles:
+ return TestArchive_Extra_TwoFiles(Logger, hMpq, dwSearchFlags, (PTEST_EXTRA_TWOFILES)(pExtra));
+
+ case PatchList:
+ return TestArchive_Extra_Patches(Logger, hMpq, (PTEST_EXTRA_PATCHES)(pExtra));
+
+ default:
+ return ERROR_SUCCESS;
+ }
+}
+
static DWORD TestArchive(
- LPCTSTR szPlainName, // Plain name of the MPQ
- LPCTSTR szListFile, // Listfile name (NULL if none)
- DWORD dwFlags, // Flags
- LPCSTR szParam1,
- LPCSTR szParam2)
+ LPCTSTR szMpqName, // Name of the MPQ
+ LPCTSTR szListFile, // Name of the listfile or NULL
+ LPCSTR szExpectedHash, // Expected name+data hash
+ DWORD dwFlags, // Test flags. Lower 16 bits contains the number of files
+ const void * pExtra) // Extra parameter
{
- TFileData * FileDataList[2] = {NULL};
- TLogHelper Logger("TestMpq", szPlainName);
- LPCSTR FileNameList[2] = {NULL};
- LPCSTR szExpectedMD5 = NULL;
+ TLogHelper Logger("TestMpq", szMpqName);
HANDLE hMpq = NULL;
- DWORD dwFileCount = 0;
- DWORD dwSearchFlags = 0;
- DWORD dwErrCode;
- DWORD dwCrc32 = 0;
DWORD dwExpectedFileCount = 0;
+ DWORD dwSearchFlags = 0;
DWORD dwMpqFlags = 0;
- TCHAR szFullName[MAX_PATH];
- LCID lcFileLocale = 0;
- BYTE ObtainedMD5[MD5_DIGEST_SIZE] = {0};
- bool bIgnoreOpedwErrCodes = false;
+ DWORD dwErrCode;
// If the file is a partial MPQ, don't load all files
- if(_tcsstr(szPlainName, _T(".MPQ.part")) == NULL)
+ if(_tcsstr(szMpqName, _T(".MPQ.part")) == NULL)
dwSearchFlags |= SEARCH_FLAG_LOAD_FILES;
- // If the MPQ is a protected MPQ, do different tests
- if(dwFlags & TFLG_COUNT_HASH)
+ // If we shall hash the files, do it
+ if(IS_VALID_STRING(szExpectedHash))
{
- if((szExpectedMD5 = szParam1) != NULL)
- dwSearchFlags |= SEARCH_FLAG_HASH_FILES;
dwExpectedFileCount = (dwFlags & TFLG_VALUE_MASK);
- szParam1 = NULL;
- }
-
- // If locale entered
- if(dwFlags & TFLG_FILE_LOCALE)
- {
- lcFileLocale = (LCID)(dwFlags & TFLG_VALUE_MASK);
+ dwSearchFlags |= SEARCH_FLAG_HASH_FILES;
}
- // 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);
+ dwErrCode = OpenExistingArchiveWithCopy(&Logger, szMpqName, NULL, &hMpq);
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;
- bIgnoreOpedwErrCodes = true;
- }
+ dwSearchFlags |= (dwMpqFlags & MPQ_FLAG_MALFORMED) ? SEARCH_FLAG_IGNORE_ERRORS : 0;
+ dwSearchFlags |= (GetExtraType(pExtra) == PatchList) ? SEARCH_FLAG_IGNORE_ERRORS : 0;
+
+ // Perform extra action, dependent on the data passed
+ if((dwErrCode = TestArchive_ExtraType(Logger, hMpq, dwSearchFlags, pExtra)) != ERROR_SUCCESS)
+ break;
// If the listfile was given, add it to the MPQ
- if(szListFile && szListFile[0])
- {
- Logger.PrintProgress(_T("Adding listfile %s ..."), szListFile);
- CreateFullPathName(szFullName, _countof(szFullName), szListFileDir, szListFile);
- if((dwErrCode = SFileAddListFile(hMpq, szFullName)) != ERROR_SUCCESS)
- Logger.PrintMessage("Failed to add the listfile to the MPQ");
- }
+ if((dwErrCode = TestArchive_AddListFile(Logger, hMpq, szListFile)) != ERROR_SUCCESS)
+ break;
// Attempt to open the (listfile), (attributes), (signature)
- dwErrCode = TestArchive_LoadFiles(&Logger, hMpq, bIgnoreOpedwErrCodes, LISTFILE_NAME, ATTRIBUTES_NAME, SIGNATURE_NAME, NULL);
- if(dwErrCode != ERROR_SUCCESS)
+ if((TestArchive_LoadFiles(&Logger, hMpq, (dwMpqFlags & MPQ_FLAG_MALFORMED), LISTFILE_NAME, ATTRIBUTES_NAME, SIGNATURE_NAME, NULL)) != ERROR_SUCCESS)
break;
- // For every file name given, load it and check its CRC
- for(size_t i = 0; i < _countof(FileNameList); i++)
- {
- TFileData * pFileData;
- LPCSTR szFileName = FileNameList[i];
-
- if(szFileName && szFileName[0])
- {
- // Test setting position
- dwErrCode = TestArchive_SetPos(hMpq, szFileName);
- if(dwErrCode != ERROR_SUCCESS)
- break;
-
- // Load the entire file 1
- FileDataList[i] = pFileData = LoadMpqFile(&Logger, hMpq, szFileName, lcFileLocale);
- if(pFileData == NULL)
- {
- dwErrCode = Logger.PrintError("Failed to load the file %s", szFileName);
- 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);
- }
-
-#ifdef _DEBUG
-/*
- FILE * fp = fopen("e:\\out_file.wav", "wb");
- if(fp)
- {
- fwrite(pFileData->FileData, 1, pFileData->dwFileSize, fp);
- fclose(fp);
- }
-*/
-#endif
- }
- }
-
- // If two files were given, compare them
- if(FileDataList[0] && FileDataList[1])
- {
- // Compare both files
- if(!CompareTwoFiles(&Logger, FileDataList[0], FileDataList[1]))
- {
- dwErrCode = Logger.PrintError("The file has different size/content of files");
- break;
- }
- }
-
- // Search the archive
- dwErrCode = SearchArchive(&Logger, hMpq, dwSearchFlags, &dwFileCount, ObtainedMD5);
-
- // Shall we check the file count and overall MD5?
- if(dwFlags & TFLG_COUNT_HASH)
- {
- if(dwFileCount != dwExpectedFileCount)
- {
- Logger.PrintMessage("File count mismatch(expected: %u, found: %u)", dwExpectedFileCount, dwFileCount);
- dwErrCode = ERROR_CAN_NOT_COMPLETE;
- }
- }
-
- // Shall we check overall MD5?
- if(szExpectedMD5 && szExpectedMD5[0])
- {
- char szObtainedMD5[0x40];
+ // If required, we search the archive and compare file cound and name hash
+ if((dwErrCode = VerifyDataChecksum(Logger, hMpq, dwSearchFlags, szExpectedHash, dwExpectedFileCount)) != ERROR_SUCCESS)
+ break;
- StringFromBinary(ObtainedMD5, MD5_DIGEST_SIZE, szObtainedMD5);
- if(_stricmp(szObtainedMD5, szExpectedMD5))
- {
- Logger.PrintMessage("Extracted files MD5 mismatch (expected: %s, obtained: %s)", szExpectedMD5, szObtainedMD5);
- dwErrCode = ERROR_CAN_NOT_COMPLETE;
- }
- }
break;
}
- // Common cleanup
- if(FileDataList[1] != NULL)
- STORM_FREE(FileDataList[1]);
- if(FileDataList[0] != NULL)
- STORM_FREE(FileDataList[0]);
+ // Cleanup and exit
if(hMpq != NULL)
SFileCloseArchive(hMpq);
return Logger.PrintVerdict(dwErrCode);
}
-// Opens a patched MPQ archive
-static DWORD TestArchive_Patched(LPCTSTR PatchList[], LPCSTR szPatchedFile, DWORD dwFlags)
+static DWORD TestArchive(const TEST_INFO2 & TestInfo)
{
- TLogHelper Logger("PatchedMPQ", PatchList[0]);
- HANDLE hMpq;
- HANDLE hFile;
- BYTE Buffer[0x100];
- DWORD dwExpectedPatchCount = (dwFlags & TFLG_VALUE_MASK);
- DWORD dwFileCount = 0;
- DWORD BytesRead = 0;
- DWORD dwErrCode;
- bool bExpectedToFail = (dwFlags & TFLG_WILL_FAIL) ? true : false;
-
- // Open a patched MPQ archive
- dwErrCode = OpenPatchedArchive(&Logger, &hMpq, PatchList);
- if(dwErrCode == ERROR_SUCCESS)
- {
- // Check patch count
- if(szPatchedFile != NULL)
- dwErrCode = VerifyFilePatchCount(&Logger, hMpq, szPatchedFile, dwExpectedPatchCount);
-
- // Try to open and read the file
- if(dwErrCode == ERROR_SUCCESS)
- {
- if(SFileOpenFileEx(hMpq, szPatchedFile, 0, &hFile))
- {
- SFileReadFile(hFile, Buffer, sizeof(Buffer), &BytesRead, NULL);
- SFileCloseFile(hFile);
- }
- }
-
- // Search the archive and load every file
- 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(dwErrCode == ERROR_CANT_FIND_PATCH_PREFIX && bExpectedToFail)
- dwErrCode = ERROR_SUCCESS;
- return dwErrCode;
+ return TestArchive(TestInfo.szName1, // Name of the MPQ
+ TestInfo.szName2, // Name of the listfile or NULL
+ TestInfo.szDataHash, // Compound name+data hash
+ TestInfo.dwFlags, // Test flags
+ TestInfo.pExtra); // Extra parameter
}
// Open an archive for read-only access
@@ -2895,9 +2654,9 @@ static DWORD TestOpenArchive_SignatureTest(LPCTSTR szPlainName, LPCTSTR szOrigin static DWORD TestOpenArchive_CompactArchive(LPCTSTR szPlainName, LPCTSTR szCopyName, BOOL bAddUserData)
{
TLogHelper Logger("CompactMpqTest", szPlainName);
- ULONGLONG PreMpqDataSize = (bAddUserData) ? 0x400 : 0;
- ULONGLONG UserDataSize = (bAddUserData) ? 0x531 : 0;
- HANDLE hMpq;
+ ULONGLONG PreMpqDataSize = (bAddUserData) ? 0x400 : 0;
+ ULONGLONG UserDataSize = (bAddUserData) ? 0x531 : 0;
+ HANDLE hMpq;
DWORD dwFileCount1 = 0;
DWORD dwFileCount2 = 0;
TCHAR szFullPath[MAX_PATH];
@@ -2974,7 +2733,7 @@ static DWORD TestOpenArchive_CompactArchive(LPCTSTR szPlainName, LPCTSTR szCopyN static DWORD ForEachFile_VerifyFileChecksum(LPCTSTR szFullPath)
{
- TFileData * pFileData;
+ PFILE_DATA pFileData;
TCHAR * szExtension;
TCHAR szShaFileName[MAX_PATH+1];
TCHAR szSha1Text[0x40];
@@ -3058,35 +2817,11 @@ static DWORD ForEachFile_OpenArchive(LPCTSTR szFullPath) return dwErrCode;
}
-// Adding a file to MPQ that had size of the file table equal
-// or greater than hash table, but has free entries
-static DWORD TestAddFile_FullTable(LPCTSTR szFullMpqName)
-{
- TLogHelper Logger("FullMpqTest", szFullMpqName);
- LPCSTR szFileName = "AddedFile001.txt";
- LPCSTR szFileData = "0123456789ABCDEF";
- HANDLE hMpq = NULL;
- DWORD dwErrCode = ERROR_SUCCESS;
-
- // Copy the archive so we won't fuck up the original one
- dwErrCode = OpenExistingArchiveWithCopy(&Logger, szFullMpqName, szFullMpqName, &hMpq);
- if(dwErrCode == ERROR_SUCCESS)
- {
- // Attempt to add a file
- dwErrCode = AddFileToMpq(&Logger, hMpq, szFileName, szFileData, MPQ_FILE_IMPLODE, MPQ_COMPRESSION_PKWARE, ERROR_SUCCESS);
- SFileCloseArchive(hMpq);
- }
-
- return dwErrCode;
-}
-
-// Adding a file to MPQ that had no (listfile) and no (attributes).
-// We expect that neither of these will be present after the archive is closed
-static DWORD TestAddFile_ListFileTest(LPCTSTR szSourceMpq, bool bShouldHaveListFile, bool bShouldHaveAttributes)
+static DWORD TestOpenArchive_AddFile(LPCTSTR szMpqName, DWORD dwFlags)
{
- TLogHelper Logger("ListFileTest", szSourceMpq);
- TFileData * pFileData = NULL;
- LPCTSTR szBackupMpq = bShouldHaveListFile ? _T("StormLibTest_HasListFile.mpq") : _T("StormLibTest_NoListFile.mpq");
+ TLogHelper Logger("AddFileToMpqTest", szMpqName);
+ PFILE_DATA pFileData = NULL;
+ LPCTSTR szBackupMpq = (dwFlags & TFLAG_REOPEN) ? _T("StormLibTest_Reopened.mpq") : szMpqName;
LPCSTR szFileName = "AddedFile001.txt";
LPCSTR szFileData = "0123456789ABCDEF";
HANDLE hMpq = NULL;
@@ -3094,61 +2829,54 @@ static DWORD TestAddFile_ListFileTest(LPCTSTR szSourceMpq, bool bShouldHaveListF DWORD dwErrCode = ERROR_SUCCESS;
// Copy the archive so we won't fuck up the original one
- dwErrCode = OpenExistingArchiveWithCopy(&Logger, szSourceMpq, szBackupMpq, &hMpq);
-
- // Add a file
+ dwErrCode = OpenExistingArchiveWithCopy(&Logger, szMpqName, szBackupMpq, &hMpq);
if(dwErrCode == ERROR_SUCCESS)
{
- // Now add a file
- dwErrCode = AddFileToMpq(&Logger, hMpq, szFileName, szFileData, MPQ_FILE_IMPLODE, MPQ_COMPRESSION_PKWARE);
+ dwErrCode = AddFileToMpq(&Logger, hMpq, szFileName, szFileData, MPQ_FILE_IMPLODE, MPQ_COMPRESSION_PKWARE, ERROR_SUCCESS);
SFileCloseArchive(hMpq);
- hMpq = NULL;
}
- // Now reopen the archive
- if(dwErrCode == ERROR_SUCCESS)
- dwErrCode = OpenExistingArchiveWithCopy(&Logger, NULL, szBackupMpq, &hMpq);
-
// Now the file has been written and the MPQ has been saved.
- // We Reopen the MPQ and check if there is no (listfile) nor (attributes).
- if(dwErrCode == ERROR_SUCCESS)
+ // We reopen the MPQ and check the state of (listfile) and (attributes)
+ if((dwErrCode == ERROR_SUCCESS) && (dwFlags & TFLAG_REOPEN))
{
- // Verify presence of (listfile) and (attributes)
- CheckIfFileIsPresent(&Logger, hMpq, LISTFILE_NAME, bShouldHaveListFile);
- CheckIfFileIsPresent(&Logger, hMpq, ATTRIBUTES_NAME, bShouldHaveAttributes);
-
- // Try to open the file that we recently added
- pFileData = LoadMpqFile(&Logger, hMpq, szFileName);
- if(pFileData != NULL)
+ if((dwErrCode = OpenExistingArchiveWithCopy(&Logger, NULL, szBackupMpq, &hMpq)) == ERROR_SUCCESS)
{
- // Verify if the file size matches
- if(pFileData->dwFileSize == dwFileSize)
+ // Verify presence of (listfile) and (attributes)
+ CheckIfFileIsPresent(&Logger, hMpq, LISTFILE_NAME, (dwFlags & TFLAG_HAS_LISTFILE));
+ CheckIfFileIsPresent(&Logger, hMpq, ATTRIBUTES_NAME, (dwFlags & TFLAG_HAS_ATTRIBUTES));
+
+ // Try to open the file that we recently added
+ dwErrCode = LoadMpqFile(Logger, hMpq, szFileName, 0, 0, &pFileData);
+ if(dwErrCode == ERROR_SUCCESS)
{
- // Verify if the file data match
- if(memcmp(pFileData->FileData, szFileData, dwFileSize))
+ // Verify if the file size matches
+ if(pFileData->dwFileSize == dwFileSize)
+ {
+ // Verify if the file data match
+ if(memcmp(pFileData->FileData, szFileData, dwFileSize))
+ {
+ Logger.PrintError("The data of the added file does not match");
+ dwErrCode = ERROR_FILE_CORRUPT;
+ }
+ }
+ else
{
- Logger.PrintError("The data of the added file does not match");
+ Logger.PrintError("The size of the added file does not match");
dwErrCode = ERROR_FILE_CORRUPT;
}
+
+ // Delete the file data
+ STORM_FREE(pFileData);
}
else
{
- Logger.PrintError("The size of the added file does not match");
- dwErrCode = ERROR_FILE_CORRUPT;
+ Logger.PrintError("Failed to open the file previously added");
}
-
- // Delete the file data
- STORM_FREE(pFileData);
- }
- else
- {
- dwErrCode = Logger.PrintError("Failed to open the file previously added");
+
+ SFileCloseArchive(hMpq);
}
}
-
- // Close the MPQ archive
- if(hMpq != NULL)
- SFileCloseArchive(hMpq);
return dwErrCode;
}
@@ -3749,7 +3477,7 @@ static DWORD TestCreateArchive_WaveCompressionsTest(LPCTSTR szPlainName, LPCTSTR static DWORD TestCreateArchive_ListFilePos(LPCTSTR szPlainName)
{
- TFileData * pFileData;
+ PFILE_DATA pFileData;
LPCSTR szReaddedFile = "AddedFile_##.txt";
LPCSTR szFileMask = "AddedFile_%02u.txt";
TLogHelper Logger("ListFilePos", szPlainName);
@@ -3803,16 +3531,14 @@ static DWORD TestCreateArchive_ListFilePos(LPCTSTR szPlainName) // Check that (listfile) is at the end
if(dwErrCode == ERROR_SUCCESS)
{
- pFileData = LoadMpqFile(&Logger, hMpq, LISTFILE_NAME);
- if(pFileData != NULL)
+ if(LoadMpqFile(Logger, hMpq, LISTFILE_NAME, 0, 0, &pFileData) == ERROR_SUCCESS)
{
if(pFileData->dwBlockIndex < dwFileCount)
Logger.PrintMessage("Unexpected file index of %s", LISTFILE_NAME);
STORM_FREE(pFileData);
}
- pFileData = LoadMpqFile(&Logger, hMpq, ATTRIBUTES_NAME);
- if(pFileData != NULL)
+ if(LoadMpqFile(Logger, hMpq, ATTRIBUTES_NAME, 0, 0, &pFileData) == ERROR_SUCCESS)
{
if(pFileData->dwBlockIndex <= dwFileCount)
Logger.PrintMessage("Unexpected file index of %s", ATTRIBUTES_NAME);
@@ -3827,8 +3553,7 @@ static DWORD TestCreateArchive_ListFilePos(LPCTSTR szPlainName) SFileFlushArchive(hMpq);
// Load the file
- pFileData = LoadMpqFile(&Logger, hMpq, szReaddedFile);
- if(pFileData != NULL)
+ if(LoadMpqFile(Logger, hMpq, szReaddedFile, 0, 0, &pFileData) == ERROR_SUCCESS)
{
if(pFileData->dwBlockIndex != dwFileCount)
Logger.PrintMessage("Unexpected file index of %s", szReaddedFile);
@@ -3926,7 +3651,7 @@ static DWORD TestModifyArchive_ReplaceFile(LPCTSTR szMpqPlainName, LPCTSTR szFil // Open the file, load to memory, calculate hash
if(dwErrCode == ERROR_SUCCESS)
{
- dwErrCode = LoadMpqFileMD5(&Logger, hMpq, szArchivedName, md5_file_in_mpq1);
+ dwErrCode = LoadMpqFileMD5(Logger, hMpq, szArchivedName, md5_file_in_mpq1);
}
// Open the local file, calculate hash
@@ -3951,7 +3676,7 @@ static DWORD TestModifyArchive_ReplaceFile(LPCTSTR szMpqPlainName, LPCTSTR szFil if(dwErrCode == ERROR_SUCCESS)
{
// Load the file from the MPQ again
- dwErrCode = LoadMpqFileMD5(&Logger, hMpq, szArchivedName, md5_file_in_mpq2);
+ dwErrCode = LoadMpqFileMD5(Logger, hMpq, szArchivedName, md5_file_in_mpq2);
if(dwErrCode == ERROR_SUCCESS)
{
// New MPQ file must be different from the old one
@@ -3991,7 +3716,7 @@ static DWORD TestModifyArchive_ReplaceFile(LPCTSTR szMpqPlainName, LPCTSTR szFil if(dwErrCode == ERROR_SUCCESS)
{
// Load the file from the MPQ again
- dwErrCode = LoadMpqFileMD5(&Logger, hMpq, szArchivedName, md5_file_in_mpq3);
+ dwErrCode = LoadMpqFileMD5(Logger, hMpq, szArchivedName, md5_file_in_mpq3);
if(dwErrCode == ERROR_SUCCESS)
{
// New MPQ file must be the same like the local one
@@ -4038,87 +3763,235 @@ static const TEST_INFO TestList_MasterMirror[] = // {_T("MPQ_2013_v4_alternate-downloaded.MPQ"), _T("http://www.zezula.net\\mpqs\\alternate.zip"), 0}
};
-static const TEST_INFO Test_Mpqs[] =
+static const TEST_EXTRA_TWOFILES TwoFilesD1 = {TwoFiles, "music\\dintro.wav", "File00000023.xxx" };
+static const TEST_EXTRA_TWOFILES TwoFilesD2 = {TwoFiles, "waitingroombkgd.dc6"};
+static const TEST_EXTRA_TWOFILES TwoFilesW3M = {TwoFiles, "file00000002.blp"};
+static const TEST_EXTRA_TWOFILES TwoFilesW3X = {TwoFiles, "BlueCrystal.mdx"};
+
+static const TEST_EXTRA_PATCHES PatchSC1 =
+{
+ PatchList,
+ _T("s1-1998-BroodWar.mpq\0"),
+ "music\\terran1.wav",
+ 0
+};
+
+static const TEST_EXTRA_PATCHES Patch13286 =
+{
+ PatchList,
+ _T("wow-update-oldworld-13154.MPQ\0")
+ _T("wow-update-oldworld-13286.MPQ\0"),
+ "OldWorld\\World\\Model.blob",
+ 2
+};
+
+static const TEST_EXTRA_PATCHES Patch15050 =
+{
+ PatchList,
+ _T("wow-update-13164.MPQ\0")
+ _T("wow-update-13205.MPQ\0")
+ _T("wow-update-13287.MPQ\0")
+ _T("wow-update-13329.MPQ\0")
+ _T("wow-update-13596.MPQ\0")
+ _T("wow-update-13623.MPQ\0")
+ _T("wow-update-base-13914.MPQ\0")
+ _T("wow-update-base-14007.MPQ\0")
+ _T("wow-update-base-14333.MPQ\0")
+ _T("wow-update-base-14480.MPQ\0")
+ _T("wow-update-base-14545.MPQ\0")
+ _T("wow-update-base-14946.MPQ\0")
+ _T("wow-update-base-15005.MPQ\0")
+ _T("wow-update-base-15050.MPQ\0"),
+ "World\\Model.blob",
+ 8
+};
+
+static const TEST_EXTRA_PATCHES Patch16965 =
+{
+ PatchList,
+ _T("wow-update-enGB-16016.MPQ\0")
+ _T("wow-update-enGB-16048.MPQ\0")
+ _T("wow-update-enGB-16057.MPQ\0")
+ _T("wow-update-enGB-16309.MPQ\0")
+ _T("wow-update-enGB-16357.MPQ\0")
+ _T("wow-update-enGB-16516.MPQ\0")
+ _T("wow-update-enGB-16650.MPQ\0")
+ _T("wow-update-enGB-16844.MPQ\0")
+ _T("wow-update-enGB-16965.MPQ\0"),
+ "DBFilesClient\\BattlePetNPCTeamMember.db2",
+ 0
+};
+
+static const TEST_EXTRA_PATCHES Patch32283 =
+{
+ PatchList,
+ _T("s2-update-base-23258.MPQ\0")
+ _T("s2-update-base-24540.MPQ\0")
+ _T("s2-update-base-26147.MPQ\0")
+ _T("s2-update-base-28522.MPQ\0")
+ _T("s2-update-base-30508.MPQ\0")
+ _T("s2-update-base-32283.MPQ\0"),
+ "TriggerLibs\\natives.galaxy",
+ 6
+};
+
+static const TEST_EXTRA_PATCHES Patch32283a =
+{
+ PatchList,
+ _T("s2-update-enGB-23258.MPQ\0")
+ _T("s2-update-enGB-24540.MPQ\0")
+ _T("s2-update-enGB-26147.MPQ\0")
+ _T("s2-update-enGB-28522.MPQ\0")
+ _T("s2-update-enGB-30508.MPQ\0")
+ _T("s2-update-enGB-32283.MPQ\0"),
+ "Assets\\Textures\\startupimage.dds",
+ 0
+};
+
+static const TEST_EXTRA_PATCHES Patch34644 =
+{
+ PatchList,
+ _T("s2-update-base-23258.MPQ\0")
+ _T("s2-update-base-24540.MPQ\0")
+ _T("s2-update-base-26147.MPQ\0")
+ _T("s2-update-base-28522.MPQ\0")
+ _T("s2-update-base-32384.MPQ\0")
+ _T("s2-update-base-34644.MPQ\0"),
+ "TriggerLibs\\GameData\\GameData.galaxy",
+ 2
+};
+
+static const TEST_EXTRA_PATCHES Patch34644m =
+{
+ PatchList,
+ _T("s2-update-base-23258.MPQ\0")
+ _T("s2-update-base-24540.MPQ\0")
+ _T("s2-update-base-26147.MPQ\0")
+ _T("s2-update-base-28522.MPQ\0")
+ _T("s2-update-base-32384.MPQ\0")
+ _T("s2-update-base-34644.MPQ\0"),
+ "Maps\\Campaign\\THorner03.SC2Map\\BankList.xml",
+ 3
+};
+
+static const TEST_EXTRA_PATCHES Patch36281 =
+{
+ PatchList,
+ _T("s2-update-enGB-23258.MPQ\0")
+ _T("s2-update-enGB-24540.MPQ\0")
+ _T("s2-update-enGB-26147.MPQ\0")
+ _T("s2-update-enGB-28522.MPQ\0")
+ _T("s2-update-enGB-32384.MPQ\0")
+ _T("s2-update-enGB-34644.MPQ\0")
+ _T("s2-update-enGB-36281.MPQ\0"),
+ "LocalizedData\\GameHotkeys.txt",
+ 6
+};
+
+static const TEST_EXTRA_PATCHES PatchH3604 =
+{
+ PatchList,
+ _T("hs-0-3604-Win-final.MPQ\0"),
+ "Hearthstone.exe",
+ 1
+};
+
+static const TEST_EXTRA_PATCHES PatchH6898 =
+{
+ PatchList,
+ _T("hs-0-5314-Win-final.MPQ\0")
+ _T("hs-5314-5435-Win-final.MPQ\0")
+ _T("hs-5435-5506-Win-final.MPQ\0")
+ _T("hs-5506-5834-Win-final.MPQ\0")
+ _T("hs-5834-6024-Win-final.MPQ\0")
+ _T("hs-6024-6141-Win-final.MPQ\0")
+ _T("hs-6141-6187-Win-final.MPQ\0")
+ _T("hs-6187-6284-Win-final.MPQ\0")
+ _T("hs-6284-6485-Win-final.MPQ\0")
+ _T("hs-6485-6898-Win-final.MPQ\0"),
+ "Hearthstone_Data\\Managed\\Assembly-Csharp.dll",
+ 10
+};
+
+static const TEST_INFO2 Test_Mpqs[] =
{
// Correct or damaged archives
- {_T("MPQ_1997_v1_Diablo1_DIABDAT.MPQ"), NULL, 0, "music\\dintro.wav", "File00000023.xxx"},
- {_T("MPQ_1997_v1_patch_rt_SC1B.mpq"), NULL, TEST_DATA("43fe7d362955be68a708486e399576a7", 10)}, // From Starcraft 1 BETA
- {_T("MPQ_1997_v1_StarDat_SC1B.mpq"), NULL, TEST_DATA("0094b23f28cfff7386071ef3bd19a577", 2468)}, // From Starcraft 1 BETA
- {_T("MPQ_1997_v1_INSTALL_SC1B.EXE_"), NULL, TEST_DATA("3248460c89bb6f8e3b8fc3e08de7ffbb", 79)}, // From Starcraft 1 BETA
- {_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"), Bliz, 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("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
+ {_T("MPQ_1997_v1_Diablo1_DIABDAT.MPQ"), NULL, "554b538541e42170ed41cb236483489e", 2910, &TwoFilesD1}, // Base MPQ from Diablo 1
+ {_T("MPQ_1997_v1_patch_rt_SC1B.mpq"), NULL, "43fe7d362955be68a708486e399576a7", 10}, // From Starcraft 1 BETA
+ {_T("MPQ_1997_v1_StarDat_SC1B.mpq"), NULL, "0094b23f28cfff7386071ef3bd19a577", 2468}, // From Starcraft 1 BETA
+ {_T("MPQ_1997_v1_INSTALL_SC1B.EXE_"), NULL, "3248460c89bb6f8e3b8fc3e08de7ffbb", 79}, // From Starcraft 1 BETA
+ {_T("MPQ_2016_v1_D2XP_IX86_1xx_114a.mpq"), NULL, "255d87a62f3c9518f72cf723a1818946", 221, &TwoFilesD2}, // Update MPQ from Diablo II (patch 2016)
+ {_T("MPQ_2018_v1_icon_error.w3m"), NULL, "fcefa25fb50c391e8714f2562d1e10ff", 19, &TwoFilesW3M},
+ {_T("MPQ_1997_v1_Diablo1_STANDARD.SNP"), Bliz, "5ef18ef9a26b5704d8d46a344d976c89", 2}, // File whose archive's (signature) file has flags = 0x90000000
+ {_T("MPQ_2012_v2_EmptyMpq.MPQ"), NULL, "00000000000000000000000000000000", 0}, // Empty archive (found in WoW cache - it's just a header)
+ {_T("MPQ_2013_v4_EmptyMpq.MPQ"), NULL, "00000000000000000000000000000000", 0}, // Empty archive (created artificially - it's just a header)
+ {_T("MPQ_2013_v4_patch-base-16357.MPQ"), NULL, "d41d8cd98f00b204e9800998ecf8427e", 1}, // Empty archive (found in WoW cache - it's just a header)
+ {_T("MPQ_2011_v4_InvalidHetEntryCount.MPQ"), NULL, "be4b49ecc3942d1957249f9da0021659", 6}, // Empty archive (with invalid HET entry count)
+ {_T("MPQ_2002_v1_BlockTableCut.MPQ"), NULL, "a9499ab74d939303d8cda7c397c36275", 287}, // Truncated archive
+ {_T("MPQ_2010_v2_HasUserData.s2ma"), NULL, "feff9e2c86db716b6ff5ffc906181200", 52}, // MPQ that actually has user data
+ {_T("MPQ_2014_v1_AttributesOneEntryLess.w3x"), NULL, "90451b7052eb0f1d6f4bf69b2daff7f5", 116}, // Warcraft III map whose "(attributes)" file has (BlockTableSize-1) entries
+ {_T("MPQ_2020_v1_AHF04patch.mix"), NULL, "d3c6aac48bc12813ef5ce4ad113e58bf", 2891}, // MIX file
+ {_T("MPQ_2010_v3_expansion-locale-frFR.MPQ"), NULL, "0c8fc921466f07421a281a05fad08b01", 53}, // MPQ archive v 3.0 (the only one I know)
+ {_T("mpqe-file://MPQ_2011_v2_EncryptedMpq.MPQE"), NULL, "10e4dcdbe95b7ad731c563ec6b71bc16", 82}, // Encrypted archive from Starcraft II installer
+ {_T("part-file://MPQ_2010_v2_HashTableCompressed.MPQ.part"),NULL, "d41d8cd98f00b204e9800998ecf8427e", 14263}, // Partial MPQ with compressed hash table
+ {_T("blk4-file://streaming/model.MPQ.0"), NULL, "e06b00efb2fc7e7469dd8b3b859ae15d", 39914}, // Archive that is merged with multiple files
// Protected archives
- {_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("44111a3edf7645bc44bb1afd3a813576", 1715)},
- {_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("7ec2f4d0f3982d8b12d88bc08ef0c1fb", 640)}, // 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("cbe1fd7ed5ed2fc005fba9beafcefe40", 16334)}, // 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("055fd548a789c910d9dd37472ecc1e66", 28)},
- {_T("MPQ_2022_v1_Sniper.scx"), NULL, TEST_DATA("2e955271b70b79344ad85b698f6ce9d8", 64)}, // Multiple items in hash table for staredit\scenario.chk (locale=0, platform=0)
- {_T("MPQ_2022_v1_OcOc_Bound_2.scx"), NULL, TEST_DATA("25cad16a2fb4e883767a1f512fc1dce7", 16)},
+ {_T("MPQ_2002_v1_ProtectedMap_InvalidUserData.w3x"), NULL, "b900364cc134a51ddeca21a13697c3ca", 79},
+ {_T("MPQ_2002_v1_ProtectedMap_InvalidMpqFormat.w3x"), NULL, "db67e894da9de618a1cdf86d02d315ff", 117},
+ {_T("MPQ_2002_v1_ProtectedMap_Spazzler.w3x"), NULL, "72d7963aa799a7fb4117c55b7beabaf9", 470}, // Warcraft III map locked by the Spazzler protector
+ {_T("MPQ_2014_v1_ProtectedMap_Spazzler2.w3x"), NULL, "72d7963aa799a7fb4117c55b7beabaf9", 470}, // Warcraft III map locked by the Spazzler protector
+ {_T("MPQ_2014_v1_ProtectedMap_Spazzler3.w3x"), NULL, "e55aad2dd33cf68b372ca8e30dcb78a7", 130}, // Warcraft III map locked by the Spazzler protector
+ {_T("MPQ_2002_v1_ProtectedMap_BOBA.w3m"), NULL, "7b725d87e07a2173c42fe2314b95fa6c", 17}, // Warcraft III map locked by the BOBA protector
+ {_T("MPQ_2015_v1_ProtectedMap_KangTooJee.w3x"), NULL, "44111a3edf7645bc44bb1afd3a813576", 1715},
+ {_T("MPQ_2015_v1_ProtectedMap_Somj2hM16.w3x"), NULL, "b411f9a51a6e9a9a509150c8d66ba359", 92},
+ {_T("MPQ_2015_v1_ProtectedMap_Spazy.w3x"), NULL, "6e491bd055511435dcb4d9c8baed0516", 4089}, // Warcraft III map locked by Spazy protector
+ {_T("MPQ_2015_v1_MessListFile.mpq"), NULL, "15e25d5be124d8ad71519f967997efc2", 8},
+ {_T("MPQ_2016_v1_ProtectedMap_TableSizeOverflow.w3x"), NULL, "ad81b43cbd37bbfa27e4bed4c17e6a81", 176},
+ {_T("MPQ_2016_v1_ProtectedMap_HashOffsIsZero.w3x"), NULL, "d6e712c275a26dc51f16b3a02f6187df", 228},
+ {_T("MPQ_2016_v1_ProtectedMap_Somj2.w3x"), NULL, "457cdbf97a9ca41cfe8ea130dafaa0bb", 21}, // Something like Somj 2.0
+ {_T("MPQ_2016_v1_WME4_4.w3x"), NULL, "7ec2f4d0f3982d8b12d88bc08ef0c1fb", 640}, // Protector from China (2016-05-27)
+ {_T("MPQ_2016_v1_SP_(4)Adrenaline.w3x"), NULL, "b6f6d56f4f8aaef04c2c4b1f08881a8b", 16},
+ {_T("MPQ_2016_v1_ProtectedMap_1.4.w3x"), NULL, "3c7908b29d3feac9ec952282390a242d", 5027},
+ {_T("MPQ_2016_v1_KoreanFile.w3m"), NULL, "805d1f75712472a81c6df27b2a71f946", 18},
+ {_T("MPQ_2017_v1_Eden_RPG_S2_2.5J.w3x"), NULL, "cbe1fd7ed5ed2fc005fba9beafcefe40", 16334}, // Protected by PG1.11.973
+ {_T("MPQ_2017_v1_BigDummyFiles.w3x"), NULL, "f4d2ee9d85d2c4107e0b2d00ff302dd7", 9086},
+ {_T("MPQ_2017_v1_TildeInFileName.mpq"), NULL, "f203e3979247a4dbf7f3828695ac810c", 5},
+ {_T("MPQ_2018_v1_EWIX_v8_7.w3x"), NULL, "12c0f4e15c7361b7c13acd37a181d83b", 857, &TwoFilesW3X},
+ {_T("MPQ_2020_v4_FakeMpqHeaders.SC2Mod"), NULL, "f45392f6523250c943990a017c230b41", 24}, // Archive that has two fake headers before the real one
+ {_T("MPQ_2020_v4_NP_Protect_1.s2ma"), NULL, "1a1ea40ac1165bcdb4f2e434edfc7636", 21}, // SC2 map that is protected by the NP_Protect
+ {_T("MPQ_2020_v4_NP_Protect_2.s2ma"), NULL, "7d1a379da8bd966da1f4fa6e4646049b", 55}, // SC2 map that is protected by the NP_Protect
+ {_T("MPQ_2015_v1_flem1.w3x"), NULL, "1c4c13e627658c473e84d94371e31f37", 20},
+ {_T("MPQ_2002_v1_ProtectedMap_HashTable_FakeValid.w3x"), NULL, "5250975ed917375fc6540d7be436d4de", 114},
+ {_T("MPQ_2021_v1_CantExtractCHK.scx"), NULL, "055fd548a789c910d9dd37472ecc1e66", 28},
+ {_T("MPQ_2022_v1_Sniper.scx"), NULL, "2e955271b70b79344ad85b698f6ce9d8", 64}, // Multiple items in hash table for staredit\scenario.chk (locale=0, platform=0)
+ {_T("MPQ_2022_v1_OcOc_Bound_2.scx"), NULL, "25cad16a2fb4e883767a1f512fc1dce7", 16},
// ASI plugins
- {_T("MPQ_2020_v1_HS0.1.asi"), NULL, TEST_DATA("50cba7460a6e6d270804fb9776a7ec4f", 6022)},
- {_T("MPQ_2022_v1_hs0.8.asi"), NULL, TEST_DATA("6a40f733428001805bfe6e107ca9aec1", 11352)}, // Items in hash table have platform = 0xFF
- {_T("MPQ_2022_v1_MoeMoeMod.asi"), NULL, TEST_DATA("89b923c7cde06de48815844a5bbb0ec4", 2578)},
+ {_T("MPQ_2020_v1_HS0.1.asi"), NULL, "50cba7460a6e6d270804fb9776a7ec4f", 6022},
+ {_T("MPQ_2022_v1_hs0.8.asi"), NULL, "6a40f733428001805bfe6e107ca9aec1", 11352}, // Items in hash table have platform = 0xFF
+ {_T("MPQ_2022_v1_MoeMoeMod.asi"), NULL, "89b923c7cde06de48815844a5bbb0ec4", 2578},
// MPQ modifications from Chinese games
- {_T("MPx_2013_v1_LongwuOnline.mpk"), NULL, TEST_DATA("548f7db88284097f7e94c95a08c5bc24", 469)}, // MPK archive from Longwu online
- {_T("MPx_2013_v1_WarOfTheImmortals.sqp"), WotI, TEST_DATA("a048f37f7c6162a96253d8081722b6d9", 9396)}, // SQP archive from War of the Immortals
- {_T("MPx_2022_v1_Music.mpk"), NULL, TEST_DATA("fc369cff4ff4b573dd024de963e4cdd5", 650)}, // MPK archive from Warriors of the Ghost Valley
- {_T("MPx_2022_v1_Scp.mpk"), NULL, TEST_DATA("9cb453dc159f2e667c14f48957fd9e77", 113)}, // MPK archive from Warriors of the Ghost Valley
- {_T("MPx_2022_v1_UI.mpk"), NULL, TEST_DATA("677a36b458d528a3158ced3dfb711e49", 3086)}, // MPK archive from Warriors of the Ghost Valley
-};
-
-static const TEST_INFO Test_Patched_Mpqs[] =
-{
- {NULL, NULL, 0, PatchList_StarCraft, "music\\terran1.wav"},
- {NULL, NULL, 2, PatchList_WoW_OldWorld13286, "OldWorld\\World\\Model.blob"},
- {NULL, NULL, 8, PatchList_WoW_15050, "World\\Model.blob"},
- {NULL, NULL, 0, PatchList_WoW_16965, "DBFilesClient\\BattlePetNPCTeamMember.db2"},
- {NULL, NULL, 6, PatchList_SC2_32283, "TriggerLibs\\natives.galaxy"},
- {NULL, NULL, 2, PatchList_SC2_34644, "TriggerLibs\\GameData\\GameData.galaxy"},
- {NULL, NULL, 3, PatchList_SC2_34644_Maps, "Maps\\Campaign\\THorner03.SC2Map\\BankList.xml"},
- {NULL, NULL, TFLG_WILL_FAIL, PatchList_SC2_32283_enGB, "Assets\\Textures\\startupimage.dds"},
- {NULL, NULL, 6, PatchList_SC2_36281_enGB, "LocalizedData\\GameHotkeys.txt"},
- {NULL, NULL, 1, PatchList_HS_3604_enGB, "Hearthstone.exe"},
- {NULL, NULL, 10, PatchList_HS_6898_enGB, "Hearthstone_Data\\Managed\\Assembly-Csharp.dll"}
+ {_T("MPx_2013_v1_LongwuOnline.mpk"), NULL, "548f7db88284097f7e94c95a08c5bc24", 469}, // MPK archive from Longwu online
+ {_T("MPx_2013_v1_WarOfTheImmortals.sqp"), WotI, "a048f37f7c6162a96253d8081722b6d9", 9396}, // SQP archive from War of the Immortals
+ {_T("MPx_2022_v1_Music.mpk"), NULL, "fc369cff4ff4b573dd024de963e4cdd5", 650}, // MPK archive from Warriors of the Ghost Valley
+ {_T("MPx_2022_v1_Scp.mpk"), NULL, "9cb453dc159f2e667c14f48957fd9e77", 113}, // MPK archive from Warriors of the Ghost Valley
+ {_T("MPx_2022_v1_UI.mpk"), NULL, "677a36b458d528a3158ced3dfb711e49", 3086}, // MPK archive from Warriors of the Ghost Valley
+
+ // Patched MPQs
+ {_T("MPQ_1998_v1_StarCraft.mpq"), NULL, "5ecef2f41c5fd44c264e269416de9495", 1943, &PatchSC1}, // Patched MPQ from StarCraft I
+ {_T("MPQ_2012_v4_OldWorld.MPQ"), NULL, "07643ec62864b4dd4fc8f8a6a16ce006", 71439, &Patch13286}, // WoW 13286: Patched "OldWorld.MPQ"
+ {_T("MPQ_2013_v4_world.MPQ"), NULL, "246b46105b85a3a80a23ff68a402c01e", 52286, &Patch15050}, // WoW 15050: Patched "world.MPQ"
+ {_T("MPQ_2013_v4_locale-enGB.MPQ"), NULL, "d39e743aaf6dad51d643d65e6e564804", 14349, &Patch16965}, // WoW 16965: Patched "locale-enGB.MPQ"
+ {_T("MPQ_2013_v4_Base1.SC2Data"), NULL, "28a0f3cff1f400feb268ddae0efb2985", 1459, &Patch32283}, // SC2 32283: Patched "Base1.SC2Data"
+ {_T("MPQ_2013_v4_Mods#Core.SC2Mod#enGB.SC2Assets"), NULL, "89df7ddac15700721b3f4c37d2673c1f", 11, &Patch32283a},// SC2 32283: Patched "Mods#Core.SC2Mod#enGB.SC2Assets"
+ {_T("MPQ_2013_v4_Base1.SC2Data"), NULL, "7b65d0a3c3c0e67e4c61f53f277e5ae7", 1459, &Patch34644}, // SC2 34644: Patched "Base1.SC2Data"
+ {_T("MPQ_2013_v4_Base3.SC2Maps"), NULL, "831ed96de221b4018d4bc9e09593c540", 2080, &Patch34644m},// SC2 34644: Patched "Base3.SC2Maps"
+ {_T("MPQ_2013_v4_Mods#Liberty.SC2Mod#enGB.SC2Data"), NULL, "fde3842552c1a9cd5ceee0e571227d18", 17, &Patch36281}, // SC2 36281: Patched "Mods#Liberty.SC2Mod#enGB.SC2Data"
+ {_T("MPQ_2014_v4_base-Win.MPQ"), NULL, "337b609b2469a6732f2837eae8f730a4", 207, &PatchH3604}, // HSTN 3604: Patched "base-Win.MPQ"
+ {_T("MPQ_2014_v4_base-Win.MPQ"), NULL, "28c3447bdc6b221b5cb346123ea03a94", 234, &PatchH6898}, // HSTN 6898: Patched "base-Win.MPQ"
};
static const TEST_INFO Test_Signature[] =
@@ -4159,6 +4032,18 @@ static const TEST_INFO Test_CompactArchive[] = {_T("MPQ_2013_v4_expansion1.MPQ"), _T("StormLibTest_CraftedMpq3_v4.mpq"), TRUE}
};
+static const TEST_INFO Test_AddFile[] =
+{
+ // Adding a file to MPQ that had size of the file table equal
+ // or greater than hash table, but has free entries
+ {_T("MPQ_2014_v1_out1.w3x"), NULL, 0},
+ {_T("MPQ_2014_v1_out2.w3x"), NULL, 0},
+
+ // Adding a file to MPQ and testing that (listfile) and (attributes) has the same state like before
+ {_T("MPQ_1997_v1_Diablo1_DIABDAT.MPQ"), NULL, TFLAG_REOPEN},
+ {_T("MPQ_2013_v4_SC2_EmptyMap.SC2Map"), NULL, TFLAG_REOPEN | TFLAG_HAS_LISTFILE | TFLAG_HAS_ATTRIBUTES},
+};
+
//-----------------------------------------------------------------------------
// Main
@@ -4167,10 +4052,10 @@ static const TEST_INFO Test_CompactArchive[] = #define TEST_STREAM_OPERATIONS
#define TEST_MASTER_MIRROR
#define TEST_SINGLE_MPQS
-#define TEST_PATCHED_MPQS
#define TEST_VERIFY_SIGNATURE
#define TEST_MISC_TESTS
#define TEST_COMPACT_ARCHIVES
+#define TEST_ADD_NEW_FILE
int _tmain(int argc, TCHAR * argv[])
{
@@ -4232,34 +4117,13 @@ int _tmain(int argc, TCHAR * argv[]) {
for(size_t i = 0; i < _countof(Test_Mpqs); i++)
{
- // Ignore the error code here; we want to see results of all opens
- dwErrCode = TestArchive(Test_Mpqs[i].szMpqName1, // Plain archive name
- Test_Mpqs[i].szMpqName2, // List file (NULL if none)
- Test_Mpqs[i].dwFlags, // What exactly to do
- (LPCSTR)Test_Mpqs[i].param1, // The 1st parameter
- (LPCSTR)Test_Mpqs[i].param2); // The 2nd parameter
- dwErrCode = ERROR_SUCCESS;
+ dwErrCode = TestArchive(Test_Mpqs[i]);
+ if(dwErrCode != ERROR_SUCCESS)
+ break;
}
}
#endif // TEST_LOCAL_MPQs
-#ifdef TEST_PATCHED_MPQS // Test opening patched archives - correct, damaged, protected
- if(dwErrCode == ERROR_SUCCESS)
- {
- for(size_t i = 0; i < _countof(Test_Patched_Mpqs); i++)
- {
- LPCTSTR * PatchList = (LPCTSTR *)Test_Patched_Mpqs[i].param1;
- LPCSTR szFileName = (LPCSTR)Test_Patched_Mpqs[i].param2;
-
- // Ignore the error code here; we want to see results of all opens
- dwErrCode = TestArchive_Patched(PatchList, // List of patches
- szFileName, // Name of a file
- Test_Patched_Mpqs[i].dwFlags);
- dwErrCode = ERROR_SUCCESS;
- }
- }
-#endif // TEST_PATCHED_MPQS
-
#ifdef TEST_VERIFY_SIGNATURE // Verify digital signatures of the archives
if(dwErrCode == ERROR_SUCCESS)
{
@@ -4296,13 +4160,29 @@ int _tmain(int argc, TCHAR * argv[]) for(size_t i = 0; i < _countof(Test_CompactArchive); i++)
{
// Ignore the error code here; we want to see results of all opens
- TestOpenArchive_CompactArchive(Test_CompactArchive[i].szMpqName1,
- Test_CompactArchive[i].szMpqName2,
- Test_CompactArchive[i].dwFlags);
+ dwErrCode = TestOpenArchive_CompactArchive(Test_CompactArchive[i].szMpqName1,
+ Test_CompactArchive[i].szMpqName2,
+ Test_CompactArchive[i].dwFlags);
+ if(dwErrCode != ERROR_SUCCESS)
+ break;
}
}
#endif
+#ifdef TEST_ADD_NEW_FILE // Test adding new file to existing archive
+ if(dwErrCode == ERROR_SUCCESS)
+ {
+ for(size_t i = 0; i < _countof(Test_AddFile); i++)
+ {
+ // Ignore the error code here; we want to see results of all opens
+ dwErrCode = TestOpenArchive_AddFile(Test_AddFile[i].szMpqName1,
+ Test_AddFile[i].dwFlags);
+ if(dwErrCode != ERROR_SUCCESS)
+ break;
+ }
+ }
+#endif // TEST_ADD_NEW_FILE
+
// Verify SHA1 of each MPQ that we have in the list
if(dwErrCode == ERROR_SUCCESS)
dwErrCode = FindFiles(ForEachFile_VerifyFileChecksum, szMpqSubDir);
@@ -4311,21 +4191,6 @@ int _tmain(int argc, TCHAR * argv[]) if(dwErrCode == ERROR_SUCCESS)
dwErrCode = FindFiles(ForEachFile_OpenArchive, NULL);
- // Compact the archive
- if(dwErrCode == ERROR_SUCCESS)
- dwErrCode = TestAddFile_FullTable(_T("MPQ_2014_v1_out1.w3x"));
-
- if(dwErrCode == ERROR_SUCCESS)
- dwErrCode = TestAddFile_FullTable(_T("MPQ_2014_v1_out2.w3x"));
-
- // Test modifying file with no (listfile) and no (attributes)
- if(dwErrCode == ERROR_SUCCESS)
- dwErrCode = TestAddFile_ListFileTest(_T("MPQ_1997_v1_Diablo1_DIABDAT.MPQ"), false, false);
-
- // Test modifying an archive that contains (listfile) and (attributes)
- if(dwErrCode == ERROR_SUCCESS)
- dwErrCode = TestAddFile_ListFileTest(_T("MPQ_2013_v4_SC2_EmptyMap.SC2Map"), true, true);
-
// Create an empty archive v2
if(dwErrCode == ERROR_SUCCESS)
dwErrCode = TestCreateArchive_EmptyMpq(_T("StormLibTest_EmptyMpq_v2.mpq"), MPQ_CREATE_ARCHIVE_V2 | MPQ_CREATE_LISTFILE | MPQ_CREATE_ATTRIBUTES);
diff --git a/test/stormlib-test-001.txt b/test/stormlib-test-001.txt index 89aac44..8165ba8 100644 --- a/test/stormlib-test-001.txt +++ b/test/stormlib-test-001.txt @@ -22,6 +22,8 @@ TestMpq (MPQ_1997_v1_Diablo1_DIABDAT.MPQ) succeeded. TestMpq (MPQ_1997_v1_patch_rt_SC1B.mpq) succeeded. TestMpq (MPQ_1997_v1_StarDat_SC1B.mpq) succeeded. TestMpq (MPQ_1997_v1_INSTALL_SC1B.EXE_) succeeded. +TestMpq: Warning: CRC32 error on (signature) +TestMpq: Warning: CRC32 error on (signature) TestMpq (MPQ_2016_v1_D2XP_IX86_1xx_114a.mpq) succeeded. TestMpq (MPQ_2018_v1_icon_error.w3m) succeeded. TestMpq (MPQ_1997_v1_Diablo1_STANDARD.SNP) succeeded. @@ -31,6 +33,9 @@ TestMpq (MPQ_2013_v4_patch-base-16357.MPQ) succeeded. TestMpq (MPQ_2011_v4_InvalidHetEntryCount.MPQ) succeeded. TestMpq (MPQ_2002_v1_BlockTableCut.MPQ) succeeded. TestMpq (MPQ_2010_v2_HasUserData.s2ma) succeeded. +TestMpq: Warning: CRC32 error on (listfile) +TestMpq: Warning: CRC32 error on (listfile) +TestMpq: Warning: CRC32 error on File00000003.xxx TestMpq (MPQ_2014_v1_AttributesOneEntryLess.w3x) succeeded. TestMpq (MPQ_2020_v1_AHF04patch.mix) succeeded. TestMpq (MPQ_2010_v3_expansion-locale-frFR.MPQ) succeeded. @@ -74,17 +79,17 @@ TestMpq (MPx_2013_v1_WarOfTheImmortals.sqp) succeeded. TestMpq (MPx_2022_v1_Music.mpk) succeeded. TestMpq (MPx_2022_v1_Scp.mpk) succeeded. TestMpq (MPx_2022_v1_UI.mpk) succeeded. -PatchedMPQ (MPQ_1998_v1_StarCraft.mpq) succeeded. -PatchedMPQ (MPQ_2012_v4_OldWorld.MPQ) succeeded. -PatchedMPQ (MPQ_2013_v4_world.MPQ) succeeded. -PatchedMPQ (MPQ_2013_v4_locale-enGB.MPQ) succeeded. -PatchedMPQ (MPQ_2013_v4_Base1.SC2Data) succeeded. -PatchedMPQ (MPQ_2013_v4_Base1.SC2Data) succeeded. -PatchedMPQ (MPQ_2013_v4_Base3.SC2Maps) succeeded. -PatchedMPQ (MPQ_2013_v4_Mods#Core.SC2Mod#enGB.SC2Assets) succeeded. -PatchedMPQ (MPQ_2013_v4_Mods#Liberty.SC2Mod#enGB.SC2Data) succeeded. -PatchedMPQ (MPQ_2014_v4_base-Win.MPQ) succeeded. -PatchedMPQ (MPQ_2014_v4_base-Win.MPQ) succeeded. +TestMpq (MPQ_1998_v1_StarCraft.mpq) succeeded. +TestMpq (MPQ_2012_v4_OldWorld.MPQ) succeeded. +TestMpq (MPQ_2013_v4_world.MPQ) succeeded. +TestMpq (MPQ_2013_v4_locale-enGB.MPQ) succeeded. +TestMpq (MPQ_2013_v4_Base1.SC2Data) succeeded. +TestMpq (MPQ_2013_v4_Mods#Core.SC2Mod#enGB.SC2Assets) succeeded. +TestMpq (MPQ_2013_v4_Base1.SC2Data) succeeded. +TestMpq (MPQ_2013_v4_Base3.SC2Maps) succeeded. +TestMpq (MPQ_2013_v4_Mods#Liberty.SC2Mod#enGB.SC2Data) succeeded. +TestMpq (MPQ_2014_v4_base-Win.MPQ) succeeded. +TestMpq (MPQ_2014_v4_base-Win.MPQ) succeeded. SignatureTest (MPQ_1997_v1_Diablo1_STANDARD.SNP) succeeded. SignatureTest (MPQ_1997_v1_Diablo1_STANDARD.SNP) succeeded. SignatureTest (MPQ_1999_v1_WeakSignature.exe) succeeded. @@ -105,6 +110,10 @@ CompactMpqTest: The file "(attributes)" is not present, but it should be CompactMpqTest: The file "(attributes)" is not present, but it should be CompactMpqTest (MPQ_2013_v4_SC2_EmptyMap.SC2Map) succeeded. CompactMpqTest (MPQ_2013_v4_expansion1.MPQ) succeeded. +AddFileToMpqTest (MPQ_2014_v1_out1.w3x) succeeded. +AddFileToMpqTest (MPQ_2014_v1_out2.w3x) succeeded. +AddFileToMpqTest (MPQ_1997_v1_Diablo1_DIABDAT.MPQ) succeeded. +AddFileToMpqTest (MPQ_2013_v4_SC2_EmptyMap.SC2Map) succeeded. VerifyFileHash succeeded. VerifyFileHash succeeded. VerifyFileHash succeeded. @@ -2336,11 +2345,8 @@ OpenEachMpqTest (StormLibTest_NoListFile.mpq) succeeded. OpenEachMpqTest (StormLibTest_NonStdNames.mpq) succeeded. OpenEachMpqTest (StormLibTest_ReadOnly.mpq) succeeded. OpenEachMpqTest (StormLibTest_ReadWrite.mpq) succeeded. +OpenEachMpqTest (StormLibTest_Reopened.mpq) succeeded. OpenEachMpqTest (File00000003.mpq) succeeded. -FullMpqTest (MPQ_2014_v1_out1.w3x) succeeded. -FullMpqTest (MPQ_2014_v1_out2.w3x) succeeded. -ListFileTest (MPQ_1997_v1_Diablo1_DIABDAT.MPQ) succeeded. -ListFileTest (MPQ_2013_v4_SC2_EmptyMap.SC2Map) succeeded. CreateEmptyMpq: The file "File00000000.xxx" is present, but it should not be CreateEmptyMpq: The file "File00000000.xxx" is present, but it should not be CreateGapsTest (StormLibTest_GapsTest.mpq) succeeded. @@ -2353,9 +2359,11 @@ CreateFullMpq (StormLibTest_FileTableFull.mpq) succeeded. IncMaxFileCount (StormLibTest_IncMaxFileCount.mpq) succeeded. MpqUnicodeName succeeded. FileFlagTest (StormLibTest_FileFlagTest.mpq) succeeded. -CompressionsTest (StormLibTest_AddWaveMonoTest.mpq) succeeded. +CompressionsTest: Warning: CRC32 error on WaveFile_01.wav +CompressionsTest: Warning: CRC32 error on WaveFile_02.wav CompressionsTest (StormLibTest_AddWaveMonoBadTest.mpq) succeeded. -CompressionsTest (StormLibTest_AddWaveStereoTest.mpq) succeeded. +CompressionsTest: Warning: CRC32 error on WaveFile_01.wav +CompressionsTest: Warning: CRC32 error on WaveFile_02.wav ListFilePos (StormLibTest_ListFilePos.mpq) succeeded. BigMpqTest (StormLibTest_BigArchive_v4.mpq) succeeded. ModifyTest (MPQ_2014_v4_Base.StormReplay) succeeded. |