From cb56fff1a5aa1fd3b69c92c38dd07aec4ae28dec Mon Sep 17 00:00:00 2001 From: Ladislav Zezula Date: Sat, 23 Sep 2023 01:08:58 +0200 Subject: StormLib will not make Warcraft III maps larger than 2GB --- Publish.bat | 25 --- make-msvc.bat | 16 +- src/DllMain.rc | 24 ++- src/LibTomCrypt.c | 1 + src/SBaseCommon.cpp | 3 +- src/SFileAddFile.cpp | 8 + src/StormLib.h | 4 + src/libtomcrypt/src/hashes/hash_memory.c | 69 -------- src/libtomcrypt/src/headers/tomcrypt_custom.h | 36 ++--- test/StormTest.cpp | 217 ++++++++------------------ test/stormlib-test-001.txt | 3 + 11 files changed, 124 insertions(+), 282 deletions(-) delete mode 100644 Publish.bat delete mode 100644 src/libtomcrypt/src/hashes/hash_memory.c diff --git a/Publish.bat b/Publish.bat deleted file mode 100644 index b5c71fc..0000000 --- a/Publish.bat +++ /dev/null @@ -1,25 +0,0 @@ -@echo off -rem This BAT file updates the ZIP file that is to be uploaded to web -rem Only use when both 32-bit and 64-bit are properly compiled - -set STORMLIB_NAME=stormlib-9.00 - -echo Creating %STORMLIB_NAME%.zip ... -cd \Ladik\Appdir -zip.exe -ur9 ..\WWW\web\download\%STORMLIB_NAME%.zip StormLib\doc\* -zip.exe -ur9 ..\WWW\web\download\%STORMLIB_NAME%.zip StormLib\src\* -zip.exe -ur9 ..\WWW\web\download\%STORMLIB_NAME%.zip StormLib\storm_dll\* -zip.exe -ur9 ..\WWW\web\download\%STORMLIB_NAME%.zip StormLib\StormLib.xcodeproj\* -zip.exe -ur9 ..\WWW\web\download\%STORMLIB_NAME%.zip StormLib\stormlib_dll\* -zip.exe -ur9 ..\WWW\web\download\%STORMLIB_NAME%.zip StormLib\test\* -zip.exe -u9 ..\WWW\web\download\%STORMLIB_NAME%.zip StormLib\CMakeLists.txt -zip.exe -u9 ..\WWW\web\download\%STORMLIB_NAME%.zip StormLib\makefile.* -zip.exe -u9 ..\WWW\web\download\%STORMLIB_NAME%.zip StormLib\Info.plist -zip.exe -u9 ..\WWW\web\download\%STORMLIB_NAME%.zip StormLib\*.bat -zip.exe -u9 ..\WWW\web\download\%STORMLIB_NAME%.zip StormLib\*.sln -zip.exe -u9 ..\WWW\web\download\%STORMLIB_NAME%.zip StormLib\*.vcproj -zip.exe -u9 ..\WWW\web\download\%STORMLIB_NAME%.zip StormLib\*.vcxproj -echo. - -echo Press any key to exit ... -pause >nul diff --git a/make-msvc.bat b/make-msvc.bat index 6e3782d..7d1052a 100644 --- a/make-msvc.bat +++ b/make-msvc.bat @@ -2,9 +2,10 @@ @echo off :: Save the values of INCLUDE, LIB and PATH +set PROJECT_DIR=%~dp0 set SAVE_INCLUDE=%INCLUDE% -set SAVE_LIB=%LIB% set SAVE_PATH=%PATH% +set SAVE_LIB=%LIB% set LIB_NAME=StormLib :: Determine where the program files are, both for 64-bit and 32-bit Windows @@ -59,13 +60,18 @@ call :BuildAndCopyLib %3 %SLN_TRG% %LIB_TRG% ReleaseAS call :BuildAndCopyLib %3 %SLN_TRG% %LIB_TRG% ReleaseUD call :BuildAndCopyLib %3 %SLN_TRG% %LIB_TRG% ReleaseUS -:: Restore environment variables to the old level +:: Restore environment variables to the old values set INCLUDE=%SAVE_INCLUDE% -set LIB=%SAVE_LIB% set PATH=%SAVE_PATH% +set LIB=%SAVE_LIB% + +:: Delete environment variables that are set by Visual Studio +set __VSCMD_PREINIT_PATH= +set EXTERNAL_INCLUDE= set VSINSTALLDIR= set VCINSTALLDIR= set DevEnvDir= +set LIBPATH= goto:eof ::----------------------------------------------------------------------------- @@ -73,7 +79,7 @@ goto:eof :: :: Parameters: :: -:: %1 Plain name of the .sln solution file ("StormLib_vs##.sln") +:: %1 Plain name of the .sln solution file :: %2 Target build platform ("Win32" or "x64") :: %3 Target directory for the library ("lib32", "lib32\vs2008", "lib64" or "lib64\vs2008") :: %4 Subvariant of the library ("DebugAD", "ReleaseUS", ...) @@ -86,4 +92,4 @@ if not exist ..\aaa goto:eof xcopy.exe /Y /D .\src\StormLib.h ..\aaa\inc >nul xcopy.exe /Y /D .\src\StormPort.h ..\aaa\inc >nul xcopy.exe /Y /D .\bin\StormLib\%2\%4\*.lib ..\aaa\%3 >nul -goto:eof + diff --git a/src/DllMain.rc b/src/DllMain.rc index 27f43e2..69b5cf0 100644 --- a/src/DllMain.rc +++ b/src/DllMain.rc @@ -16,10 +16,8 @@ // Neutral resources #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_NEU) -#ifdef _WIN32 LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL #pragma code_page(1250) -#endif //_WIN32 ///////////////////////////////////////////////////////////////////////////// // @@ -27,8 +25,8 @@ LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL // VS_VERSION_INFO VERSIONINFO - FILEVERSION 9,22,0,3 - PRODUCTVERSION 9,22,0,3 + FILEVERSION 9,25,0,3 + PRODUCTVERSION 9,25,0,3 FILEFLAGSMASK 0x17L #ifdef _DEBUG FILEFLAGS 0x1L @@ -45,12 +43,12 @@ BEGIN BEGIN VALUE "Comments", "http://www.zezula.net/mpq.html" VALUE "FileDescription", "StormLib library for reading Blizzard MPQ archives" - VALUE "FileVersion", "9, 22, 0, 3\0" + VALUE "FileVersion", "9.25.0.3" VALUE "InternalName", "StormLib" - VALUE "LegalCopyright", "Copyright (c) 2014 - 2020 Ladislav Zezula" + VALUE "LegalCopyright", "Copyright (c) 2014 - 2023 Ladislav Zezula" VALUE "OriginalFilename", "StormLib.dll" VALUE "ProductName", "StormLib" - VALUE "ProductVersion", "9, 22, 0, 3\0" + VALUE "ProductVersion", "9.25.0.3" END END BLOCK "VarFileInfo" @@ -64,13 +62,11 @@ END ///////////////////////////////////////////////////////////////////////////// -// Czech resources +// Czech (Czech Republic) resources #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CSY) -#ifdef _WIN32 LANGUAGE LANG_CZECH, SUBLANG_DEFAULT #pragma code_page(1250) -#endif //_WIN32 #ifdef APSTUDIO_INVOKED ///////////////////////////////////////////////////////////////////////////// @@ -78,26 +74,26 @@ LANGUAGE LANG_CZECH, SUBLANG_DEFAULT // TEXTINCLUDE // -2 TEXTINCLUDE +2 TEXTINCLUDE BEGIN "#include ""afxres.h""\r\n" "\0" END -3 TEXTINCLUDE +3 TEXTINCLUDE BEGIN "\r\n" "\0" END -1 TEXTINCLUDE +1 TEXTINCLUDE BEGIN "resource.h\0" END #endif // APSTUDIO_INVOKED -#endif // Czech resources +#endif // Czech (Czech Republic) resources ///////////////////////////////////////////////////////////////////////////// diff --git a/src/LibTomCrypt.c b/src/LibTomCrypt.c index 012f5e0..f77b604 100644 --- a/src/LibTomCrypt.c +++ b/src/LibTomCrypt.c @@ -8,6 +8,7 @@ #include "libtomcrypt/src/hashes/hash_memory.c" #include "libtomcrypt/src/hashes/md5.c" #include "libtomcrypt/src/hashes/sha1.c" +#include "libtomcrypt/src/hashes/sha256.c" #include "libtomcrypt/src/math/multi.c" #include "libtomcrypt/src/math/rand_prime.c" #include "libtomcrypt/src/misc/base64_decode.c" diff --git a/src/SBaseCommon.cpp b/src/SBaseCommon.cpp index b5b880e..664d4b0 100644 --- a/src/SBaseCommon.cpp +++ b/src/SBaseCommon.cpp @@ -244,8 +244,9 @@ void InitializeMpqCryptography() } // Also register both MD5 and SHA1 hash algorithms - register_hash(&md5_desc); + register_hash(&sha256_desc); register_hash(&sha1_desc); + register_hash(&md5_desc); // Use LibTomMath as support math library for LibTomCrypt ltc_mp = ltm_desc; diff --git a/src/SFileAddFile.cpp b/src/SFileAddFile.cpp index 5913424..2d14dda 100644 --- a/src/SFileAddFile.cpp +++ b/src/SFileAddFile.cpp @@ -246,6 +246,14 @@ static DWORD WriteDataToMpqFile( BSWAP_ARRAY32_UNSIGNED(pbToWrite, dwBytesInSector); } + // Do not allow Warcraft III maps to go over 2GB. + // https://github.com/ladislav-zezula/StormLib/issues/306 + if((ha->dwFlags & MPQ_FLAG_WAR3_MAP) && (ByteOffset + dwBytesInSector) > 0x7FFFFFFF) + { + dwErrCode = ERROR_DISK_FULL; + break; + } + // Write the file sector if(!FileStream_Write(ha->pStream, &ByteOffset, pbToWrite, dwBytesInSector)) { diff --git a/src/StormLib.h b/src/StormLib.h index 4d5992d..0bab24e 100644 --- a/src/StormLib.h +++ b/src/StormLib.h @@ -403,6 +403,10 @@ extern "C" { #define SHA1_DIGEST_SIZE 0x14 // 160 bits #endif +#ifndef SHA256_DIGEST_SIZE +#define SHA256_DIGEST_SIZE 0x20 // 256 bits +#endif + #ifndef LANG_NEUTRAL #define LANG_NEUTRAL 0x00 // Neutral locale #endif diff --git a/src/libtomcrypt/src/hashes/hash_memory.c b/src/libtomcrypt/src/hashes/hash_memory.c deleted file mode 100644 index 1daf0bf..0000000 --- a/src/libtomcrypt/src/hashes/hash_memory.c +++ /dev/null @@ -1,69 +0,0 @@ -/* LibTomCrypt, modular cryptographic library -- Tom St Denis - * - * LibTomCrypt is a library that provides various cryptographic - * algorithms in a highly modular and flexible manner. - * - * The library is free for all purposes without any express - * guarantee it works. - * - * Tom St Denis, tomstdenis@gmail.com, http://libtom.org - */ -#include "../headers/tomcrypt.h" - -/** - @file hash_memory.c - Hash memory helper, Tom St Denis -*/ - -/** - Hash a block of memory and store the digest. - @param hash The index of the hash you wish to use - @param in The data you wish to hash - @param inlen The length of the data to hash (octets) - @param out [out] Where to store the digest - @param outlen [in/out] Max size and resulting size of the digest - @return CRYPT_OK if successful -*/ -int hash_memory(int hash, const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen) -{ - hash_state *md; - int err; - - LTC_ARGCHK(in != NULL); - LTC_ARGCHK(out != NULL); - LTC_ARGCHK(outlen != NULL); - - if ((err = hash_is_valid(hash)) != CRYPT_OK) { - return err; - } - - if (*outlen < hash_descriptor[hash].hashsize) { - *outlen = hash_descriptor[hash].hashsize; - return CRYPT_BUFFER_OVERFLOW; - } - - md = XMALLOC(sizeof(hash_state)); - if (md == NULL) { - return CRYPT_MEM; - } - - if ((err = hash_descriptor[hash].init(md)) != CRYPT_OK) { - goto LBL_ERR; - } - if ((err = hash_descriptor[hash].process(md, in, inlen)) != CRYPT_OK) { - goto LBL_ERR; - } - err = hash_descriptor[hash].done(md, out); - *outlen = hash_descriptor[hash].hashsize; -LBL_ERR: -#ifdef LTC_CLEAN_STACK - zeromem(md, sizeof(hash_state)); -#endif - XFREE(md); - - return err; -} - -/* $Source: /cvs/libtom/libtomcrypt/src/hashes/helper/hash_memory.c,v $ */ -/* $Revision: 1.6 $ */ -/* $Date: 2006/12/28 01:27:23 $ */ diff --git a/src/libtomcrypt/src/headers/tomcrypt_custom.h b/src/libtomcrypt/src/headers/tomcrypt_custom.h index 312a4c2..d53eef7 100644 --- a/src/libtomcrypt/src/headers/tomcrypt_custom.h +++ b/src/libtomcrypt/src/headers/tomcrypt_custom.h @@ -11,29 +11,29 @@ #define LTC_NO_ROLC #define LTC_SOURCE +#define LTC_SHA256 #define LTC_SHA1 #define LTC_MD5 #define LTC_DER -#define LTC_RC4 -#define USE_LTM #define LTM_DESC +#define USE_LTM /* macros for various libc functions you can change for embedded targets */ #ifndef XMALLOC - #ifdef malloc + #ifdef malloc #define LTC_NO_PROTOTYPES #endif #define XMALLOC LibTomMalloc #endif #ifndef XREALLOC - #ifdef realloc + #ifdef realloc #define LTC_NO_PROTOTYPES #endif #define XREALLOC LibTomRealloc #endif #ifndef XCALLOC - #ifdef calloc + #ifdef calloc #define LTC_NO_PROTOTYPES #endif #define XCALLOC LibTomCalloc @@ -58,7 +58,7 @@ #define XMEMCPY memcpy #endif #ifndef XMEMCMP - #ifdef memcmp + #ifdef memcmp #define LTC_NO_PROTOTYPES_MEMCMP #endif #define XMEMCMP memcmp @@ -91,19 +91,19 @@ #define LTC_BLOWFISH #define LTC_DES #define LTC_CAST5 - + #define LTC_NO_MODES #define LTC_ECB_MODE #define LTC_CBC_MODE #define LTC_CTR_MODE - + #define LTC_NO_HASHES #define LTC_SHA1 #define LTC_SHA512 #define LTC_SHA384 #define LTC_SHA256 #define LTC_SHA224 - + #define LTC_NO_MACS #define LTC_HMAC #define LTC_OMAC @@ -114,11 +114,11 @@ #define LTC_YARROW #define LTC_DEVRANDOM #define TRY_URANDOM_FIRST - + #define LTC_NO_PK #define LTC_MRSA #define LTC_MECC -#endif +#endif /* Use small code where possible */ /* #define LTC_SMALL_CODE */ @@ -194,7 +194,7 @@ #define LTC_LRW_MODE #ifndef LTC_NO_TABLES /* like GCM mode this will enable 16 8x128 tables [64KB] that make - * seeking very fast. + * seeking very fast. */ #define LRW_TABLES #endif @@ -205,7 +205,7 @@ #endif /* LTC_NO_MODES */ /* ---> One-Way Hash Functions <--- */ -#ifndef LTC_NO_HASHES +#ifndef LTC_NO_HASHES #define LTC_CHC_HASH #define LTC_WHIRLPOOL @@ -252,7 +252,7 @@ /* Use 64KiB tables */ #ifndef LTC_NO_TABLES - #define LTC_GCM_TABLES + #define LTC_GCM_TABLES #endif /* USE SSE2? requires GCC works on x86_32 and x86_64*/ @@ -319,7 +319,7 @@ #define LTC_MRSA /* Include Katja (a Rabin variant like RSA) */ -/* #define MKAT */ +/* #define MKAT */ /* Digital Signature Algorithm */ #define LTC_MDSA @@ -332,7 +332,7 @@ #if defined(TFM_LTC_DESC) && defined(LTC_MECC) #define LTC_MECC_ACCEL -#endif +#endif /* do we want fixed point ECC */ /* #define LTC_MECC_FP */ @@ -376,9 +376,9 @@ #ifdef LTC_MRSA #define LTC_PKCS_1 -#endif +#endif -#if defined(LTC_DER) && !defined(MPI) +#if defined(LTC_DER) && !defined(MPI) #error ASN.1 DER requires MPI functionality #endif diff --git a/test/StormTest.cpp b/test/StormTest.cpp index 99138e4..c25ec84 100755 --- a/test/StormTest.cpp +++ b/test/StormTest.cpp @@ -155,11 +155,6 @@ static TCHAR szMpqPatchDir[MAX_PATH] = {0}; #define SFLAG_SIGN_ARCHIVE 0x00000010 // Sign the archive #define SFLAG_VERIFY_AFTER 0x00000020 // Verify the signature after modification -// 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 @@ -277,43 +272,6 @@ LPCTSTR GetRelativePath(LPCTSTR szFullPath) return _T(""); } -static bool IsMpqExtension(LPCTSTR szFileName) -{ - LPCTSTR szExtension = _tcsrchr(szFileName, '.'); - - if(szExtension != NULL) - { - if(!_tcsicmp(szExtension, _T(".mpq"))) - return true; - if(!_tcsicmp(szExtension, _T(".w3m"))) - return true; - if(!_tcsicmp(szExtension, _T(".w3x"))) - return true; - if(!_tcsicmp(szExtension, _T(".asi"))) - return true; - if(!_tcsicmp(szExtension, _T(".mpqe"))) - return true; - if(!_tcsicmp(szExtension, _T(".part"))) - return true; - if(!_tcsicmp(szExtension, _T(".sv"))) - return true; - if(!_tcsicmp(szExtension, _T(".s2ma"))) - return true; - if(!_tcsicmp(szExtension, _T(".SC2Map"))) - return true; - if(!_tcsicmp(szExtension, _T(".SC2Mod"))) - return true; - if(!_tcsicmp(szExtension, _T(".SC2Replay"))) - return true; - if(!_tcsicmp(szExtension, _T(".0"))) // .MPQ.0 - return true; -// if(!_tcsicmp(szExtension, ".link")) -// return true; - } - - return false; -} - // Converts binary array to string. // The caller must ensure that the buffer has at least ((cbBinary * 2) + 1) characters template @@ -418,33 +376,19 @@ static const XCHAR * GetShortPlainName(const XCHAR * szFileName) return szPlainName; } -static bool CopyStringAndVerifyConversion( - LPCTSTR szFoundFile, - TCHAR * szBufferT, - char * szBufferA, - size_t cchMaxChars) -{ - // Convert the TCHAR name to ANSI name - StringCopy(szBufferA, cchMaxChars, szFoundFile); - StringCopy(szBufferT, cchMaxChars, szBufferA); - - // Compare both TCHAR strings - return (_tcsicmp(szBufferT, szFoundFile) == 0) ? true : false; -} - -static size_t ConvertSha1ToText(const unsigned char * sha1_digest, TCHAR * szSha1Text) +static size_t ConvertSha256ToText(const unsigned char * sha_digest, LPTSTR szBuffer) { LPCSTR szTable = "0123456789abcdef"; - for(size_t i = 0; i < SHA1_DIGEST_SIZE; i++) + for(size_t i = 0; i < SHA256_DIGEST_SIZE; i++) { - *szSha1Text++ = szTable[(sha1_digest[0] >> 0x04)]; - *szSha1Text++ = szTable[(sha1_digest[0] & 0x0F)]; - sha1_digest++; + *szBuffer++ = szTable[(sha_digest[0] >> 0x04)]; + *szBuffer++ = szTable[(sha_digest[0] & 0x0F)]; + sha_digest++; } - *szSha1Text = 0; - return (SHA1_DIGEST_SIZE * 2); + *szBuffer = 0; + return (SHA256_DIGEST_SIZE * 2); } static void CreateFullPathName(TCHAR * szBuffer, size_t cchBuffer, LPCTSTR szSubDir, LPCTSTR szNamePart1, LPCTSTR szNamePart2 = NULL) @@ -537,12 +481,12 @@ static void CreateFullPathName(char * szBuffer, size_t cchBuffer, LPCTSTR szSubD } #endif -static DWORD CalculateFileSha1(TLogHelper * pLogger, LPCTSTR szFullPath, TCHAR * szFileSha1) +static DWORD CalculateFileHash(TLogHelper * pLogger, LPCTSTR szFullPath, LPTSTR szFileHash) { TFileStream * pStream; - unsigned char sha1_digest[SHA1_DIGEST_SIZE]; + unsigned char file_hash[SHA256_DIGEST_SIZE]; LPCTSTR szShortPlainName = GetShortPlainName(szFullPath); - hash_state sha1_state; + hash_state sha256_state; ULONGLONG ByteOffset = 0; ULONGLONG FileSize = 0; LPCTSTR szHashingFormat = _T("Hashing %s " fmt_X_of_Y_a); @@ -553,7 +497,7 @@ static DWORD CalculateFileSha1(TLogHelper * pLogger, LPCTSTR szFullPath, TCHAR * // Notify the user pLogger->PrintProgress(_T("Hashing %s ..."), szShortPlainName); - szFileSha1[0] = 0; + szFileHash[0] = 0; // Open the file to be verified pStream = FileStream_OpenFile(szFullPath, STREAM_FLAG_READ_ONLY); @@ -566,10 +510,10 @@ static DWORD CalculateFileSha1(TLogHelper * pLogger, LPCTSTR szFullPath, TCHAR * pbFileBlock = STORM_ALLOC(BYTE, cbFileBlock); if(pbFileBlock != NULL) { - // Initialize SHA1 calculation - sha1_init(&sha1_state); + // Initialize SHA256 calculation + sha256_init(&sha256_state); - // Calculate the SHA1 of the file + // Calculate the SHA256 of the file while(ByteOffset < FileSize) { // Notify the user @@ -583,19 +527,19 @@ static DWORD CalculateFileSha1(TLogHelper * pLogger, LPCTSTR szFullPath, TCHAR * break; } - // Add to SHA1 - sha1_process(&sha1_state, pbFileBlock, cbBytesToRead); + // Add to SHA256 + sha256_process(&sha256_state, pbFileBlock, cbBytesToRead); ByteOffset += cbBytesToRead; } // Notify the user pLogger->PrintProgress(szHashingFormat, szShortPlainName, ByteOffset, FileSize); - // Finalize SHA1 - sha1_done(&sha1_state, sha1_digest); + // Finalize SHA256 + sha256_done(&sha256_state, file_hash); - // Convert the SHA1 to ANSI text - ConvertSha1ToText(sha1_digest, szFileSha1); + // Convert the SHA256 to ANSI text + ConvertSha256ToText(file_hash, szFileHash); STORM_FREE(pbFileBlock); } @@ -603,7 +547,7 @@ static DWORD CalculateFileSha1(TLogHelper * pLogger, LPCTSTR szFullPath, TCHAR * } // If we calculated something, return OK - if(dwErrCode == ERROR_SUCCESS && szFileSha1[0] == 0) + if(dwErrCode == ERROR_SUCCESS && szFileHash[0] == 0) dwErrCode = ERROR_CAN_NOT_COMPLETE; return dwErrCode; } @@ -790,10 +734,11 @@ static DWORD ForEachFile_VerifyFileHash(LPCTSTR szFullPath, void * lpContext) { TLogHelper * pLogger = (TLogHelper *)(lpContext); PFILE_DATA pFileData; - TCHAR * szExtension; + LPCTSTR szHashExtension = _T(".sha256"); + LPTSTR szExtension; TCHAR szShaFileName[MAX_PATH + 1]; - TCHAR szSha1Text[0x40]; - char szSha1TextA[0x40]; + TCHAR szHashText[0x80]; + char szHashTextA[0x80]; DWORD dwErrCode = ERROR_SUCCESS; // Try to load the file with the SHA extension @@ -802,25 +747,25 @@ static DWORD ForEachFile_VerifyFileHash(LPCTSTR szFullPath, void * lpContext) if(szExtension == NULL) return ERROR_SUCCESS; - // Skip .SHA and .TXT files - if(!_tcsicmp(szExtension, _T(".sha")) || !_tcsicmp(szExtension, _T(".txt"))) + // Skip .SHA256 + if(!_tcsicmp(szExtension, szHashExtension)) return ERROR_SUCCESS; // Load the local file to memory - _tcscpy(szExtension, _T(".sha")); + _tcscpy(szExtension, szHashExtension); pFileData = LoadLocalFile(pLogger, szShaFileName, false); if(pFileData != NULL) { - // Calculate SHA1 of the entire file - dwErrCode = CalculateFileSha1(pLogger, szFullPath, szSha1Text); + // Calculate SHA256 of the entire file + dwErrCode = CalculateFileHash(pLogger, szFullPath, szHashText); if(dwErrCode == ERROR_SUCCESS) { // Compare with what we loaded from the file - if(pFileData->dwFileSize >= (SHA1_DIGEST_SIZE * 2)) + if(pFileData->dwFileSize >= (SHA256_DIGEST_SIZE * 2)) { - // Compare the SHA1 - StringCopy(szSha1TextA, _countof(szSha1TextA), szSha1Text); - if(_strnicmp(szSha1TextA, (char *)pFileData->FileData, (SHA1_DIGEST_SIZE * 2))) + // Compare the SHA256 + StringCopy(szHashTextA, _countof(szHashTextA), szHashText); + if(_strnicmp(szHashTextA, (char *)pFileData->FileData, (SHA256_DIGEST_SIZE * 2))) { SetLastError(dwErrCode = ERROR_FILE_CORRUPT); pLogger->PrintError(_T("File hash check failed: %s"), szFullPath); @@ -1995,22 +1940,6 @@ static DWORD AddLocalFileToMpq( return ERROR_SUCCESS; } -static DWORD RenameMpqFile(TLogHelper * pLogger, HANDLE hMpq, LPCSTR szOldFileName, LPCSTR szNewFileName, DWORD dwExpectedError) -{ - DWORD dwErrCode = ERROR_SUCCESS; - - // Notify the user - pLogger->PrintProgress("Renaming %s to %s ...", szOldFileName, szNewFileName); - - // Perform the deletion - if(!SFileRenameFile(hMpq, szOldFileName, szNewFileName)) - dwErrCode = GetLastError(); - - if(dwErrCode != dwExpectedError) - return pLogger->PrintErrorVa("Unexpected result from SFileRenameFile(%s -> %s)", szOldFileName, szNewFileName); - return ERROR_SUCCESS; -} - static DWORD RemoveMpqFile(TLogHelper * pLogger, HANDLE hMpq, LPCSTR szFileName, DWORD dwExpectedError) { DWORD dwErrCode = ERROR_SUCCESS; @@ -2946,66 +2875,50 @@ static DWORD TestOpenArchive_CompactArchive(LPCTSTR szPlainName, LPCTSTR szCopyN return dwErrCode; } -static DWORD TestOpenArchive_AddFile(LPCTSTR szMpqName, DWORD dwFlags) +static DWORD TestOpenArchive_AddFiles2GB(LPCTSTR szMpqName, DWORD /* dwFlags */) { - TLogHelper Logger("TestAddFileToMpq", szMpqName); - PFILE_DATA pFileData = NULL; - LPCTSTR szBackupMpq = (dwFlags & TFLAG_REOPEN) ? _T("StormLibTest_Reopened.mpq") : szMpqName; - LPCSTR szFileName = "AddedFile001.txt"; - LPCSTR szFileData = "0123456789ABCDEF"; + TLogHelper Logger("TestAddFileOver2GB", szMpqName); + LPCTSTR szCopyName = _T("size-overflow.w3m"); HANDLE hMpq = NULL; - DWORD dwFileSize = (DWORD)strlen(szFileData); DWORD dwErrCode = ERROR_SUCCESS; + TCHAR szFullPath[MAX_PATH]; + bool bSucceeded = true; // Copy the archive so we won't fuck up the original one - dwErrCode = OpenExistingArchiveWithCopy(&Logger, szMpqName, szBackupMpq, &hMpq); + dwErrCode = OpenExistingArchiveWithCopy(&Logger, szMpqName, szCopyName, &hMpq); if(dwErrCode == ERROR_SUCCESS) { - dwErrCode = AddFileToMpq(&Logger, hMpq, szFileName, szFileData, MPQ_FILE_IMPLODE, MPQ_COMPRESSION_PKWARE, ERROR_SUCCESS); + // Create both file names + CreateFullPathName(szFullPath, _countof(szFullPath), szDataFileDir, _T("new-file-big.mp4")); + + // Add the file to MPQ. This must fail, because the map size + // will go over 2GB and StormLib marks the file malformed on subsequent open + dwErrCode = AddLocalFileToMpq(&Logger, hMpq, "added-extra-file.mp4", szFullPath); + if(dwErrCode != ERROR_DISK_FULL) + bSucceeded = false; + SFileCloseArchive(hMpq); } - // Now the file has been written and the MPQ has been saved. - // We reopen the MPQ and check the state of (listfile) and (attributes) - if((dwErrCode == ERROR_SUCCESS) && (dwFlags & TFLAG_REOPEN)) + // Open the MPQ again + if(dwErrCode == ERROR_SUCCESS || dwErrCode == ERROR_DISK_FULL) { - if((dwErrCode = OpenExistingArchiveWithCopy(&Logger, NULL, szBackupMpq, &hMpq)) == ERROR_SUCCESS) + CreateFullPathName(szFullPath, _countof(szFullPath), NULL, szCopyName); + if((dwErrCode = OpenExistingArchive(&Logger, szFullPath, 0, &hMpq)) == ERROR_SUCCESS) { - // Verify presence of (listfile) and (attributes) - CheckIfFileIsPresent(&Logger, hMpq, LISTFILE_NAME, (dwFlags & TFLAG_HAS_LISTFILE)); - CheckIfFileIsPresent(&Logger, hMpq, ATTRIBUTES_NAME, (dwFlags & TFLAG_HAS_ATTRIBUTES)); + DWORD dwFlags = 0; - // 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 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 size of the added file does not match"); - dwErrCode = ERROR_FILE_CORRUPT; - } + SFileGetFileInfo(hMpq, SFileMpqFlags, &dwFlags, sizeof(dwFlags), NULL); + if(dwFlags & MPQ_FLAG_MALFORMED) + bSucceeded = false; - // Delete the file data - STORM_FREE(pFileData); - } - else - { - Logger.PrintError("Failed to open the file previously added"); - } - SFileCloseArchive(hMpq); } } + + // Both tests must have succeeded + if(bSucceeded == false) + dwErrCode = ERROR_CAN_NOT_COMPLETE; return dwErrCode; } @@ -4232,7 +4145,7 @@ static const TEST_INFO Test_ReplaceFile[] = //----------------------------------------------------------------------------- // Main -//#define TEST_COMMAND_LINE +#define TEST_COMMAND_LINE #define TEST_LOCAL_LISTFILE #define TEST_STREAM_OPERATIONS #define TEST_MASTER_MIRROR @@ -4355,7 +4268,11 @@ int _tmain(int argc, TCHAR * argv[]) } #endif - // Verify SHA1 of each MPQ that we have in the list + // Add files so the archive will go over 2GB + if(dwErrCode == ERROR_SUCCESS) + dwErrCode = TestOpenArchive_AddFiles2GB(_T("MPQ_2002_v1_LargeMapFile.w3m"), 0); + + // Verify SHA256 of each MPQ that we have in the list if(dwErrCode == ERROR_SUCCESS) dwErrCode = VerifyFileHashes(szMpqSubDir); diff --git a/test/stormlib-test-001.txt b/test/stormlib-test-001.txt index 91af3c2..a80b2f5 100644 --- a/test/stormlib-test-001.txt +++ b/test/stormlib-test-001.txt @@ -119,6 +119,7 @@ Test_Signature (MPQ_1999_v1_WeakSigned1.mpq) succeeded. TestModifyMpq (MPQ_2014_v4_Base.StormReplay) succeeded. TestModifyMpq (MPQ_2022_v1_v4.329.w3x) succeeded. TestModifyMpq (MPQ_2023_v1_StarcraftMap.scm) succeeded. +TestAddFileOver2GB (MPQ_2002_v1_LargeMapFile.w3m) succeeded. TestVerifyHash succeeded. CreateEmptyMpq (StormLibTest_EmptyMpq_v2.mpq) succeeded. CreateEmptyMpq (StormLibTest_EmptyMpq_v4.mpq) succeeded. @@ -139,3 +140,5 @@ TestCompressions: Warning: CRC32 error on WaveFile_01.wav TestCompressions: Warning: CRC32 error on WaveFile_02.wav ListFilePos (StormLibTest_ListFilePos.mpq) succeeded. TestBigArchive (StormLibTest_BigArchive_v4.mpq) succeeded. + +E:\Ladik\Appdir\StormLib\bin\StormLib_test\x64\Release> \ No newline at end of file -- cgit v1.2.3