aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorLadislav Zezula <zezula@volny.cz>2020-11-21 04:27:09 +0100
committerLadislav Zezula <zezula@volny.cz>2020-11-21 04:27:09 +0100
commit809005c7f025bcc55bfa4ede78cb4cc45d3c0e6c (patch)
treee5d10b093dd215147f3e7128b11f96cc6afed04a /src
parentaea84bea149020385eadcd3df348d8e6fcbab733 (diff)
* Release 9.23v9.23
* Fixed regressions * Fixed test program
Diffstat (limited to 'src')
-rw-r--r--src/SBaseDumpData.cpp50
-rw-r--r--src/SBaseFileTable.cpp6
-rw-r--r--src/SFileAddFile.cpp20
-rw-r--r--src/SFileFindFile.cpp2
-rw-r--r--src/SFileGetFileInfo.cpp887
-rw-r--r--src/SFileListFile.cpp8
-rw-r--r--src/SFileOpenArchive.cpp2
-rw-r--r--src/SFileReadFile.cpp2
-rw-r--r--src/StormLib.h4
-rw-r--r--src/huffman/huff.cpp61
-rw-r--r--src/huffman/huff.h2
11 files changed, 328 insertions, 716 deletions
diff --git a/src/SBaseDumpData.cpp b/src/SBaseDumpData.cpp
index 334561b..2454f22 100644
--- a/src/SBaseDumpData.cpp
+++ b/src/SBaseDumpData.cpp
@@ -111,39 +111,33 @@ void DumpHetAndBetTable(TMPQHetTable * pHetTable, TMPQBetTable * pBetTable)
DWORD dwFlags = 0;
DWORD dwBetIndex = 0;
- GetBits(pHetTable->pBetIndexes, i * pHetTable->dwIndexSizeTotal,
- pHetTable->dwIndexSize,
- &dwBetIndex,
- 4);
+ GetMPQBits(pHetTable->pBetIndexes, i * pHetTable->dwIndexSizeTotal,
+ pHetTable->dwIndexSize,
+ &dwBetIndex, 4);
if(dwBetIndex < pHetTable->dwTotalCount)
{
DWORD dwEntryIndex = pBetTable->dwTableEntrySize * dwBetIndex;
- GetBits(pBetTable->pNameHashes, dwBetIndex * pBetTable->dwBitTotal_NameHash2,
- pBetTable->dwBitCount_NameHash2,
- &BetHash,
- 8);
-
- GetBits(pBetTable->pFileTable, dwEntryIndex + pBetTable->dwBitIndex_FilePos,
- pBetTable->dwBitCount_FilePos,
- &ByteOffset,
- 8);
-
- GetBits(pBetTable->pFileTable, dwEntryIndex + pBetTable->dwBitIndex_FileSize,
- pBetTable->dwBitCount_FileSize,
- &dwFileSize,
- 4);
-
- GetBits(pBetTable->pFileTable, dwEntryIndex + pBetTable->dwBitIndex_CmpSize,
- pBetTable->dwBitCount_CmpSize,
- &dwCmpSize,
- 4);
-
- GetBits(pBetTable->pFileTable, dwEntryIndex + pBetTable->dwBitIndex_FlagIndex,
- pBetTable->dwBitCount_FlagIndex,
- &dwFlagIndex,
- 4);
+ GetMPQBits(pBetTable->pNameHashes, dwBetIndex * pBetTable->dwBitTotal_NameHash2,
+ pBetTable->dwBitCount_NameHash2,
+ &BetHash, 8);
+
+ GetMPQBits(pBetTable->pFileTable, dwEntryIndex + pBetTable->dwBitIndex_FilePos,
+ pBetTable->dwBitCount_FilePos,
+ &ByteOffset, 8);
+
+ GetMPQBits(pBetTable->pFileTable, dwEntryIndex + pBetTable->dwBitIndex_FileSize,
+ pBetTable->dwBitCount_FileSize,
+ &dwFileSize, 4);
+
+ GetMPQBits(pBetTable->pFileTable, dwEntryIndex + pBetTable->dwBitIndex_CmpSize,
+ pBetTable->dwBitCount_CmpSize,
+ &dwCmpSize, 4);
+
+ GetMPQBits(pBetTable->pFileTable, dwEntryIndex + pBetTable->dwBitIndex_FlagIndex,
+ pBetTable->dwBitCount_FlagIndex,
+ &dwFlagIndex, 4);
dwFlags = pBetTable->pFileFlags[dwFlagIndex];
}
diff --git a/src/SBaseFileTable.cpp b/src/SBaseFileTable.cpp
index af8d290..7fe1042 100644
--- a/src/SBaseFileTable.cpp
+++ b/src/SBaseFileTable.cpp
@@ -432,9 +432,9 @@ int ConvertMpqHeaderToFormat4(
// If version 1.0 is forced, then the format version is forced to be 1.0
// Reason: Storm.dll in Warcraft III ignores format version value
- if((dwFlags & MPQ_OPEN_FORCE_MPQ_V1) || (MapType == MapTypeWarcraft3))
+ if((MapType == MapTypeWarcraft3) || (dwFlags & MPQ_OPEN_FORCE_MPQ_V1))
wFormatVersion = MPQ_FORMAT_VERSION_1;
- if(MapType == MapTypeStarcraft2)
+ if((MapType == MapTypeStarcraft2) && (pHeader->wFormatVersion > MPQ_FORMAT_VERSION_4))
wFormatVersion = MPQ_FORMAT_VERSION_4;
// Format-specific fixes
@@ -647,7 +647,7 @@ int ConvertMpqHeaderToFormat4(
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)
+ if(pHeader->wFormatVersion != MPQ_FORMAT_VERSION_4 || (MpqOffset + pHeader->ArchiveSize64) != FileSize || (MpqOffset + pHeader->HiBlockTablePos64) >= FileSize)
{
pHeader->wFormatVersion = MPQ_FORMAT_VERSION_4;
pHeader->dwHeaderSize = MPQ_HEADER_SIZE_V4;
diff --git a/src/SFileAddFile.cpp b/src/SFileAddFile.cpp
index 7dd583f..e756781 100644
--- a/src/SFileAddFile.cpp
+++ b/src/SFileAddFile.cpp
@@ -236,7 +236,7 @@ static int WriteDataToMpqFile(
// We have to calculate sector CRC, if enabled
if(hf->SectorChksums != NULL)
hf->SectorChksums[dwSectorIndex] = adler32(0, pbCompressed, nOutBuffer);
- }
+ }
// Encrypt the sector, if necessary
if(pFileEntry->dwFlags & MPQ_FILE_ENCRYPTED)
@@ -592,7 +592,7 @@ int SFileAddFile_Write(TMPQFile * hf, const void * pvData, DWORD dwSize, DWORD d
if(hf->pPatchInfo == NULL && IsIncrementalPatchFile(pvData, dwSize, &hf->dwPatchedFileSize))
{
// Set the MPQ_FILE_PATCH_FILE flag
- hf->pFileEntry->dwFlags |= MPQ_FILE_PATCH_FILE;
+ pFileEntry->dwFlags |= MPQ_FILE_PATCH_FILE;
// Allocate the patch info
hf->nAddFileError = nError = AllocatePatchInfo(hf, false);
@@ -659,10 +659,10 @@ int SFileAddFile_Write(TMPQFile * hf, const void * pvData, DWORD dwSize, DWORD d
if(hf->dwFilePos >= pFileEntry->dwFileSize)
{
// Finish calculating CRC32
- hf->pFileEntry->dwCrc32 = hf->dwCrc32;
+ pFileEntry->dwCrc32 = hf->dwCrc32;
// Finish calculating MD5
- md5_done((hash_state *)hf->hctx, hf->pFileEntry->md5);
+ md5_done((hash_state *)hf->hctx, pFileEntry->md5);
// If we also have sector checksums, write them to the file
if(hf->SectorChksums != NULL)
@@ -673,9 +673,9 @@ int SFileAddFile_Write(TMPQFile * hf, const void * pvData, DWORD dwSize, DWORD d
// Now write patch info
if(hf->pPatchInfo != NULL)
{
- memcpy(hf->pPatchInfo->md5, hf->pFileEntry->md5, MD5_DIGEST_SIZE);
- hf->pPatchInfo->dwDataSize = hf->pFileEntry->dwFileSize;
- hf->pFileEntry->dwFileSize = hf->dwPatchedFileSize;
+ memcpy(hf->pPatchInfo->md5, pFileEntry->md5, MD5_DIGEST_SIZE);
+ hf->pPatchInfo->dwDataSize = pFileEntry->dwFileSize;
+ pFileEntry->dwFileSize = hf->dwPatchedFileSize;
nError = WritePatchInfo(hf);
}
@@ -689,13 +689,17 @@ int SFileAddFile_Write(TMPQFile * hf, const void * pvData, DWORD dwSize, DWORD d
if(ha->pHeader->dwRawChunkSize != 0)
{
nError = WriteMpqDataMD5(ha->pStream,
- ha->MpqPos + hf->pFileEntry->ByteOffset,
+ ha->MpqPos + pFileEntry->ByteOffset,
hf->pFileEntry->dwCmpSize,
ha->pHeader->dwRawChunkSize);
}
}
}
+ // Update the archive size
+ if((ha->MpqPos + pFileEntry->ByteOffset + pFileEntry->dwCmpSize) > ha->FileSize)
+ ha->FileSize = ha->MpqPos + pFileEntry->ByteOffset + pFileEntry->dwCmpSize;
+
// Store the error code from the Write File operation
hf->nAddFileError = nError;
return nError;
diff --git a/src/SFileFindFile.cpp b/src/SFileFindFile.cpp
index 7e8502b..6a4cecd 100644
--- a/src/SFileFindFile.cpp
+++ b/src/SFileFindFile.cpp
@@ -238,6 +238,8 @@ static bool DoMPQSearch_FileEntry(
// Prepare the block index
dwBlockIndex = (DWORD)(pFileEntry - ha->pFileTable);
+ if(dwBlockIndex == 569)
+ szNameBuff[0] = 'F';
// Get the file name. If it's not known, we will create pseudo-name
szFileName = pFileEntry->szFileName;
diff --git a/src/SFileGetFileInfo.cpp b/src/SFileGetFileInfo.cpp
index c57b3b7..4ec05e2 100644
--- a/src/SFileGetFileInfo.cpp
+++ b/src/SFileGetFileInfo.cpp
@@ -13,35 +13,8 @@
#include "StormCommon.h"
//-----------------------------------------------------------------------------
-// Local defines
-
-// Information types for SFileGetFileInfo
-#define SFILE_INFO_TYPE_INVALID_HANDLE 0
-#define SFILE_INFO_TYPE_NOT_FOUND 1
-#define SFILE_INFO_TYPE_DIRECT_POINTER 2
-#define SFILE_INFO_TYPE_ALLOCATED 3
-#define SFILE_INFO_TYPE_READ_FROM_FILE 4
-#define SFILE_INFO_TYPE_TABLE_POINTER 5
-#define SFILE_INFO_TYPE_FILE_ENTRY 6
-
-//-----------------------------------------------------------------------------
// Local functions
-static void ConvertFileEntryToSelfRelative(TFileEntry * pFileEntry, TFileEntry * pSrcFileEntry)
-{
- // Copy the file entry itself
- memcpy(pFileEntry, pSrcFileEntry, sizeof(TFileEntry));
-
- // If source is NULL, leave it NULL
- if(pSrcFileEntry->szFileName != NULL)
- {
- // Set the file name pointer after the file entry
- pFileEntry->szFileName = (char *)(pFileEntry + 1);
- strcpy(pFileEntry->szFileName, pSrcFileEntry->szFileName);
- }
-}
-
-
static DWORD GetMpqFileCount(TMPQArchive * ha)
{
TFileEntry * pFileTableEnd;
@@ -69,56 +42,138 @@ static DWORD GetMpqFileCount(TMPQArchive * ha)
return dwFileCount;
}
-static bool GetFilePatchChain(TMPQFile * hf, void * pvFileInfo, DWORD cbFileInfo, DWORD * pcbLengthNeeded)
+static bool GetInfo_ReturnError(DWORD dwErrCode)
+{
+ SetLastError(dwErrCode);
+ return false;
+}
+
+static bool GetInfo_BufferCheck(void * pvFileInfo, DWORD cbFileInfo, DWORD cbData, LPDWORD pcbLengthNeeded)
+{
+ // Give the length needed to store the info
+ if(pcbLengthNeeded != NULL)
+ pcbLengthNeeded[0] = cbData;
+
+ // Check for sufficient buffer
+ if(cbData > cbFileInfo)
+ return GetInfo_ReturnError(ERROR_INSUFFICIENT_BUFFER);
+
+ // If the buffer size is sufficient, check for valid user buffer
+ if(pvFileInfo == NULL)
+ return GetInfo_ReturnError(ERROR_INVALID_PARAMETER);
+
+ // Buffers and sizes are OK, we are ready to proceed file copying
+ return true;
+}
+
+static bool GetInfo(void * pvFileInfo, DWORD cbFileInfo, const void * pvData, DWORD cbData, LPDWORD pcbLengthNeeded)
+{
+ // Verify buffer pointer and buffer size
+ if(!GetInfo_BufferCheck(pvFileInfo, cbFileInfo, cbData, pcbLengthNeeded))
+ return false;
+
+ // Copy the data to the caller-supplied buffer
+ memcpy(pvFileInfo, pvData, cbData);
+ return true;
+}
+
+static bool GetInfo_Allocated(void * pvFileInfo, DWORD cbFileInfo, void * pvData, DWORD cbData, LPDWORD pcbLengthNeeded)
+{
+ bool bResult;
+
+ // Verify buffer pointer and buffer size
+ if((bResult = GetInfo_BufferCheck(pvFileInfo, cbFileInfo, cbData, pcbLengthNeeded)) != false)
+ memcpy(pvFileInfo, pvData, cbData);
+
+ // Copy the data to the user buffer
+ STORM_FREE(pvData);
+ return bResult;
+}
+
+static bool GetInfo_TablePointer(void * pvFileInfo, DWORD cbFileInfo, void * pvTablePointer, SFileInfoClass InfoClass, LPDWORD pcbLengthNeeded)
+{
+ // Verify buffer pointer and buffer size
+ if(!GetInfo_BufferCheck(pvFileInfo, cbFileInfo, sizeof(void *), pcbLengthNeeded))
+ {
+ SFileFreeFileInfo(pvTablePointer, InfoClass);
+ return false;
+ }
+
+ // The user buffer receives pointer to the table.
+ // When done, the caller needs to call SFileFreeFileInfo on it
+ *(void **)pvFileInfo = pvTablePointer;
+ return true;
+}
+
+static bool GetInfo_ReadFromFile(void * pvFileInfo, DWORD cbFileInfo, TFileStream * pStream, ULONGLONG ByteOffset, DWORD cbData, LPDWORD pcbLengthNeeded)
+{
+ // Verify buffer pointer and buffer size
+ if(!GetInfo_BufferCheck(pvFileInfo, cbFileInfo, cbData, pcbLengthNeeded))
+ return false;
+
+ return FileStream_Read(pStream, &ByteOffset, pvFileInfo, cbData);
+}
+
+static bool GetInfo_FileEntry(void * pvFileInfo, DWORD cbFileInfo, TFileEntry * pFileEntry, LPDWORD pcbLengthNeeded)
+{
+ LPBYTE pbFileInfo = (LPBYTE)pvFileInfo;
+ DWORD cbSrcFileInfo = sizeof(TFileEntry);
+ DWORD cbFileName = 1;
+
+ // The file name belongs to the file entry
+ if(pFileEntry->szFileName)
+ cbFileName = (DWORD)strlen(pFileEntry->szFileName) + 1;
+ cbSrcFileInfo += cbFileName;
+
+ // Verify buffer pointer and buffer size
+ if(!GetInfo_BufferCheck(pvFileInfo, cbFileInfo, cbSrcFileInfo, pcbLengthNeeded))
+ return false;
+
+ // Copy the file entry
+ memcpy(pbFileInfo, pFileEntry, sizeof(TFileEntry));
+ pbFileInfo += sizeof(TFileEntry);
+ pbFileInfo[0] = 0;
+
+ // Copy the file name
+ if(pFileEntry->szFileName)
+ memcpy(pbFileInfo, pFileEntry->szFileName, cbFileName);
+ return true;
+}
+
+static bool GetInfo_PatchChain(TMPQFile * hf, void * pvFileInfo, DWORD cbFileInfo, LPDWORD pcbLengthNeeded)
{
TMPQFile * hfTemp;
- TCHAR * szFileInfo = (TCHAR *)pvFileInfo;
+ LPCTSTR szPatchName;
+ LPTSTR szFileInfo = (LPTSTR)pvFileInfo;
size_t cchCharsNeeded = 1;
- size_t cchFileInfo = (cbFileInfo / sizeof(TCHAR));
size_t nLength;
- // Patch chain is only supported on MPQ files.
+ // Patch chain is only supported on MPQ files. Local files are not supported.
if(hf->pStream != NULL)
- {
- SetLastError(ERROR_INVALID_PARAMETER);
- return false;
- }
+ return GetInfo_ReturnError(ERROR_INVALID_PARAMETER);
// Calculate the necessary length of the multi-string
for(hfTemp = hf; hfTemp != NULL; hfTemp = hfTemp->hfPatch)
cchCharsNeeded += _tcslen(FileStream_GetFileName(hfTemp->ha->pStream)) + 1;
- // Give the caller the needed length
- if(pcbLengthNeeded != NULL)
- pcbLengthNeeded[0] = (DWORD)(cchCharsNeeded * sizeof(TCHAR));
+ // Verify whether the caller gave us valid buffer with enough size
+ if(!GetInfo_BufferCheck(pvFileInfo, cbFileInfo, (DWORD)(cchCharsNeeded * sizeof(TCHAR)), pcbLengthNeeded))
+ return false;
- // If the caller gave both buffer pointer and data length,
- // try to copy the patch chain
- if(szFileInfo != NULL && cchFileInfo != 0)
+ // Copy each patch name
+ for(hfTemp = hf; hfTemp != NULL; hfTemp = hfTemp->hfPatch)
{
- // If there is enough space in the buffer, copy the patch chain
- if(cchCharsNeeded > cchFileInfo)
- {
- SetLastError(ERROR_INSUFFICIENT_BUFFER);
- return false;
- }
+ // Get the file name and its length
+ szPatchName = FileStream_GetFileName(hfTemp->ha->pStream);
+ nLength = _tcslen(szPatchName) + 1;
- // Copy each patch
- for(hfTemp = hf; hfTemp != NULL; hfTemp = hfTemp->hfPatch)
- {
- // Get the file name and its length
- const TCHAR * szFileName = FileStream_GetFileName(hfTemp->ha->pStream);
- nLength = _tcslen(szFileName) + 1;
-
- // Copy the file name
- memcpy(szFileInfo, szFileName, nLength * sizeof(TCHAR));
- szFileInfo += nLength;
- }
-
- // Make it multi-string
- szFileInfo[0] = 0;
+ // Copy the file name
+ memcpy(szFileInfo, szPatchName, nLength * sizeof(TCHAR));
+ szFileInfo += nLength;
}
+ // Make it multi-string
+ szFileInfo[0] = 0;
return true;
}
@@ -139,719 +194,253 @@ bool WINAPI SFileGetFileInfo(
LPDWORD pcbLengthNeeded)
{
MPQ_SIGNATURE_INFO SignatureInfo;
+ const TCHAR * szSrcFileInfo;
TMPQArchive * ha = NULL;
TFileEntry * pFileEntry = NULL;
+ TMPQHeader * pHeader = NULL;
ULONGLONG Int64Value = 0;
- ULONGLONG ByteOffset = 0;
TMPQFile * hf = NULL;
void * pvSrcFileInfo = NULL;
DWORD cbSrcFileInfo = 0;
DWORD dwInt32Value = 0;
- int nInfoType = SFILE_INFO_TYPE_INVALID_HANDLE;
- int nError = ERROR_SUCCESS;
+ // Validate archive/file handle
+ if((int)InfoClass <= (int)SFileMpqFlags)
+ {
+ if((ha = IsValidMpqHandle(hMpqOrFile)) == NULL)
+ return GetInfo_ReturnError(ERROR_INVALID_HANDLE);
+ pHeader = ha->pHeader;
+ }
+ else
+ {
+ if((hf = IsValidFileHandle(hMpqOrFile)) == NULL)
+ return GetInfo_ReturnError(ERROR_INVALID_HANDLE);
+ pFileEntry = hf->pFileEntry;
+ }
+
+ // Return info-class-specific data
switch(InfoClass)
{
case SFileMpqFileName:
- ha = IsValidMpqHandle(hMpqOrFile);
- if(ha != NULL)
- {
- pvSrcFileInfo = (void *)FileStream_GetFileName(ha->pStream);
- cbSrcFileInfo = (DWORD)(_tcslen((TCHAR *)pvSrcFileInfo) + 1) * sizeof(TCHAR);
- nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER;
- }
- break;
+ szSrcFileInfo = FileStream_GetFileName(ha->pStream);
+ cbSrcFileInfo = (DWORD)((_tcslen(szSrcFileInfo) + 1) * sizeof(TCHAR));
+ return GetInfo(pvFileInfo, cbFileInfo, szSrcFileInfo, cbSrcFileInfo, pcbLengthNeeded);
case SFileMpqStreamBitmap:
- ha = IsValidMpqHandle(hMpqOrFile);
- if(ha != NULL)
- return FileStream_GetBitmap(ha->pStream, pvFileInfo, cbFileInfo, pcbLengthNeeded);
- break;
+ return FileStream_GetBitmap(ha->pStream, pvFileInfo, cbFileInfo, pcbLengthNeeded);
case SFileMpqUserDataOffset:
- ha = IsValidMpqHandle(hMpqOrFile);
- if(ha != NULL)
- {
- nInfoType = SFILE_INFO_TYPE_NOT_FOUND;
- if(ha->pUserData != NULL)
- {
- pvSrcFileInfo = &ha->UserDataPos;
- cbSrcFileInfo = sizeof(ULONGLONG);
- nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER;
- }
- }
- break;
+ return GetInfo(pvFileInfo, cbFileInfo, &ha->UserDataPos, sizeof(ULONGLONG), pcbLengthNeeded);
case SFileMpqUserDataHeader:
- ha = IsValidMpqHandle(hMpqOrFile);
- if(ha != NULL)
- {
- nInfoType = SFILE_INFO_TYPE_NOT_FOUND;
- if(ha->pUserData != NULL)
- {
- ByteOffset = ha->UserDataPos;
- cbSrcFileInfo = sizeof(TMPQUserData);
- nInfoType = SFILE_INFO_TYPE_READ_FROM_FILE;
- }
- }
- break;
+ return GetInfo_ReadFromFile(pvFileInfo, cbFileInfo, ha->pStream, ha->UserDataPos, sizeof(TMPQUserData), pcbLengthNeeded);
case SFileMpqUserData:
- ha = IsValidMpqHandle(hMpqOrFile);
- if(ha != NULL)
- {
- nInfoType = SFILE_INFO_TYPE_NOT_FOUND;
- if(ha->pUserData != NULL)
- {
- ByteOffset = ha->UserDataPos + sizeof(TMPQUserData);
- cbSrcFileInfo = ha->pUserData->dwHeaderOffs - sizeof(TMPQUserData);
- nInfoType = SFILE_INFO_TYPE_READ_FROM_FILE;
- }
- }
- break;
+ return GetInfo_ReadFromFile(pvFileInfo, cbFileInfo, ha->pStream, ha->UserDataPos + sizeof(TMPQUserData), ha->pUserData->dwHeaderOffs - sizeof(TMPQUserData), pcbLengthNeeded);
case SFileMpqHeaderOffset:
- ha = IsValidMpqHandle(hMpqOrFile);
- if(ha != NULL)
- {
- pvSrcFileInfo = &ha->MpqPos;
- cbSrcFileInfo = sizeof(ULONGLONG);
- nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER;
- }
- break;
+ return GetInfo(pvFileInfo, cbFileInfo, &ha->MpqPos, sizeof(ULONGLONG), pcbLengthNeeded);
case SFileMpqHeaderSize:
- ha = IsValidMpqHandle(hMpqOrFile);
- if(ha != NULL)
- {
- pvSrcFileInfo = &ha->pHeader->dwHeaderSize;
- cbSrcFileInfo = sizeof(DWORD);
- nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER;
- }
- break;
+ return GetInfo(pvFileInfo, cbFileInfo, &pHeader->dwHeaderSize, sizeof(DWORD), pcbLengthNeeded);
case SFileMpqHeader:
- ha = IsValidMpqHandle(hMpqOrFile);
- if(ha != NULL)
- {
- ByteOffset = ha->MpqPos;
- cbSrcFileInfo = ha->pHeader->dwHeaderSize;
- nInfoType = SFILE_INFO_TYPE_READ_FROM_FILE;
- }
- break;
+ return GetInfo_ReadFromFile(pvFileInfo, cbFileInfo, ha->pStream, ha->MpqPos, pHeader->dwHeaderSize, pcbLengthNeeded);
case SFileMpqHetTableOffset:
- ha = IsValidMpqHandle(hMpqOrFile);
- if(ha != NULL)
- {
- pvSrcFileInfo = &ha->pHeader->HetTablePos64;
- cbSrcFileInfo = sizeof(ULONGLONG);
- nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER;
- }
- break;
+ return GetInfo(pvFileInfo, cbFileInfo, &pHeader->HetTablePos64, sizeof(ULONGLONG), pcbLengthNeeded);
case SFileMpqHetTableSize:
- ha = IsValidMpqHandle(hMpqOrFile);
- if(ha != NULL)
- {
- pvSrcFileInfo = &ha->pHeader->HetTableSize64;
- cbSrcFileInfo = sizeof(ULONGLONG);
- nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER;
- }
- break;
+ return GetInfo(pvFileInfo, cbFileInfo, &pHeader->HetTableSize64, sizeof(ULONGLONG), pcbLengthNeeded);
case SFileMpqHetHeader:
- ha = IsValidMpqHandle(hMpqOrFile);
- if(ha != NULL)
- {
- nInfoType = SFILE_INFO_TYPE_NOT_FOUND;
- pvSrcFileInfo = LoadExtTable(ha, ha->pHeader->HetTablePos64, (size_t)ha->pHeader->HetTableSize64, HET_TABLE_SIGNATURE, MPQ_KEY_HASH_TABLE);
- if(pvSrcFileInfo != NULL)
- {
- cbSrcFileInfo = sizeof(TMPQHetHeader);
- nInfoType = SFILE_INFO_TYPE_ALLOCATED;
- }
- }
- break;
+ pvSrcFileInfo = LoadExtTable(ha, pHeader->HetTablePos64, (size_t)pHeader->HetTableSize64, HET_TABLE_SIGNATURE, MPQ_KEY_HASH_TABLE);
+ if(pvSrcFileInfo == NULL)
+ return GetInfo_ReturnError(ERROR_FILE_NOT_FOUND);
+ return GetInfo_Allocated(pvFileInfo, cbFileInfo, pvSrcFileInfo, sizeof(TMPQHetHeader), pcbLengthNeeded);
case SFileMpqHetTable:
- ha = IsValidMpqHandle(hMpqOrFile);
- if(ha != NULL)
- {
- nInfoType = SFILE_INFO_TYPE_NOT_FOUND;
- pvSrcFileInfo = LoadHetTable(ha);
- if(pvSrcFileInfo != NULL)
- {
- cbSrcFileInfo = sizeof(void *);
- nInfoType = SFILE_INFO_TYPE_TABLE_POINTER;
- }
- }
- break;
+ if((pvSrcFileInfo = LoadHetTable(ha)) == NULL)
+ return GetInfo_ReturnError(ERROR_NOT_ENOUGH_MEMORY);
+ return GetInfo_TablePointer(pvFileInfo, cbFileInfo, pvSrcFileInfo, InfoClass, pcbLengthNeeded);
case SFileMpqBetTableOffset:
- ha = IsValidMpqHandle(hMpqOrFile);
- if(ha != NULL)
- {
- pvSrcFileInfo = &ha->pHeader->BetTablePos64;
- cbSrcFileInfo = sizeof(ULONGLONG);
- nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER;
- }
- break;
+ return GetInfo(pvFileInfo, cbFileInfo, &pHeader->BetTablePos64, sizeof(ULONGLONG), pcbLengthNeeded);
case SFileMpqBetTableSize:
- ha = IsValidMpqHandle(hMpqOrFile);
- if(ha != NULL)
- {
- pvSrcFileInfo = &ha->pHeader->BetTableSize64;
- cbSrcFileInfo = sizeof(ULONGLONG);
- nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER;
- }
- break;
+ return GetInfo(pvFileInfo, cbFileInfo, &pHeader->BetTableSize64, sizeof(ULONGLONG), pcbLengthNeeded);
case SFileMpqBetHeader:
- ha = IsValidMpqHandle(hMpqOrFile);
- if(ha != NULL)
- {
- nInfoType = SFILE_INFO_TYPE_NOT_FOUND;
- pvSrcFileInfo = LoadExtTable(ha, ha->pHeader->BetTablePos64, (size_t)ha->pHeader->BetTableSize64, BET_TABLE_SIGNATURE, MPQ_KEY_BLOCK_TABLE);
- if(pvSrcFileInfo != NULL)
- {
- // It is allowed for the caller to only require BET header.
- cbSrcFileInfo = sizeof(TMPQBetHeader) + ((TMPQBetHeader *)pvSrcFileInfo)->dwFlagCount * sizeof(DWORD);
- if(cbFileInfo == sizeof(TMPQBetHeader))
- cbSrcFileInfo = sizeof(TMPQBetHeader);
- nInfoType = SFILE_INFO_TYPE_ALLOCATED;
- }
- }
- break;
+
+ // Retrieve the table and its size
+ pvSrcFileInfo = LoadExtTable(ha, pHeader->BetTablePos64, (size_t)pHeader->BetTableSize64, BET_TABLE_SIGNATURE, MPQ_KEY_BLOCK_TABLE);
+ if(pvSrcFileInfo == NULL)
+ return GetInfo_ReturnError(ERROR_FILE_NOT_FOUND);
+ cbSrcFileInfo = sizeof(TMPQBetHeader) + ((TMPQBetHeader *)pvSrcFileInfo)->dwFlagCount * sizeof(DWORD);
+
+ // It is allowed for the caller to only require BET header
+ if(cbFileInfo == sizeof(TMPQBetHeader))
+ cbSrcFileInfo = sizeof(TMPQBetHeader);
+ return GetInfo_Allocated(pvFileInfo, cbFileInfo, pvSrcFileInfo, cbSrcFileInfo, pcbLengthNeeded);
case SFileMpqBetTable:
- ha = IsValidMpqHandle(hMpqOrFile);
- if(ha != NULL)
- {
- nInfoType = SFILE_INFO_TYPE_NOT_FOUND;
- pvSrcFileInfo = LoadBetTable(ha);
- if(pvSrcFileInfo != NULL)
- {
- cbSrcFileInfo = sizeof(void *);
- nInfoType = SFILE_INFO_TYPE_TABLE_POINTER;
- }
- }
- break;
+ if((pvSrcFileInfo = LoadBetTable(ha)) == NULL)
+ return GetInfo_ReturnError(ERROR_NOT_ENOUGH_MEMORY);
+ return GetInfo_TablePointer(pvFileInfo, cbFileInfo, pvSrcFileInfo, InfoClass, pcbLengthNeeded);
case SFileMpqHashTableOffset:
- ha = IsValidMpqHandle(hMpqOrFile);
- if(ha != NULL)
- {
- Int64Value = MAKE_OFFSET64(ha->pHeader->wHashTablePosHi, ha->pHeader->dwHashTablePos);
- pvSrcFileInfo = &Int64Value;
- cbSrcFileInfo = sizeof(ULONGLONG);
- nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER;
- }
- break;
+ Int64Value = MAKE_OFFSET64(pHeader->wHashTablePosHi, pHeader->dwHashTablePos);
+ return GetInfo(pvFileInfo, cbFileInfo, &Int64Value, sizeof(ULONGLONG), pcbLengthNeeded);
case SFileMpqHashTableSize64:
- ha = IsValidMpqHandle(hMpqOrFile);
- if(ha != NULL)
- {
- pvSrcFileInfo = &ha->pHeader->HashTableSize64;
- cbSrcFileInfo = sizeof(ULONGLONG);
- nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER;
- }
- break;
+ return GetInfo(pvFileInfo, cbFileInfo, &pHeader->HashTableSize64, sizeof(ULONGLONG), pcbLengthNeeded);
case SFileMpqHashTableSize:
- ha = IsValidMpqHandle(hMpqOrFile);
- if(ha != NULL)
- {
- pvSrcFileInfo = &ha->pHeader->dwHashTableSize;
- cbSrcFileInfo = sizeof(DWORD);
- nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER;
- }
- break;
+ return GetInfo(pvFileInfo, cbFileInfo, &pHeader->dwHashTableSize, sizeof(DWORD), pcbLengthNeeded);
case SFileMpqHashTable:
- ha = IsValidMpqHandle(hMpqOrFile);
- if(ha != NULL && ha->pHashTable != NULL)
- {
- pvSrcFileInfo = ha->pHashTable;
- cbSrcFileInfo = ha->pHeader->dwHashTableSize * sizeof(TMPQHash);
- nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER;
- }
- break;
+ cbSrcFileInfo = pHeader->dwHashTableSize * sizeof(TMPQHash);
+ return GetInfo(pvFileInfo, cbFileInfo, ha->pHashTable, cbSrcFileInfo, pcbLengthNeeded);
case SFileMpqBlockTableOffset:
- ha = IsValidMpqHandle(hMpqOrFile);
- if(ha != NULL)
- {
- Int64Value = MAKE_OFFSET64(ha->pHeader->wBlockTablePosHi, ha->pHeader->dwBlockTablePos);
- pvSrcFileInfo = &Int64Value;
- cbSrcFileInfo = sizeof(ULONGLONG);
- nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER;
- }
- break;
+ Int64Value = MAKE_OFFSET64(pHeader->wBlockTablePosHi, pHeader->dwBlockTablePos);
+ return GetInfo(pvFileInfo, cbFileInfo, &Int64Value, sizeof(ULONGLONG), pcbLengthNeeded);
case SFileMpqBlockTableSize64:
- ha = IsValidMpqHandle(hMpqOrFile);
- if(ha != NULL)
- {
- pvSrcFileInfo = &ha->pHeader->BlockTableSize64;
- cbSrcFileInfo = sizeof(ULONGLONG);
- nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER;
- }
- break;
+ return GetInfo(pvFileInfo, cbFileInfo, &pHeader->BlockTableSize64, sizeof(ULONGLONG), pcbLengthNeeded);
case SFileMpqBlockTableSize:
- ha = IsValidMpqHandle(hMpqOrFile);
- if(ha != NULL)
- {
- pvSrcFileInfo = &ha->pHeader->dwBlockTableSize;
- cbSrcFileInfo = sizeof(DWORD);
- nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER;
- }
- break;
+ return GetInfo(pvFileInfo, cbFileInfo, &pHeader->dwBlockTableSize, sizeof(DWORD), pcbLengthNeeded);
case SFileMpqBlockTable:
- ha = IsValidMpqHandle(hMpqOrFile);
- if(ha != NULL)
- {
- nInfoType = SFILE_INFO_TYPE_NOT_FOUND;
- if(MAKE_OFFSET64(ha->pHeader->wBlockTablePosHi, ha->pHeader->dwBlockTablePos) < ha->FileSize)
- {
- cbSrcFileInfo = ha->pHeader->dwBlockTableSize * sizeof(TMPQBlock);
- if(cbFileInfo >= cbSrcFileInfo)
- pvSrcFileInfo = LoadBlockTable(ha, true);
- nInfoType = SFILE_INFO_TYPE_ALLOCATED;
- }
- }
- break;
+ if(MAKE_OFFSET64(pHeader->wBlockTablePosHi, pHeader->dwBlockTablePos) >= ha->FileSize)
+ return GetInfo_ReturnError(ERROR_FILE_NOT_FOUND);
+ cbSrcFileInfo = pHeader->dwBlockTableSize * sizeof(TMPQBlock);
+ pvSrcFileInfo = LoadBlockTable(ha, true);
+ return GetInfo_Allocated(pvFileInfo, cbFileInfo, pvSrcFileInfo, cbSrcFileInfo, pcbLengthNeeded);
case SFileMpqHiBlockTableOffset:
- ha = IsValidMpqHandle(hMpqOrFile);
- if(ha != NULL)
- {
- pvSrcFileInfo = &ha->pHeader->HiBlockTablePos64;
- cbSrcFileInfo = sizeof(ULONGLONG);
- nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER;
- }
- break;
+ return GetInfo(pvFileInfo, cbFileInfo, &pHeader->HiBlockTablePos64, sizeof(ULONGLONG), pcbLengthNeeded);
case SFileMpqHiBlockTableSize64:
- ha = IsValidMpqHandle(hMpqOrFile);
- if(ha != NULL)
- {
- pvSrcFileInfo = &ha->pHeader->HiBlockTableSize64;
- cbSrcFileInfo = sizeof(ULONGLONG);
- nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER;
- }
- break;
+ return GetInfo(pvFileInfo, cbFileInfo, &pHeader->HiBlockTableSize64, sizeof(ULONGLONG), pcbLengthNeeded);
case SFileMpqHiBlockTable:
- ha = IsValidMpqHandle(hMpqOrFile);
- if(ha != NULL)
- {
- nInfoType = SFILE_INFO_TYPE_NOT_FOUND;
- if(ha->pHeader->HiBlockTablePos64 && ha->pHeader->HiBlockTableSize64)
- {
- assert(false);
- }
- }
- break;
+ return GetInfo_ReturnError(ERROR_FILE_NOT_FOUND);
case SFileMpqSignatures:
- ha = IsValidMpqHandle(hMpqOrFile);
- if(ha != NULL && QueryMpqSignatureInfo(ha, &SignatureInfo))
- {
- pvSrcFileInfo = &SignatureInfo.SignatureTypes;
- cbSrcFileInfo = sizeof(DWORD);
- nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER;
- }
- break;
+ if(!QueryMpqSignatureInfo(ha, &SignatureInfo))
+ return GetInfo_ReturnError(ERROR_FILE_NOT_FOUND);
+ return GetInfo(pvFileInfo, cbFileInfo, &SignatureInfo.SignatureTypes, sizeof(DWORD), pcbLengthNeeded);
case SFileMpqStrongSignatureOffset:
- ha = IsValidMpqHandle(hMpqOrFile);
- if(ha != NULL)
- {
- nInfoType = SFILE_INFO_TYPE_NOT_FOUND;
- if(QueryMpqSignatureInfo(ha, &SignatureInfo) && (SignatureInfo.SignatureTypes & SIGNATURE_TYPE_STRONG))
- {
- pvSrcFileInfo = &SignatureInfo.EndMpqData;
- cbSrcFileInfo = sizeof(ULONGLONG);
- nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER;
- }
- }
- break;
+ if(QueryMpqSignatureInfo(ha, &SignatureInfo) == false || (SignatureInfo.SignatureTypes & SIGNATURE_TYPE_STRONG) == 0)
+ return GetInfo_ReturnError(ERROR_FILE_NOT_FOUND);
+ return GetInfo(pvFileInfo, cbFileInfo, &SignatureInfo.EndMpqData, sizeof(ULONGLONG), pcbLengthNeeded);
case SFileMpqStrongSignatureSize:
- ha = IsValidMpqHandle(hMpqOrFile);
- if(ha != NULL)
- {
- nInfoType = SFILE_INFO_TYPE_NOT_FOUND;
- if(QueryMpqSignatureInfo(ha, &SignatureInfo) && (SignatureInfo.SignatureTypes & SIGNATURE_TYPE_STRONG))
- {
- dwInt32Value = MPQ_STRONG_SIGNATURE_SIZE + 4;
- pvSrcFileInfo = &dwInt32Value;
- cbSrcFileInfo = sizeof(DWORD);
- nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER;
- }
- }
- break;
+ if(QueryMpqSignatureInfo(ha, &SignatureInfo) == false || (SignatureInfo.SignatureTypes & SIGNATURE_TYPE_STRONG) == 0)
+ return GetInfo_ReturnError(ERROR_FILE_NOT_FOUND);
+ dwInt32Value = MPQ_STRONG_SIGNATURE_SIZE + 4;
+ return GetInfo(pvFileInfo, cbFileInfo, &dwInt32Value, sizeof(DWORD), pcbLengthNeeded);
case SFileMpqStrongSignature:
- ha = IsValidMpqHandle(hMpqOrFile);
- if(ha != NULL)
- {
- nInfoType = SFILE_INFO_TYPE_NOT_FOUND;
- if(QueryMpqSignatureInfo(ha, &SignatureInfo) && (SignatureInfo.SignatureTypes & SIGNATURE_TYPE_STRONG))
- {
- pvSrcFileInfo = SignatureInfo.Signature;
- cbSrcFileInfo = MPQ_STRONG_SIGNATURE_SIZE + 4;
- nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER;
- }
- }
- break;
+ if(QueryMpqSignatureInfo(ha, &SignatureInfo) == false || (SignatureInfo.SignatureTypes & SIGNATURE_TYPE_STRONG) == 0)
+ return GetInfo_ReturnError(ERROR_FILE_NOT_FOUND);
+ return GetInfo(pvFileInfo, cbFileInfo, SignatureInfo.Signature, MPQ_STRONG_SIGNATURE_SIZE + 4, pcbLengthNeeded);
case SFileMpqArchiveSize64:
- ha = IsValidMpqHandle(hMpqOrFile);
- if(ha != NULL)
- {
- pvSrcFileInfo = &ha->pHeader->ArchiveSize64;
- cbSrcFileInfo = sizeof(DWORD);
- nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER;
- }
- break;
+ return GetInfo(pvFileInfo, cbFileInfo, &pHeader->ArchiveSize64, sizeof(ULONGLONG), pcbLengthNeeded);
case SFileMpqArchiveSize:
- ha = IsValidMpqHandle(hMpqOrFile);
- if(ha != NULL)
- {
- pvSrcFileInfo = &ha->pHeader->dwArchiveSize;
- cbSrcFileInfo = sizeof(DWORD);
- nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER;
- }
- break;
+ return GetInfo(pvFileInfo, cbFileInfo, &pHeader->dwArchiveSize, sizeof(DWORD), pcbLengthNeeded);
case SFileMpqMaxFileCount:
- ha = IsValidMpqHandle(hMpqOrFile);
- if(ha != NULL)
- {
- pvSrcFileInfo = &ha->dwMaxFileCount;
- cbSrcFileInfo = sizeof(DWORD);
- nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER;
- }
- break;
+ return GetInfo(pvFileInfo, cbFileInfo, &ha->dwMaxFileCount, sizeof(DWORD), pcbLengthNeeded);
case SFileMpqFileTableSize:
- ha = IsValidMpqHandle(hMpqOrFile);
- if(ha != NULL)
- {
- pvSrcFileInfo = &ha->dwFileTableSize;
- cbSrcFileInfo = sizeof(DWORD);
- nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER;
- }
- break;
+ return GetInfo(pvFileInfo, cbFileInfo, &ha->dwFileTableSize, sizeof(DWORD), pcbLengthNeeded);
case SFileMpqSectorSize:
- ha = IsValidMpqHandle(hMpqOrFile);
- if(ha != NULL)
- {
- pvSrcFileInfo = &ha->dwSectorSize;
- cbSrcFileInfo = sizeof(DWORD);
- nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER;
- }
- break;
+ return GetInfo(pvFileInfo, cbFileInfo, &ha->dwSectorSize, sizeof(DWORD), pcbLengthNeeded);
case SFileMpqNumberOfFiles:
- ha = IsValidMpqHandle(hMpqOrFile);
- if(ha != NULL)
- {
- pvSrcFileInfo = &dwInt32Value;
- cbSrcFileInfo = sizeof(DWORD);
- dwInt32Value = GetMpqFileCount(ha);
- nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER;
- }
- break;
+ dwInt32Value = GetMpqFileCount(ha);
+ return GetInfo(pvFileInfo, cbFileInfo, &dwInt32Value, sizeof(DWORD), pcbLengthNeeded);
case SFileMpqRawChunkSize:
- ha = IsValidMpqHandle(hMpqOrFile);
- if(ha != NULL)
- {
- nInfoType = SFILE_INFO_TYPE_NOT_FOUND;
- if(ha->pHeader->dwRawChunkSize != 0)
- {
- pvSrcFileInfo = &ha->pHeader->dwRawChunkSize;
- cbSrcFileInfo = sizeof(DWORD);
- nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER;
- }
- }
- break;
+ if(pHeader->dwRawChunkSize == 0)
+ return GetInfo_ReturnError(ERROR_FILE_NOT_FOUND);
+ return GetInfo(pvFileInfo, cbFileInfo, &pHeader->dwRawChunkSize, sizeof(DWORD), pcbLengthNeeded);
case SFileMpqStreamFlags:
- ha = IsValidMpqHandle(hMpqOrFile);
- if(ha != NULL)
- {
- FileStream_GetFlags(ha->pStream, &dwInt32Value);
- pvSrcFileInfo = &dwInt32Value;
- cbSrcFileInfo = sizeof(DWORD);
- nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER;
- }
- break;
+ FileStream_GetFlags(ha->pStream, &dwInt32Value);
+ return GetInfo(pvFileInfo, cbFileInfo, &dwInt32Value, sizeof(DWORD), pcbLengthNeeded);
case SFileMpqFlags:
- ha = IsValidMpqHandle(hMpqOrFile);
- if(ha != NULL)
- {
- dwInt32Value = ha->dwFlags;
- pvSrcFileInfo = &dwInt32Value;
- cbSrcFileInfo = sizeof(DWORD);
- nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER;
- }
- break;
+ return GetInfo(pvFileInfo, cbFileInfo, &ha->dwFlags, sizeof(DWORD), pcbLengthNeeded);
case SFileInfoPatchChain:
- hf = IsValidFileHandle(hMpqOrFile);
- if(hf != NULL)
- return GetFilePatchChain(hf, pvFileInfo, cbFileInfo, pcbLengthNeeded);
- break;
+ return GetInfo_PatchChain(hf, pvFileInfo, cbFileInfo, pcbLengthNeeded);
case SFileInfoFileEntry:
- hf = IsValidFileHandle(hMpqOrFile);
- if(hf != NULL && hf->pFileEntry != NULL)
- {
- pvSrcFileInfo = pFileEntry = hf->pFileEntry;
- cbSrcFileInfo = sizeof(TFileEntry);
- if(pFileEntry->szFileName != NULL)
- cbSrcFileInfo += (DWORD)strlen(pFileEntry->szFileName) + 1;
- nInfoType = SFILE_INFO_TYPE_FILE_ENTRY;
- }
- break;
+ if(pFileEntry == NULL)
+ return GetInfo_ReturnError(ERROR_FILE_NOT_FOUND);
+ return GetInfo_FileEntry(pvFileInfo, cbFileInfo, pFileEntry, pcbLengthNeeded);
case SFileInfoHashEntry:
- hf = IsValidFileHandle(hMpqOrFile);
- if(hf != NULL && hf->pHashEntry != NULL)
- {
- pvSrcFileInfo = hf->pHashEntry;
- cbSrcFileInfo = sizeof(TMPQHash);
- nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER;
- }
- break;
+ return GetInfo(pvFileInfo, cbFileInfo, hf->pHashEntry, sizeof(TMPQHash), pcbLengthNeeded);
case SFileInfoHashIndex:
- hf = IsValidFileHandle(hMpqOrFile);
- if(hf != NULL && hf->pHashEntry != NULL)
- {
- pvSrcFileInfo = &hf->dwHashIndex;
- cbSrcFileInfo = sizeof(DWORD);
- nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER;
- }
- break;
+ return GetInfo(pvFileInfo, cbFileInfo, &hf->dwHashIndex, sizeof(DWORD), pcbLengthNeeded);
case SFileInfoNameHash1:
- hf = IsValidFileHandle(hMpqOrFile);
- if(hf != NULL && hf->pHashEntry != NULL)
- {
- dwInt32Value = hf->pHashEntry->dwName1;
- pvSrcFileInfo = &dwInt32Value;
- cbSrcFileInfo = sizeof(DWORD);
- nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER;
- }
- break;
+ return GetInfo(pvFileInfo, cbFileInfo, &hf->pHashEntry->dwName1, sizeof(DWORD), pcbLengthNeeded);
case SFileInfoNameHash2:
- hf = IsValidFileHandle(hMpqOrFile);
- if(hf != NULL && hf->pHashEntry != NULL)
- {
- dwInt32Value = hf->pHashEntry->dwName2;
- pvSrcFileInfo = &dwInt32Value;
- cbSrcFileInfo = sizeof(DWORD);
- nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER;
- }
- break;
+ return GetInfo(pvFileInfo, cbFileInfo, &hf->pHashEntry->dwName2, sizeof(DWORD), pcbLengthNeeded);
case SFileInfoNameHash3:
- hf = IsValidFileHandle(hMpqOrFile);
- if(hf != NULL && hf->pFileEntry != NULL)
- {
- pvSrcFileInfo = &hf->pFileEntry->FileNameHash;
- cbSrcFileInfo = sizeof(ULONGLONG);
- nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER;
- }
- break;
+ return GetInfo(pvFileInfo, cbFileInfo, &pFileEntry->FileNameHash, sizeof(ULONGLONG), pcbLengthNeeded);
case SFileInfoLocale:
- hf = IsValidFileHandle(hMpqOrFile);
- if(hf != NULL && hf->pHashEntry != NULL)
- {
- dwInt32Value = hf->pHashEntry->lcLocale;
- pvSrcFileInfo = &dwInt32Value;
- cbSrcFileInfo = sizeof(DWORD);
- nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER;
- }
- break;
+ dwInt32Value = hf->pHashEntry->lcLocale;
+ return GetInfo(pvFileInfo, cbFileInfo, &dwInt32Value, sizeof(DWORD), pcbLengthNeeded);
case SFileInfoFileIndex:
- hf = IsValidFileHandle(hMpqOrFile);
- if(hf != NULL && hf->ha != NULL && hf->pFileEntry != NULL)
- {
- dwInt32Value = (DWORD)(hf->pFileEntry - hf->ha->pFileTable);
- pvSrcFileInfo = &dwInt32Value;
- cbSrcFileInfo = sizeof(DWORD);
- nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER;
- }
- break;
+ dwInt32Value = (DWORD)(pFileEntry - hf->ha->pFileTable);
+ return GetInfo(pvFileInfo, cbFileInfo, &dwInt32Value, sizeof(DWORD), pcbLengthNeeded);
case SFileInfoByteOffset:
- hf = IsValidFileHandle(hMpqOrFile);
- if(hf != NULL && hf->pFileEntry != NULL)
- {
- pvSrcFileInfo = &hf->pFileEntry->ByteOffset;
- cbSrcFileInfo = sizeof(ULONGLONG);
- nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER;
- }
- break;
+ return GetInfo(pvFileInfo, cbFileInfo, &pFileEntry->ByteOffset, sizeof(ULONGLONG), pcbLengthNeeded);
case SFileInfoFileTime:
- hf = IsValidFileHandle(hMpqOrFile);
- if(hf != NULL && hf->pFileEntry != NULL)
- {
- pvSrcFileInfo = &hf->pFileEntry->FileTime;
- cbSrcFileInfo = sizeof(ULONGLONG);
- nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER;
- }
- break;
+ return GetInfo(pvFileInfo, cbFileInfo, &pFileEntry->FileTime, sizeof(ULONGLONG), pcbLengthNeeded);
case SFileInfoFileSize:
- hf = IsValidFileHandle(hMpqOrFile);
- if(hf != NULL && hf->pFileEntry != NULL)
- {
- pvSrcFileInfo = &hf->pFileEntry->dwFileSize;
- cbSrcFileInfo = sizeof(DWORD);
- nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER;
- }
- break;
+ return GetInfo(pvFileInfo, cbFileInfo, &pFileEntry->dwFileSize, sizeof(DWORD), pcbLengthNeeded);
case SFileInfoCompressedSize:
- hf = IsValidFileHandle(hMpqOrFile);
- if(hf != NULL && hf->pFileEntry != NULL)
- {
- pvSrcFileInfo = &hf->pFileEntry->dwCmpSize;
- cbSrcFileInfo = sizeof(DWORD);
- nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER;
- }
- break;
+ return GetInfo(pvFileInfo, cbFileInfo, &pFileEntry->dwCmpSize, sizeof(DWORD), pcbLengthNeeded);
case SFileInfoFlags:
- hf = IsValidFileHandle(hMpqOrFile);
- if(hf != NULL && hf->pFileEntry != NULL)
- {
- pvSrcFileInfo = &hf->pFileEntry->dwFlags;
- cbSrcFileInfo = sizeof(DWORD);
- nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER;
- }
- break;
+ return GetInfo(pvFileInfo, cbFileInfo, &pFileEntry->dwFlags, sizeof(DWORD), pcbLengthNeeded);
case SFileInfoEncryptionKey:
- hf = IsValidFileHandle(hMpqOrFile);
- if(hf != NULL)
- {
- pvSrcFileInfo = &hf->dwFileKey;
- cbSrcFileInfo = sizeof(DWORD);
- nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER;
- }
- break;
+ return GetInfo(pvFileInfo, cbFileInfo, &hf->dwFileKey, sizeof(DWORD), pcbLengthNeeded);
case SFileInfoEncryptionKeyRaw:
- hf = IsValidFileHandle(hMpqOrFile);
- if(hf != NULL && hf->pFileEntry != NULL)
- {
- dwInt32Value = hf->dwFileKey;
- if(hf->pFileEntry->dwFlags & MPQ_FILE_FIX_KEY)
- dwInt32Value = (dwInt32Value ^ hf->pFileEntry->dwFileSize) - (DWORD)hf->MpqFilePos;
- pvSrcFileInfo = &dwInt32Value;
- cbSrcFileInfo = sizeof(DWORD);
- nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER;
- }
- break;
+ dwInt32Value = hf->dwFileKey;
+ if(pFileEntry->dwFlags & MPQ_FILE_FIX_KEY)
+ dwInt32Value = (dwInt32Value ^ pFileEntry->dwFileSize) - (DWORD)hf->MpqFilePos;
+ return GetInfo(pvFileInfo, cbFileInfo, &dwInt32Value, sizeof(DWORD), pcbLengthNeeded);
case SFileInfoCRC32:
- hf = IsValidFileHandle(hMpqOrFile);
- if(hf != NULL && hf->pFileEntry != NULL)
- {
- dwInt32Value = hf->pFileEntry->dwCrc32;
- pvSrcFileInfo = &dwInt32Value;
- cbSrcFileInfo = sizeof(DWORD);
- nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER;
- }
- break;
-
- default: // Invalid info class
- SetLastError(ERROR_INVALID_PARAMETER);
- return false;
- }
-
- // If we validated the handle and info class, give as much info as possible
- if(nInfoType >= SFILE_INFO_TYPE_DIRECT_POINTER)
- {
- // Give the length needed, if wanted
- if(pcbLengthNeeded != NULL)
- pcbLengthNeeded[0] = cbSrcFileInfo;
-
- // If the caller entered an output buffer, the output size must also be entered
- if(pvFileInfo != NULL && cbFileInfo != 0)
- {
- // Check if there is enough space in the output buffer
- if(cbSrcFileInfo <= cbFileInfo)
- {
- switch(nInfoType)
- {
- case SFILE_INFO_TYPE_DIRECT_POINTER:
- case SFILE_INFO_TYPE_ALLOCATED:
- assert(pvSrcFileInfo != NULL);
- memcpy(pvFileInfo, pvSrcFileInfo, cbSrcFileInfo);
- break;
-
- case SFILE_INFO_TYPE_READ_FROM_FILE:
- if(!FileStream_Read(ha->pStream, &ByteOffset, pvFileInfo, cbSrcFileInfo))
- nError = GetLastError();
- break;
-
- case SFILE_INFO_TYPE_TABLE_POINTER:
- assert(pvSrcFileInfo != NULL);
- *(void **)pvFileInfo = pvSrcFileInfo;
- pvSrcFileInfo = NULL;
- break;
-
- case SFILE_INFO_TYPE_FILE_ENTRY:
- assert(pFileEntry != NULL);
- ConvertFileEntryToSelfRelative((TFileEntry *)pvFileInfo, pFileEntry);
- break;
- }
- }
- else
- {
- nError = ERROR_INSUFFICIENT_BUFFER;
- }
- }
-
- // Free the file info if needed
- if(nInfoType == SFILE_INFO_TYPE_ALLOCATED && pvSrcFileInfo != NULL)
- STORM_FREE(pvSrcFileInfo);
- if(nInfoType == SFILE_INFO_TYPE_TABLE_POINTER && pvSrcFileInfo != NULL)
- SFileFreeFileInfo(pvSrcFileInfo, InfoClass);
- }
- else
- {
- // Handle error cases
- if(nInfoType == SFILE_INFO_TYPE_INVALID_HANDLE)
- nError = ERROR_INVALID_HANDLE;
- if(nInfoType == SFILE_INFO_TYPE_NOT_FOUND)
- nError = ERROR_FILE_NOT_FOUND;
+ return GetInfo(pvFileInfo, cbFileInfo, &hf->pFileEntry->dwCrc32, sizeof(DWORD), pcbLengthNeeded);
}
- // Set the last error value, if needed
- if(nError != ERROR_SUCCESS)
- SetLastError(nError);
- return (nError == ERROR_SUCCESS);
+ // Invalid info class
+ return GetInfo_ReturnError(ERROR_INVALID_PARAMETER);
}
bool WINAPI SFileFreeFileInfo(void * pvFileInfo, SFileInfoClass InfoClass)
diff --git a/src/SFileListFile.cpp b/src/SFileListFile.cpp
index aa8969c..fe9bc69 100644
--- a/src/SFileListFile.cpp
+++ b/src/SFileListFile.cpp
@@ -17,7 +17,7 @@
// Listfile entry structure
#define CACHE_BUFFER_SIZE 0x1000 // Size of the cache buffer
-#define MAX_LISTFILE_SIZE 0x04000000 // Maximum accepted listfile size is about 68 MB
+#define MAX_LISTFILE_SIZE 0x8000000 // Maximum accepted listfile size is 128 MB
union TListFileHandle
{
@@ -148,6 +148,10 @@ static TListFileCache * CreateListFileCache(
TListFileCache * pCache = NULL;
TListFileHandle ListHandle = {NULL};
+ // Put default value to dwMaxSize
+ if(dwMaxSize == 0)
+ dwMaxSize = MAX_LISTFILE_SIZE;
+
// Internal listfile: hMPQ must be non NULL and szListFile must be NULL.
// We load the MPQ::(listfile) file
if(hMpq != NULL && szListFile == NULL)
@@ -181,7 +185,7 @@ static TListFileCache * CreateListFileCache(
{
// Verify the file size
FileStream_GetSize(ListHandle.pStream, &FileSize);
- if(0 < FileSize && FileSize < MAX_LISTFILE_SIZE)
+ if(0 < FileSize && FileSize < dwMaxSize)
{
pCache = CreateListFileCache(LoadListFile_Stream, &ListHandle, szWildCard, (DWORD)FileSize, dwMaxSize, dwFlags);
}
diff --git a/src/SFileOpenArchive.cpp b/src/SFileOpenArchive.cpp
index d1cc4d6..3e333a9 100644
--- a/src/SFileOpenArchive.cpp
+++ b/src/SFileOpenArchive.cpp
@@ -9,7 +9,7 @@
/*---------------------------------------------------------------------------*/
/* Date Ver Who Comment */
/* -------- ---- --- ------- */
-/* xx.xx.xx 1.00 Lad The first version of SFileOpenArchive.cpp */
+/* xx.xx.xx 1.00 Lad Created */
/* 19.11.03 1.01 Dan Big endian handling */
/*****************************************************************************/
diff --git a/src/SFileReadFile.cpp b/src/SFileReadFile.cpp
index a693e70..0320677 100644
--- a/src/SFileReadFile.cpp
+++ b/src/SFileReadFile.cpp
@@ -725,7 +725,7 @@ bool WINAPI SFileReadFile(HANDLE hFile, void * pvBuffer, DWORD dwToRead, LPDWORD
// Otherwise read it as sector based MPQ file
else
- {
+ {
nError = ReadMpqFileSectorFile(hf, pvBuffer, hf->dwFilePos, dwToRead, &dwBytesRead);
}
diff --git a/src/StormLib.h b/src/StormLib.h
index d913a54..f254290 100644
--- a/src/StormLib.h
+++ b/src/StormLib.h
@@ -142,8 +142,8 @@ extern "C" {
//-----------------------------------------------------------------------------
// Defines
-#define STORMLIB_VERSION 0x0916 // Current version of StormLib (9.21)
-#define STORMLIB_VERSION_STRING "9.22" // String version of StormLib version
+#define STORMLIB_VERSION 0x0917 // Current version of StormLib (9.23)
+#define STORMLIB_VERSION_STRING "9.23" // String version of StormLib version
#define ID_MPQ 0x1A51504D // MPQ archive header ID ('MPQ\x1A')
#define ID_MPQ_USERDATA 0x1B51504D // MPQ userdata entry ('MPQ\x1B')
diff --git a/src/huffman/huff.cpp b/src/huffman/huff.cpp
index 9de5acb..fa0964d 100644
--- a/src/huffman/huff.cpp
+++ b/src/huffman/huff.cpp
@@ -478,19 +478,24 @@ THTreeItem * THuffmannTree::FindHigherOrEqualItem(THTreeItem * pItem, unsigned i
THTreeItem * THuffmannTree::CreateNewItem(unsigned int DecompressedValue, unsigned int Weight, TInsertPoint InsertPoint)
{
- THTreeItem * pNewItem;
+ THTreeItem * pNewItem = NULL;
- // Allocate new item from the item pool
- pNewItem = &ItemBuffer[ItemsUsed++];
+ // Don't let the item buffer run out of space
+ if(ItemsUsed < HUFF_ITEM_COUNT)
+ {
+ // Allocate new item from the item pool
+ pNewItem = &ItemBuffer[ItemsUsed++];
- // Insert this item to the top of the tree
- InsertItem(pNewItem, InsertPoint, NULL);
+ // Insert this item to the top of the tree
+ InsertItem(pNewItem, InsertPoint, NULL);
- // Fill the rest of the item
- pNewItem->DecompressedValue = DecompressedValue;
- pNewItem->Weight = Weight;
- pNewItem->pParent = NULL;
- pNewItem->pChildLo = NULL;
+ // Fill the rest of the item
+ pNewItem->DecompressedValue = DecompressedValue;
+ pNewItem->Weight = Weight;
+ pNewItem->pParent = NULL;
+ pNewItem->pChildLo = NULL;
+ }
+
return pNewItem;
}
@@ -567,6 +572,8 @@ bool THuffmannTree::BuildTree(unsigned int CompressionType)
// Create new parent item for the children
pNewItem = CreateNewItem(0, pChildHi->Weight + pChildLo->Weight, InsertAfter);
+ if(pNewItem == NULL)
+ return false;
// Link both child items to their new parent
pChildLo->pParent = pNewItem;
@@ -631,7 +638,7 @@ void THuffmannTree::IncWeightsAndRebalance(THTreeItem * pItem)
}
}
-void THuffmannTree::InsertNewBranchAndRebalance(unsigned int Value1, unsigned int Value2)
+bool THuffmannTree::InsertNewBranchAndRebalance(unsigned int Value1, unsigned int Value2)
{
THTreeItem * pLastItem = pLast;
THTreeItem * pChildHi;
@@ -639,16 +646,26 @@ void THuffmannTree::InsertNewBranchAndRebalance(unsigned int Value1, unsigned in
// Create higher-weight child
pChildHi = CreateNewItem(Value1, pLastItem->Weight, InsertBefore);
- pChildHi->pParent = pLastItem;
- ItemsByByte[Value1] = pChildHi;
+ if(pChildHi != NULL)
+ {
+ pChildHi->pParent = pLastItem;
+ ItemsByByte[Value1] = pChildHi;
- // Create lower-weight child
- pChildLo = CreateNewItem(Value2, 0, InsertBefore);
- pChildLo->pParent = pLastItem;
- pLastItem->pChildLo = pChildLo;
- ItemsByByte[Value2] = pChildLo;
+ // Create lower-weight child
+ pChildLo = CreateNewItem(Value2, 0, InsertBefore);
+ if(pChildLo != NULL)
+ {
+ pChildLo->pParent = pLastItem;
+ pLastItem->pChildLo = pChildLo;
+ ItemsByByte[Value2] = pChildLo;
+
+ IncWeightsAndRebalance(pChildLo);
+ return true;
+ }
+ }
- IncWeightsAndRebalance(pChildLo);
+ // No more space in the tree buffer
+ return false;
}
void THuffmannTree::EncodeOneByte(TOutputStream * os, THTreeItem * pItem)
@@ -789,7 +806,8 @@ unsigned int THuffmannTree::Compress(TOutputStream * os, void * pvInBuffer, int
// Store the loaded byte into output stream
os->PutBits(InputByte, 8);
- InsertNewBranchAndRebalance(pLast->DecompressedValue, InputByte);
+ if(!InsertNewBranchAndRebalance(pLast->DecompressedValue, InputByte))
+ return 0;
if(bIsCmp0)
{
@@ -851,7 +869,8 @@ unsigned int THuffmannTree::Decompress(void * pvOutBuffer, unsigned int cbOutLen
// The decompressed byte is stored in the next 8 bits
DecompressedValue = is->Get8Bits();
- InsertNewBranchAndRebalance(pLast->DecompressedValue, DecompressedValue);
+ if(!InsertNewBranchAndRebalance(pLast->DecompressedValue, DecompressedValue))
+ return 0;
if(bIsCmp0 == 0)
IncWeightsAndRebalance(ItemsByByte[DecompressedValue]);
diff --git a/src/huffman/huff.h b/src/huffman/huff.h
index 89993fd..d2c3e3e 100644
--- a/src/huffman/huff.h
+++ b/src/huffman/huff.h
@@ -118,7 +118,7 @@ class THuffmannTree
bool BuildTree(unsigned int CompressionType);
void IncWeightsAndRebalance(THTreeItem * pItem);
- void InsertNewBranchAndRebalance(unsigned int Value1, unsigned int Value2);
+ bool InsertNewBranchAndRebalance(unsigned int Value1, unsigned int Value2);
void EncodeOneByte(TOutputStream * os, THTreeItem * pItem);
unsigned int DecodeOneByte(TInputStream * is);