diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/SBaseFileTable.cpp | 25 | ||||
-rw-r--r-- | src/SFileGetFileInfo.cpp | 4 |
2 files changed, 22 insertions, 7 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);
|