diff options
Diffstat (limited to 'src/SFileGetFileInfo.cpp')
-rw-r--r-- | src/SFileGetFileInfo.cpp | 1984 |
1 files changed, 992 insertions, 992 deletions
diff --git a/src/SFileGetFileInfo.cpp b/src/SFileGetFileInfo.cpp index bf6273d..9874793 100644 --- a/src/SFileGetFileInfo.cpp +++ b/src/SFileGetFileInfo.cpp @@ -1,992 +1,992 @@ -/*****************************************************************************/ -/* SFileGetFileInfo.cpp Copyright (c) Ladislav Zezula 2013 */ -/*---------------------------------------------------------------------------*/ -/* Description: */ -/*---------------------------------------------------------------------------*/ -/* Date Ver Who Comment */ -/* -------- ---- --- ------- */ -/* 30.11.13 1.00 Lad The first version of SFileGetFileInfo.cpp */ -/*****************************************************************************/ - -#define __STORMLIB_SELF__ -#include "StormLib.h" -#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; - TFileEntry * pFileEntry; - DWORD dwFileCount = 0; - - // Go through all open MPQs, including patches - while(ha != NULL) - { - // Only count files that are not patch files - pFileTableEnd = ha->pFileTable + ha->dwFileTableSize; - for(pFileEntry = ha->pFileTable; pFileEntry < pFileTableEnd; pFileEntry++) - { - // If the file is patch file and this is not primary archive, skip it - // BUGBUG: This errorneously counts non-patch files that are in both - // base MPQ and in patches, and increases the number of files by cca 50% - if((pFileEntry->dwFlags & (MPQ_FILE_EXISTS | MPQ_FILE_PATCH_FILE)) == MPQ_FILE_EXISTS) - dwFileCount++; - } - - // Move to the next patch archive - ha = ha->haPatch; - } - - return dwFileCount; -} - -static bool GetFilePatchChain(TMPQFile * hf, void * pvFileInfo, DWORD cbFileInfo, DWORD * pcbLengthNeeded) -{ - TMPQFile * hfTemp; - TCHAR * szFileInfo = (TCHAR *)pvFileInfo; - size_t cchCharsNeeded = 1; - size_t cchFileInfo = (cbFileInfo / sizeof(TCHAR)); - size_t nLength; - - // Patch chain is only supported on MPQ files. - if(hf->pStream != NULL) - { - SetLastError(ERROR_INVALID_PARAMETER); - return false; - } - - // 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)); - - // If the caller gave both buffer pointer and data length, - // try to copy the patch chain - if(szFileInfo != NULL && cchFileInfo != 0) - { - // If there is enough space in the buffer, copy the patch chain - if(cchCharsNeeded > cchFileInfo) - { - SetLastError(ERROR_INSUFFICIENT_BUFFER); - return false; - } - - // 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; - } - - return true; -} - -//----------------------------------------------------------------------------- -// Retrieves an information about an archive or about a file within the archive -// -// hMpqOrFile - Handle to an MPQ archive or to a file -// InfoClass - Information to obtain -// pvFileInfo - Pointer to buffer to store the information -// cbFileInfo - Size of the buffer pointed by pvFileInfo -// pcbLengthNeeded - Receives number of bytes necessary to store the information - -bool WINAPI SFileGetFileInfo( - HANDLE hMpqOrFile, - SFileInfoClass InfoClass, - void * pvFileInfo, - DWORD cbFileInfo, - LPDWORD pcbLengthNeeded) -{ - MPQ_SIGNATURE_INFO SignatureInfo; - TMPQArchive * ha = NULL; - TFileEntry * pFileEntry = 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; - - 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; - - case SFileMpqStreamBitmap: - ha = IsValidMpqHandle(hMpqOrFile); - if(ha != NULL) - return FileStream_GetBitmap(ha->pStream, pvFileInfo, cbFileInfo, pcbLengthNeeded); - break; - - 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; - - 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; - - 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; - - case SFileMpqHeaderOffset: - ha = IsValidMpqHandle(hMpqOrFile); - if(ha != NULL) - { - pvSrcFileInfo = &ha->MpqPos; - cbSrcFileInfo = sizeof(ULONGLONG); - nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER; - } - break; - - case SFileMpqHeaderSize: - ha = IsValidMpqHandle(hMpqOrFile); - if(ha != NULL) - { - pvSrcFileInfo = &ha->pHeader->dwHeaderSize; - cbSrcFileInfo = sizeof(DWORD); - nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER; - } - break; - - case SFileMpqHeader: - ha = IsValidMpqHandle(hMpqOrFile); - if(ha != NULL) - { - ByteOffset = ha->MpqPos; - cbSrcFileInfo = ha->pHeader->dwHeaderSize; - nInfoType = SFILE_INFO_TYPE_READ_FROM_FILE; - } - break; - - case SFileMpqHetTableOffset: - ha = IsValidMpqHandle(hMpqOrFile); - if(ha != NULL) - { - pvSrcFileInfo = &ha->pHeader->HetTablePos64; - cbSrcFileInfo = sizeof(ULONGLONG); - nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER; - } - break; - - case SFileMpqHetTableSize: - ha = IsValidMpqHandle(hMpqOrFile); - if(ha != NULL) - { - pvSrcFileInfo = &ha->pHeader->HetTableSize64; - cbSrcFileInfo = sizeof(ULONGLONG); - nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER; - } - break; - - 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; - - 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; - - case SFileMpqBetTableOffset: - ha = IsValidMpqHandle(hMpqOrFile); - if(ha != NULL) - { - pvSrcFileInfo = &ha->pHeader->BetTablePos64; - cbSrcFileInfo = sizeof(ULONGLONG); - nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER; - } - break; - - case SFileMpqBetTableSize: - ha = IsValidMpqHandle(hMpqOrFile); - if(ha != NULL) - { - pvSrcFileInfo = &ha->pHeader->BetTableSize64; - cbSrcFileInfo = sizeof(ULONGLONG); - nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER; - } - break; - - 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; - - 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; - - 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; - - case SFileMpqHashTableSize64: - ha = IsValidMpqHandle(hMpqOrFile); - if(ha != NULL) - { - pvSrcFileInfo = &ha->pHeader->HashTableSize64; - cbSrcFileInfo = sizeof(ULONGLONG); - nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER; - } - break; - - case SFileMpqHashTableSize: - ha = IsValidMpqHandle(hMpqOrFile); - if(ha != NULL) - { - pvSrcFileInfo = &ha->pHeader->dwHashTableSize; - cbSrcFileInfo = sizeof(DWORD); - nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER; - } - break; - - 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; - - 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; - - case SFileMpqBlockTableSize64: - ha = IsValidMpqHandle(hMpqOrFile); - if(ha != NULL) - { - pvSrcFileInfo = &ha->pHeader->BlockTableSize64; - cbSrcFileInfo = sizeof(ULONGLONG); - nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER; - } - break; - - case SFileMpqBlockTableSize: - ha = IsValidMpqHandle(hMpqOrFile); - if(ha != NULL) - { - pvSrcFileInfo = &ha->pHeader->dwBlockTableSize; - cbSrcFileInfo = sizeof(DWORD); - nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER; - } - break; - - case SFileMpqBlockTable: - ha = IsValidMpqHandle(hMpqOrFile); - if(ha != NULL) - { - nInfoType = SFILE_INFO_TYPE_NOT_FOUND; - if(MAKE_OFFSET64(ha->pHeader->wBlockTablePosHi, ha->pHeader->dwBlockTablePos) != 0) - { - cbSrcFileInfo = ha->pHeader->dwBlockTableSize * sizeof(TMPQBlock); - if(cbFileInfo >= cbSrcFileInfo) - pvSrcFileInfo = LoadBlockTable(ha, true); - nInfoType = SFILE_INFO_TYPE_ALLOCATED; - } - } - break; - - case SFileMpqHiBlockTableOffset: - ha = IsValidMpqHandle(hMpqOrFile); - if(ha != NULL) - { - pvSrcFileInfo = &ha->pHeader->HiBlockTablePos64; - cbSrcFileInfo = sizeof(ULONGLONG); - nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER; - } - break; - - case SFileMpqHiBlockTableSize64: - ha = IsValidMpqHandle(hMpqOrFile); - if(ha != NULL) - { - pvSrcFileInfo = &ha->pHeader->HiBlockTableSize64; - cbSrcFileInfo = sizeof(ULONGLONG); - nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER; - } - break; - - case SFileMpqHiBlockTable: - ha = IsValidMpqHandle(hMpqOrFile); - if(ha != NULL) - { - nInfoType = SFILE_INFO_TYPE_NOT_FOUND; - if(ha->pHeader->HiBlockTablePos64 && ha->pHeader->HiBlockTableSize64) - { - assert(false); - } - } - break; - - case SFileMpqSignatures: - ha = IsValidMpqHandle(hMpqOrFile); - if(ha != NULL && QueryMpqSignatureInfo(ha, &SignatureInfo)) - { - pvSrcFileInfo = &SignatureInfo.SignatureTypes; - cbSrcFileInfo = sizeof(DWORD); - nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER; - } - break; - - 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; - - 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; - - 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; - - case SFileMpqArchiveSize64: - ha = IsValidMpqHandle(hMpqOrFile); - if(ha != NULL) - { - pvSrcFileInfo = &ha->pHeader->ArchiveSize64; - cbSrcFileInfo = sizeof(DWORD); - nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER; - } - break; - - case SFileMpqArchiveSize: - ha = IsValidMpqHandle(hMpqOrFile); - if(ha != NULL) - { - pvSrcFileInfo = &ha->pHeader->dwArchiveSize; - cbSrcFileInfo = sizeof(DWORD); - nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER; - } - break; - - case SFileMpqMaxFileCount: - ha = IsValidMpqHandle(hMpqOrFile); - if(ha != NULL) - { - pvSrcFileInfo = &ha->dwMaxFileCount; - cbSrcFileInfo = sizeof(DWORD); - nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER; - } - break; - - case SFileMpqFileTableSize: - ha = IsValidMpqHandle(hMpqOrFile); - if(ha != NULL) - { - pvSrcFileInfo = &ha->dwFileTableSize; - cbSrcFileInfo = sizeof(DWORD); - nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER; - } - break; - - case SFileMpqSectorSize: - ha = IsValidMpqHandle(hMpqOrFile); - if(ha != NULL) - { - pvSrcFileInfo = &ha->dwSectorSize; - cbSrcFileInfo = sizeof(DWORD); - nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER; - } - break; - - case SFileMpqNumberOfFiles: - ha = IsValidMpqHandle(hMpqOrFile); - if(ha != NULL) - { - pvSrcFileInfo = &dwInt32Value; - cbSrcFileInfo = sizeof(DWORD); - dwInt32Value = GetMpqFileCount(ha); - nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER; - } - break; - - 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; - - 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; - - case SFileMpqFlags: - ha = IsValidMpqHandle(hMpqOrFile); - if(ha != NULL) - { - dwInt32Value = ha->dwFlags; - pvSrcFileInfo = &dwInt32Value; - cbSrcFileInfo = sizeof(DWORD); - nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER; - } - break; - - case SFileInfoPatchChain: - hf = IsValidFileHandle(hMpqOrFile); - if(hf != NULL) - return GetFilePatchChain(hf, pvFileInfo, cbFileInfo, pcbLengthNeeded); - break; - - 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; - - case SFileInfoHashEntry: - hf = IsValidFileHandle(hMpqOrFile); - if(hf != NULL && hf->pHashEntry != NULL) - { - pvSrcFileInfo = hf->pHashEntry; - cbSrcFileInfo = sizeof(TMPQHash); - nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER; - } - break; - - case SFileInfoHashIndex: - hf = IsValidFileHandle(hMpqOrFile); - if(hf != NULL && hf->pHashEntry != NULL) - { - pvSrcFileInfo = &hf->dwHashIndex; - cbSrcFileInfo = sizeof(DWORD); - nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER; - } - break; - - 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; - - 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; - - 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; - - 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; - - 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; - - 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; - - 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; - - 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; - - 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; - - 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; - - case SFileInfoEncryptionKey: - hf = IsValidFileHandle(hMpqOrFile); - if(hf != NULL) - { - pvSrcFileInfo = &hf->dwFileKey; - cbSrcFileInfo = sizeof(DWORD); - nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER; - } - break; - - 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; - - 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; - } - - // Set the last error value, if needed - if(nError != ERROR_SUCCESS) - SetLastError(nError); - return (nError == ERROR_SUCCESS); -} - -bool WINAPI SFileFreeFileInfo(void * pvFileInfo, SFileInfoClass InfoClass) -{ - switch(InfoClass) - { - case SFileMpqHetTable: - FreeHetTable((TMPQHetTable *)pvFileInfo); - return true; - - case SFileMpqBetTable: - FreeBetTable((TMPQBetTable *)pvFileInfo); - return true; - - default: - break; - } - - SetLastError(ERROR_INVALID_PARAMETER); - return false; -} - -//----------------------------------------------------------------------------- -// Tries to retrieve the file name - -struct TFileHeader2Ext -{ - DWORD dwOffset00Data; // Required data at offset 00 (32-bits) - DWORD dwOffset00Mask; // Mask for data at offset 00 (32 bits). 0 = data are ignored - DWORD dwOffset04Data; // Required data at offset 04 (32-bits) - DWORD dwOffset04Mask; // Mask for data at offset 04 (32 bits). 0 = data are ignored - const char * szExt; // Supplied extension, if the condition is true -}; - -static TFileHeader2Ext data2ext[] = -{ - {0x00005A4D, 0x0000FFFF, 0x00000000, 0x00000000, "exe"}, // EXE files - {0x00000006, 0xFFFFFFFF, 0x00000001, 0xFFFFFFFF, "dc6"}, // EXE files - {0x1A51504D, 0xFFFFFFFF, 0x00000000, 0x00000000, "mpq"}, // MPQ archive header ID ('MPQ\x1A') - {0x46464952, 0xFFFFFFFF, 0x00000000, 0x00000000, "wav"}, // WAVE header 'RIFF' - {0x324B4D53, 0xFFFFFFFF, 0x00000000, 0x00000000, "smk"}, // Old "Smacker Video" files 'SMK2' - {0x694B4942, 0xFFFFFFFF, 0x00000000, 0x00000000, "bik"}, // Bink video files (new) - {0x0801050A, 0xFFFFFFFF, 0x00000000, 0x00000000, "pcx"}, // PCX images used in Diablo I - {0x544E4F46, 0xFFFFFFFF, 0x00000000, 0x00000000, "fnt"}, // Font files used in Diablo II - {0x6D74683C, 0xFFFFFFFF, 0x00000000, 0x00000000, "html"}, // HTML '<htm' - {0x4D54483C, 0xFFFFFFFF, 0x00000000, 0x00000000, "html"}, // HTML '<HTM - {0x216F6F57, 0xFFFFFFFF, 0x00000000, 0x00000000, "tbl"}, // Table files - {0x31504C42, 0xFFFFFFFF, 0x00000000, 0x00000000, "blp"}, // BLP textures - {0x32504C42, 0xFFFFFFFF, 0x00000000, 0x00000000, "blp"}, // BLP textures (v2) - {0x584C444D, 0xFFFFFFFF, 0x00000000, 0x00000000, "mdx"}, // MDX files - {0x45505954, 0xFFFFFFFF, 0x00000000, 0x00000000, "pud"}, // Warcraft II maps - {0x38464947, 0xFFFFFFFF, 0x00000000, 0x00000000, "gif"}, // GIF images 'GIF8' - {0x3032444D, 0xFFFFFFFF, 0x00000000, 0x00000000, "m2"}, // WoW ??? .m2 - {0x43424457, 0xFFFFFFFF, 0x00000000, 0x00000000, "dbc"}, // ??? .dbc - {0x47585053, 0xFFFFFFFF, 0x00000000, 0x00000000, "bls"}, // WoW pixel shaders - {0xE0FFD8FF, 0xFFFFFFFF, 0x00000000, 0x00000000, "jpg"}, // JPEG image - {0x503B4449, 0xFFFFFFFF, 0x3B4C5857, 0xFFFFFFFF, "slk"}, // SLK file (usually starts with "ID;PWXL;N;E") - {0x00000000, 0x00000000, 0x00000000, 0x00000000, "xxx"}, // Default extension - {0, 0, 0, 0, NULL} // Terminator -}; - -static int CreatePseudoFileName(HANDLE hFile, TFileEntry * pFileEntry, char * szFileName) -{ - TMPQFile * hf = (TMPQFile *)hFile; // MPQ File handle - DWORD FirstBytes[2] = {0, 0}; // The first 4 bytes of the file - DWORD dwBytesRead = 0; - DWORD dwFilePos; // Saved file position - - // Read the first 2 DWORDs bytes from the file - dwFilePos = SFileSetFilePointer(hFile, 0, NULL, FILE_CURRENT); - SFileReadFile(hFile, FirstBytes, sizeof(FirstBytes), &dwBytesRead, NULL); - SFileSetFilePointer(hFile, dwFilePos, NULL, FILE_BEGIN); - - // If we read at least 8 bytes - if(dwBytesRead == sizeof(FirstBytes)) - { - // Make sure that the array is properly BSWAP-ed - BSWAP_ARRAY32_UNSIGNED(FirstBytes, sizeof(FirstBytes)); - - // Try to guess file extension from those 2 DWORDs - for(size_t i = 0; data2ext[i].szExt != NULL; i++) - { - if((FirstBytes[0] & data2ext[i].dwOffset00Mask) == data2ext[i].dwOffset00Data && - (FirstBytes[1] & data2ext[i].dwOffset04Mask) == data2ext[i].dwOffset04Data) - { - char szPseudoName[20] = ""; - - // Format the pseudo-name - sprintf(szPseudoName, "File%08u.%s", (unsigned int)(pFileEntry - hf->ha->pFileTable), data2ext[i].szExt); - - // Save the pseudo-name in the file entry as well - AllocateFileName(hf->ha, pFileEntry, szPseudoName); - - // If the caller wants to copy the file name, do it - if(szFileName != NULL) - strcpy(szFileName, szPseudoName); - return ERROR_SUCCESS; - } - } - } - - return ERROR_CAN_NOT_COMPLETE; -} - -bool WINAPI SFileGetFileName(HANDLE hFile, char * szFileName) -{ - TMPQFile * hf = (TMPQFile *)hFile; // MPQ File handle - int nError = ERROR_INVALID_HANDLE; - - // Check valid parameters - if(IsValidFileHandle(hFile)) - { - TFileEntry * pFileEntry = hf->pFileEntry; - - // For MPQ files, retrieve the file name from the file entry - if(hf->pStream == NULL) - { - if(pFileEntry != NULL) - { - // If the file name is not there yet, create a pseudo name - if(pFileEntry->szFileName == NULL) - nError = CreatePseudoFileName(hFile, pFileEntry, szFileName); - - // Copy the file name to the output buffer, if any - if(pFileEntry->szFileName && szFileName) - { - strcpy(szFileName, pFileEntry->szFileName); - nError = ERROR_SUCCESS; - } - } - } - - // For local files, copy the file name from the stream - else - { - if(szFileName != NULL) - { - const TCHAR * szStreamName = FileStream_GetFileName(hf->pStream); - CopyFileName(szFileName, szStreamName, _tcslen(szStreamName)); - } - nError = ERROR_SUCCESS; - } - } - - if(nError != ERROR_SUCCESS) - SetLastError(nError); - return (nError == ERROR_SUCCESS); -} - +/*****************************************************************************/
+/* SFileGetFileInfo.cpp Copyright (c) Ladislav Zezula 2013 */
+/*---------------------------------------------------------------------------*/
+/* Description: */
+/*---------------------------------------------------------------------------*/
+/* Date Ver Who Comment */
+/* -------- ---- --- ------- */
+/* 30.11.13 1.00 Lad The first version of SFileGetFileInfo.cpp */
+/*****************************************************************************/
+
+#define __STORMLIB_SELF__
+#include "StormLib.h"
+#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;
+ TFileEntry * pFileEntry;
+ DWORD dwFileCount = 0;
+
+ // Go through all open MPQs, including patches
+ while(ha != NULL)
+ {
+ // Only count files that are not patch files
+ pFileTableEnd = ha->pFileTable + ha->dwFileTableSize;
+ for(pFileEntry = ha->pFileTable; pFileEntry < pFileTableEnd; pFileEntry++)
+ {
+ // If the file is patch file and this is not primary archive, skip it
+ // BUGBUG: This errorneously counts non-patch files that are in both
+ // base MPQ and in patches, and increases the number of files by cca 50%
+ if((pFileEntry->dwFlags & (MPQ_FILE_EXISTS | MPQ_FILE_PATCH_FILE)) == MPQ_FILE_EXISTS)
+ dwFileCount++;
+ }
+
+ // Move to the next patch archive
+ ha = ha->haPatch;
+ }
+
+ return dwFileCount;
+}
+
+static bool GetFilePatchChain(TMPQFile * hf, void * pvFileInfo, DWORD cbFileInfo, DWORD * pcbLengthNeeded)
+{
+ TMPQFile * hfTemp;
+ TCHAR * szFileInfo = (TCHAR *)pvFileInfo;
+ size_t cchCharsNeeded = 1;
+ size_t cchFileInfo = (cbFileInfo / sizeof(TCHAR));
+ size_t nLength;
+
+ // Patch chain is only supported on MPQ files.
+ if(hf->pStream != NULL)
+ {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return false;
+ }
+
+ // 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));
+
+ // If the caller gave both buffer pointer and data length,
+ // try to copy the patch chain
+ if(szFileInfo != NULL && cchFileInfo != 0)
+ {
+ // If there is enough space in the buffer, copy the patch chain
+ if(cchCharsNeeded > cchFileInfo)
+ {
+ SetLastError(ERROR_INSUFFICIENT_BUFFER);
+ return false;
+ }
+
+ // 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;
+ }
+
+ return true;
+}
+
+//-----------------------------------------------------------------------------
+// Retrieves an information about an archive or about a file within the archive
+//
+// hMpqOrFile - Handle to an MPQ archive or to a file
+// InfoClass - Information to obtain
+// pvFileInfo - Pointer to buffer to store the information
+// cbFileInfo - Size of the buffer pointed by pvFileInfo
+// pcbLengthNeeded - Receives number of bytes necessary to store the information
+
+bool WINAPI SFileGetFileInfo(
+ HANDLE hMpqOrFile,
+ SFileInfoClass InfoClass,
+ void * pvFileInfo,
+ DWORD cbFileInfo,
+ LPDWORD pcbLengthNeeded)
+{
+ MPQ_SIGNATURE_INFO SignatureInfo;
+ TMPQArchive * ha = NULL;
+ TFileEntry * pFileEntry = 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;
+
+ 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;
+
+ case SFileMpqStreamBitmap:
+ ha = IsValidMpqHandle(hMpqOrFile);
+ if(ha != NULL)
+ return FileStream_GetBitmap(ha->pStream, pvFileInfo, cbFileInfo, pcbLengthNeeded);
+ break;
+
+ 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;
+
+ 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;
+
+ 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;
+
+ case SFileMpqHeaderOffset:
+ ha = IsValidMpqHandle(hMpqOrFile);
+ if(ha != NULL)
+ {
+ pvSrcFileInfo = &ha->MpqPos;
+ cbSrcFileInfo = sizeof(ULONGLONG);
+ nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER;
+ }
+ break;
+
+ case SFileMpqHeaderSize:
+ ha = IsValidMpqHandle(hMpqOrFile);
+ if(ha != NULL)
+ {
+ pvSrcFileInfo = &ha->pHeader->dwHeaderSize;
+ cbSrcFileInfo = sizeof(DWORD);
+ nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER;
+ }
+ break;
+
+ case SFileMpqHeader:
+ ha = IsValidMpqHandle(hMpqOrFile);
+ if(ha != NULL)
+ {
+ ByteOffset = ha->MpqPos;
+ cbSrcFileInfo = ha->pHeader->dwHeaderSize;
+ nInfoType = SFILE_INFO_TYPE_READ_FROM_FILE;
+ }
+ break;
+
+ case SFileMpqHetTableOffset:
+ ha = IsValidMpqHandle(hMpqOrFile);
+ if(ha != NULL)
+ {
+ pvSrcFileInfo = &ha->pHeader->HetTablePos64;
+ cbSrcFileInfo = sizeof(ULONGLONG);
+ nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER;
+ }
+ break;
+
+ case SFileMpqHetTableSize:
+ ha = IsValidMpqHandle(hMpqOrFile);
+ if(ha != NULL)
+ {
+ pvSrcFileInfo = &ha->pHeader->HetTableSize64;
+ cbSrcFileInfo = sizeof(ULONGLONG);
+ nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER;
+ }
+ break;
+
+ 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;
+
+ 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;
+
+ case SFileMpqBetTableOffset:
+ ha = IsValidMpqHandle(hMpqOrFile);
+ if(ha != NULL)
+ {
+ pvSrcFileInfo = &ha->pHeader->BetTablePos64;
+ cbSrcFileInfo = sizeof(ULONGLONG);
+ nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER;
+ }
+ break;
+
+ case SFileMpqBetTableSize:
+ ha = IsValidMpqHandle(hMpqOrFile);
+ if(ha != NULL)
+ {
+ pvSrcFileInfo = &ha->pHeader->BetTableSize64;
+ cbSrcFileInfo = sizeof(ULONGLONG);
+ nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER;
+ }
+ break;
+
+ 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;
+
+ 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;
+
+ 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;
+
+ case SFileMpqHashTableSize64:
+ ha = IsValidMpqHandle(hMpqOrFile);
+ if(ha != NULL)
+ {
+ pvSrcFileInfo = &ha->pHeader->HashTableSize64;
+ cbSrcFileInfo = sizeof(ULONGLONG);
+ nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER;
+ }
+ break;
+
+ case SFileMpqHashTableSize:
+ ha = IsValidMpqHandle(hMpqOrFile);
+ if(ha != NULL)
+ {
+ pvSrcFileInfo = &ha->pHeader->dwHashTableSize;
+ cbSrcFileInfo = sizeof(DWORD);
+ nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER;
+ }
+ break;
+
+ 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;
+
+ 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;
+
+ case SFileMpqBlockTableSize64:
+ ha = IsValidMpqHandle(hMpqOrFile);
+ if(ha != NULL)
+ {
+ pvSrcFileInfo = &ha->pHeader->BlockTableSize64;
+ cbSrcFileInfo = sizeof(ULONGLONG);
+ nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER;
+ }
+ break;
+
+ case SFileMpqBlockTableSize:
+ ha = IsValidMpqHandle(hMpqOrFile);
+ if(ha != NULL)
+ {
+ pvSrcFileInfo = &ha->pHeader->dwBlockTableSize;
+ cbSrcFileInfo = sizeof(DWORD);
+ nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER;
+ }
+ break;
+
+ case SFileMpqBlockTable:
+ ha = IsValidMpqHandle(hMpqOrFile);
+ if(ha != NULL)
+ {
+ nInfoType = SFILE_INFO_TYPE_NOT_FOUND;
+ if(MAKE_OFFSET64(ha->pHeader->wBlockTablePosHi, ha->pHeader->dwBlockTablePos) != 0)
+ {
+ cbSrcFileInfo = ha->pHeader->dwBlockTableSize * sizeof(TMPQBlock);
+ if(cbFileInfo >= cbSrcFileInfo)
+ pvSrcFileInfo = LoadBlockTable(ha, true);
+ nInfoType = SFILE_INFO_TYPE_ALLOCATED;
+ }
+ }
+ break;
+
+ case SFileMpqHiBlockTableOffset:
+ ha = IsValidMpqHandle(hMpqOrFile);
+ if(ha != NULL)
+ {
+ pvSrcFileInfo = &ha->pHeader->HiBlockTablePos64;
+ cbSrcFileInfo = sizeof(ULONGLONG);
+ nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER;
+ }
+ break;
+
+ case SFileMpqHiBlockTableSize64:
+ ha = IsValidMpqHandle(hMpqOrFile);
+ if(ha != NULL)
+ {
+ pvSrcFileInfo = &ha->pHeader->HiBlockTableSize64;
+ cbSrcFileInfo = sizeof(ULONGLONG);
+ nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER;
+ }
+ break;
+
+ case SFileMpqHiBlockTable:
+ ha = IsValidMpqHandle(hMpqOrFile);
+ if(ha != NULL)
+ {
+ nInfoType = SFILE_INFO_TYPE_NOT_FOUND;
+ if(ha->pHeader->HiBlockTablePos64 && ha->pHeader->HiBlockTableSize64)
+ {
+ assert(false);
+ }
+ }
+ break;
+
+ case SFileMpqSignatures:
+ ha = IsValidMpqHandle(hMpqOrFile);
+ if(ha != NULL && QueryMpqSignatureInfo(ha, &SignatureInfo))
+ {
+ pvSrcFileInfo = &SignatureInfo.SignatureTypes;
+ cbSrcFileInfo = sizeof(DWORD);
+ nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER;
+ }
+ break;
+
+ 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;
+
+ 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;
+
+ 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;
+
+ case SFileMpqArchiveSize64:
+ ha = IsValidMpqHandle(hMpqOrFile);
+ if(ha != NULL)
+ {
+ pvSrcFileInfo = &ha->pHeader->ArchiveSize64;
+ cbSrcFileInfo = sizeof(DWORD);
+ nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER;
+ }
+ break;
+
+ case SFileMpqArchiveSize:
+ ha = IsValidMpqHandle(hMpqOrFile);
+ if(ha != NULL)
+ {
+ pvSrcFileInfo = &ha->pHeader->dwArchiveSize;
+ cbSrcFileInfo = sizeof(DWORD);
+ nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER;
+ }
+ break;
+
+ case SFileMpqMaxFileCount:
+ ha = IsValidMpqHandle(hMpqOrFile);
+ if(ha != NULL)
+ {
+ pvSrcFileInfo = &ha->dwMaxFileCount;
+ cbSrcFileInfo = sizeof(DWORD);
+ nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER;
+ }
+ break;
+
+ case SFileMpqFileTableSize:
+ ha = IsValidMpqHandle(hMpqOrFile);
+ if(ha != NULL)
+ {
+ pvSrcFileInfo = &ha->dwFileTableSize;
+ cbSrcFileInfo = sizeof(DWORD);
+ nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER;
+ }
+ break;
+
+ case SFileMpqSectorSize:
+ ha = IsValidMpqHandle(hMpqOrFile);
+ if(ha != NULL)
+ {
+ pvSrcFileInfo = &ha->dwSectorSize;
+ cbSrcFileInfo = sizeof(DWORD);
+ nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER;
+ }
+ break;
+
+ case SFileMpqNumberOfFiles:
+ ha = IsValidMpqHandle(hMpqOrFile);
+ if(ha != NULL)
+ {
+ pvSrcFileInfo = &dwInt32Value;
+ cbSrcFileInfo = sizeof(DWORD);
+ dwInt32Value = GetMpqFileCount(ha);
+ nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER;
+ }
+ break;
+
+ 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;
+
+ 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;
+
+ case SFileMpqFlags:
+ ha = IsValidMpqHandle(hMpqOrFile);
+ if(ha != NULL)
+ {
+ dwInt32Value = ha->dwFlags;
+ pvSrcFileInfo = &dwInt32Value;
+ cbSrcFileInfo = sizeof(DWORD);
+ nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER;
+ }
+ break;
+
+ case SFileInfoPatchChain:
+ hf = IsValidFileHandle(hMpqOrFile);
+ if(hf != NULL)
+ return GetFilePatchChain(hf, pvFileInfo, cbFileInfo, pcbLengthNeeded);
+ break;
+
+ 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;
+
+ case SFileInfoHashEntry:
+ hf = IsValidFileHandle(hMpqOrFile);
+ if(hf != NULL && hf->pHashEntry != NULL)
+ {
+ pvSrcFileInfo = hf->pHashEntry;
+ cbSrcFileInfo = sizeof(TMPQHash);
+ nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER;
+ }
+ break;
+
+ case SFileInfoHashIndex:
+ hf = IsValidFileHandle(hMpqOrFile);
+ if(hf != NULL && hf->pHashEntry != NULL)
+ {
+ pvSrcFileInfo = &hf->dwHashIndex;
+ cbSrcFileInfo = sizeof(DWORD);
+ nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER;
+ }
+ break;
+
+ 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;
+
+ 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;
+
+ 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;
+
+ 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;
+
+ 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;
+
+ 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;
+
+ 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;
+
+ 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;
+
+ 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;
+
+ 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;
+
+ case SFileInfoEncryptionKey:
+ hf = IsValidFileHandle(hMpqOrFile);
+ if(hf != NULL)
+ {
+ pvSrcFileInfo = &hf->dwFileKey;
+ cbSrcFileInfo = sizeof(DWORD);
+ nInfoType = SFILE_INFO_TYPE_DIRECT_POINTER;
+ }
+ break;
+
+ 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;
+
+ 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;
+ }
+
+ // Set the last error value, if needed
+ if(nError != ERROR_SUCCESS)
+ SetLastError(nError);
+ return (nError == ERROR_SUCCESS);
+}
+
+bool WINAPI SFileFreeFileInfo(void * pvFileInfo, SFileInfoClass InfoClass)
+{
+ switch(InfoClass)
+ {
+ case SFileMpqHetTable:
+ FreeHetTable((TMPQHetTable *)pvFileInfo);
+ return true;
+
+ case SFileMpqBetTable:
+ FreeBetTable((TMPQBetTable *)pvFileInfo);
+ return true;
+
+ default:
+ break;
+ }
+
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return false;
+}
+
+//-----------------------------------------------------------------------------
+// Tries to retrieve the file name
+
+struct TFileHeader2Ext
+{
+ DWORD dwOffset00Data; // Required data at offset 00 (32-bits)
+ DWORD dwOffset00Mask; // Mask for data at offset 00 (32 bits). 0 = data are ignored
+ DWORD dwOffset04Data; // Required data at offset 04 (32-bits)
+ DWORD dwOffset04Mask; // Mask for data at offset 04 (32 bits). 0 = data are ignored
+ const char * szExt; // Supplied extension, if the condition is true
+};
+
+static TFileHeader2Ext data2ext[] =
+{
+ {0x00005A4D, 0x0000FFFF, 0x00000000, 0x00000000, "exe"}, // EXE files
+ {0x00000006, 0xFFFFFFFF, 0x00000001, 0xFFFFFFFF, "dc6"}, // EXE files
+ {0x1A51504D, 0xFFFFFFFF, 0x00000000, 0x00000000, "mpq"}, // MPQ archive header ID ('MPQ\x1A')
+ {0x46464952, 0xFFFFFFFF, 0x00000000, 0x00000000, "wav"}, // WAVE header 'RIFF'
+ {0x324B4D53, 0xFFFFFFFF, 0x00000000, 0x00000000, "smk"}, // Old "Smacker Video" files 'SMK2'
+ {0x694B4942, 0xFFFFFFFF, 0x00000000, 0x00000000, "bik"}, // Bink video files (new)
+ {0x0801050A, 0xFFFFFFFF, 0x00000000, 0x00000000, "pcx"}, // PCX images used in Diablo I
+ {0x544E4F46, 0xFFFFFFFF, 0x00000000, 0x00000000, "fnt"}, // Font files used in Diablo II
+ {0x6D74683C, 0xFFFFFFFF, 0x00000000, 0x00000000, "html"}, // HTML '<htm'
+ {0x4D54483C, 0xFFFFFFFF, 0x00000000, 0x00000000, "html"}, // HTML '<HTM
+ {0x216F6F57, 0xFFFFFFFF, 0x00000000, 0x00000000, "tbl"}, // Table files
+ {0x31504C42, 0xFFFFFFFF, 0x00000000, 0x00000000, "blp"}, // BLP textures
+ {0x32504C42, 0xFFFFFFFF, 0x00000000, 0x00000000, "blp"}, // BLP textures (v2)
+ {0x584C444D, 0xFFFFFFFF, 0x00000000, 0x00000000, "mdx"}, // MDX files
+ {0x45505954, 0xFFFFFFFF, 0x00000000, 0x00000000, "pud"}, // Warcraft II maps
+ {0x38464947, 0xFFFFFFFF, 0x00000000, 0x00000000, "gif"}, // GIF images 'GIF8'
+ {0x3032444D, 0xFFFFFFFF, 0x00000000, 0x00000000, "m2"}, // WoW ??? .m2
+ {0x43424457, 0xFFFFFFFF, 0x00000000, 0x00000000, "dbc"}, // ??? .dbc
+ {0x47585053, 0xFFFFFFFF, 0x00000000, 0x00000000, "bls"}, // WoW pixel shaders
+ {0xE0FFD8FF, 0xFFFFFFFF, 0x00000000, 0x00000000, "jpg"}, // JPEG image
+ {0x503B4449, 0xFFFFFFFF, 0x3B4C5857, 0xFFFFFFFF, "slk"}, // SLK file (usually starts with "ID;PWXL;N;E")
+ {0x00000000, 0x00000000, 0x00000000, 0x00000000, "xxx"}, // Default extension
+ {0, 0, 0, 0, NULL} // Terminator
+};
+
+static int CreatePseudoFileName(HANDLE hFile, TFileEntry * pFileEntry, char * szFileName)
+{
+ TMPQFile * hf = (TMPQFile *)hFile; // MPQ File handle
+ DWORD FirstBytes[2] = {0, 0}; // The first 4 bytes of the file
+ DWORD dwBytesRead = 0;
+ DWORD dwFilePos; // Saved file position
+
+ // Read the first 2 DWORDs bytes from the file
+ dwFilePos = SFileSetFilePointer(hFile, 0, NULL, FILE_CURRENT);
+ SFileReadFile(hFile, FirstBytes, sizeof(FirstBytes), &dwBytesRead, NULL);
+ SFileSetFilePointer(hFile, dwFilePos, NULL, FILE_BEGIN);
+
+ // If we read at least 8 bytes
+ if(dwBytesRead == sizeof(FirstBytes))
+ {
+ // Make sure that the array is properly BSWAP-ed
+ BSWAP_ARRAY32_UNSIGNED(FirstBytes, sizeof(FirstBytes));
+
+ // Try to guess file extension from those 2 DWORDs
+ for(size_t i = 0; data2ext[i].szExt != NULL; i++)
+ {
+ if((FirstBytes[0] & data2ext[i].dwOffset00Mask) == data2ext[i].dwOffset00Data &&
+ (FirstBytes[1] & data2ext[i].dwOffset04Mask) == data2ext[i].dwOffset04Data)
+ {
+ char szPseudoName[20] = "";
+
+ // Format the pseudo-name
+ sprintf(szPseudoName, "File%08u.%s", (unsigned int)(pFileEntry - hf->ha->pFileTable), data2ext[i].szExt);
+
+ // Save the pseudo-name in the file entry as well
+ AllocateFileName(hf->ha, pFileEntry, szPseudoName);
+
+ // If the caller wants to copy the file name, do it
+ if(szFileName != NULL)
+ strcpy(szFileName, szPseudoName);
+ return ERROR_SUCCESS;
+ }
+ }
+ }
+
+ return ERROR_CAN_NOT_COMPLETE;
+}
+
+bool WINAPI SFileGetFileName(HANDLE hFile, char * szFileName)
+{
+ TMPQFile * hf = (TMPQFile *)hFile; // MPQ File handle
+ int nError = ERROR_INVALID_HANDLE;
+
+ // Check valid parameters
+ if(IsValidFileHandle(hFile))
+ {
+ TFileEntry * pFileEntry = hf->pFileEntry;
+
+ // For MPQ files, retrieve the file name from the file entry
+ if(hf->pStream == NULL)
+ {
+ if(pFileEntry != NULL)
+ {
+ // If the file name is not there yet, create a pseudo name
+ if(pFileEntry->szFileName == NULL)
+ nError = CreatePseudoFileName(hFile, pFileEntry, szFileName);
+
+ // Copy the file name to the output buffer, if any
+ if(pFileEntry->szFileName && szFileName)
+ {
+ strcpy(szFileName, pFileEntry->szFileName);
+ nError = ERROR_SUCCESS;
+ }
+ }
+ }
+
+ // For local files, copy the file name from the stream
+ else
+ {
+ if(szFileName != NULL)
+ {
+ const TCHAR * szStreamName = FileStream_GetFileName(hf->pStream);
+ CopyFileName(szFileName, szStreamName, _tcslen(szStreamName));
+ }
+ nError = ERROR_SUCCESS;
+ }
+ }
+
+ if(nError != ERROR_SUCCESS)
+ SetLastError(nError);
+ return (nError == ERROR_SUCCESS);
+}
+
|