diff options
author | Ladislav Zezula <zezula@volny.cz> | 2020-11-18 19:12:53 +0100 |
---|---|---|
committer | Ladislav Zezula <zezula@volny.cz> | 2020-11-18 19:12:53 +0100 |
commit | b13aaed6d0a940934dcb26aa3cb28ffc0dd06c48 (patch) | |
tree | 4886ebc5f1aba7695a5bcc96baa6e97885b8c045 /src | |
parent | 725327a23b0ad9a148521353697eb4b27e3f7631 (diff) |
Fixed some variants of NP_Protect-ed maps
Diffstat (limited to 'src')
-rw-r--r-- | src/SBaseCommon.cpp | 2 | ||||
-rw-r--r-- | src/SBaseFileTable.cpp | 97 | ||||
-rw-r--r-- | src/SFileOpenArchive.cpp | 5 | ||||
-rw-r--r-- | src/StormLib.h | 20 |
4 files changed, 73 insertions, 51 deletions
diff --git a/src/SBaseCommon.cpp b/src/SBaseCommon.cpp index 34a7a25..97ebc59 100644 --- a/src/SBaseCommon.cpp +++ b/src/SBaseCommon.cpp @@ -962,7 +962,7 @@ void * LoadMpqTable( }
}
- // If everything succeeded, read the raw table form the MPQ
+ // If everything succeeded, read the raw table from the MPQ
if(FileStream_Read(ha->pStream, &ByteOffset, pbToRead, dwBytesToRead))
{
// First of all, decrypt the table
diff --git a/src/SBaseFileTable.cpp b/src/SBaseFileTable.cpp index e08daef..af8d290 100644 --- a/src/SBaseFileTable.cpp +++ b/src/SBaseFileTable.cpp @@ -57,11 +57,11 @@ static DWORD GetNecessaryBitCount(ULONGLONG MaxValue) }
//-----------------------------------------------------------------------------
-// Implementation of the TStormBits struc
+// Implementation of the TMPQBits struct
-struct TStormBits
+struct TMPQBits
{
- static TStormBits * Create(DWORD NumberOfBits, BYTE FillValue);
+ static TMPQBits * Create(DWORD NumberOfBits, BYTE FillValue);
void GetBits(unsigned int nBitPosition, unsigned int nBitLength, void * pvBuffer, int nResultSize);
void SetBits(unsigned int nBitPosition, unsigned int nBitLength, void * pvBuffer, int nResultSize);
@@ -73,17 +73,17 @@ struct TStormBits BYTE Elements[1]; // Array of elements (variable length)
};
-const USHORT TStormBits::SetBitsMask[] = {0x00, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF};
+const USHORT TMPQBits::SetBitsMask[] = {0x00, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF};
-TStormBits * TStormBits::Create(
+TMPQBits * TMPQBits::Create(
DWORD NumberOfBits,
BYTE FillValue)
{
- TStormBits * pBitArray;
- size_t nSize = sizeof(TStormBits) + (NumberOfBits + 7) / 8;
+ TMPQBits * pBitArray;
+ size_t nSize = sizeof(TMPQBits) + (NumberOfBits + 7) / 8;
// Allocate the bit array
- pBitArray = (TStormBits *)STORM_ALLOC(BYTE, nSize);
+ pBitArray = (TMPQBits *)STORM_ALLOC(BYTE, nSize);
if(pBitArray != NULL)
{
memset(pBitArray, FillValue, nSize);
@@ -94,7 +94,7 @@ TStormBits * TStormBits::Create( return pBitArray;
}
-void TStormBits::GetBits(
+void TMPQBits::GetBits(
unsigned int nBitPosition,
unsigned int nBitLength,
void * pvBuffer,
@@ -159,7 +159,7 @@ void TStormBits::GetBits( }
}
-void TStormBits::SetBits(
+void TMPQBits::SetBits(
unsigned int nBitPosition,
unsigned int nBitLength,
void * pvBuffer,
@@ -225,6 +225,11 @@ void TStormBits::SetBits( }
}
+void GetMPQBits(TMPQBits * pBits, unsigned int nBitPosition, unsigned int nBitLength, void * pvBuffer, int nResultByteSize)
+{
+ pBits->GetBits(nBitPosition, nBitLength, pvBuffer, nResultByteSize);
+}
+
//-----------------------------------------------------------------------------
// Support for MPQ header
@@ -234,19 +239,22 @@ static bool VerifyTablePosition64( ULONGLONG TableSize, // Size of the MPQ table, in bytes
ULONGLONG FileSize) // Size of the entire file, in bytes
{
- // Verify overflows
- if((MpqOffset + TableOffset) < MpqOffset)
- return false;
- if((MpqOffset + TableOffset + TableSize) < MpqOffset)
- return false;
-
- // Verify sizes
- if(TableOffset >= FileSize || TableSize >= FileSize)
- return false;
- if((MpqOffset + TableOffset) >= FileSize)
- return false;
- if((MpqOffset + TableOffset + TableSize) >= FileSize)
- return false;
+ if(TableOffset != 0)
+ {
+ // Verify overflows
+ if((MpqOffset + TableOffset) < MpqOffset)
+ return false;
+ if((MpqOffset + TableOffset + TableSize) < MpqOffset)
+ return false;
+
+ // Verify sizes
+ if(TableOffset >= FileSize || TableSize >= FileSize)
+ return false;
+ if((MpqOffset + TableOffset) >= FileSize)
+ return false;
+ if((MpqOffset + TableOffset + TableSize) >= FileSize)
+ return false;
+ }
return true;
}
@@ -333,10 +341,21 @@ static ULONGLONG DetermineArchiveSize_V4( // This could only be called for MPQs version 4
assert(pHeader->wFormatVersion == MPQ_FORMAT_VERSION_4);
- // Determine the archive size as the greatest of all valid values
- EndOfTable = pHeader->BetTablePos64 + pHeader->BetTableSize64;
- if(EndOfTable > ArchiveSize)
- ArchiveSize = EndOfTable;
+ // Check position of BET table, if correct
+ if((pHeader->BetTablePos64 >> 0x20) == 0 && (pHeader->BetTableSize64 >> 0x20) == 0)
+ {
+ EndOfTable = pHeader->BetTablePos64 + pHeader->BetTableSize64;
+ if(EndOfTable > ArchiveSize)
+ ArchiveSize = EndOfTable;
+ }
+
+ // Check position of HET table, if correct
+ if((pHeader->HetTablePos64 >> 0x20) == 0 && (pHeader->HetTableSize64 >> 0x20) == 0)
+ {
+ EndOfTable = pHeader->HetTablePos64 + pHeader->HetTableSize64;
+ if(EndOfTable > ArchiveSize)
+ ArchiveSize = EndOfTable;
+ }
EndOfTable = pHeader->dwHashTablePos + pHeader->dwHashTableSize * sizeof(TMPQHash);
if(EndOfTable > ArchiveSize)
@@ -346,10 +365,6 @@ static ULONGLONG DetermineArchiveSize_V4( if(EndOfTable > ArchiveSize)
ArchiveSize = EndOfTable;
- EndOfTable = pHeader->HetTablePos64 + pHeader->HetTableSize64;
- if(EndOfTable > ArchiveSize)
- ArchiveSize = EndOfTable;
-
// Return the calculated archive size
return ArchiveSize;
}
@@ -628,6 +643,8 @@ int ConvertMpqHeaderToFormat4( return ERROR_FAKE_MPQ_HEADER;
if(!VerifyTablePosition64(MpqOffset, pHeader->HiBlockTablePos64, pHeader->HiBlockTableSize64, FileSize))
return ERROR_FAKE_MPQ_HEADER;
+ if(!VerifyTablePosition64(MpqOffset, pHeader->HetTablePos64, pHeader->HetTableSize64, FileSize))
+ return ERROR_FAKE_MPQ_HEADER;
// Check for malformed MPQs
if(pHeader->wFormatVersion != MPQ_FORMAT_VERSION_4 || (ha->MpqPos + pHeader->ArchiveSize64) != FileSize || (ha->MpqPos + pHeader->HiBlockTablePos64) >= FileSize)
@@ -1332,7 +1349,7 @@ TMPQHetTable * CreateHetTable(DWORD dwEntryCount, DWORD dwTotalCount, DWORD dwNa memset(pHetTable->pNameHashes, 0, dwTotalCount);
// Allocate the bit array for file indexes
- pHetTable->pBetIndexes = TStormBits::Create(dwTotalCount * pHetTable->dwIndexSizeTotal, 0xFF);
+ pHetTable->pBetIndexes = TMPQBits::Create(dwTotalCount * pHetTable->dwIndexSizeTotal, 0xFF);
if(pHetTable->pBetIndexes != NULL)
{
// Initialize the HET table from the source data (if given)
@@ -1732,7 +1749,7 @@ static TMPQBetTable * TranslateBetTable( }
// Load the bit-based file table
- pBetTable->pFileTable = TStormBits::Create(pBetTable->dwTableEntrySize * pBetHeader->dwEntryCount, 0);
+ pBetTable->pFileTable = TMPQBits::Create(pBetTable->dwTableEntrySize * pBetHeader->dwEntryCount, 0);
if(pBetTable->pFileTable != NULL)
{
LengthInBytes = (pBetTable->pFileTable->NumberOfBits + 7) / 8;
@@ -1746,7 +1763,7 @@ static TMPQBetTable * TranslateBetTable( pBetTable->dwBitCount_NameHash2 = pBetHeader->dwBitCount_NameHash2;
// Create and load the array of BET hashes
- pBetTable->pNameHashes = TStormBits::Create(pBetTable->dwBitTotal_NameHash2 * pBetHeader->dwEntryCount, 0);
+ pBetTable->pNameHashes = TMPQBits::Create(pBetTable->dwBitTotal_NameHash2 * pBetHeader->dwEntryCount, 0);
if(pBetTable->pNameHashes != NULL)
{
LengthInBytes = (pBetTable->pNameHashes->NumberOfBits + 7) / 8;
@@ -1771,7 +1788,7 @@ TMPQExtHeader * TranslateBetTable( TMPQBetHeader BetHeader;
TFileEntry * pFileTableEnd = ha->pFileTable + ha->dwFileTableSize;
TFileEntry * pFileEntry;
- TStormBits * pBitArray = NULL;
+ TMPQBits * pBitArray = NULL;
LPBYTE pbLinearTable = NULL;
LPBYTE pbTrgData;
DWORD LengthInBytes;
@@ -1791,7 +1808,7 @@ TMPQExtHeader * TranslateBetTable( pbTrgData = (LPBYTE)(pBetHeader + 1);
// Save the bit-based block table
- pBitArray = TStormBits::Create(BetHeader.dwEntryCount * BetHeader.dwTableEntrySize, 0);
+ pBitArray = TMPQBits::Create(BetHeader.dwEntryCount * BetHeader.dwTableEntrySize, 0);
if(pBitArray != NULL)
{
DWORD dwFlagIndex = 0;
@@ -1846,7 +1863,7 @@ TMPQExtHeader * TranslateBetTable( }
// Create bit array for name hashes
- pBitArray = TStormBits::Create(BetHeader.dwBitTotal_NameHash2 * BetHeader.dwEntryCount, 0);
+ pBitArray = TMPQBits::Create(BetHeader.dwBitTotal_NameHash2 * BetHeader.dwEntryCount, 0);
if(pBitArray != NULL)
{
DWORD dwFileIndex = 0;
@@ -2376,7 +2393,7 @@ TMPQHetTable * LoadHetTable(TMPQArchive * ha) TMPQHeader * pHeader = ha->pHeader;
// If the HET table position is not 0, we expect the table to be present
- if(pHeader->HetTablePos64 != 0 && pHeader->HetTableSize64 != 0)
+ if(pHeader->HetTablePos64 && pHeader->HetTableSize64)
{
// Attempt to load the HET table (Hash Extended Table)
pExtTable = LoadExtTable(ha, pHeader->HetTablePos64, (size_t)pHeader->HetTableSize64, HET_TABLE_SIGNATURE, MPQ_KEY_HASH_TABLE);
@@ -2398,7 +2415,7 @@ TMPQBetTable * LoadBetTable(TMPQArchive * ha) TMPQHeader * pHeader = ha->pHeader;
// If the BET table position is not 0, we expect the table to be present
- if(pHeader->BetTablePos64 != 0 && pHeader->BetTableSize64 != 0)
+ if(pHeader->BetTablePos64 && pHeader->BetTableSize64)
{
// Attempt to load the HET table (Hash Extended Table)
pExtTable = LoadExtTable(ha, pHeader->BetTablePos64, (size_t)pHeader->BetTableSize64, BET_TABLE_SIGNATURE, MPQ_KEY_BLOCK_TABLE);
@@ -2518,7 +2535,7 @@ static int BuildFileTable_HetBet(TMPQArchive * ha) TMPQHetTable * pHetTable = ha->pHetTable;
TMPQBetTable * pBetTable;
TFileEntry * pFileEntry = ha->pFileTable;
- TStormBits * pBitArray;
+ TMPQBits * pBitArray;
DWORD dwBitPosition = 0;
DWORD i;
int nError = ERROR_FILE_CORRUPT;
diff --git a/src/SFileOpenArchive.cpp b/src/SFileOpenArchive.cpp index 2020e56..d1cc4d6 100644 --- a/src/SFileOpenArchive.cpp +++ b/src/SFileOpenArchive.cpp @@ -5,7 +5,7 @@ /* E-mail : ladik@zezula.net */ /* WWW : www.zezula.net */ /*---------------------------------------------------------------------------*/ -/* Archive functions of Storm.dll */ +/* Implementation of archive functions */ /*---------------------------------------------------------------------------*/ /* Date Ver Who Comment */ /* -------- ---- --- ------- */ @@ -100,6 +100,7 @@ static int VerifyMpqTablePositions(TMPQArchive * ha, ULONGLONG FileSize) { TMPQHeader * pHeader = ha->pHeader; ULONGLONG ByteOffset; + //bool bMalformed = (ha->dwFlags & MPQ_FLAG_MALFORMED) ? true : false; // Check the begin of HET table if(pHeader->HetTablePos64) @@ -298,7 +299,7 @@ bool WINAPI SFileOpenArchive( // If there is the MPQ user data, process it // Note that Warcraft III does not check for user data, which is abused by many map protectors dwHeaderID = BSWAP_INT32_UNSIGNED(ha->HeaderData[0]); - if(MapType == MapTypeNotRecognized && (dwFlags & MPQ_OPEN_FORCE_MPQ_V1) == 0) + if(MapType != MapTypeWarcraft3 && (dwFlags & MPQ_OPEN_FORCE_MPQ_V1) == 0) { if(ha->pUserData == NULL && dwHeaderID == ID_MPQ_USERDATA) { diff --git a/src/StormLib.h b/src/StormLib.h index 4f19772..d913a54 100644 --- a/src/StormLib.h +++ b/src/StormLib.h @@ -480,7 +480,7 @@ typedef void (WINAPI * SFILE_ADDFILE_CALLBACK)(void * pvUserData, DWORD dwBytesW typedef void (WINAPI * SFILE_COMPACT_CALLBACK)(void * pvUserData, DWORD dwWorkType, ULONGLONG BytesProcessed, ULONGLONG TotalBytes); struct TFileStream; -struct TStormBits; +struct TMPQBits; //----------------------------------------------------------------------------- // Structures related to MPQ format @@ -748,7 +748,7 @@ typedef struct _TMPQBetHeader // Structure for parsed HET table typedef struct _TMPQHetTable { - TStormBits * pBetIndexes; // Bit array of FileIndex values + TMPQBits * pBetIndexes; // Bit array of FileIndex values LPBYTE pNameHashes; // Array of NameHash1 values (NameHash1 = upper 8 bits of FileName hashe) ULONGLONG AndMask64; // AND mask used for calculating file name hash ULONGLONG OrMask64; // OR mask used for setting the highest bit of the file name hash @@ -764,8 +764,8 @@ typedef struct _TMPQHetTable // Structure for parsed BET table typedef struct _TMPQBetTable { - TStormBits * pNameHashes; // Array of NameHash2 entries (lower 24 bits of FileName hash) - TStormBits * pFileTable; // Bit-based file table + TMPQBits * pNameHashes; // Array of NameHash2 entries (lower 24 bits of FileName hash) + TMPQBits * pFileTable; // Bit-based file table LPDWORD pFileFlags; // Array of file flags DWORD dwTableEntrySize; // Size of one table entry, in bits @@ -925,10 +925,15 @@ typedef struct _SFILE_CREATE_MPQ } SFILE_CREATE_MPQ, *PSFILE_CREATE_MPQ; //----------------------------------------------------------------------------- +// TMPQBits support - functions + +void GetMPQBits(TMPQBits * pBits, unsigned int nBitPosition, unsigned int nBitLength, void * pvBuffer, int nResultByteSize); + +//----------------------------------------------------------------------------- // Stream support - functions // Structure used by FileStream_GetBitmap -typedef struct _TStreamBitmap +struct TStreamBitmap { ULONGLONG StreamSize; // Size of the stream, in bytes DWORD BitmapSize; // Size of the block map, in bytes @@ -937,8 +942,7 @@ typedef struct _TStreamBitmap DWORD IsComplete; // Nonzero if the file is complete // Followed by the BYTE array, each bit means availability of one block - -} TStreamBitmap; +}; // UNICODE versions of the file access functions TFileStream * FileStream_CreateFile(const TCHAR * szFileName, DWORD dwStreamFlags); @@ -948,7 +952,7 @@ size_t FileStream_Prefix(const TCHAR * szFileName, DWORD * pdwProvider); bool FileStream_SetCallback(TFileStream * pStream, SFILE_DOWNLOAD_CALLBACK pfnCallback, void * pvUserData); -bool FileStream_GetBitmap(TFileStream * pStream, void * pvBitmap, DWORD cbBitmap, LPDWORD pcbLengthNeeded); +bool FileStream_GetBitmap(TFileStream * pStream, void * pvBitmap, DWORD cbBitmap, DWORD * pcbLengthNeeded); bool FileStream_Read(TFileStream * pStream, ULONGLONG * pByteOffset, void * pvBuffer, DWORD dwBytesToRead); bool FileStream_Write(TFileStream * pStream, ULONGLONG * pByteOffset, const void * pvBuffer, DWORD dwBytesToWrite); bool FileStream_SetSize(TFileStream * pStream, ULONGLONG NewFileSize); |