aboutsummaryrefslogtreecommitdiff
path: root/src/SFileReadFile.cpp
diff options
context:
space:
mode:
authorLadislav Zezula <ladislav.zezula@avg.com>2013-12-05 15:59:00 +0100
committerLadislav Zezula <ladislav.zezula@avg.com>2013-12-05 15:59:00 +0100
commitc34c37b3418f1e5ab3678ce65d46f81803dec91d (patch)
tree4a9cf4c61634691981f9dc367b53dac4070f8d0d /src/SFileReadFile.cpp
parentff0c25952a28a927c48738ab5207b9bda69e588a (diff)
+ StormLib 9.0 BETA
Diffstat (limited to 'src/SFileReadFile.cpp')
-rw-r--r--src/SFileReadFile.cpp476
1 files changed, 11 insertions, 465 deletions
diff --git a/src/SFileReadFile.cpp b/src/SFileReadFile.cpp
index 6eb0d10..cfc8d2a 100644
--- a/src/SFileReadFile.cpp
+++ b/src/SFileReadFile.cpp
@@ -14,103 +14,8 @@
#include "StormCommon.h"
//-----------------------------------------------------------------------------
-// Local structures
-
-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
-};
-
-//-----------------------------------------------------------------------------
// 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 GetFilePatchChain(TMPQFile * hf, void * pvFileInfo, DWORD cbFileInfo, LPDWORD pcbLengthNeeded)
-{
- TMPQFile * hfTemp;
- TCHAR * szPatchChain = (TCHAR *)pvFileInfo;
- TCHAR * szFileName;
- size_t cchCharsNeeded = 1;
- size_t nLength;
- DWORD cbLengthNeeded;
-
- // Check if the "hf" is a MPQ file
- if(hf->pStream != NULL)
- {
- // Calculate the length needed
- szFileName = FileStream_GetFileName(hf->pStream);
- cchCharsNeeded += _tcslen(szFileName) + 1;
- cbLengthNeeded = (DWORD)(cchCharsNeeded * sizeof(TCHAR));
-
- // If we have enough space, copy the file name
- if(cbFileInfo >= cbLengthNeeded)
- {
- nLength = _tcslen(szFileName) + 1;
- memcpy(szPatchChain, szFileName, nLength * sizeof(TCHAR));
- szPatchChain += nLength;
-
- // Terminate the multi-string
- *szPatchChain = 0;
- }
- }
- else
- {
- // Calculate number of characters needed
- for(hfTemp = hf; hfTemp != NULL; hfTemp = hfTemp->hfPatchFile)
- cchCharsNeeded += _tcslen(FileStream_GetFileName(hfTemp->ha->pStream)) + 1;
- cbLengthNeeded = (DWORD)(cchCharsNeeded * sizeof(TCHAR));
-
- // If we have enough space, the copy the patch chain
- if(cbFileInfo >= cbLengthNeeded)
- {
- for(hfTemp = hf; hfTemp != NULL; hfTemp = hfTemp->hfPatchFile)
- {
- szFileName = FileStream_GetFileName(hfTemp->ha->pStream);
- nLength = _tcslen(szFileName) + 1;
- memcpy(szPatchChain, szFileName, nLength * sizeof(TCHAR));
- szPatchChain += nLength;
- }
-
- // Terminate the multi-string
- *szPatchChain = 0;
- }
- }
-
- // Give result length, terminate multi-string and return
- *pcbLengthNeeded = cbLengthNeeded;
- return true;
-}
-
// hf - MPQ File handle.
// pbBuffer - Pointer to target buffer to store sectors.
// dwByteOffset - Position of sector in the file (relative to file begin)
@@ -453,7 +358,12 @@ static int ReadMpkFileSingleUnit(TMPQFile * hf, void * pvBuffer, DWORD dwFilePos
nError = AllocateSectorBuffer(hf);
if(nError != ERROR_SUCCESS)
return nError;
+ pbRawData = hf->pbFileSector;
+ }
+ // If the file sector is not loaded yet, do it
+ if(hf->dwSectorOffs != 0)
+ {
// Is the file compressed?
if(pFileEntry->dwFlags & MPQ_FILE_COMPRESS_MASK)
{
@@ -750,7 +660,7 @@ bool WINAPI SFileReadFile(HANDLE hFile, void * pvBuffer, DWORD dwToRead, LPDWORD
lpOverlapped = lpOverlapped;
// Check valid parameters
- if(!IsValidFileHandle(hf))
+ if(!IsValidFileHandle(hFile))
{
SetLastError(ERROR_INVALID_HANDLE);
return false;
@@ -769,7 +679,7 @@ bool WINAPI SFileReadFile(HANDLE hFile, void * pvBuffer, DWORD dwToRead, LPDWORD
}
// If the file is a patch file, we have to read it special way
- else if(hf->hfPatchFile != NULL && (hf->pFileEntry->dwFlags & MPQ_FILE_PATCH_FILE) == 0)
+ else if(hf->hfPatch != NULL && (hf->pFileEntry->dwFlags & MPQ_FILE_PATCH_FILE) == 0)
{
nError = ReadMpqFilePatchFile(hf, pvBuffer, hf->dwFilePos, dwToRead, &dwBytesRead);
}
@@ -819,13 +729,13 @@ DWORD WINAPI SFileGetFileSize(HANDLE hFile, LPDWORD pdwFileSizeHigh)
TMPQFile * hf = (TMPQFile *)hFile;
// Validate the file handle before we go on
- if(IsValidFileHandle(hf))
+ if(IsValidFileHandle(hFile))
{
// Make sure that the variable is initialized
FileSize = 0;
// If the file is patched file, we have to get the size of the last version
- if(hf->hfPatchFile != NULL)
+ if(hf->hfPatch != NULL)
{
// Walk through the entire patch chain, take the last version
while(hf != NULL)
@@ -834,7 +744,7 @@ DWORD WINAPI SFileGetFileSize(HANDLE hFile, LPDWORD pdwFileSizeHigh)
FileSize = hf->pFileEntry->dwFileSize;
// Move to the next patch file in the hierarchy
- hf = hf->hfPatchFile;
+ hf = hf->hfPatch;
}
}
else
@@ -868,7 +778,7 @@ DWORD WINAPI SFileSetFilePointer(HANDLE hFile, LONG lFilePos, LONG * plFilePosHi
DWORD dwFilePosHi;
// If the hFile is not a valid file handle, return an error.
- if(!IsValidFileHandle(hf))
+ if(!IsValidFileHandle(hFile))
{
SetLastError(ERROR_INVALID_HANDLE);
return SFILE_INVALID_POS;
@@ -954,367 +864,3 @@ DWORD WINAPI SFileSetFilePointer(HANDLE hFile, LONG lFilePos, LONG * plFilePosHi
}
}
-//-----------------------------------------------------------------------------
-// Tries to retrieve the file name
-
-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
- {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(pFileEntry, szPseudoName);
-
- // If the caller wants to copy the file name, do it
- if(szFileName != NULL)
- strcpy(szFileName, szPseudoName);
- return ERROR_SUCCESS;
- }
- }
- }
-
- return ERROR_NOT_SUPPORTED;
-}
-
-bool WINAPI SFileGetFileName(HANDLE hFile, char * szFileName)
-{
- TMPQFile * hf = (TMPQFile *)hFile; // MPQ File handle
- TCHAR * szFileNameT;
- int nError = ERROR_INVALID_HANDLE;
-
- // Pre-zero the output buffer
- if(szFileName != NULL)
- *szFileName = 0;
-
- // Check valid parameters
- if(IsValidFileHandle(hf))
- {
- 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);
- }
- else
- {
- if(szFileName != NULL)
- strcpy(szFileName, pFileEntry->szFileName);
- nError = ERROR_SUCCESS;
- }
- }
- }
-
- // For local files, copy the file name from the stream
- else
- {
- if(szFileName != NULL)
- {
- szFileNameT = FileStream_GetFileName(hf->pStream);
- CopyFileName(szFileName, szFileNameT, _tcslen(szFileNameT));
- }
- nError = ERROR_SUCCESS;
- }
- }
-
- if(nError != ERROR_SUCCESS)
- SetLastError(nError);
- return (nError == ERROR_SUCCESS);
-}
-
-//-----------------------------------------------------------------------------
-// Retrieves an information about an archive or about a file within the archive
-//
-// hMpqOrFile - Handle to an MPQ archive or to a file
-// dwInfoType - Information to obtain
-
-#define VERIFY_MPQ_HANDLE(h) \
- if(!IsValidMpqHandle(h)) \
- { \
- nError = ERROR_INVALID_HANDLE; \
- break; \
- }
-
-#define VERIFY_FILE_HANDLE(h) \
- if(!IsValidFileHandle(h)) \
- { \
- nError = ERROR_INVALID_HANDLE; \
- break; \
- }
-
-bool WINAPI SFileGetFileInfo(
- HANDLE hMpqOrFile,
- DWORD dwInfoType,
- void * pvFileInfo,
- DWORD cbFileInfo,
- LPDWORD pcbLengthNeeded)
-{
- TMPQArchive * ha = (TMPQArchive *)hMpqOrFile;
- TMPQBlock * pBlock;
- TMPQFile * hf = (TMPQFile *)hMpqOrFile;
- void * pvSrcFileInfo = NULL;
- DWORD cbLengthNeeded = 0;
- DWORD dwIsReadOnly;
- DWORD dwFileCount = 0;
- DWORD dwFileIndex;
- DWORD dwFileKey;
- DWORD i;
- int nError = ERROR_SUCCESS;
-
- switch(dwInfoType)
- {
- case SFILE_INFO_ARCHIVE_NAME:
- VERIFY_MPQ_HANDLE(ha);
-
- // pvFileInfo receives the name of the archive, terminated by 0
- pvSrcFileInfo = FileStream_GetFileName(ha->pStream);
- cbLengthNeeded = (DWORD)(_tcslen((TCHAR *)pvSrcFileInfo) + 1) * sizeof(TCHAR);
- break;
-
- case SFILE_INFO_ARCHIVE_SIZE: // Size of the archive
- VERIFY_MPQ_HANDLE(ha);
- cbLengthNeeded = sizeof(DWORD);
- pvSrcFileInfo = &ha->pHeader->dwArchiveSize;
- break;
-
- case SFILE_INFO_MAX_FILE_COUNT: // Max. number of files in the MPQ
- VERIFY_MPQ_HANDLE(ha);
- cbLengthNeeded = sizeof(DWORD);
- pvSrcFileInfo = &ha->dwMaxFileCount;
- break;
-
- case SFILE_INFO_HASH_TABLE_SIZE: // Size of the hash table
- VERIFY_MPQ_HANDLE(ha);
- cbLengthNeeded = sizeof(DWORD);
- pvSrcFileInfo = &ha->pHeader->dwHashTableSize;
- break;
-
- case SFILE_INFO_BLOCK_TABLE_SIZE: // Size of the block table
- VERIFY_MPQ_HANDLE(ha);
- cbLengthNeeded = sizeof(DWORD);
- pvSrcFileInfo = &ha->pHeader->dwBlockTableSize;
- break;
-
- case SFILE_INFO_SECTOR_SIZE:
- VERIFY_MPQ_HANDLE(ha);
- cbLengthNeeded = sizeof(DWORD);
- pvSrcFileInfo = &ha->dwSectorSize;
- break;
-
- case SFILE_INFO_HASH_TABLE:
- VERIFY_MPQ_HANDLE(ha);
- cbLengthNeeded = ha->pHeader->dwHashTableSize * sizeof(TMPQHash);
- pvSrcFileInfo = ha->pHashTable;
- break;
-
- case SFILE_INFO_BLOCK_TABLE:
- VERIFY_MPQ_HANDLE(ha);
- cbLengthNeeded = ha->dwFileTableSize * sizeof(TMPQBlock);
- if(cbFileInfo < cbLengthNeeded)
- {
- nError = ERROR_INSUFFICIENT_BUFFER;
- break;
- }
-
- // Construct block table from file table size
- pBlock = (TMPQBlock *)pvFileInfo;
- for(i = 0; i < ha->dwFileTableSize; i++)
- {
- pBlock->dwFilePos = (DWORD)ha->pFileTable[i].ByteOffset;
- pBlock->dwFSize = ha->pFileTable[i].dwFileSize;
- pBlock->dwCSize = ha->pFileTable[i].dwCmpSize;
- pBlock->dwFlags = ha->pFileTable[i].dwFlags;
- pBlock++;
- }
- break;
-
- case SFILE_INFO_NUM_FILES:
- VERIFY_MPQ_HANDLE(ha);
- dwFileCount = GetMpqFileCount(ha);
- cbLengthNeeded = sizeof(DWORD);
- pvSrcFileInfo = &dwFileCount;
- break;
-
- case SFILE_INFO_STREAM_FLAGS:
- VERIFY_MPQ_HANDLE(ha);
- FileStream_GetFlags(ha->pStream, &dwFileKey);
- cbLengthNeeded = sizeof(DWORD);
- pvSrcFileInfo = &dwFileKey;
- break;
-
- case SFILE_INFO_IS_READ_ONLY:
- VERIFY_MPQ_HANDLE(ha);
- dwIsReadOnly = (FileStream_IsReadOnly(ha->pStream) || (ha->dwFlags & MPQ_FLAG_READ_ONLY));
- cbLengthNeeded = sizeof(DWORD);
- pvSrcFileInfo = &dwIsReadOnly;
- break;
-
- case SFILE_INFO_HASH_INDEX:
- VERIFY_FILE_HANDLE(hf);
- cbLengthNeeded = sizeof(DWORD);
- pvSrcFileInfo = &hf->pFileEntry->dwHashIndex;
- break;
-
- case SFILE_INFO_CODENAME1:
- VERIFY_FILE_HANDLE(hf);
- cbLengthNeeded = sizeof(DWORD);
- pvSrcFileInfo = &hf->pFileEntry->dwHashIndex;
- if(ha->pHashTable != NULL)
- pvSrcFileInfo = &ha->pHashTable[hf->pFileEntry->dwHashIndex].dwName1;
- break;
-
- case SFILE_INFO_CODENAME2:
- VERIFY_FILE_HANDLE(hf);
- cbLengthNeeded = sizeof(DWORD);
- if(ha->pHashTable != NULL)
- pvSrcFileInfo = &ha->pHashTable[hf->pFileEntry->dwHashIndex].dwName2;
- break;
-
- case SFILE_INFO_LOCALEID:
- VERIFY_FILE_HANDLE(hf);
- cbLengthNeeded = sizeof(DWORD);
- pvSrcFileInfo = &hf->pFileEntry->lcLocale;
- break;
-
- case SFILE_INFO_BLOCKINDEX:
- VERIFY_FILE_HANDLE(hf);
- dwFileIndex = (DWORD)(hf->pFileEntry - hf->ha->pFileTable);
- cbLengthNeeded = sizeof(DWORD);
- pvSrcFileInfo = &dwFileIndex;
- break;
-
- case SFILE_INFO_FILE_SIZE:
- VERIFY_FILE_HANDLE(hf);
- cbLengthNeeded = sizeof(DWORD);
- pvSrcFileInfo = &hf->pFileEntry->dwFileSize;
- break;
-
- case SFILE_INFO_COMPRESSED_SIZE:
- VERIFY_FILE_HANDLE(hf);
- cbLengthNeeded = sizeof(DWORD);
- pvSrcFileInfo = &hf->pFileEntry->dwCmpSize;
- break;
-
- case SFILE_INFO_FLAGS:
- VERIFY_FILE_HANDLE(hf);
- cbLengthNeeded = sizeof(DWORD);
- pvSrcFileInfo = &hf->pFileEntry->dwFlags;
- break;
-
- case SFILE_INFO_POSITION:
- VERIFY_FILE_HANDLE(hf);
- cbLengthNeeded = sizeof(ULONGLONG);
- pvSrcFileInfo = &hf->pFileEntry->ByteOffset;
- break;
-
- case SFILE_INFO_KEY:
- VERIFY_FILE_HANDLE(hf);
- cbLengthNeeded = sizeof(DWORD);
- pvSrcFileInfo = &hf->dwFileKey;
- break;
-
- case SFILE_INFO_KEY_UNFIXED:
- VERIFY_FILE_HANDLE(hf);
- dwFileKey = hf->dwFileKey;
- if(hf->pFileEntry->dwFlags & MPQ_FILE_FIX_KEY)
- dwFileKey = (dwFileKey ^ hf->pFileEntry->dwFileSize) - (DWORD)hf->MpqFilePos;
- cbLengthNeeded = sizeof(DWORD);
- pvSrcFileInfo = &dwFileKey;
- break;
-
- case SFILE_INFO_FILETIME:
- VERIFY_FILE_HANDLE(hf);
- cbLengthNeeded = sizeof(ULONGLONG);
- pvSrcFileInfo = &hf->pFileEntry->FileTime;
- break;
-
- case SFILE_INFO_PATCH_CHAIN:
- VERIFY_FILE_HANDLE(hf);
- GetFilePatchChain(hf, pvFileInfo, cbFileInfo, &cbLengthNeeded);
- break;
-
- default:
- nError = ERROR_INVALID_PARAMETER;
- break;
- }
-
- // If everything is OK so far, copy the information
- if(nError == ERROR_SUCCESS)
- {
- // Is the output buffer large enough?
- if(cbFileInfo >= cbLengthNeeded)
- {
- // Copy the data
- if(pvSrcFileInfo != NULL)
- memcpy(pvFileInfo, pvSrcFileInfo, cbLengthNeeded);
- }
- else
- {
- nError = ERROR_INSUFFICIENT_BUFFER;
- }
-
- // Give the size to the caller
- if(pcbLengthNeeded != NULL)
- *pcbLengthNeeded = cbLengthNeeded;
- }
-
- // Set the last error value, if needed
- if(nError != ERROR_SUCCESS)
- SetLastError(nError);
- return (nError == ERROR_SUCCESS);
-}