aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLadislav Zezula <zezula@volny.cz>2022-02-06 18:05:38 +0100
committerGitHub <noreply@github.com>2022-02-06 18:05:38 +0100
commitb79a6cc62e610ed405edb38cb990bfe7e6571bd6 (patch)
tree0e7ff5e34562a85ca2cd5e674ca892ccdb1034e2
parentca0e437ff5577870d6d757eba5b9430a781df4a2 (diff)
parent9eef856125e84a00169f64a854241ff43f500592 (diff)
Merge pull request #241 from ladislav-zezula/LZ_AnotherSCXProtector
Fixed file search order for Starcraft I
-rw-r--r--src/SBaseFileTable.cpp25
-rw-r--r--src/SFileGetFileInfo.cpp4
-rw-r--r--test/StormTest.cpp20
3 files changed, 33 insertions, 16 deletions
diff --git a/src/SBaseFileTable.cpp b/src/SBaseFileTable.cpp
index 97fa3a2..90b7aa4 100644
--- a/src/SBaseFileTable.cpp
+++ b/src/SBaseFileTable.cpp
@@ -769,6 +769,7 @@ static TMPQHash * GetHashEntryLocale(TMPQArchive * ha, const char * szFileName,
{
TMPQHash * pFirstHash = GetFirstHashEntry(ha, szFileName);
TMPQHash * pBestEntry = NULL;
+ TMPQHash * p1stEntry = NULL;
TMPQHash * pHash = pFirstHash;
// Parse the found hashes
@@ -776,26 +777,38 @@ static TMPQHash * GetHashEntryLocale(TMPQArchive * ha, const char * szFileName,
{
// Storm_2016.dll: 150209CB
// If the hash entry matches both locale and platform, return it immediately
- // Note: We only succeed this check if the locale is non-neutral, because
- // some Warcraft III maps have several items with neutral locale&platform, which leads
- // to wrong item being returned
+ // 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)
return pHash;
// Storm_2016.dll: 150209D9
- // If (locale matches or is neutral) OR (platform matches or is neutral)
- // remember this as the best entry
+ // If (locale matches or is neutral) OR (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->Platform == 0 || pHash->Platform == Platform)
+ {
+ p1stEntry = (p1stEntry != NULL) ? p1stEntry : pHash;
pBestEntry = pHash;
+ }
}
// Get the next hash entry for that file
pHash = GetNextHashEntry(ha, pFirstHash, pHash);
}
- // At the end, return neutral hash (if found), otherwise NULL
+ //
+ // Different processing (Starcraft vs. Warcraft III), abused by some protectors
+ //
+ // * Starcraft I: for an entry with locale&platform = 0, then the first entry is returned
+ // Map: MPQ_2022_v1_Sniper.scx
+ // * Warcraft III: for an entry with locale&platform = 0, then the last entry is returned
+ // Map: MPQ_2015_v1_ProtectedMap_Spazy.w3x
+ //
+
+ if(ha->dwValidFileFlags == MPQ_FILE_VALID_FLAGS_SCX)
+ return p1stEntry;
return pBestEntry;
}
diff --git a/src/SFileGetFileInfo.cpp b/src/SFileGetFileInfo.cpp
index 5bc3a3f..b980755 100644
--- a/src/SFileGetFileInfo.cpp
+++ b/src/SFileGetFileInfo.cpp
@@ -199,6 +199,7 @@ bool WINAPI SFileGetFileInfo(
TFileEntry * pFileEntry = NULL;
TMPQHeader * pHeader = NULL;
ULONGLONG Int64Value = 0;
+ ULONGLONG ByteOffset;
TMPQFile * hf = NULL;
void * pvSrcFileInfo = NULL;
DWORD cbSrcFileInfo = 0;
@@ -317,7 +318,8 @@ bool WINAPI SFileGetFileInfo(
return GetInfo(pvFileInfo, cbFileInfo, &pHeader->dwBlockTableSize, sizeof(DWORD), pcbLengthNeeded);
case SFileMpqBlockTable:
- if(MAKE_OFFSET64(pHeader->wBlockTablePosHi, pHeader->dwBlockTablePos) >= ha->FileSize)
+ ByteOffset = FileOffsetFromMpqOffset(ha, MAKE_OFFSET64(pHeader->wBlockTablePosHi, pHeader->dwBlockTablePos));
+ if(ByteOffset >= ha->FileSize)
return GetInfo_ReturdwErrCode(ERROR_FILE_NOT_FOUND);
cbSrcFileInfo = pHeader->dwBlockTableSize * sizeof(TMPQBlock);
pvSrcFileInfo = LoadBlockTable(ha, true);
diff --git a/test/StormTest.cpp b/test/StormTest.cpp
index 2700bf1..88b12d9 100644
--- a/test/StormTest.cpp
+++ b/test/StormTest.cpp
@@ -4214,8 +4214,8 @@ static DWORD TestModifyArchive_ReplaceFile(LPCTSTR szMpqPlainName, LPCTSTR szFil
//-----------------------------------------------------------------------------
// Tables
-static LPCTSTR szBliz = _T("ListFile_Blizzard.txt");
-static LPCTSTR szWotI = _T("ListFile_WarOfTheImmortals.txt");
+static LPCTSTR Bliz = _T("ListFile_Blizzard.txt");
+static LPCTSTR WotI = _T("ListFile_WarOfTheImmortals.txt");
static const TEST_INFO TestList_StreamOps[] =
{
@@ -4246,7 +4246,7 @@ static const TEST_INFO Test_Mpqs[] =
{_T("MPQ_1997_v1_Diablo1_DIABDAT.MPQ"), NULL, 0, "music\\dintro.wav", "File00000023.xxx"},
{_T("MPQ_2016_v1_D2XP_IX86_1xx_114a.mpq"), NULL, TEST_DATA("255d87a62f3c9518f72cf723a1818946", 221), "waitingroombkgd.dc6"}, // Update MPQ from Diablo II (patch 2016)
{_T("MPQ_2018_v1_icon_error.w3m"), NULL, TEST_DATA("fcefa25fb50c391e8714f2562d1e10ff", 19), "file00000002.blp"},
- {_T("MPQ_1997_v1_Diablo1_STANDARD.SNP"), szBliz, TEST_DATA("5ef18ef9a26b5704d8d46a344d976c89", 2)}, // File whose archive's (signature) file has flags = 0x90000000
+ {_T("MPQ_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)
@@ -4258,7 +4258,7 @@ static const TEST_INFO Test_Mpqs[] =
{_T("MPQ_2010_v3_expansion-locale-frFR.MPQ"), NULL, TEST_DATA("0c8fc921466f07421a281a05fad08b01", 53)}, // MPQ archive v 3.0 (the only one I know)
{_T("mpqe-file://MPQ_2011_v2_EncryptedMpq.MPQE"), NULL, TEST_DATA("10e4dcdbe95b7ad731c563ec6b71bc16", 82)}, // Encrypted archive from Starcraft II installer
{_T("MPx_2013_v1_LongwuOnline.mpk"), NULL, TEST_DATA("548f7db88284097f7e94c95a08c5bc24", 469)}, // MPK archive from Longwu online
- {_T("MPx_2013_v1_WarOfTheImmortals.sqp"), szWotI, TEST_DATA("a048f37f7c6162a96253d8081722b6d9", 9396)}, // SQP archive from War of the Immortals
+ {_T("MPx_2013_v1_WarOfTheImmortals.sqp"), WotI, TEST_DATA("a048f37f7c6162a96253d8081722b6d9", 9396)}, // SQP archive from War of the Immortals
{_T("part-file://MPQ_2010_v2_HashTableCompressed.MPQ.part"),0, TEST_DATA("d41d8cd98f00b204e9800998ecf8427e", 14263)}, // Partial MPQ with compressed hash table
{_T("blk4-file://streaming/model.MPQ.0"), NULL, TEST_DATA("e06b00efb2fc7e7469dd8b3b859ae15d", 39914)}, // Archive that is merged with multiple files
@@ -4290,6 +4290,7 @@ static const TEST_INFO Test_Mpqs[] =
{_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", 63)}, // Multiple items in hash table for staredit\scenario.chk (locale=0, platform=0)
};
static const TEST_INFO Patched_Mpqs[] =
@@ -4323,13 +4324,14 @@ int _tmain(int argc, TCHAR * argv[])
dwErrCode = InitializeMpqDirectory(argv, argc);
//
- // Open all files from the command line
+ // Test-open MPQs from the command line. They must be plain name
+ // and must be plade in the Test-MPQs folder
//
- //for(int i = 1; i < argc; i++)
- //{
- // TestArchive(_T("MPQ_2021_v1_CantExtractCHK.scx"), NULL, TFLG_FILE_LOCALE | 0x0409, "File00000014.xxx", NULL);
- //}
+ for(int i = 2; i < argc; i++)
+ {
+ TestArchive(argv[i], NULL, TFLG_FILE_LOCALE | 0x0409, "File00000014.xxx", NULL);
+ }
//
// Tests on a local listfile