diff --git a/make-msvc.bat b/make-msvc.bat index 1a22835..80d99fe 100644 --- a/make-msvc.bat +++ b/make-msvc.bat @@ -21,10 +21,10 @@ 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 2019 -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 +if not "x%VCVARS_2008%" == "x" call :BuildLibs "%VCVARS_2008%" x86 %LIB_NAME%_vs08.sln \vs2008 +if not "x%VCVARS_2008%" == "x" call :BuildLibs "%VCVARS_2008%" x64 %LIB_NAME%_vs08.sln \vs2008 +if not "x%VCVARS_2019%" == "x" call :BuildLibs "%VCVARS_2019%" x86 %LIB_NAME%_vs19.sln +if not "x%VCVARS_2019%" == "x" call :BuildLibs "%VCVARS_2019%" x64 %LIB_NAME%_vs19.sln goto:eof ::----------------------------------------------------------------------------- diff --git a/src/SBaseCommon.cpp b/src/SBaseCommon.cpp index 4b2bd6d..77590d6 100644 --- a/src/SBaseCommon.cpp +++ b/src/SBaseCommon.cpp @@ -23,8 +23,7 @@ char StormLibCopyright[] = "StormLib v " STORMLIB_VERSION_STRING " Copyright Lad DWORD g_dwMpqSignature = ID_MPQ; // Marker for MPQ header DWORD g_dwHashTableKey = MPQ_KEY_HASH_TABLE; // Key for hash table DWORD g_dwBlockTableKey = MPQ_KEY_BLOCK_TABLE; // Key for block table -LCID g_lcFileLocale = LANG_NEUTRAL; // File locale -USHORT wPlatform = 0; // File platform +LCID g_lcFileLocale = 0; // Compound of file locale and platform //----------------------------------------------------------------------------- // Conversion to uppercase/lowercase @@ -737,12 +736,13 @@ TMPQFile * IsValidFileHandle(HANDLE hFile) // Hash table and block table manipulation // Attempts to search a free hash entry, or an entry whose names and locale matches -TMPQHash * FindFreeHashEntry(TMPQArchive * ha, DWORD dwStartIndex, DWORD dwName1, DWORD dwName2, LCID lcLocale) +TMPQHash * FindFreeHashEntry(TMPQArchive * ha, DWORD dwStartIndex, DWORD dwName1, DWORD dwName2, LCID lcFileLocale) { TMPQHash * pDeletedEntry = NULL; // If a deleted entry was found in the continuous hash range TMPQHash * pFreeEntry = NULL; // If a free entry was found in the continuous hash range DWORD dwHashIndexMask = HASH_INDEX_MASK(ha); DWORD dwIndex; + USHORT Locale = SFILE_LOCALE(lcFileLocale); // Set the initial index dwStartIndex = dwIndex = (dwStartIndex & dwHashIndexMask); @@ -757,7 +757,7 @@ TMPQHash * FindFreeHashEntry(TMPQArchive * ha, DWORD dwStartIndex, DWORD dwName1 TMPQHash * pHash = ha->pHashTable + dwIndex; // If we found a matching entry, return that one - if(pHash->dwName1 == dwName1 && pHash->dwName2 == dwName2 && pHash->lcLocale == lcLocale) + if(pHash->dwName1 == dwName1 && pHash->dwName2 == dwName2 && pHash->Locale == Locale) return pHash; // If we found a deleted entry, remember it but keep searching @@ -849,7 +849,7 @@ TMPQHash * GetNextHashEntry(TMPQArchive * ha, TMPQHash * pFirstHash, TMPQHash * TMPQHash * AllocateHashEntry( TMPQArchive * ha, TFileEntry * pFileEntry, - LCID lcLocale) + LCID lcFileLocale) { TMPQHash * pHash; DWORD dwStartIndex = ha->pfnHashString(pFileEntry->szFileName, MPQ_HASH_TABLE_INDEX); @@ -857,14 +857,15 @@ TMPQHash * AllocateHashEntry( DWORD dwName2 = ha->pfnHashString(pFileEntry->szFileName, MPQ_HASH_NAME_B); // Attempt to find a free hash entry - pHash = FindFreeHashEntry(ha, dwStartIndex, dwName1, dwName2, lcLocale); + pHash = FindFreeHashEntry(ha, dwStartIndex, dwName1, dwName2, lcFileLocale); if(pHash != NULL) { // Fill the free hash entry pHash->dwName1 = dwName1; pHash->dwName2 = dwName2; - pHash->lcLocale = (USHORT)lcLocale; - pHash->Platform = 0; + pHash->Locale = SFILE_LOCALE(lcFileLocale); + pHash->Platform = SFILE_PLATFORM(lcFileLocale); + pHash->Reserved = 0; pHash->dwBlockIndex = (DWORD)(pFileEntry - ha->pFileTable); } diff --git a/src/SBaseDumpData.cpp b/src/SBaseDumpData.cpp index b08796a..16313dd 100644 --- a/src/SBaseDumpData.cpp +++ b/src/SBaseDumpData.cpp @@ -54,7 +54,7 @@ void DumpHashTable(TMPQHash * pHashTable, DWORD dwHashTableSize) printf("[%08x] %08X %08X %04X %02X %08X\n", i, pHashTable[i].dwName1, pHashTable[i].dwName2, - pHashTable[i].lcLocale, + pHashTable[i].Locale, pHashTable[i].Platform, pHashTable[i].dwBlockIndex); } diff --git a/src/SBaseFileTable.cpp b/src/SBaseFileTable.cpp index 1122ab1..b68de51 100644 --- a/src/SBaseFileTable.cpp +++ b/src/SBaseFileTable.cpp @@ -765,11 +765,13 @@ static bool IsValidHashEntry1(TMPQArchive * ha, TMPQHash * pHash, TMPQBlock * pB // 2) A hash table entry with the neutral|matching locale and neutral|matching platform // 3) NULL // Storm_2016.dll: 15020940 -static TMPQHash * GetHashEntryLocale(TMPQArchive * ha, const char * szFileName, LCID lcLocale, BYTE Platform) +static TMPQHash * GetHashEntryLocale(TMPQArchive * ha, const char * szFileName, LCID lcFileLocale) { TMPQHash * pFirstHash = GetFirstHashEntry(ha, szFileName); TMPQHash * pBestEntry = NULL; TMPQHash * pHash = pFirstHash; + USHORT Locale = SFILE_LOCALE(lcFileLocale); + BYTE Platform = SFILE_PLATFORM(lcFileLocale); // Parse the found hashes while(pHash != NULL) @@ -778,13 +780,13 @@ static TMPQHash * GetHashEntryLocale(TMPQArchive * ha, const char * szFileName, // If the hash entry matches both locale and platform, return it immediately // Only do that for non-0 locale&platform, because for loc&plat=0, there's different // processing in Warcraft III vs. Starcraft, which is abused by some protectors. - if((lcLocale || Platform) && pHash->lcLocale == lcLocale && pHash->Platform == Platform) + if((Locale || Platform) && pHash->Locale == Locale && pHash->Platform == Platform) return pHash; // Storm_2016.dll: 150209D9 // If (locale matches or is neutral) AND (platform matches or is neutral), remember this as the best entry // Also remember the first matching entry for Starcraft maps - if(pHash->lcLocale == 0 || pHash->lcLocale == lcLocale) + if(pHash->Locale == 0 || pHash->Locale == Locale) { if(pHash->Platform == 0 || pHash->Platform == Platform) { @@ -801,26 +803,31 @@ static TMPQHash * GetHashEntryLocale(TMPQArchive * ha, const char * szFileName, } // Returns a hash table entry in the following order: -// 1) A hash table entry with the preferred locale +// 1) A hash table entry with the preferred locale&platform // 2) NULL -static TMPQHash * GetHashEntryExact(TMPQArchive * ha, const char * szFileName, LCID lcLocale) +// In case there are multiple items with the same locale&platform, +// we need to return the last one. This is because it must correspond to SFileOpenFileEx +static TMPQHash * GetHashEntryExact(TMPQArchive * ha, const char * szFileName, LCID lcFileLocale) { TMPQHash * pFirstHash = GetFirstHashEntry(ha, szFileName); + TMPQHash * pBestHash = NULL; TMPQHash * pHash = pFirstHash; + USHORT Locale = SFILE_LOCALE(lcFileLocale); + BYTE Platform = SFILE_PLATFORM(lcFileLocale); // Parse the found hashes while(pHash != NULL) { - // If the locales match, return it - if(pHash->lcLocale == lcLocale) - return pHash; + // If the locales match, we remember this one as the best one + if(pHash->Locale == Locale && pHash->Platform == Platform) + pBestHash = pHash; // Get the next hash entry for that file pHash = GetNextHashEntry(ha, pFirstHash, pHash); } - // Not found - return NULL; + // Return the best hash or NULL + return pBestHash; } // Defragment the file table so it does not contain any gaps @@ -925,7 +932,6 @@ static DWORD BuildFileTableFromBlockTable( if(ha->dwFlags & (MPQ_FLAG_HASH_TABLE_CUT | MPQ_FLAG_BLOCK_TABLE_CUT)) { // Sanity checks - assert(pHeader->wFormatVersion == MPQ_FORMAT_VERSION_1); assert(pHeader->HiBlockTablePos64 == 0); // Allocate the translation table @@ -1967,7 +1973,7 @@ void FreeBetTable(TMPQBetTable * pBetTable) //----------------------------------------------------------------------------- // Support for file table -TFileEntry * GetFileEntryLocale(TMPQArchive * ha, const char * szFileName, LCID lcLocale, LPDWORD PtrHashIndex) +TFileEntry * GetFileEntryLocale(TMPQArchive * ha, const char * szFileName, LCID lcFileLocale, LPDWORD PtrHashIndex) { TMPQHash * pHash; DWORD dwFileIndex; @@ -1977,7 +1983,7 @@ TFileEntry * GetFileEntryLocale(TMPQArchive * ha, const char * szFileName, LCID // we will need the pointer to hash table entry if(ha->pHashTable != NULL) { - pHash = GetHashEntryLocale(ha, szFileName, lcLocale, 0); + pHash = GetHashEntryLocale(ha, szFileName, lcFileLocale); if(pHash != NULL && MPQ_BLOCK_INDEX(pHash) < ha->dwFileTableSize) { if(PtrHashIndex != NULL) @@ -1998,7 +2004,7 @@ TFileEntry * GetFileEntryLocale(TMPQArchive * ha, const char * szFileName, LCID return NULL; } -TFileEntry * GetFileEntryExact(TMPQArchive * ha, const char * szFileName, LCID lcLocale, LPDWORD PtrHashIndex) +TFileEntry * GetFileEntryExact(TMPQArchive * ha, const char * szFileName, LCID lcFileLocale, LPDWORD PtrHashIndex) { TMPQHash * pHash; DWORD dwFileIndex; @@ -2006,7 +2012,7 @@ TFileEntry * GetFileEntryExact(TMPQArchive * ha, const char * szFileName, LCID l // If the hash table is present, find the entry from hash table if(ha->pHashTable != NULL) { - pHash = GetHashEntryExact(ha, szFileName, lcLocale); + pHash = GetHashEntryExact(ha, szFileName, lcFileLocale); if(pHash != NULL && MPQ_BLOCK_INDEX(pHash) < ha->dwFileTableSize) { if(PtrHashIndex != NULL) @@ -2062,7 +2068,7 @@ void AllocateFileName(TMPQArchive * ha, TFileEntry * pFileEntry, const char * sz } } -TFileEntry * AllocateFileEntry(TMPQArchive * ha, const char * szFileName, LCID lcLocale, LPDWORD PtrHashIndex) +TFileEntry * AllocateFileEntry(TMPQArchive * ha, const char * szFileName, LCID lcFileLocale, LPDWORD PtrHashIndex) { TFileEntry * pFileTableEnd = ha->pFileTable + ha->dwFileTableSize; TFileEntry * pFreeEntry = NULL; @@ -2109,10 +2115,10 @@ TFileEntry * AllocateFileEntry(TMPQArchive * ha, const char * szFileName, LCID l if(ha->pHashTable != NULL) { // Make sure that the entry is not there yet - assert(GetHashEntryExact(ha, szFileName, lcLocale) == NULL); + assert(GetHashEntryExact(ha, szFileName, lcFileLocale) == NULL); // Find a free hash table entry for the name - pHash = AllocateHashEntry(ha, pFreeEntry, lcLocale); + pHash = AllocateHashEntry(ha, pFreeEntry, lcFileLocale); if(pHash == NULL) return NULL; @@ -2139,7 +2145,7 @@ DWORD RenameFileEntry( { TFileEntry * pFileEntry = hf->pFileEntry; TMPQHash * pHashEntry = hf->pHashEntry; - LCID lcLocale = 0; + LCID lcFileLocale = 0; // If the archive hash hash table, we need to free the hash table entry if(ha->pHashTable != NULL) @@ -2150,12 +2156,12 @@ DWORD RenameFileEntry( return ERROR_NOT_SUPPORTED; // Save the locale - lcLocale = pHashEntry->lcLocale; + lcFileLocale = SFILE_MAKE_LCID(pHashEntry->Locale, pHashEntry->Platform); // Mark the hash table entry as deleted pHashEntry->dwName1 = 0xFFFFFFFF; pHashEntry->dwName2 = 0xFFFFFFFF; - pHashEntry->lcLocale = 0xFFFF; + pHashEntry->Locale = 0xFFFF; pHashEntry->Platform = 0xFF; pHashEntry->Reserved = 0xFF; pHashEntry->dwBlockIndex = HASH_ENTRY_DELETED; @@ -2173,7 +2179,7 @@ DWORD RenameFileEntry( if(ha->pHashTable != NULL) { // Since we freed one hash entry before, this must succeed - hf->pHashEntry = AllocateHashEntry(ha, pFileEntry, lcLocale); + hf->pHashEntry = AllocateHashEntry(ha, pFileEntry, lcFileLocale); assert(hf->pHashEntry != NULL); } @@ -2196,7 +2202,7 @@ DWORD DeleteFileEntry(TMPQArchive * ha, TMPQFile * hf) // Mark the hash table entry as deleted pHashEntry->dwName1 = 0xFFFFFFFF; pHashEntry->dwName2 = 0xFFFFFFFF; - pHashEntry->lcLocale = 0xFFFF; + pHashEntry->Locale = 0xFFFF; pHashEntry->Platform = 0xFF; pHashEntry->Reserved = 0xFF; pHashEntry->dwBlockIndex = HASH_ENTRY_DELETED; @@ -2928,7 +2934,7 @@ DWORD RebuildFileTable(TMPQArchive * ha, DWORD dwNewHashTableSize) if(IsValidHashEntry(ha, pHash)) { pFileEntry = ha->pFileTable + MPQ_BLOCK_INDEX(pHash); - AllocateHashEntry(ha, pFileEntry, pHash->lcLocale); + AllocateHashEntry(ha, pFileEntry, SFILE_MAKE_LCID(pHash->Locale, pHash->Platform)); } } diff --git a/src/SBaseSubTypes.cpp b/src/SBaseSubTypes.cpp index 9808ef3..59be7e8 100644 --- a/src/SBaseSubTypes.cpp +++ b/src/SBaseSubTypes.cpp @@ -53,7 +53,7 @@ typedef struct _TSQPHeader typedef struct _TSQPHash { - // Most likely the lcLocale+wPlatform. + // Most likely the Locale + Platform DWORD dwAlwaysZero; // If the hash table entry is valid, this is the index into the block table of the file. @@ -216,8 +216,8 @@ TMPQHash * LoadSqpHashTable(TMPQArchive * ha) pMpqHash->dwName1 = TempEntry.dwName1; pMpqHash->dwName2 = TempEntry.dwName2; pMpqHash->dwBlockIndex = MPQ_BLOCK_INDEX(&TempEntry); + pMpqHash->Locale = 0; pMpqHash->Platform = 0; - pMpqHash->lcLocale = 0; pMpqHash->Reserved = 0; } } @@ -547,8 +547,9 @@ TMPQHash * LoadMpkHashTable(TMPQArchive * ha) // Copy the MPK hash entry to the hash table pHash->dwBlockIndex = pMpkHash[i].dwBlockIndex; + pHash->Locale = 0; pHash->Platform = 0; - pHash->lcLocale = 0; + pHash->Reserved = 0; pHash->dwName1 = pMpkHash[i].dwName2; pHash->dwName2 = pMpkHash[i].dwName3; } diff --git a/src/SFileAddFile.cpp b/src/SFileAddFile.cpp index a65244e..b1288f1 100644 --- a/src/SFileAddFile.cpp +++ b/src/SFileAddFile.cpp @@ -400,7 +400,7 @@ DWORD SFileAddFile_Init( const char * szFileName, ULONGLONG FileTime, DWORD dwFileSize, - LCID lcLocale, + LCID lcFileLocale, DWORD dwFlags, TMPQFile ** phf) { @@ -430,7 +430,7 @@ DWORD SFileAddFile_Init( // If the MPQ is of version 3.0 or higher, we ignore file locale. // This is because HET and BET tables have no known support for it if(ha->pHeader->wFormatVersion >= MPQ_FORMAT_VERSION_3) - lcLocale = 0; + lcFileLocale = 0; // Allocate the TMPQFile entry for newly added file hf = CreateWritableHandle(ha, dwFileSize); @@ -441,7 +441,7 @@ DWORD SFileAddFile_Init( if(dwErrCode == ERROR_SUCCESS) { // Check if the file already exists in the archive - pFileEntry = GetFileEntryLocale(ha, szFileName, lcLocale, &dwHashIndex); + pFileEntry = GetFileEntryExact(ha, szFileName, lcFileLocale, &dwHashIndex); if(pFileEntry != NULL) { if(dwFlags & MPQ_FILE_REPLACEEXISTING) @@ -452,7 +452,7 @@ DWORD SFileAddFile_Init( else { // Attempt to allocate new file entry - pFileEntry = AllocateFileEntry(ha, szFileName, lcLocale, &dwHashIndex); + pFileEntry = AllocateFileEntry(ha, szFileName, lcFileLocale, &dwHashIndex); if(pFileEntry != NULL) InvalidateInternalFiles(ha); else @@ -467,7 +467,9 @@ DWORD SFileAddFile_Init( if(dwErrCode == ERROR_SUCCESS && ha->pHashTable != NULL && dwHashIndex < ha->pHeader->dwHashTableSize) { hf->pHashEntry = ha->pHashTable + dwHashIndex; - hf->pHashEntry->lcLocale = (USHORT)lcLocale; + hf->pHashEntry->Locale = SFILE_LOCALE(lcFileLocale); + hf->pHashEntry->Platform = SFILE_PLATFORM(lcFileLocale); + hf->pHashEntry->Reserved = 0; } // Prepare the file key @@ -762,7 +764,7 @@ bool WINAPI SFileCreateFile( const char * szArchivedName, ULONGLONG FileTime, DWORD dwFileSize, - LCID lcLocale, + LCID lcFileLocale, DWORD dwFlags, HANDLE * phFile) { @@ -805,7 +807,7 @@ bool WINAPI SFileCreateFile( // Initiate the add file operation if(dwErrCode == ERROR_SUCCESS) - dwErrCode = SFileAddFile_Init(ha, szArchivedName, FileTime, dwFileSize, lcLocale, dwFlags, (TMPQFile **)phFile); + dwErrCode = SFileAddFile_Init(ha, szArchivedName, FileTime, dwFileSize, lcFileLocale, dwFlags, (TMPQFile **)phFile); // Deal with the errors if(dwErrCode != ERROR_SUCCESS) @@ -1293,7 +1295,9 @@ bool WINAPI SFileSetFileLocale(HANDLE hFile, LCID lcNewLocale) } // Update the locale in the hash table entry - hf->pHashEntry->lcLocale = (USHORT)lcNewLocale; + hf->pHashEntry->Locale = SFILE_LOCALE(lcNewLocale); + hf->pHashEntry->Platform = SFILE_PLATFORM(lcNewLocale); + hf->pHashEntry->Reserved = 0; ha->dwFlags |= MPQ_FLAG_CHANGED; return true; } diff --git a/src/SFileFindFile.cpp b/src/SFileFindFile.cpp index 223e194..4de1022 100644 --- a/src/SFileFindFile.cpp +++ b/src/SFileFindFile.cpp @@ -263,7 +263,7 @@ static bool DoMPQSearch_FileEntry( lpFindFileData->dwFileSize = pPatchEntry->dwFileSize; lpFindFileData->dwFileFlags = pPatchEntry->dwFlags; lpFindFileData->dwCompSize = pPatchEntry->dwCmpSize; - lpFindFileData->lcLocale = 0; // pPatchEntry->lcLocale; + lpFindFileData->lcLocale = 0; // pPatchEntry->lcFileLocale; // Fill the filetime lpFindFileData->dwFileTimeHi = (DWORD)(pPatchEntry->FileTime >> 32); @@ -273,7 +273,7 @@ static bool DoMPQSearch_FileEntry( if(pHashEntry != NULL) { lpFindFileData->dwHashIndex = (DWORD)(pHashEntry - ha->pHashTable); - lpFindFileData->lcLocale = pHashEntry->lcLocale; + lpFindFileData->lcLocale = SFILE_MAKE_LCID(pHashEntry->Locale, pHashEntry->Platform); } // Fill the file name and plain file name diff --git a/src/SFileGetFileInfo.cpp b/src/SFileGetFileInfo.cpp index b980755..77c86fd 100644 --- a/src/SFileGetFileInfo.cpp +++ b/src/SFileGetFileInfo.cpp @@ -410,7 +410,7 @@ bool WINAPI SFileGetFileInfo( return GetInfo(pvFileInfo, cbFileInfo, &pFileEntry->FileNameHash, sizeof(ULONGLONG), pcbLengthNeeded); case SFileInfoLocale: - dwInt32Value = hf->pHashEntry->lcLocale; + dwInt32Value = SFILE_MAKE_LCID(hf->pHashEntry->Locale, hf->pHashEntry->Platform); return GetInfo(pvFileInfo, cbFileInfo, &dwInt32Value, sizeof(DWORD), pcbLengthNeeded); case SFileInfoFileIndex: diff --git a/src/SFileListFile.cpp b/src/SFileListFile.cpp index 8ce9ae4..6adf1ab 100644 --- a/src/SFileListFile.cpp +++ b/src/SFileListFile.cpp @@ -580,7 +580,7 @@ static DWORD SFileAddInternalListFile( while(dwErrCode == ERROR_SUCCESS && pHash != NULL) { // Set the prefered locale to that from list file - SFileSetLocale(pHash->lcLocale); + SFileSetLocale(SFILE_MAKE_LCID(pHash->Locale, pHash->Platform)); // Add that listfile dwErrCode = SFileAddArbitraryListFile(ha, hMpq, NULL, dwMaxSize); diff --git a/src/SFileOpenArchive.cpp b/src/SFileOpenArchive.cpp index b85f24c..16e2491 100644 --- a/src/SFileOpenArchive.cpp +++ b/src/SFileOpenArchive.cpp @@ -209,10 +209,9 @@ LCID WINAPI SFileGetLocale() return g_lcFileLocale; } -LCID WINAPI SFileSetLocale(LCID lcNewLocale) +LCID WINAPI SFileSetLocale(LCID lcFileLocale) { - g_lcFileLocale = lcNewLocale; - return g_lcFileLocale; + return (g_lcFileLocale = lcFileLocale); } //----------------------------------------------------------------------------- diff --git a/src/SFileOpenFileEx.cpp b/src/SFileOpenFileEx.cpp index 96d8cfc..5dc2dbf 100644 --- a/src/SFileOpenFileEx.cpp +++ b/src/SFileOpenFileEx.cpp @@ -170,13 +170,13 @@ bool OpenPatchedFile(HANDLE hMpq, const char * szFileName, HANDLE * PtrFile) //----------------------------------------------------------------------------- // SFileEnumLocales enums all locale versions within MPQ. // Functions fills all available language identifiers on a file into the buffer -// pointed by plcLocales. There must be enough entries to copy the localed, +// pointed by PtrFileLocales. There must be enough entries to copy the localed, // otherwise the function returns ERROR_INSUFFICIENT_BUFFER. DWORD WINAPI SFileEnumLocales( HANDLE hMpq, const char * szFileName, - LCID * PtrLocales, + LCID * PtrFileLocales, LPDWORD PtrMaxLocales, DWORD dwSearchScope) { @@ -208,8 +208,8 @@ DWORD WINAPI SFileEnumLocales( while(pHash != NULL) { // Put the locales to the buffer - if(PtrLocales != NULL && dwLocales < dwMaxLocales) - *PtrLocales++ = pHash->lcLocale; + if(PtrFileLocales != NULL && dwLocales < dwMaxLocales) + *PtrFileLocales++ = SFILE_MAKE_LCID(pHash->Locale, pHash->Platform); dwLocales++; // Get the next locale diff --git a/src/StormCommon.h b/src/StormCommon.h index 7ff55e8..48fd86f 100644 --- a/src/StormCommon.h +++ b/src/StormCommon.h @@ -141,7 +141,7 @@ typedef struct _MPQ_SIGNATURE_INFO extern DWORD g_dwMpqSignature; // Marker for MPQ header extern DWORD g_dwHashTableKey; // Key for hash table extern DWORD g_dwBlockTableKey; // Key for block table -extern LCID g_lcFileLocale; // Preferred file locale +extern LCID g_lcFileLocale; // Preferred file locale and platform //----------------------------------------------------------------------------- // Conversion to uppercase/lowercase (and "/" to "\") @@ -250,10 +250,10 @@ DWORD ConvertMpqHeaderToFormat4(TMPQArchive * ha, ULONGLONG MpqOffset, ULONGLONG bool IsValidHashEntry(TMPQArchive * ha, TMPQHash * pHash); -TMPQHash * FindFreeHashEntry(TMPQArchive * ha, DWORD dwStartIndex, DWORD dwName1, DWORD dwName2, LCID lcLocale); +TMPQHash * FindFreeHashEntry(TMPQArchive * ha, DWORD dwStartIndex, DWORD dwName1, DWORD dwName2, LCID lcFileLocale); TMPQHash * GetFirstHashEntry(TMPQArchive * ha, const char * szFileName); TMPQHash * GetNextHashEntry(TMPQArchive * ha, TMPQHash * pFirstHash, TMPQHash * pPrevHash); -TMPQHash * AllocateHashEntry(TMPQArchive * ha, TFileEntry * pFileEntry, LCID lcLocale); +TMPQHash * AllocateHashEntry(TMPQArchive * ha, TFileEntry * pFileEntry, LCID lcFileLocale); TMPQExtHeader * LoadExtTable(TMPQArchive * ha, ULONGLONG ByteOffset, size_t Size, DWORD dwSignature, DWORD dwKey); TMPQHetTable * LoadHetTable(TMPQArchive * ha); @@ -282,14 +282,14 @@ TMPQBetTable * CreateBetTable(DWORD dwMaxFileCount); void FreeBetTable(TMPQBetTable * pBetTable); // Functions for finding files in the file table -TFileEntry * GetFileEntryLocale(TMPQArchive * ha, const char * szFileName, LCID lcLocale, LPDWORD PtrHashIndex = NULL); -TFileEntry * GetFileEntryExact(TMPQArchive * ha, const char * szFileName, LCID lcLocale, LPDWORD PtrHashIndex); +TFileEntry * GetFileEntryLocale(TMPQArchive * ha, const char * szFileName, LCID lcFileLocale, LPDWORD PtrHashIndex = NULL); +TFileEntry * GetFileEntryExact(TMPQArchive * ha, const char * szFileName, LCID lcFileLocale, LPDWORD PtrHashIndex); // Allocates file name in the file entry void AllocateFileName(TMPQArchive * ha, TFileEntry * pFileEntry, const char * szFileName); // Allocates new file entry in the MPQ tables. Reuses existing, if possible -TFileEntry * AllocateFileEntry(TMPQArchive * ha, const char * szFileName, LCID lcLocale, LPDWORD PtrHashIndex); +TFileEntry * AllocateFileEntry(TMPQArchive * ha, const char * szFileName, LCID lcFileLocale, LPDWORD PtrHashIndex); DWORD RenameFileEntry(TMPQArchive * ha, TMPQFile * hf, const char * szNewFileName); DWORD DeleteFileEntry(TMPQArchive * ha, TMPQFile * hf); @@ -378,7 +378,7 @@ DWORD SFileAddFile_Init( const char * szArchivedName, ULONGLONG ft, DWORD dwFileSize, - LCID lcLocale, + LCID lcFileLocale, DWORD dwFlags, TMPQFile ** phf ); diff --git a/src/StormLib.h b/src/StormLib.h index 1c4e199..85f5c4b 100644 --- a/src/StormLib.h +++ b/src/StormLib.h @@ -73,6 +73,7 @@ /* 18.09.15 9.20 Lad Release 9.20 */ /* 12.12.16 9.21 Lad Release 9.21 */ /* 10.11.17 9.22 Lad Release 9.22 */ +/* 28.09.22 9.24 Lad lcLocale -> lcFileLocale, also contains platform */ /*****************************************************************************/ #ifndef __STORMLIB_H__ @@ -142,8 +143,8 @@ extern "C" { //----------------------------------------------------------------------------- // Defines -#define STORMLIB_VERSION 0x0917 // Current version of StormLib (9.23) -#define STORMLIB_VERSION_STRING "9.23" // String version of StormLib version +#define STORMLIB_VERSION 0x0918 // Current version of StormLib (9.24) +#define STORMLIB_VERSION_STRING "9.24" // String version of StormLib version #define ID_MPQ 0x1A51504D // MPQ archive header ID ('MPQ\x1A') #define ID_MPQ_USERDATA 0x1B51504D // MPQ userdata entry ('MPQ\x1B') @@ -627,7 +628,7 @@ typedef struct _TMPQHash // The language of the file. This is a Windows LANGID data type, and uses the same values. // 0 indicates the default language (American English), or that the file is language-neutral. - USHORT lcLocale; + USHORT Locale; // The platform the file is used for. 0 indicates the default platform. // No other values have been observed. @@ -638,7 +639,7 @@ typedef struct _TMPQHash BYTE Reserved; BYTE Platform; - USHORT lcLocale; + USHORT Locale; #endif @@ -910,7 +911,7 @@ typedef struct _SFILE_FIND_DATA DWORD dwCompSize; // Compressed file size DWORD dwFileTimeLo; // Low 32-bits of the file time (0 if not present) DWORD dwFileTimeHi; // High 32-bits of the file time (0 if not present) - LCID lcLocale; // Locale version + LCID lcLocale; // Compound of file locale (16 bits) and platform (8 bits) } SFILE_FIND_DATA, *PSFILE_FIND_DATA; @@ -994,13 +995,18 @@ typedef bool (WINAPI * SFILEREADFILE)(HANDLE, void *, DWORD, LPDWORD, LPOVERLAP //----------------------------------------------------------------------------- // Functions for manipulation with StormLib global flags +// Macros for making LCID from Locale and Platform +#define SFILE_MAKE_LCID(locale, platform) ((LCID)(USHORT)locale | (LCID)(BYTE)platform << 0x10) +#define SFILE_LOCALE(lcFileLocale) (USHORT)(lcFileLocale & 0xFFFF) +#define SFILE_PLATFORM(lcFileLocale) (BYTE)(lcFileLocale >> 0x10) + // Alternate marker support. This is for MPQs masked as DLLs (*.asi), which // patch Storm.dll at runtime. Call before SFileOpenArchive bool WINAPI SFileSetArchiveMarkers(PSFILE_MARKERS pMarkers); // Call before SFileOpenFileEx LCID WINAPI SFileGetLocale(); -LCID WINAPI SFileSetLocale(LCID lcNewLocale); +LCID WINAPI SFileSetLocale(LCID lcFileLocale); //----------------------------------------------------------------------------- // Functions for archive manipulation @@ -1085,12 +1091,12 @@ bool WINAPI SListFileFindNextFile(HANDLE hFind, SFILE_FIND_DATA * lpFindFileDa bool WINAPI SListFileFindClose(HANDLE hFind); // Locale support -DWORD WINAPI SFileEnumLocales(HANDLE hMpq, const char * szFileName, LCID * plcLocales, LPDWORD pdwMaxLocales, DWORD dwSearchScope); +DWORD WINAPI SFileEnumLocales(HANDLE hMpq, const char * szFileName, LCID * PtrFileLocales, LPDWORD PtrMaxLocales, DWORD dwSearchScope); //----------------------------------------------------------------------------- // Support for adding files to the MPQ -bool WINAPI SFileCreateFile(HANDLE hMpq, const char * szArchivedName, ULONGLONG FileTime, DWORD dwFileSize, LCID lcLocale, DWORD dwFlags, HANDLE * phFile); +bool WINAPI SFileCreateFile(HANDLE hMpq, const char * szArchivedName, ULONGLONG FileTime, DWORD dwFileSize, LCID lcFileLocale, DWORD dwFlags, HANDLE * phFile); bool WINAPI SFileWriteFile(HANDLE hFile, const void * pvData, DWORD dwSize, DWORD dwCompression); bool WINAPI SFileFinishFile(HANDLE hFile); diff --git a/test/StormTest.cpp b/test/StormTest.cpp index c4b3179..e7a2434 100644 --- a/test/StormTest.cpp +++ b/test/StormTest.cpp @@ -41,6 +41,10 @@ #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 struct _TEST_INFO { LPCTSTR szMpqName1; @@ -85,11 +89,6 @@ 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); - -#define ERROR_UNDETERMINED_RESULT 0xC000FFFF - //----------------------------------------------------------------------------- // Testing data @@ -156,6 +155,12 @@ static const wchar_t szUnicodeName6[] = { // Arabic 0x0627, 0x0644, 0x0639, 0x0639, 0x0631, 0x0628, 0x064A, 0x0629, _T('.'), _T('m'), _T('p'), _T('q'), 0 }; +static SFILE_MARKERS MpqMarkers[] = +{ + {sizeof(SFILE_MARKERS), ID_MPQ, "(hash table)", "(block table)"}, + {sizeof(SFILE_MARKERS), 'XHSC', "(cash table)", "(clock table)"} +}; + static LPCTSTR PatchList_StarCraft[] = { _T("MPQ_1998_v1_StarCraft.mpq"), @@ -1386,14 +1391,14 @@ static TFileData * LoadLocalFile(TLogHelper * pLogger, LPCTSTR szFileName, bool return pFileData; } -static DWORD LoadLocalFileMD5(TLogHelper * pLogger, LPCTSTR szLocalFileName, LPBYTE md5_file_local) +static DWORD LoadLocalFileMD5(TLogHelper * pLogger, LPCTSTR szFileFullName, LPBYTE md5_file_local) { TFileData * pFileData; // Load the local file to memory - if((pFileData = LoadLocalFile(pLogger, szLocalFileName, true)) == NULL) + if((pFileData = LoadLocalFile(pLogger, szFileFullName, true)) == NULL) { - return pLogger->PrintError(_T("The file \"%s\" could not be loaded"), szLocalFileName); + return pLogger->PrintError(_T("The file \"%s\" could not be loaded"), szFileFullName); } // Calculate the hash @@ -1402,7 +1407,7 @@ static DWORD LoadLocalFileMD5(TLogHelper * pLogger, LPCTSTR szLocalFileName, LPB return ERROR_SUCCESS; } -static TFileData * LoadMpqFile(TLogHelper * pLogger, HANDLE hMpq, LPCSTR szFileName, LCID lcLocale = 0, bool bIgnoreOpedwErrCodes = false) +static TFileData * LoadMpqFile(TLogHelper * pLogger, HANDLE hMpq, LPCSTR szFileName, LCID lcFileLocale = 0, bool bIgnoreOpedwErrCodes = false) { TFileData * pFileData = NULL; HANDLE hFile; @@ -1421,7 +1426,7 @@ static TFileData * LoadMpqFile(TLogHelper * pLogger, HANDLE hMpq, LPCSTR szFileN #endif // Make sure that we open the proper locale file - SFileSetLocale(lcLocale); + SFileSetLocale(lcFileLocale); // Open the file from MPQ if(SFileOpenFileEx(hMpq, szFileName, 0, &hFile)) @@ -1817,7 +1822,7 @@ static DWORD CreateNewArchiveU(TLogHelper * pLogger, const wchar_t * szPlainName static DWORD OpenExistingArchive(TLogHelper * pLogger, LPCTSTR szFullPath, DWORD dwFlags, HANDLE * phMpq) { HANDLE hMpq = NULL; -// bool bReopenResult; + size_t nMarkerIndex; DWORD dwErrCode = ERROR_SUCCESS; // Is it an encrypted MPQ ? @@ -1830,6 +1835,10 @@ static DWORD OpenExistingArchive(TLogHelper * pLogger, LPCTSTR szFullPath, DWORD if(_tcsstr(szFullPath, _T(".MPQ.0")) != NULL) dwFlags |= STREAM_PROVIDER_BLOCK4; + // Handle ASI files properly + nMarkerIndex = (_tcsstr(szFullPath, _T(".asi")) != NULL) ? 1 : 0; + SFileSetArchiveMarkers(&MpqMarkers[nMarkerIndex]); + // Open the copied archive pLogger->PrintProgress(_T("Opening archive %s ..."), GetShortPlainName(szFullPath)); if(!SFileOpenArchive(szFullPath, 0, dwFlags, &hMpq)) @@ -1991,7 +2000,7 @@ static DWORD AddLocalFileToMpq( TLogHelper * pLogger, HANDLE hMpq, LPCSTR szArchivedName, - LPCTSTR szLocalFileName, + LPCTSTR szFileFullName, DWORD dwFlags = 0, DWORD dwCompression = 0, bool bMustSucceed = false) @@ -2000,7 +2009,7 @@ static DWORD AddLocalFileToMpq( DWORD dwVerifyResult; // Notify the user - pLogger->PrintProgress("Adding file %s (%u of %u)...", GetShortPlainName(szLocalFileName), pLogger->UserCount, pLogger->UserTotal); + pLogger->PrintProgress("Adding file %s (%u of %u)...", GetShortPlainName(szFileFullName), pLogger->UserCount, pLogger->UserTotal); pLogger->UserString = szArchivedName; // Get the default flags @@ -2013,7 +2022,7 @@ static DWORD AddLocalFileToMpq( SFileSetAddFileCallback(hMpq, AddFileCallback, pLogger); // Add the file to the MPQ - StringCopy(szFileName, _countof(szFileName), szLocalFileName); + StringCopy(szFileName, _countof(szFileName), szFileFullName); if(!SFileAddFileEx(hMpq, szFileName, szArchivedName, dwFlags, dwCompression, MPQ_COMPRESSION_NEXT_SAME)) { if(bMustSucceed) @@ -2507,7 +2516,7 @@ static DWORD TestArchive( DWORD dwExpectedFileCount = 0; DWORD dwMpqFlags = 0; TCHAR szFullName[MAX_PATH]; - LCID lcLocale = 0; + LCID lcFileLocale = 0; BYTE ObtainedMD5[MD5_DIGEST_SIZE] = {0}; bool bIgnoreOpedwErrCodes = false; @@ -2527,7 +2536,7 @@ static DWORD TestArchive( // If locale entered if(dwFlags & TFLG_FILE_LOCALE) { - lcLocale = (LCID)(dwFlags & TFLG_VALUE_MASK); + lcFileLocale = (LCID)(dwFlags & TFLG_VALUE_MASK); } // Put all file names into list @@ -2574,7 +2583,7 @@ static DWORD TestArchive( break; // Load the entire file 1 - FileDataList[i] = pFileData = LoadMpqFile(&Logger, hMpq, szFileName, lcLocale); + FileDataList[i] = pFileData = LoadMpqFile(&Logger, hMpq, szFileName, lcFileLocale); if(pFileData == NULL) { dwErrCode = Logger.PrintError("Failed to load the file %s", szFileName); @@ -3838,7 +3847,7 @@ static DWORD TestCreateArchive_FileFlagTest(LPCTSTR szPlainName) TCHAR szFileName2[MAX_PATH]; TCHAR szFullPath[MAX_PATH]; LPCSTR szMiddleFile = "FileTest_10.exe"; - LCID LocaleIDs[] = {0x000, 0x405, 0x406, 0x407, 0xFFFF}; + LCID LocaleIDs[] = {0x000, 0x405, 0x406, 0x407}; char szArchivedName[MAX_PATH]; DWORD dwMaxFileCount = 0; DWORD dwFileCount = 0; @@ -3896,7 +3905,7 @@ static DWORD TestCreateArchive_FileFlagTest(LPCTSTR szPlainName) // Add ZeroSize.txt several times under a different locale if(dwErrCode == ERROR_SUCCESS) { - for(size_t i = 0; LocaleIDs[i] != 0xFFFF; i++) + for(size_t i = 0; i < _countof(LocaleIDs); i++) { bool bMustSucceed = ((dwFileCount + 2) < dwMaxFileCount); @@ -4194,11 +4203,12 @@ static DWORD TestCreateArchive_BigArchive(LPCTSTR szPlainName) } // "MPQ_2014_v4_Heroes_Replay.MPQ", "AddFile-replay.message.events" -static DWORD TestModifyArchive_ReplaceFile(LPCTSTR szMpqPlainName, LPCTSTR szFileName) +static DWORD TestModifyArchive_ReplaceFile(LPCTSTR szMpqPlainName, LPCTSTR szFilePlainName) { TLogHelper Logger("ModifyTest", szMpqPlainName); HANDLE hMpq = NULL; - TCHAR szLocalFileName[MAX_PATH]; + TCHAR szFileFullName[MAX_PATH]; + TCHAR szMpqFullName[MAX_PATH]; char szArchivedName[MAX_PATH]; size_t nOffset = 0; DWORD dwErrCode; @@ -4207,11 +4217,14 @@ static DWORD TestModifyArchive_ReplaceFile(LPCTSTR szMpqPlainName, LPCTSTR szFil BYTE md5_file_in_mpq3[MD5_DIGEST_SIZE]; BYTE md5_file_local[MD5_DIGEST_SIZE]; - // Get the name of archived file - if(!_tcsnicmp(szFileName, _T("AddFile-"), 8)) + // Get the name of archived file as plain text + if(!_tcsnicmp(szFilePlainName, _T("AddFile-"), 8)) nOffset = 8; - StringCopy(szArchivedName, _countof(szArchivedName), szFileName + nOffset); - CreateFullPathName(szLocalFileName, _countof(szLocalFileName), szMpqSubDir, szFileName); + StringCopy(szArchivedName, _countof(szArchivedName), szFilePlainName + nOffset); + + // Get the full path of the archive and local file + CreateFullPathName(szFileFullName, _countof(szFileFullName), szMpqSubDir, szFilePlainName); + CreateFullPathName(szMpqFullName, _countof(szMpqFullName), NULL, szMpqPlainName); // Open an existing archive dwErrCode = OpenExistingArchiveWithCopy(&Logger, szMpqPlainName, szMpqPlainName, &hMpq); @@ -4225,7 +4238,7 @@ static DWORD TestModifyArchive_ReplaceFile(LPCTSTR szMpqPlainName, LPCTSTR szFil // Open the local file, calculate hash if(dwErrCode == ERROR_SUCCESS) { - dwErrCode = LoadLocalFileMD5(&Logger, szLocalFileName, md5_file_local); + dwErrCode = LoadLocalFileMD5(&Logger, szFileFullName, md5_file_local); } // Add the given file @@ -4234,7 +4247,7 @@ static DWORD TestModifyArchive_ReplaceFile(LPCTSTR szMpqPlainName, LPCTSTR szFil // Add the file to MPQ dwErrCode = AddLocalFileToMpq(&Logger, hMpq, szArchivedName, - szLocalFileName, + szFileFullName, MPQ_FILE_REPLACEEXISTING | MPQ_FILE_COMPRESS | MPQ_FILE_SINGLE_UNIT, MPQ_COMPRESSION_ZLIB, true); @@ -4271,16 +4284,16 @@ static DWORD TestModifyArchive_ReplaceFile(LPCTSTR szMpqPlainName, LPCTSTR szFil if(!SFileSetCompactCallback(hMpq, CompactCallback, &Logger)) dwErrCode = Logger.PrintError(_T("Failed to compact archive %s"), szMpqPlainName); - if(!SFileCompactArchive(hMpq, NULL, 0)) - dwErrCode = GetLastError(); - + // Some test archives (like MPQ_2022_v1_v4.329.w3x) can't be compacted. + // For that reason, we ignore the result of SFileCompactArchive(). + SFileCompactArchive(hMpq, NULL, 0); SFileCloseArchive(hMpq); } // Try to open the archive again. Ignore the previous errors if(dwErrCode == ERROR_SUCCESS) { - dwErrCode = OpenExistingArchive(&Logger, szLocalFileName, 0, &hMpq); + dwErrCode = OpenExistingArchive(&Logger, szMpqFullName, 0, &hMpq); if(dwErrCode == ERROR_SUCCESS) { // Load the file from the MPQ again @@ -4288,7 +4301,7 @@ static DWORD TestModifyArchive_ReplaceFile(LPCTSTR szMpqPlainName, LPCTSTR szFil if(dwErrCode == ERROR_SUCCESS) { // New MPQ file must be the same like the local one - if(!memcmp(md5_file_in_mpq3, md5_file_local, MD5_DIGEST_SIZE)) + if(memcmp(md5_file_in_mpq3, md5_file_local, MD5_DIGEST_SIZE)) { Logger.PrintError("Data mismatch after adding the file \"%s\"", szArchivedName); dwErrCode = ERROR_CHECKSUM_ERROR; @@ -4386,6 +4399,11 @@ static const TEST_INFO Test_Mpqs[] = {_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)}, + + // 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)}, }; static const TEST_INFO Patched_Mpqs[] = @@ -4476,13 +4494,12 @@ 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 -// if(dwErrCode != ERROR_SUCCESS) -// break; dwErrCode = ERROR_SUCCESS; } } @@ -4498,11 +4515,10 @@ int _tmain(int argc, TCHAR * argv[]) LPCTSTR * PatchList = (LPCTSTR *)Patched_Mpqs[i].param1; LPCSTR szFileName = (LPCSTR)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 Patched_Mpqs[i].dwFlags); -// if(dwErrCode != ERROR_SUCCESS) -// break; dwErrCode = ERROR_SUCCESS; } } diff --git a/test/stormlib-test.txt b/test/stormlib-test.txt index 4a1bd2c..947a387 100644 --- a/test/stormlib-test.txt +++ b/test/stormlib-test.txt @@ -1,8 +1,8 @@ -Microsoft Windows [Version 10.0.19044.1706] +Microsoft Windows [Version 10.0.19044.2006] (c) Microsoft Corporation. All rights reserved. E:\Ladik\AppDir\StormLib\bin\StormLib_test\x64\Release>StormLib_test.exe -==== Test Suite for StormLib version 9.23 ==== +==== Test Suite for StormLib version 9.24 ==== InitWorkDir: Work directory \Multimedia\MPQs (default) LocalListFile (FLAT-MAP:ListFile_Blizzard.txt) succeeded. LocalListFile (ListFile_Blizzard.txt) succeeded. @@ -68,6 +68,9 @@ TestMpq (MPQ_2002_v1_ProtectedMap_HashTable_FakeValid.w3x) succeeded. TestMpq (MPQ_2021_v1_CantExtractCHK.scx) succeeded. TestMpq (MPQ_2022_v1_Sniper.scx) succeeded. TestMpq (MPQ_2022_v1_OcOc_Bound_2.scx) succeeded. +TestMpq (MPQ_2020_v1_HS0.1.asi) succeeded. +TestMpq (MPQ_2022_v1_hs0.8.asi) succeeded. +TestMpq (MPQ_2022_v1_MoeMoeMod.asi) succeeded. PatchedMPQ (MPQ_1998_v1_StarCraft.mpq) succeeded. PatchedMPQ (MPQ_2012_v4_OldWorld.MPQ) succeeded. PatchedMPQ (MPQ_2013_v4_world.MPQ) succeeded. @@ -171,6 +174,8 @@ VerifyFileHash succeeded. VerifyFileHash succeeded. VerifyFileHash succeeded. VerifyFileHash succeeded. +VerifyFileHash succeeded. +VerifyFileHash succeeded. OpenEachMpqTest ((10)DustwallowKeys.w3m) succeeded. OpenEachMpqTest (MPQ_1997_v1_Diablo1_DIABDAT.MPQ) succeeded. OpenEachMpqTest (MPQ_1997_v1_Diablo1_single_0.sv) succeeded. @@ -236,7 +241,7 @@ OpenEachMpqTest (MPQ_2017_v1_Eden_RPG_S2_2.5J.w3x) succeeded. OpenEachMpqTest (MPQ_2017_v1_TildeInFileName.mpq) succeeded. OpenEachMpqTest (MPQ_2018_v1_EWIX_v8_7.w3x) succeeded. OpenEachMpqTest (MPQ_2018_v1_icon_error.w3m) succeeded. -OpenEachMpqTest: Failed to open archive \Multimedia\MPQs\1995 - Test MPQs\MPQ_2020_v1_HS0.1.asi (error code: 11) +OpenEachMpqTest (MPQ_2020_v1_HS0.1.asi) succeeded. OpenEachMpqTest (MPQ_2020_v4_FakeMpqHeaders.SC2Mod) succeeded. OpenEachMpqTest (MPQ_2020_v4_NP_Protect_1.s2ma) succeeded. OpenEachMpqTest (MPQ_2020_v4_NP_Protect_2.s2ma) succeeded. @@ -245,7 +250,9 @@ OpenEachMpqTest (MPQ_2020_v4_NP_Protect_4.s2ma) succeeded. OpenEachMpqTest (MPQ_2020_v4_ThreeFakeHeaders.s2ma) succeeded. OpenEachMpqTest (MPQ_2021_v1_CrossLinkedFiles.w3x) succeeded. OpenEachMpqTest (MPQ_2021_v4_BzipError.SC2Replay) succeeded. -OpenEachMpqTest: Failed to open archive \Multimedia\MPQs\1995 - Test MPQs\MPQ_2022_v1_MoeMoeMod.asi (error code: 11) +OpenEachMpqTest (MPQ_2022_v1_hs0.8.asi) succeeded. +OpenEachMpqTest (MPQ_2022_v1_MoeMoeMod.asi) succeeded. +OpenEachMpqTest (MPQ_2022_v1_v4.329.w3x) succeeded. OpenEachMpqTest (hs-0-3604-Win-final.MPQ) succeeded. OpenEachMpqTest (hs-0-5314-Win-final.MPQ) succeeded. OpenEachMpqTest (hs-5314-5435-Win-final.MPQ) succeeded. @@ -343,10 +350,10 @@ OpenEachMpqTest ((4)aaaa.w3x) succeeded. OpenEachMpqTest (a_tvse_x_1_2_f.w3x) succeeded. OpenEachMpqTest (Shopping_Maul_ USA 9.10.7.w3x) succeeded. OpenEachMpqTest (siverrpg_1.9_ver.w3x) succeeded. -OpenEachMpqTest: Failed to open archive \Multimedia\MPQs\2002 - Warcraft III\MIX-files\Markers-CSHX\ACGExternal0.2.asi (error code: 11) -OpenEachMpqTest: Failed to open archive \Multimedia\MPQs\2002 - Warcraft III\MIX-files\Markers-CSHX\grandparty.asi (error code: 11) -OpenEachMpqTest: Failed to open archive \Multimedia\MPQs\2002 - Warcraft III\MIX-files\Markers-CSHX\HS0.1.asi (error code: 11) -OpenEachMpqTest: Failed to open archive \Multimedia\MPQs\2002 - Warcraft III\MIX-files\Markers-CSHX\HS0.5.asi (error code: 11) +OpenEachMpqTest (ACGExternal0.2.asi) succeeded. +OpenEachMpqTest (grandparty.asi) succeeded. +OpenEachMpqTest (HS0.1.asi) succeeded. +OpenEachMpqTest (HS0.5.asi) succeeded. OpenEachMpqTest (Patch_War3x.mpq) succeeded. OpenEachMpqTest (Patch_War3_Low.mpq) succeeded. OpenEachMpqTest (Patch_War3_Med.mpq) succeeded. @@ -2277,6 +2284,7 @@ OpenEachMpqTest (MPQ_2013_v4_alternate-incomplete.MPQ) succeeded. OpenEachMpqTest (MPQ_2013_v4_alternate-original.MPQ) succeeded. OpenEachMpqTest (MPQ_2014_v1_out1.w3x) succeeded. OpenEachMpqTest (MPQ_2014_v1_out2.w3x) succeeded. +OpenEachMpqTest (MPQ_2022_v1_v4.329.w3x) succeeded. OpenEachMpqTest (StormLibTest_AddWaveMonoBadTest.mpq) succeeded. OpenEachMpqTest (StormLibTest_AddWaveMonoTest.mpq) succeeded. OpenEachMpqTest (StormLibTest_AddWaveStereoTest.mpq) succeeded. @@ -2338,5 +2346,6 @@ CompressionsTest (StormLibTest_AddWaveStereoTest.mpq) succeeded. ListFilePos (StormLibTest_ListFilePos.mpq) succeeded. BigMpqTest (StormLibTest_BigArchive_v4.mpq) succeeded. ModifyTest (MPQ_2014_v4_Base.StormReplay) succeeded. +ModifyTest (MPQ_2022_v1_v4.329.w3x) succeeded. E:\Ladik\AppDir\StormLib\bin\StormLib_test\x64\Release> \ No newline at end of file