aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/SBaseCommon.cpp4
-rw-r--r--src/SBaseFileTable.cpp46
-rw-r--r--src/SBaseSubTypes.cpp8
-rw-r--r--src/SFileFindFile.cpp2
-rw-r--r--src/SFileListFile.cpp2
-rw-r--r--src/SFileOpenArchive.cpp4
-rw-r--r--src/StormLib.h7
7 files changed, 33 insertions, 40 deletions
diff --git a/src/SBaseCommon.cpp b/src/SBaseCommon.cpp
index 54fc6d0..95bdeb4 100644
--- a/src/SBaseCommon.cpp
+++ b/src/SBaseCommon.cpp
@@ -628,7 +628,7 @@ TMPQHash * GetFirstHashEntry(TMPQArchive * ha, const char * szFileName)
TMPQHash * pHash = ha->pHashTable + dwIndex;
// If the entry matches, we found it.
- if(pHash->dwName1 == dwName1 && pHash->dwName2 == dwName2 && pHash->dwBlockIndex < ha->dwFileTableSize)
+ if(pHash->dwName1 == dwName1 && pHash->dwName2 == dwName2 && MPQ_BLOCK_INDEX(pHash) < ha->dwFileTableSize)
return pHash;
// If that hash entry is a free entry, it means we haven't found the file
@@ -663,7 +663,7 @@ TMPQHash * GetNextHashEntry(TMPQArchive * ha, TMPQHash * pFirstHash, TMPQHash *
pHash = ha->pHashTable + dwIndex;
// If the entry matches, we found it.
- if(pHash->dwName1 == dwName1 && pHash->dwName2 == dwName2 && pHash->dwBlockIndex < ha->dwFileTableSize)
+ if(pHash->dwName1 == dwName1 && pHash->dwName2 == dwName2 && MPQ_BLOCK_INDEX(pHash) < ha->dwFileTableSize)
return pHash;
// If that hash entry is a free entry, it means we haven't found the file
diff --git a/src/SBaseFileTable.cpp b/src/SBaseFileTable.cpp
index 9d37ff1..981328b 100644
--- a/src/SBaseFileTable.cpp
+++ b/src/SBaseFileTable.cpp
@@ -581,11 +581,9 @@ int ConvertMpqHeaderToFormat4(
// Hash entry verification when the file table does not exist yet
bool IsValidHashEntry(TMPQArchive * ha, TMPQHash * pHash)
{
- TFileEntry * pFileEntry = ha->pFileTable + MPQ_BLOCK_INDEX(pHash->dwBlockIndex);
- DWORD dwBlockIndex = MPQ_BLOCK_INDEX(pHash->dwBlockIndex);
+ TFileEntry * pFileEntry = ha->pFileTable + MPQ_BLOCK_INDEX(pHash);
- pFileEntry = ha->pFileTable + dwBlockIndex;
- return ((dwBlockIndex < ha->dwFileTableSize) && (pFileEntry->dwFlags & MPQ_FILE_EXISTS)) ? true : false;
+ return ((MPQ_BLOCK_INDEX(pHash) < ha->dwFileTableSize) && (pFileEntry->dwFlags & MPQ_FILE_EXISTS)) ? true : false;
}
// Hash entry verification when the file table does not exist yet
@@ -593,20 +591,12 @@ static bool IsValidHashEntry1(TMPQArchive * ha, TMPQHash * pHash, TMPQBlock * pB
{
ULONGLONG ByteOffset;
TMPQBlock * pBlock;
- DWORD dwBlockIndex;
-
- // We need to mask out the upper 4 bits of the block table index.
- // This is because it gets shifted out when calculating block table offset
- // BlockTableOffset = pHash->dwBlockIndex * 0x10
- // Malformed MPQ maps may contain invalid entries
- // Note that Storm.dll does not perfom this check
- dwBlockIndex = MPQ_BLOCK_INDEX(pHash->dwBlockIndex);
// The block index is considered valid if it's less than block table size
- if(dwBlockIndex < ha->pHeader->dwBlockTableSize)
+ if(MPQ_BLOCK_INDEX(pHash) < ha->pHeader->dwBlockTableSize)
{
// Calculate the block table position
- pBlock = pBlockTable + dwBlockIndex;
+ pBlock = pBlockTable + MPQ_BLOCK_INDEX(pHash);
// Check whether this is an existing file
// Also we do not allow to be file size greater than 2GB
@@ -787,28 +777,28 @@ static int BuildFileTableFromBlockTable(
// - Multiple hash entries (different file name) point to the same block entry
//
// Ignore all hash table entries where:
- // - dwBlockIndex >= BlockTableSize
+ // - Block Index >= BlockTableSize
// - Flags of the appropriate block table entry
//
if(IsValidHashEntry1(ha, pHash, pBlockTable))
{
- DWORD dwBlockIndex = MPQ_BLOCK_INDEX(pHash->dwBlockIndex);
- DWORD dwNewIndex = MPQ_BLOCK_INDEX(pHash->dwBlockIndex);
+ DWORD dwOldIndex = MPQ_BLOCK_INDEX(pHash);
+ DWORD dwNewIndex = MPQ_BLOCK_INDEX(pHash);
// Determine the new block index
if(DefragmentTable != NULL)
{
// Need to handle case when multiple hash
// entries point to the same block entry
- if(DefragmentTable[dwBlockIndex] == HASH_ENTRY_FREE)
+ if(DefragmentTable[dwOldIndex] == HASH_ENTRY_FREE)
{
- DefragmentTable[dwBlockIndex] = dwItemCount;
+ DefragmentTable[dwOldIndex] = dwItemCount;
dwNewIndex = dwItemCount++;
}
else
{
- dwNewIndex = DefragmentTable[dwBlockIndex];
+ dwNewIndex = DefragmentTable[dwOldIndex];
}
// Fix the pointer in the hash entry
@@ -820,7 +810,7 @@ static int BuildFileTableFromBlockTable(
// Get the pointer to the file entry and the block entry
pFileEntry = ha->pFileTable + dwNewIndex;
- pBlock = pBlockTable + dwBlockIndex;
+ pBlock = pBlockTable + dwOldIndex;
// ByteOffset is only valid if file size is not zero
pFileEntry->ByteOffset = pBlock->dwFilePos;
@@ -1814,11 +1804,11 @@ TFileEntry * GetFileEntryLocale2(TMPQArchive * ha, const char * szFileName, LCID
if(ha->pHashTable != NULL)
{
pHash = GetHashEntryLocale(ha, szFileName, lcLocale);
- if(pHash != NULL && pHash->dwBlockIndex < ha->dwFileTableSize)
+ if(pHash != NULL && MPQ_BLOCK_INDEX(pHash) < ha->dwFileTableSize)
{
if(PtrHashIndex != NULL)
PtrHashIndex[0] = (DWORD)(pHash - ha->pHashTable);
- return ha->pFileTable + pHash->dwBlockIndex;
+ return ha->pFileTable + MPQ_BLOCK_INDEX(pHash);
}
}
@@ -1848,11 +1838,11 @@ TFileEntry * GetFileEntryExact(TMPQArchive * ha, const char * szFileName, LCID l
if(ha->pHashTable != NULL)
{
pHash = GetHashEntryExact(ha, szFileName, lcLocale);
- if(pHash != NULL && pHash->dwBlockIndex < ha->dwFileTableSize)
+ if(pHash != NULL && MPQ_BLOCK_INDEX(pHash) < ha->dwFileTableSize)
{
if(PtrHashIndex != NULL)
PtrHashIndex[0] = (DWORD)(pHash - ha->pHashTable);
- return ha->pFileTable + pHash->dwBlockIndex;
+ return ha->pFileTable + MPQ_BLOCK_INDEX(pHash);
}
}
@@ -2640,11 +2630,11 @@ int DefragmentFileTable(TMPQArchive * ha)
for(pHash = ha->pHashTable; pHash < pHashTableEnd; pHash++)
{
- if(pHash->dwBlockIndex < ha->dwFileTableSize)
+ if(MPQ_BLOCK_INDEX(pHash) < ha->dwFileTableSize)
{
// If that block entry is there, set it to the hash entry
// If not, set it as DELETED
- dwNewBlockIndex = DefragmentTable[pHash->dwBlockIndex];
+ dwNewBlockIndex = DefragmentTable[MPQ_BLOCK_INDEX(pHash)];
pHash->dwBlockIndex = (dwNewBlockIndex != HASH_ENTRY_FREE) ? dwNewBlockIndex : HASH_ENTRY_DELETED;
}
}
@@ -2753,7 +2743,7 @@ int RebuildFileTable(TMPQArchive * ha, DWORD dwNewHashTableSize)
{
if(IsValidHashEntry(ha, pHash))
{
- pFileEntry = ha->pFileTable + pHash->dwBlockIndex;
+ pFileEntry = ha->pFileTable + MPQ_BLOCK_INDEX(pHash);
AllocateHashEntry(ha, pFileEntry, pHash->lcLocale);
}
}
diff --git a/src/SBaseSubTypes.cpp b/src/SBaseSubTypes.cpp
index 9807701..1f72c17 100644
--- a/src/SBaseSubTypes.cpp
+++ b/src/SBaseSubTypes.cpp
@@ -187,7 +187,6 @@ TMPQHash * LoadSqpHashTable(TMPQArchive * ha)
TSQPHash * pSqpHashEnd;
TSQPHash * pSqpHash;
TMPQHash * pMpqHash;
- DWORD dwBlockIndex;
int nError = ERROR_SUCCESS;
// Load the hash table
@@ -203,8 +202,7 @@ TMPQHash * LoadSqpHashTable(TMPQArchive * ha)
if(pSqpHash->dwBlockIndex != HASH_ENTRY_FREE)
{
// Check block index against the size of the block table
- dwBlockIndex = pSqpHash->dwBlockIndex;
- if(pHeader->dwBlockTableSize <= dwBlockIndex && dwBlockIndex < HASH_ENTRY_DELETED)
+ if(pHeader->dwBlockTableSize <= MPQ_BLOCK_INDEX(pSqpHash) && MPQ_BLOCK_INDEX(pSqpHash) < HASH_ENTRY_DELETED)
nError = ERROR_FILE_CORRUPT;
// We do not support nonzero locale and platform ID
@@ -216,8 +214,8 @@ TMPQHash * LoadSqpHashTable(TMPQArchive * ha)
pMpqHash->dwName2 = pSqpHash->dwName2;
// Store the rest. Note that this must be done last,
- // because pSqpHash->dwBlockIndex corresponds to pMpqHash->dwName2
- pMpqHash->dwBlockIndex = dwBlockIndex;
+ // because block index corresponds to pMpqHash->dwName2
+ pMpqHash->dwBlockIndex = MPQ_BLOCK_INDEX(pSqpHash);
pMpqHash->wPlatform = 0;
pMpqHash->lcLocale = 0;
}
diff --git a/src/SFileFindFile.cpp b/src/SFileFindFile.cpp
index 41f31e1..18bf4d5 100644
--- a/src/SFileFindFile.cpp
+++ b/src/SFileFindFile.cpp
@@ -299,7 +299,7 @@ static int DoMPQSearch_HashTable(TMPQSearch * hs, SFILE_FIND_DATA * lpFindFileDa
if(IsValidHashEntry(ha, pHash))
{
// Check if this file entry should be included in the search result
- if(DoMPQSearch_FileEntry(hs, lpFindFileData, ha, pHash, ha->pFileTable + pHash->dwBlockIndex))
+ if(DoMPQSearch_FileEntry(hs, lpFindFileData, ha, pHash, ha->pFileTable + MPQ_BLOCK_INDEX(pHash)))
return ERROR_SUCCESS;
}
}
diff --git a/src/SFileListFile.cpp b/src/SFileListFile.cpp
index 62b8f11..3918bd9 100644
--- a/src/SFileListFile.cpp
+++ b/src/SFileListFile.cpp
@@ -350,7 +350,7 @@ static int SListFileCreateNodeForAllLocales(TMPQArchive * ha, const char * szFil
while(pHash != NULL)
{
// Allocate file name for the file entry
- AllocateFileName(ha, ha->pFileTable + pHash->dwBlockIndex, szFileName);
+ AllocateFileName(ha, ha->pFileTable + MPQ_BLOCK_INDEX(pHash), szFileName);
// Now find the next language version of the file
pHash = GetNextHashEntry(ha, pFirstHash, pHash);
diff --git a/src/SFileOpenArchive.cpp b/src/SFileOpenArchive.cpp
index 2cb6698..62effe7 100644
--- a/src/SFileOpenArchive.cpp
+++ b/src/SFileOpenArchive.cpp
@@ -369,8 +369,8 @@ bool WINAPI SFileOpenArchive(
// higher than 0x10000000, it would overflow in 32-bit version
// Observed in the malformed Warcraft III maps
// Example map: MPQ_2016_v1_ProtectedMap_TableSizeOverflow.w3x
- ha->pHeader->dwBlockTableSize = MPQ_BLOCK_INDEX(ha->pHeader->dwBlockTableSize);
- ha->pHeader->dwHashTableSize = MPQ_BLOCK_INDEX(ha->pHeader->dwHashTableSize);
+ ha->pHeader->dwBlockTableSize = (ha->pHeader->dwBlockTableSize & BLOCK_INDEX_MASK);
+ ha->pHeader->dwHashTableSize = (ha->pHeader->dwHashTableSize & BLOCK_INDEX_MASK);
// Both MPQ_OPEN_NO_LISTFILE or MPQ_OPEN_NO_ATTRIBUTES trigger read only mode
if(dwFlags & (MPQ_OPEN_NO_LISTFILE | MPQ_OPEN_NO_ATTRIBUTES))
diff --git a/src/StormLib.h b/src/StormLib.h
index c25a1a8..3621096 100644
--- a/src/StormLib.h
+++ b/src/StormLib.h
@@ -230,7 +230,12 @@ extern "C" {
MPQ_FILE_SIGNATURE | \
MPQ_FILE_EXISTS)
-#define MPQ_BLOCK_INDEX(bi) ((bi) & 0x0FFFFFFF) // Index mask for block table index
+// We need to mask out the upper 4 bits of the block table index.
+// This is because it gets shifted out when calculating block table offset
+// BlockTableOffset = pHash->dwBlockIndex << 0x04
+// Malformed MPQ maps may contain block indexes like 0x40000001 or 0xF0000023
+#define BLOCK_INDEX_MASK 0x0FFFFFFF
+#define MPQ_BLOCK_INDEX(pHash) (pHash->dwBlockIndex & BLOCK_INDEX_MASK)
// Compression types for multiple compressions
#define MPQ_COMPRESSION_HUFFMANN 0x01 // Huffmann compression (used on WAVE files only)