diff options
Diffstat (limited to 'StormLib/src/SFileGetFileInfo.cpp')
| -rw-r--r-- | StormLib/src/SFileGetFileInfo.cpp | 607 |
1 files changed, 0 insertions, 607 deletions
diff --git a/StormLib/src/SFileGetFileInfo.cpp b/StormLib/src/SFileGetFileInfo.cpp deleted file mode 100644 index 28edfe0bf..000000000 --- a/StormLib/src/SFileGetFileInfo.cpp +++ /dev/null @@ -1,607 +0,0 @@ -/*****************************************************************************/ -/* 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 functions - -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 GetInfo_ReturdwErrCode(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_ReturdwErrCode(ERROR_INSUFFICIENT_BUFFER); - - // If the buffer size is sufficient, check for valid user buffer - if(pvFileInfo == NULL) - return GetInfo_ReturdwErrCode(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; - LPCTSTR szPatchName; - LPTSTR szFileInfo = (LPTSTR)pvFileInfo; - size_t cchCharsNeeded = 1; - size_t nLength; - - // Patch chain is only supported on MPQ files. Local files are not supported. - if(hf->pStream != NULL) - return GetInfo_ReturdwErrCode(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; - - // Verify whether the caller gave us valid buffer with enough size - if(!GetInfo_BufferCheck(pvFileInfo, cbFileInfo, (DWORD)(cchCharsNeeded * sizeof(TCHAR)), pcbLengthNeeded)) - return false; - - // Copy each patch name - for(hfTemp = hf; hfTemp != NULL; hfTemp = hfTemp->hfPatch) - { - // Get the file name and its length - szPatchName = FileStream_GetFileName(hfTemp->ha->pStream); - nLength = _tcslen(szPatchName) + 1; - - // Copy the file name - memcpy(szFileInfo, szPatchName, 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; - const TCHAR * szSrcFileInfo; - TMPQArchive * ha = NULL; - TFileEntry * pFileEntry = NULL; - TMPQHeader * pHeader = NULL; - ULONGLONG Int64Value = 0; - TMPQFile * hf = NULL; - void * pvSrcFileInfo = NULL; - DWORD cbSrcFileInfo = 0; - DWORD dwInt32Value = 0; - - // Validate archive/file handle - if((int)InfoClass <= (int)SFileMpqFlags) - { - if((ha = IsValidMpqHandle(hMpqOrFile)) == NULL) - return GetInfo_ReturdwErrCode(ERROR_INVALID_HANDLE); - pHeader = ha->pHeader; - } - else - { - if((hf = IsValidFileHandle(hMpqOrFile)) == NULL) - return GetInfo_ReturdwErrCode(ERROR_INVALID_HANDLE); - pFileEntry = hf->pFileEntry; - } - - // Return info-class-specific data - switch(InfoClass) - { - case SFileMpqFileName: - szSrcFileInfo = FileStream_GetFileName(ha->pStream); - cbSrcFileInfo = (DWORD)((_tcslen(szSrcFileInfo) + 1) * sizeof(TCHAR)); - return GetInfo(pvFileInfo, cbFileInfo, szSrcFileInfo, cbSrcFileInfo, pcbLengthNeeded); - - case SFileMpqStreamBitmap: - return FileStream_GetBitmap(ha->pStream, pvFileInfo, cbFileInfo, pcbLengthNeeded); - - case SFileMpqUserDataOffset: - return GetInfo(pvFileInfo, cbFileInfo, &ha->UserDataPos, sizeof(ULONGLONG), pcbLengthNeeded); - - case SFileMpqUserDataHeader: - if(ha->pUserData == NULL) - return GetInfo_ReturdwErrCode(ERROR_INVALID_PARAMETER); - return GetInfo_ReadFromFile(pvFileInfo, cbFileInfo, ha->pStream, ha->UserDataPos, sizeof(TMPQUserData), pcbLengthNeeded); - - case SFileMpqUserData: - if(ha->pUserData == NULL) - return GetInfo_ReturdwErrCode(ERROR_INVALID_PARAMETER); - return GetInfo_ReadFromFile(pvFileInfo, cbFileInfo, ha->pStream, ha->UserDataPos + sizeof(TMPQUserData), ha->pUserData->dwHeaderOffs - sizeof(TMPQUserData), pcbLengthNeeded); - - case SFileMpqHeaderOffset: - return GetInfo(pvFileInfo, cbFileInfo, &ha->MpqPos, sizeof(ULONGLONG), pcbLengthNeeded); - - case SFileMpqHeaderSize: - return GetInfo(pvFileInfo, cbFileInfo, &pHeader->dwHeaderSize, sizeof(DWORD), pcbLengthNeeded); - - case SFileMpqHeader: - return GetInfo_ReadFromFile(pvFileInfo, cbFileInfo, ha->pStream, ha->MpqPos, pHeader->dwHeaderSize, pcbLengthNeeded); - - case SFileMpqHetTableOffset: - return GetInfo(pvFileInfo, cbFileInfo, &pHeader->HetTablePos64, sizeof(ULONGLONG), pcbLengthNeeded); - - case SFileMpqHetTableSize: - return GetInfo(pvFileInfo, cbFileInfo, &pHeader->HetTableSize64, sizeof(ULONGLONG), pcbLengthNeeded); - - case SFileMpqHetHeader: - pvSrcFileInfo = LoadExtTable(ha, pHeader->HetTablePos64, (size_t)pHeader->HetTableSize64, HET_TABLE_SIGNATURE, MPQ_KEY_HASH_TABLE); - if(pvSrcFileInfo == NULL) - return GetInfo_ReturdwErrCode(ERROR_FILE_NOT_FOUND); - return GetInfo_Allocated(pvFileInfo, cbFileInfo, pvSrcFileInfo, sizeof(TMPQHetHeader), pcbLengthNeeded); - - case SFileMpqHetTable: - if((pvSrcFileInfo = LoadHetTable(ha)) == NULL) - return GetInfo_ReturdwErrCode(ERROR_NOT_ENOUGH_MEMORY); - return GetInfo_TablePointer(pvFileInfo, cbFileInfo, pvSrcFileInfo, InfoClass, pcbLengthNeeded); - - case SFileMpqBetTableOffset: - return GetInfo(pvFileInfo, cbFileInfo, &pHeader->BetTablePos64, sizeof(ULONGLONG), pcbLengthNeeded); - - case SFileMpqBetTableSize: - return GetInfo(pvFileInfo, cbFileInfo, &pHeader->BetTableSize64, sizeof(ULONGLONG), pcbLengthNeeded); - - case SFileMpqBetHeader: - - // 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_ReturdwErrCode(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: - if((pvSrcFileInfo = LoadBetTable(ha)) == NULL) - return GetInfo_ReturdwErrCode(ERROR_NOT_ENOUGH_MEMORY); - return GetInfo_TablePointer(pvFileInfo, cbFileInfo, pvSrcFileInfo, InfoClass, pcbLengthNeeded); - - case SFileMpqHashTableOffset: - Int64Value = MAKE_OFFSET64(pHeader->wHashTablePosHi, pHeader->dwHashTablePos); - return GetInfo(pvFileInfo, cbFileInfo, &Int64Value, sizeof(ULONGLONG), pcbLengthNeeded); - - case SFileMpqHashTableSize64: - return GetInfo(pvFileInfo, cbFileInfo, &pHeader->HashTableSize64, sizeof(ULONGLONG), pcbLengthNeeded); - - case SFileMpqHashTableSize: - return GetInfo(pvFileInfo, cbFileInfo, &pHeader->dwHashTableSize, sizeof(DWORD), pcbLengthNeeded); - - case SFileMpqHashTable: - cbSrcFileInfo = pHeader->dwHashTableSize * sizeof(TMPQHash); - return GetInfo(pvFileInfo, cbFileInfo, ha->pHashTable, cbSrcFileInfo, pcbLengthNeeded); - - case SFileMpqBlockTableOffset: - Int64Value = MAKE_OFFSET64(pHeader->wBlockTablePosHi, pHeader->dwBlockTablePos); - return GetInfo(pvFileInfo, cbFileInfo, &Int64Value, sizeof(ULONGLONG), pcbLengthNeeded); - - case SFileMpqBlockTableSize64: - return GetInfo(pvFileInfo, cbFileInfo, &pHeader->BlockTableSize64, sizeof(ULONGLONG), pcbLengthNeeded); - - case SFileMpqBlockTableSize: - return GetInfo(pvFileInfo, cbFileInfo, &pHeader->dwBlockTableSize, sizeof(DWORD), pcbLengthNeeded); - - case SFileMpqBlockTable: - if(MAKE_OFFSET64(pHeader->wBlockTablePosHi, pHeader->dwBlockTablePos) >= ha->FileSize) - return GetInfo_ReturdwErrCode(ERROR_FILE_NOT_FOUND); - cbSrcFileInfo = pHeader->dwBlockTableSize * sizeof(TMPQBlock); - pvSrcFileInfo = LoadBlockTable(ha, true); - return GetInfo_Allocated(pvFileInfo, cbFileInfo, pvSrcFileInfo, cbSrcFileInfo, pcbLengthNeeded); - - case SFileMpqHiBlockTableOffset: - return GetInfo(pvFileInfo, cbFileInfo, &pHeader->HiBlockTablePos64, sizeof(ULONGLONG), pcbLengthNeeded); - - case SFileMpqHiBlockTableSize64: - return GetInfo(pvFileInfo, cbFileInfo, &pHeader->HiBlockTableSize64, sizeof(ULONGLONG), pcbLengthNeeded); - - case SFileMpqHiBlockTable: - return GetInfo_ReturdwErrCode(ERROR_FILE_NOT_FOUND); - - case SFileMpqSignatures: - if(!QueryMpqSignatureInfo(ha, &SignatureInfo)) - return GetInfo_ReturdwErrCode(ERROR_FILE_NOT_FOUND); - return GetInfo(pvFileInfo, cbFileInfo, &SignatureInfo.SignatureTypes, sizeof(DWORD), pcbLengthNeeded); - - case SFileMpqStrongSignatureOffset: - if(QueryMpqSignatureInfo(ha, &SignatureInfo) == false || (SignatureInfo.SignatureTypes & SIGNATURE_TYPE_STRONG) == 0) - return GetInfo_ReturdwErrCode(ERROR_FILE_NOT_FOUND); - return GetInfo(pvFileInfo, cbFileInfo, &SignatureInfo.EndMpqData, sizeof(ULONGLONG), pcbLengthNeeded); - - case SFileMpqStrongSignatureSize: - if(QueryMpqSignatureInfo(ha, &SignatureInfo) == false || (SignatureInfo.SignatureTypes & SIGNATURE_TYPE_STRONG) == 0) - return GetInfo_ReturdwErrCode(ERROR_FILE_NOT_FOUND); - dwInt32Value = MPQ_STRONG_SIGNATURE_SIZE + 4; - return GetInfo(pvFileInfo, cbFileInfo, &dwInt32Value, sizeof(DWORD), pcbLengthNeeded); - - case SFileMpqStrongSignature: - if(QueryMpqSignatureInfo(ha, &SignatureInfo) == false || (SignatureInfo.SignatureTypes & SIGNATURE_TYPE_STRONG) == 0) - return GetInfo_ReturdwErrCode(ERROR_FILE_NOT_FOUND); - return GetInfo(pvFileInfo, cbFileInfo, SignatureInfo.Signature, MPQ_STRONG_SIGNATURE_SIZE + 4, pcbLengthNeeded); - - case SFileMpqArchiveSize64: - return GetInfo(pvFileInfo, cbFileInfo, &pHeader->ArchiveSize64, sizeof(ULONGLONG), pcbLengthNeeded); - - case SFileMpqArchiveSize: - return GetInfo(pvFileInfo, cbFileInfo, &pHeader->dwArchiveSize, sizeof(DWORD), pcbLengthNeeded); - - case SFileMpqMaxFileCount: - return GetInfo(pvFileInfo, cbFileInfo, &ha->dwMaxFileCount, sizeof(DWORD), pcbLengthNeeded); - - case SFileMpqFileTableSize: - return GetInfo(pvFileInfo, cbFileInfo, &ha->dwFileTableSize, sizeof(DWORD), pcbLengthNeeded); - - case SFileMpqSectorSize: - return GetInfo(pvFileInfo, cbFileInfo, &ha->dwSectorSize, sizeof(DWORD), pcbLengthNeeded); - - case SFileMpqNumberOfFiles: - dwInt32Value = GetMpqFileCount(ha); - return GetInfo(pvFileInfo, cbFileInfo, &dwInt32Value, sizeof(DWORD), pcbLengthNeeded); - - case SFileMpqRawChunkSize: - if(pHeader->dwRawChunkSize == 0) - return GetInfo_ReturdwErrCode(ERROR_FILE_NOT_FOUND); - return GetInfo(pvFileInfo, cbFileInfo, &pHeader->dwRawChunkSize, sizeof(DWORD), pcbLengthNeeded); - - case SFileMpqStreamFlags: - FileStream_GetFlags(ha->pStream, &dwInt32Value); - return GetInfo(pvFileInfo, cbFileInfo, &dwInt32Value, sizeof(DWORD), pcbLengthNeeded); - - case SFileMpqFlags: - return GetInfo(pvFileInfo, cbFileInfo, &ha->dwFlags, sizeof(DWORD), pcbLengthNeeded); - - case SFileInfoPatchChain: - return GetInfo_PatchChain(hf, pvFileInfo, cbFileInfo, pcbLengthNeeded); - - case SFileInfoFileEntry: - if(pFileEntry == NULL) - return GetInfo_ReturdwErrCode(ERROR_FILE_NOT_FOUND); - return GetInfo_FileEntry(pvFileInfo, cbFileInfo, pFileEntry, pcbLengthNeeded); - - case SFileInfoHashEntry: - return GetInfo(pvFileInfo, cbFileInfo, hf->pHashEntry, sizeof(TMPQHash), pcbLengthNeeded); - - case SFileInfoHashIndex: - return GetInfo(pvFileInfo, cbFileInfo, &hf->dwHashIndex, sizeof(DWORD), pcbLengthNeeded); - - case SFileInfoNameHash1: - return GetInfo(pvFileInfo, cbFileInfo, &hf->pHashEntry->dwName1, sizeof(DWORD), pcbLengthNeeded); - - case SFileInfoNameHash2: - return GetInfo(pvFileInfo, cbFileInfo, &hf->pHashEntry->dwName2, sizeof(DWORD), pcbLengthNeeded); - - case SFileInfoNameHash3: - return GetInfo(pvFileInfo, cbFileInfo, &pFileEntry->FileNameHash, sizeof(ULONGLONG), pcbLengthNeeded); - - case SFileInfoLocale: - dwInt32Value = hf->pHashEntry->lcLocale; - return GetInfo(pvFileInfo, cbFileInfo, &dwInt32Value, sizeof(DWORD), pcbLengthNeeded); - - case SFileInfoFileIndex: - dwInt32Value = (DWORD)(pFileEntry - hf->ha->pFileTable); - return GetInfo(pvFileInfo, cbFileInfo, &dwInt32Value, sizeof(DWORD), pcbLengthNeeded); - - case SFileInfoByteOffset: - return GetInfo(pvFileInfo, cbFileInfo, &pFileEntry->ByteOffset, sizeof(ULONGLONG), pcbLengthNeeded); - - case SFileInfoFileTime: - return GetInfo(pvFileInfo, cbFileInfo, &pFileEntry->FileTime, sizeof(ULONGLONG), pcbLengthNeeded); - - case SFileInfoFileSize: - return GetInfo(pvFileInfo, cbFileInfo, &pFileEntry->dwFileSize, sizeof(DWORD), pcbLengthNeeded); - - case SFileInfoCompressedSize: - return GetInfo(pvFileInfo, cbFileInfo, &pFileEntry->dwCmpSize, sizeof(DWORD), pcbLengthNeeded); - - case SFileInfoFlags: - return GetInfo(pvFileInfo, cbFileInfo, &pFileEntry->dwFlags, sizeof(DWORD), pcbLengthNeeded); - - case SFileInfoEncryptionKey: - return GetInfo(pvFileInfo, cbFileInfo, &hf->dwFileKey, sizeof(DWORD), pcbLengthNeeded); - - case SFileInfoEncryptionKeyRaw: - 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: - return GetInfo(pvFileInfo, cbFileInfo, &hf->pFileEntry->dwCrc32, sizeof(DWORD), pcbLengthNeeded); - } - - // Invalid info class - return GetInfo_ReturdwErrCode(ERROR_INVALID_PARAMETER); -} - -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") - {0x61754C1B, 0xFFFFFFFF, 0x00000000, 0x00000000, "lua"}, // Compiled LUA files - {0x20534444, 0xFFFFFFFF, 0x00000000, 0x00000000, "dds"}, // DDS textures - {0x43614C66, 0xFFFFFFFF, 0x00000000, 0x00000000, "flac"}, // FLAC sound files - {0x0000FBFF, 0x0000FFFF, 0x00000000, 0x00000000, "mp3"}, // MP3 sound files - {0x0000F3FF, 0x0000FFFF, 0x00000000, 0x00000000, "mp3"}, // MP3 sound files - {0x0000F2FF, 0x0000FFFF, 0x00000000, 0x00000000, "mp3"}, // MP3 sound files - {0x00334449, 0x00FFFFFF, 0x00000000, 0x00000000, "mp3"}, // MP3 sound files - {0x57334D48, 0xFFFFFFFF, 0x00000000, 0x00000000, "w3x"}, // Warcraft III map files, can also be w3m - {0x6F643357, 0xFFFFFFFF, 0x00000000, 0x00000000, "doo"}, // Warcraft III doodad files - {0x21453357, 0xFFFFFFFF, 0x00000000, 0x00000000, "w3e"}, // Warcraft III environment files - {0x5733504D, 0xFFFFFFFF, 0x00000000, 0x00000000, "wpm"}, // Warcraft III pathing map files - {0x21475457, 0xFFFFFFFF, 0x00000000, 0x00000000, "wtg"}, // Warcraft III trigger files - {0x00000000, 0x00000000, 0x00000000, 0x00000000, "xxx"}, // Default extension - {0, 0, 0, 0, NULL} // Terminator -}; - -static DWORD 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 - char szPseudoName[20]; - - // 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) - { - // Format the pseudo-name - StringCreatePseudoFileName(szPseudoName, _countof(szPseudoName), (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 - DWORD dwErrCode = 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) - dwErrCode = CreatePseudoFileName(hFile, pFileEntry, szFileName); - - // Copy the file name to the output buffer, if any - if(pFileEntry->szFileName && szFileName) - { - strcpy(szFileName, pFileEntry->szFileName); - dwErrCode = ERROR_SUCCESS; - } - } - } - - // For local files, copy the file name from the stream - else - { - if(szFileName != NULL) - { - const TCHAR * szStreamName = FileStream_GetFileName(hf->pStream); - StringCopy(szFileName, MAX_PATH, szStreamName); - } - dwErrCode = ERROR_SUCCESS; - } - } - - if(dwErrCode != ERROR_SUCCESS) - SetLastError(dwErrCode); - return (dwErrCode == ERROR_SUCCESS); -} - |
