+ StormLib 9.0 BETA

This commit is contained in:
Ladislav Zezula
2013-12-05 15:59:00 +01:00
parent ff0c25952a
commit c34c37b341
35 changed files with 5937 additions and 5946 deletions

View File

@@ -32,6 +32,33 @@ static bool IsAviFile(void * pvFileBegin)
return (DwordValue0 == 0x46464952 && DwordValue2 == 0x20495641 && DwordValue3 == 0x5453494C);
}
static TMPQUserData * IsValidMpqUserData(ULONGLONG ByteOffset, ULONGLONG FileSize, void * pvUserData)
{
TMPQUserData * pUserData;
// BSWAP the source data and copy them to our buffer
BSWAP_ARRAY32_UNSIGNED(&pvUserData, sizeof(TMPQUserData));
pUserData = (TMPQUserData *)pvUserData;
// Check the sizes
if(pUserData->cbUserDataHeader <= pUserData->cbUserDataSize && pUserData->cbUserDataSize <= pUserData->dwHeaderOffs)
{
// Move to the position given by the userdata
ByteOffset += pUserData->dwHeaderOffs;
// The MPQ header should be within range of the file size
if((ByteOffset + MPQ_HEADER_SIZE_V1) < FileSize)
{
// Note: We should verify if there is the MPQ header.
// However, the header could be at any position below that
// that is multiplier of 0x200
return (TMPQUserData *)pvUserData;
}
}
return NULL;
}
static TFileBitmap * CreateFileBitmap(TMPQArchive * ha, TMPQBitmap * pMpqBitmap, bool bFileIsComplete)
{
TFileBitmap * pBitmap;
@@ -144,6 +171,7 @@ bool WINAPI SFileOpenArchive(
DWORD dwFlags,
HANDLE * phMpq)
{
TMPQUserData * pUserData;
TFileStream * pStream = NULL; // Open file stream
TMPQArchive * ha = NULL; // Archive handle
TFileEntry * pFileEntry;
@@ -166,11 +194,18 @@ bool WINAPI SFileOpenArchive(
if(pStream == NULL)
nError = GetLastError();
}
// Allocate the MPQhandle
// Check the file size. There must be at least 0x20 bytes
if(nError == ERROR_SUCCESS)
{
FileStream_GetSize(pStream, &FileSize);
if(FileSize < MPQ_HEADER_SIZE_V1)
nError = ERROR_FILE_CORRUPT;
}
// Allocate the MPQhandle
if(nError == ERROR_SUCCESS)
{
if((ha = STORM_ALLOC(TMPQArchive, 1)) == NULL)
nError = ERROR_NOT_ENOUGH_MEMORY;
}
@@ -219,18 +254,18 @@ bool WINAPI SFileOpenArchive(
// If there is the MPQ user data signature, process it
dwHeaderID = BSWAP_INT32_UNSIGNED(*(LPDWORD)ha->HeaderData);
if(dwHeaderID == ID_MPQ_USERDATA && ha->pUserData == NULL)
if(dwHeaderID == ID_MPQ_USERDATA && ha->pUserData == NULL && (dwFlags & MPQ_OPEN_FORCE_MPQ_V1) == 0)
{
// Ignore the MPQ user data completely if the caller wants to open the MPQ as V1.0
if((dwFlags & MPQ_OPEN_FORCE_MPQ_V1) == 0)
// Verify if this looks like a valid user data
pUserData = IsValidMpqUserData(SearchPos, FileSize, ha->HeaderData);
if(pUserData != NULL)
{
// Fill the user data header
ha->pUserData = &ha->UserData;
memcpy(ha->pUserData, ha->HeaderData, sizeof(TMPQUserData));
BSWAP_TMPQUSERDATA(ha->pUserData);
// Remember the position of the user data and continue search
ha->UserDataPos = SearchPos;
ha->pUserData = &ha->UserData;
memcpy(ha->pUserData, pUserData, sizeof(TMPQUserData));
// Continue searching from that position
SearchPos += ha->pUserData->dwHeaderOffs;
continue;
}
@@ -266,9 +301,11 @@ bool WINAPI SFileOpenArchive(
// Did we identify one of the supported headers?
if(nError == ERROR_SUCCESS)
{
// Set the position of user data, header and file offset of the header
// Set the user data position to the MPQ header, if none
if(ha->pUserData == NULL)
ha->UserDataPos = SearchPos;
// Set the position of the MPQ header
ha->pHeader = (TMPQHeader *)ha->HeaderData;
ha->MpqPos = SearchPos;
@@ -285,7 +322,7 @@ bool WINAPI SFileOpenArchive(
// DumpMpqHeader(ha->pHeader);
// W3x Map Protectors use the fact that War3's Storm.dll ignores the MPQ user data,
// and probably ignores the MPQ format version as well. The trick is to
// and ignores the MPQ format version as well. The trick is to
// fake MPQ format 2, with an improper hi-word position of hash table and block table
// We can overcome such protectors by forcing opening the archive as MPQ v 1.0
if(dwFlags & MPQ_OPEN_FORCE_MPQ_V1)
@@ -336,13 +373,13 @@ bool WINAPI SFileOpenArchive(
// the block table, BET table, hi-block table, (attributes) and (listfile).
if(nError == ERROR_SUCCESS)
{
nError = BuildFileTable(ha, FileSize);
nError = BuildFileTable(ha);
}
// Verify the file table, if no kind of protection was detected
if(nError == ERROR_SUCCESS && (ha->dwFlags & MPQ_FLAG_PROTECTED) == 0)
{
TFileEntry * pFileTableEnd = ha->pFileTable + ha->pHeader->dwBlockTableSize;
TFileEntry * pFileTableEnd = ha->pFileTable + ha->dwFileTableSize;
ULONGLONG RawFilePos;
// Parse all file entries
@@ -379,10 +416,11 @@ bool WINAPI SFileOpenArchive(
// Save the flags for (listfile)
pFileEntry = GetFileEntryLocale(ha, LISTFILE_NAME, LANG_NEUTRAL);
if(pFileEntry != NULL)
{
// Ignore result of the operation. (listfile) is optional.
SFileAddListFile((HANDLE)ha, NULL);
ha->dwFileFlags1 = pFileEntry->dwFlags;
// Ignore result of the operation. (listfile) is optional.
SFileAddListFile((HANDLE)ha, NULL);
}
}
// Load the "(attributes)" file and merge it to the file table
@@ -391,10 +429,11 @@ bool WINAPI SFileOpenArchive(
// Save the flags for (attributes)
pFileEntry = GetFileEntryLocale(ha, ATTRIBUTES_NAME, LANG_NEUTRAL);
if(pFileEntry != NULL)
{
// Ignore result of the operation. (attributes) is optional.
SAttrLoadAttributes(ha);
ha->dwFileFlags2 = pFileEntry->dwFlags;
// Ignore result of the operation. (attributes) is optional.
SAttrLoadAttributes(ha);
}
}
// Cleanup and exit
@@ -436,12 +475,15 @@ bool WINAPI SFileFlushArchive(HANDLE hMpq)
int nError;
// Do nothing if 'hMpq' is bad parameter
if(!IsValidMpqHandle(ha))
if(!IsValidMpqHandle(hMpq))
{
SetLastError(ERROR_INVALID_HANDLE);
return false;
}
// Indicate that we are saving MPQ internal structures
ha->dwFlags |= MPQ_FLAG_SAVING_TABLES;
// If the (listfile) has been invalidated, save it
if(ha->dwFlags & MPQ_FLAG_LISTFILE_INVALID)
{
@@ -466,6 +508,9 @@ bool WINAPI SFileFlushArchive(HANDLE hMpq)
nResultError = nError;
}
// We are no longer saving internal MPQ structures
ha->dwFlags &= ~MPQ_FLAG_SAVING_TABLES;
// Return the error
if(nResultError != ERROR_SUCCESS)
SetLastError(nResultError);