X-Git-Url: https://sfsrealm.hopto.org/projects/?a=blobdiff_plain;f=SFmpqapi.cpp;h=628d29fb2bfd204a9e8f391fc8a5610e3694a23b;hb=033f7f171bfdddc8a0db52fd03f932792c26f2dd;hp=0579c2c226e6d7efc936f6198218f2241297ba58;hpb=631cb94e7243815e465e454c965b6adcd0153d54;p=SFmpqapi.git diff --git a/SFmpqapi.cpp b/SFmpqapi.cpp index 0579c2c..628d29f 100644 --- a/SFmpqapi.cpp +++ b/SFmpqapi.cpp @@ -4,7 +4,6 @@ // Includes #include -#include #include #include #include @@ -14,7 +13,13 @@ #include "../SComp/SComp.h" +#include "SFmpqInternal.h" +#include "MpqCrypt.h" +#include "MpqHashTable.h" +#include "MpqBlockTable.h" #include "SFmpqapi.h" +#include "SFUtil.h" +#include "SFTypes.h" struct SFMPQAPIMODULE { SFMPQAPIMODULE(); @@ -49,6 +54,7 @@ SFMPQLIBMODULE::~SFMPQLIBMODULE() #endif LCID LocaleID = 0; +WORD wCreationVersion = 0; BOOL SFMpqInit = FALSE; HINSTANCE hStorm = 0; #ifdef _USRDLL @@ -88,15 +94,6 @@ LCID availLocales[7] = {0x0000,0x0407,0x0409,0x040A,0x040C,0x0410,0x0416}; #define MAX_MPQ_PATH 260; -#define HASH_POSITION 0 -#define HASH_NAME_A 1 -#define HASH_NAME_B 2 -#define HASH_KEY 3 - -BOOL bCryptTableInit = FALSE; -DWORD dwCryptTable[0x500]; -DWORD dwHashTableKey; -DWORD dwBlockTableKey; MPQARCHIVE **lpOpenMpq = 0; DWORD dwOpenMpqCount = 0; MPQARCHIVE * FirstLastMpq[2] = {0,0}; @@ -106,9 +103,6 @@ MPQFILE * FirstLastFile[2] = {0,0}; char StormBasePath[MAX_PATH+1]; -#define UNSUPPORTED_COMPRESSION (0xFF ^ (0x40 | 0x80 | 0x01 | 0x02 | 0x08 | 0x10)) -#define UNSUPPORTED_DECOMPRESSION (0xFF ^ (0x40 | 0x80 | 0x01 | 0x02 | 0x08 | 0x10)) - typedef BOOL (WINAPI* funcSCompCompress)(LPVOID lpvDestinationMem, LPDWORD lpdwCompressedSize, LPVOID lpvSourceMem, DWORD dwDecompressedSize, DWORD dwCompressionType, DWORD dwCompressionSubType, DWORD dwWAVQuality); typedef BOOL (WINAPI* funcSCompDecompress)(LPVOID lpvDestinationMem, LPDWORD lpdwDecompressedSize, LPVOID lpvSourceMem, DWORD dwCompressedSize); funcSCompCompress stormSCompCompress = 0; @@ -117,11 +111,8 @@ funcSCompDecompress stormSCompDecompress = 0; void LoadStorm(); void FreeStorm(); -LPVOID WINAPI SFAlloc(DWORD dwSize); -void WINAPI SFFree(LPVOID lpvMemory); -void WINAPI SFMemZero(LPVOID lpvDestination, DWORD dwLength); BOOL WINAPI MpqOpenArchiveEx(LPCSTR lpFileName, DWORD dwPriority, DWORD dwFlags, MPQHANDLE *hMPQ, DWORD dwFlags2, DWORD dwMaximumFilesInArchive, DWORD dwBlockSize); -DWORD WINAPI FindMpqHeaderAtLocation(HANDLE hFile, DWORD dwStart, DWORD dwLength); +UInt64 WINAPI SFileFindMpqHeaderEx(HANDLE hFile, UInt64 qwStart = 0, UInt64 qwLength = 0); DWORD GetFullPath(LPCSTR lpFileName, char *lpBuffer, DWORD dwBufferLength); MPQHANDLE GetHashTableEntry(MPQHANDLE hMPQ, LPCSTR lpFileName, LCID FileLocale); MPQHANDLE GetHashTableEntryOfHash(MPQHANDLE hMPQ, DWORD dwTablePos, DWORD dwNameHashA, DWORD dwNameHashB, LCID FileLocale); @@ -131,13 +122,6 @@ void SortOpenArchivesByPriority(); DWORD GetHandleType(MPQHANDLE hFile); BOOL AddToInternalListing(MPQHANDLE hMPQ, LPCSTR lpFileName); BOOL RemoveFromInternalListing(MPQHANDLE hMPQ, LPCSTR lpFileName); -size_t strlnlen(const char *strline); -char *nextline(const char *strline); -BOOL InitCryptTable(); -DWORD HashString(LPCSTR lpszString, DWORD dwHashType); -BOOL EncryptData(LPBYTE lpbyBuffer, DWORD dwLength, DWORD dwKey); -BOOL DecryptData(LPBYTE lpbyBuffer, DWORD dwLength, DWORD dwKey); -static DWORD DetectFileSeed(DWORD * block, DWORD decrypted, DWORD blocksize); DWORD DetectFileSeedEx(MPQARCHIVE * mpqOpenArc, HASHTABLEENTRY * lpHashEntry, LPCSTR * lplpFileName); BOOL APIENTRY DllMain( HINSTANCE hInstDLL, @@ -204,38 +188,6 @@ BOOL APIENTRY DllMain( HINSTANCE hInstDLL, return TRUE; } -LPVOID WINAPI SFAlloc(DWORD dwSize) -{ - LPVOID lpMemory = malloc(dwSize); - if (lpMemory) SFMemZero(lpMemory,dwSize); - return lpMemory; -} - -void WINAPI SFFree(LPVOID lpvMemory) -{ - if (lpvMemory) free(lpvMemory); -} - -void WINAPI SFMemZero(LPVOID lpvDestination, DWORD dwLength) -{ - DWORD dwPrevLen = dwLength; - LPDWORD lpdwDestination = (LPDWORD)lpvDestination; - LPBYTE lpbyDestination; - - dwLength >>= 2; - - while (dwLength--) - *lpdwDestination++ = 0; - - lpbyDestination = (LPBYTE)lpdwDestination; - - dwLength = dwPrevLen; - dwLength &= 3; - - while (dwLength--) - *lpbyDestination++ = 0; -} - TempAlloc::TempAlloc() { lpAllocAddress = 0; @@ -334,18 +286,155 @@ void SFMPQAPI WINAPI AboutSFMpq() #endif } -BOOL WINAPI MpqOpenArchiveEx(LPCSTR lpFileName, DWORD dwPriority, DWORD dwFlags, MPQHANDLE *hMPQ, DWORD dwFlags2, DWORD dwMaximumFilesInArchive, DWORD dwBlockSize) +BOOL MpqWriteHeaders(MPQARCHIVE *mpqOpenArc) { - DWORD flen,tsz; + DWORD nIOLen; + BOOL bReturnVal = FALSE; + + SFSetFilePointer(mpqOpenArc->hFile, mpqOpenArc->qwMPQStart, FILE_BEGIN); + bReturnVal = WriteFile(mpqOpenArc->hFile, &mpqOpenArc->MpqHeader, sizeof(MPQHEADER), &nIOLen, 0); + + if (bReturnVal && mpqOpenArc->MpqHeader.wVersion > 0) { + bReturnVal = WriteFile(mpqOpenArc->hFile, &mpqOpenArc->MpqHeader_Ex, sizeof(MPQHEADER_EX), &nIOLen, 0); + } + + return bReturnVal; +} + +BOOL MpqWriteNewArchive(MPQARCHIVE *mpqOpenArc) +{ + DWORD nIOLen; + + memcpy(&mpqOpenArc->MpqHeader.dwMPQID,ID_MPQ,4); + mpqOpenArc->MpqHeader.wVersion = wCreationVersion; + + if (mpqOpenArc->MpqHeader.wVersion == 0) + mpqOpenArc->MpqHeader.dwHeaderSize = sizeof(MPQHEADER); + else + mpqOpenArc->MpqHeader.dwHeaderSize = sizeof(MPQHEADER) + sizeof(MPQHEADER_EX); + mpqOpenArc->dwHeaderSize = mpqOpenArc->MpqHeader.dwHeaderSize; + + if (mpqOpenArc->MpqHeader.wBlockSize & 0xFFFF0000) + mpqOpenArc->MpqHeader.wBlockSize = DEFAULT_BLOCK_SIZE; + DWORD i; + for (i=1;iMpqHeader.dwHashTableSize;i*=2) {} + mpqOpenArc->MpqHeader.dwHashTableSize = i; + mpqOpenArc->MpqHeader.dwBlockTableSize = 0; + mpqOpenArc->MpqHeader.dwHashTableOffset = mpqOpenArc->dwHeaderSize; + mpqOpenArc->MpqHeader.dwBlockTableOffset = mpqOpenArc->dwHeaderSize + mpqOpenArc->MpqHeader.dwHashTableSize * sizeof(HASHTABLEENTRY); + mpqOpenArc->MpqHeader_Ex.qwExtendedBlockOffsetTable = 0; + mpqOpenArc->MpqHeader_Ex.wHashTableOffsetHigh = 0; + mpqOpenArc->MpqHeader_Ex.wBlockTableOffsetHigh = 0; + mpqOpenArc->MpqHeader.dwMPQSize = mpqOpenArc->dwHeaderSize + mpqOpenArc->MpqHeader.dwHashTableSize * sizeof(HASHTABLEENTRY); + + if (!MpqWriteHeaders(mpqOpenArc)) + return FALSE; + + mpqOpenArc->lpHashTable = (HASHTABLEENTRY *)SFAlloc(sizeof(HASHTABLEENTRY) * mpqOpenArc->MpqHeader.dwHashTableSize); + if (!mpqOpenArc->lpHashTable) { + return FALSE; + } + memset(mpqOpenArc->lpHashTable, 0xFF, sizeof(HASHTABLEENTRY) * mpqOpenArc->MpqHeader.dwHashTableSize); + EncryptData((LPBYTE)mpqOpenArc->lpHashTable, sizeof(HASHTABLEENTRY) * mpqOpenArc->MpqHeader.dwHashTableSize, dwHashTableKey); + if (!WriteFile(mpqOpenArc->hFile, mpqOpenArc->lpHashTable, sizeof(HASHTABLEENTRY) * mpqOpenArc->MpqHeader.dwHashTableSize, &nIOLen, 0)) { + return FALSE; + } + return TRUE; +} + +BOOL MpqReadExistingArchive(MPQARCHIVE *mpqOpenArc) +{ + DWORD nIOLen; + + SFSetFilePointer(mpqOpenArc->hFile, mpqOpenArc->qwMPQStart, FILE_BEGIN); + if (!ReadFile(mpqOpenArc->hFile, &mpqOpenArc->MpqHeader, sizeof(MPQHEADER), &nIOLen, 0)) + return FALSE; + + if (mpqOpenArc->MpqHeader.wVersion > 0) { + mpqOpenArc->dwHeaderSize = sizeof(MPQHEADER) + sizeof(MPQHEADER_EX); + if (!ReadFile(mpqOpenArc->hFile, &mpqOpenArc->MpqHeader_Ex, sizeof(MPQHEADER_EX), &nIOLen, 0)) + return FALSE; + } + else { + mpqOpenArc->dwHeaderSize = sizeof(MPQHEADER); + memset(&mpqOpenArc->MpqHeader_Ex, 0, sizeof(MPQHEADER_EX)); + } + + mpqOpenArc->lpHashTable = (HASHTABLEENTRY *)SFAlloc(sizeof(HASHTABLEENTRY) * mpqOpenArc->MpqHeader.dwHashTableSize); + if (!mpqOpenArc->lpHashTable) + return FALSE; + + if (mpqOpenArc->MpqHeader.dwBlockTableSize) { + mpqOpenArc->lpBlockTable = (BLOCKTABLEENTRY *)SFAlloc((sizeof(BLOCKTABLEENTRY) + sizeof(UInt16)) * mpqOpenArc->MpqHeader.dwBlockTableSize); + mpqOpenArc->lpFileOffsetsHigh = (UInt16 *)(mpqOpenArc->lpBlockTable + mpqOpenArc->MpqHeader.dwBlockTableSize); + if (!mpqOpenArc->lpBlockTable) + return FALSE; + } + + SFSetFilePointer(mpqOpenArc->hFile, mpqOpenArc->qwMPQStart + MakeUInt64(mpqOpenArc->MpqHeader.dwHashTableOffset, mpqOpenArc->MpqHeader_Ex.wHashTableOffsetHigh), FILE_BEGIN); + if (!ReadFile(mpqOpenArc->hFile, mpqOpenArc->lpHashTable, sizeof(HASHTABLEENTRY) * mpqOpenArc->MpqHeader.dwHashTableSize, &nIOLen, 0)) + return FALSE; + + if (mpqOpenArc->MpqHeader.dwBlockTableSize) { + SFSetFilePointer(mpqOpenArc->hFile, mpqOpenArc->qwMPQStart + MakeUInt64(mpqOpenArc->MpqHeader.dwBlockTableOffset, mpqOpenArc->MpqHeader_Ex.wBlockTableOffsetHigh), FILE_BEGIN); + if (!ReadFile(mpqOpenArc->hFile, mpqOpenArc->lpBlockTable, sizeof(BLOCKTABLEENTRY) * mpqOpenArc->MpqHeader.dwBlockTableSize, &nIOLen, 0)) + return FALSE; + + if (mpqOpenArc->MpqHeader_Ex.qwExtendedBlockOffsetTable) { + SFSetFilePointer(mpqOpenArc->hFile, mpqOpenArc->qwMPQStart + mpqOpenArc->MpqHeader_Ex.qwExtendedBlockOffsetTable, FILE_BEGIN); + if (!ReadFile(mpqOpenArc->hFile, mpqOpenArc->lpFileOffsetsHigh, sizeof(WORD) * mpqOpenArc->MpqHeader.dwBlockTableSize, &nIOLen, 0)) + return FALSE; + } + } + + return TRUE; +} + +BOOL MpqOpenArchiveInit(MPQARCHIVE *mpqOpenArc, LPCSTR lpFileName, DWORD dwPriority, DWORD dwFlags1, DWORD dwFlags2, DWORD dwExtraFlags) +{ + /*mpqOpenArc->lpFileName = (char *)SFAlloc(strlen(lpFileName)+1); + if(!mpqOpenArc->lpFileName) + return FALSE;*/ + DecryptData((LPBYTE)mpqOpenArc->lpHashTable,sizeof(HASHTABLEENTRY) * mpqOpenArc->MpqHeader.dwHashTableSize,dwHashTableKey); + if (mpqOpenArc->lpBlockTable) DecryptData((LPBYTE)mpqOpenArc->lpBlockTable,sizeof(BLOCKTABLEENTRY) * mpqOpenArc->MpqHeader.dwBlockTableSize,dwBlockTableKey); + mpqOpenArc->lpFileName = mpqOpenArc->szFileName; + strncpy(mpqOpenArc->lpFileName,lpFileName,259); + if (FirstLastMpq[1]) FirstLastMpq[1]->lpNextArc = mpqOpenArc; + mpqOpenArc->lpNextArc = (MPQARCHIVE *)FirstLastMpq; + mpqOpenArc->lpPrevArc = (MPQARCHIVE *)FirstLastMpq[1]; + if (!FirstLastMpq[0]) { + mpqOpenArc->lpPrevArc = (MPQARCHIVE *)0xEAFC5E23; + FirstLastMpq[0] = mpqOpenArc; + } + FirstLastMpq[1] = mpqOpenArc; + mpqOpenArc->dwFlags1 = dwFlags1; + mpqOpenArc->dwPriority = dwPriority; + mpqOpenArc->lpLastReadFile = 0; + mpqOpenArc->dwUnk = 0; + mpqOpenArc->dwBlockSize = 512 << mpqOpenArc->MpqHeader.wBlockSize; + mpqOpenArc->lpLastReadBlock = 0; + mpqOpenArc->dwBufferSize = 0; + mpqOpenArc->qwMPQEnd = mpqOpenArc->qwMPQStart + mpqOpenArc->MpqHeader.dwMPQSize; + mpqOpenArc->lpMPQHeader = &mpqOpenArc->MpqHeader; + mpqOpenArc->qwReadOffset = mpqOpenArc->qwMPQEnd; + mpqOpenArc->dwRefCount = 1; + mpqOpenArc->dwFlags = dwFlags2; + mpqOpenArc->dwExtraFlags = dwExtraFlags; + + return TRUE; +} + +BOOL WINAPI MpqOpenArchiveEx(LPCSTR lpFileName, DWORD dwPriority, DWORD dwFlags, MPQHANDLE *hMPQ, DWORD dwFlags2, DWORD dwMaximumFilesInArchive, DWORD dwBlockSize) +{ if (!lpFileName || !hMPQ) { SetLastError(ERROR_INVALID_PARAMETER); - if (hMPQ) *hMPQ = 0; + if (hMPQ) *hMPQ = (MPQHANDLE)INVALID_HANDLE_VALUE; return FALSE; } + *hMPQ = (MPQHANDLE)INVALID_HANDLE_VALUE; if (!*lpFileName) { SetLastError(ERROR_INVALID_PARAMETER); - *hMPQ = 0; return FALSE; } @@ -365,7 +454,7 @@ BOOL WINAPI MpqOpenArchiveEx(LPCSTR lpFileName, DWORD dwPriority, DWORD dwFlags, else if (dwFlags&2) dwFlags1 |= 1; if (dwFlags & SFILE_OPEN_CD_ROM_FILE) - if (!(dwFlags1&2)) {*hMPQ = 0;return FALSE;} + if (!(dwFlags1&2)) {return FALSE;} #endif DWORD dwCreateFlags,dwAccessFlags,dwShareFlags; @@ -376,7 +465,6 @@ BOOL WINAPI MpqOpenArchiveEx(LPCSTR lpFileName, DWORD dwPriority, DWORD dwFlags, if (dwFlags2 & MOAU_READ_ONLY) { if (!(dwFlags2 & MOAU_OPEN_EXISTING)) { SetLastError(MPQ_ERROR_BAD_OPEN_MODE); - *hMPQ = 0; return FALSE; } dwAccessFlags = GENERIC_READ; @@ -403,169 +491,71 @@ BOOL WINAPI MpqOpenArchiveEx(LPCSTR lpFileName, DWORD dwPriority, DWORD dwFlags, if (hFile!=INVALID_HANDLE_VALUE) { MPQARCHIVE **lpnOpenMpq = (MPQARCHIVE **)SFAlloc(sizeof(MPQARCHIVE *) * (dwOpenMpqCount+1)); - if (lpnOpenMpq==0) { + if (!lpnOpenMpq) { CloseHandle(hFile); - *hMPQ = 0; return FALSE; } - DWORD dwMpqStart; MPQARCHIVE *mpqOpenArc; - if (GetFileSize(hFile,0)==0 && !(dwFlags2 & MOAU_READ_ONLY)) + if (SFGetFileSize(hFile)==0 && !(dwFlags2 & MOAU_READ_ONLY)) { - dwMpqStart = 0; mpqOpenArc = (MPQARCHIVE *)SFAlloc(sizeof(MPQARCHIVE)); if (!mpqOpenArc) { SFFree(lpnOpenMpq); CloseHandle(hFile); - *hMPQ = 0; return FALSE; } - memcpy(&mpqOpenArc->MpqHeader.dwMPQID,ID_MPQ,4); - mpqOpenArc->MpqHeader.dwHeaderSize = sizeof(MPQHEADER); - mpqOpenArc->MpqHeader.wUnused0C = 0; - if (dwBlockSize & 0xFFFF0000) - mpqOpenArc->MpqHeader.wBlockSize = DEFAULT_BLOCK_SIZE; - else - mpqOpenArc->MpqHeader.wBlockSize = (WORD)dwBlockSize; - DWORD i; - for (i=1;ihFile = hFile; + mpqOpenArc->qwMPQStart = 0; mpqOpenArc->MpqHeader.dwHashTableSize = dwMaximumFilesInArchive; - mpqOpenArc->MpqHeader.dwBlockTableSize = 0; - mpqOpenArc->MpqHeader.dwHashTableOffset = mpqOpenArc->MpqHeader.dwHeaderSize; - mpqOpenArc->MpqHeader.dwBlockTableOffset = mpqOpenArc->MpqHeader.dwHeaderSize + mpqOpenArc->MpqHeader.dwHashTableSize * sizeof(HASHTABLEENTRY); - mpqOpenArc->MpqHeader.dwMPQSize = mpqOpenArc->MpqHeader.dwHeaderSize + mpqOpenArc->MpqHeader.dwHashTableSize * sizeof(HASHTABLEENTRY); - if(WriteFile(hFile,&mpqOpenArc->MpqHeader,mpqOpenArc->MpqHeader.dwHeaderSize,&tsz,0)==0) { - SFFree(lpnOpenMpq); - SFFree(mpqOpenArc); - CloseHandle(hFile); - *hMPQ = 0; - return FALSE; - } - flen = mpqOpenArc->MpqHeader.dwMPQSize; - mpqOpenArc->lpHashTable = (HASHTABLEENTRY *)SFAlloc(sizeof(HASHTABLEENTRY) * mpqOpenArc->MpqHeader.dwHashTableSize); - if(!mpqOpenArc->lpHashTable) { - SFFree(lpnOpenMpq); + mpqOpenArc->MpqHeader.wBlockSize = (WORD)dwBlockSize; + + if (!MpqWriteNewArchive(mpqOpenArc)) { + if (mpqOpenArc->lpHashTable) SFFree(mpqOpenArc->lpHashTable); SFFree(mpqOpenArc); - CloseHandle(hFile); - *hMPQ = 0; - return FALSE; - } - memset(mpqOpenArc->lpHashTable,0xFF,sizeof(HASHTABLEENTRY) * mpqOpenArc->MpqHeader.dwHashTableSize); - EncryptData((LPBYTE)mpqOpenArc->lpHashTable,sizeof(HASHTABLEENTRY) * mpqOpenArc->MpqHeader.dwHashTableSize,dwHashTableKey); - if(WriteFile(hFile,mpqOpenArc->lpHashTable,sizeof(HASHTABLEENTRY) * mpqOpenArc->MpqHeader.dwHashTableSize,&tsz,0)==0) { - SFFree(mpqOpenArc->lpHashTable); SFFree(lpnOpenMpq); - SFFree(mpqOpenArc); CloseHandle(hFile); - *hMPQ = 0; return FALSE; } } else { - dwMpqStart = SFileFindMpqHeader(hFile); - if (dwMpqStart==0xFFFFFFFF) { + UInt64 qwMpqStart = SFileFindMpqHeaderEx(hFile); + if (qwMpqStart == (UInt64)-1) { SFFree(lpnOpenMpq); CloseHandle(hFile); SetLastError(MPQ_ERROR_MPQ_INVALID); - *hMPQ = 0; return FALSE; } - flen = GetFileSize(hFile,0); mpqOpenArc = (MPQARCHIVE *)SFAlloc(sizeof(MPQARCHIVE)); if (!mpqOpenArc) { SFFree(lpnOpenMpq); CloseHandle(hFile); - *hMPQ = 0; return FALSE; } - SetFilePointer(hFile,dwMpqStart,0,FILE_BEGIN); - if(ReadFile(hFile,&mpqOpenArc->MpqHeader,sizeof(MPQHEADER),&tsz,0)==0) { - SFFree(lpnOpenMpq); - SFFree(mpqOpenArc); - CloseHandle(hFile); - *hMPQ = 0; - return FALSE; - } - mpqOpenArc->lpHashTable = (HASHTABLEENTRY *)SFAlloc(sizeof(HASHTABLEENTRY) * mpqOpenArc->MpqHeader.dwHashTableSize); - if(!mpqOpenArc->lpHashTable) { - SFFree(lpnOpenMpq); + + mpqOpenArc->hFile = hFile; + mpqOpenArc->qwMPQStart = qwMpqStart; + + if (!MpqReadExistingArchive(mpqOpenArc)) { + if (mpqOpenArc->lpBlockTable) SFFree(mpqOpenArc->lpBlockTable); + if (mpqOpenArc->lpHashTable) SFFree(mpqOpenArc->lpHashTable); SFFree(mpqOpenArc); - CloseHandle(hFile); - *hMPQ = 0; - return FALSE; - } - if (mpqOpenArc->MpqHeader.dwBlockTableSize!=0) { - mpqOpenArc->lpBlockTable = (BLOCKTABLEENTRY *)SFAlloc(sizeof(BLOCKTABLEENTRY) * mpqOpenArc->MpqHeader.dwBlockTableSize); - if(!mpqOpenArc->lpBlockTable) { - SFFree(mpqOpenArc->lpHashTable); - SFFree(lpnOpenMpq); - SFFree(mpqOpenArc); - CloseHandle(hFile); - *hMPQ = 0; - return FALSE; - } - } - SetFilePointer(hFile,dwMpqStart+mpqOpenArc->MpqHeader.dwHashTableOffset,0,FILE_BEGIN); - if(ReadFile(hFile,mpqOpenArc->lpHashTable,sizeof(HASHTABLEENTRY) * mpqOpenArc->MpqHeader.dwHashTableSize,&tsz,0)==0) { - if(mpqOpenArc->lpBlockTable) SFFree(mpqOpenArc->lpBlockTable); - SFFree(mpqOpenArc->lpHashTable); SFFree(lpnOpenMpq); - SFFree(mpqOpenArc); CloseHandle(hFile); - *hMPQ = 0; return FALSE; } - if (mpqOpenArc->MpqHeader.dwBlockTableSize!=0) { - SetFilePointer(hFile,dwMpqStart+mpqOpenArc->MpqHeader.dwBlockTableOffset,0,FILE_BEGIN); - if(ReadFile(hFile,mpqOpenArc->lpBlockTable,sizeof(BLOCKTABLEENTRY) * mpqOpenArc->MpqHeader.dwBlockTableSize,&tsz,0)==0) { - SFFree(mpqOpenArc->lpBlockTable); - SFFree(mpqOpenArc->lpHashTable); - SFFree(lpnOpenMpq); - SFFree(mpqOpenArc); - CloseHandle(hFile); - *hMPQ = 0; - return FALSE; - } - } } - /*mpqOpenArc->lpFileName = (char *)SFAlloc(strlen(lpFileName)+1); - if(!mpqOpenArc->lpFileName) { - if(mpqOpenArc->lpBlockTable) SFFree(mpqOpenArc->lpBlockTable); + + if (!MpqOpenArchiveInit(mpqOpenArc, lpFileName, dwPriority, dwFlags1, dwFlags2, 0)) { + if (mpqOpenArc->lpBlockTable) SFFree(mpqOpenArc->lpBlockTable); SFFree(mpqOpenArc->lpHashTable); - SFFree(lpnOpenMpq); SFFree(mpqOpenArc); + SFFree(lpnOpenMpq); CloseHandle(hFile); - *hMPQ = 0; return FALSE; - }*/ - DecryptData((LPBYTE)mpqOpenArc->lpHashTable,sizeof(HASHTABLEENTRY) * mpqOpenArc->MpqHeader.dwHashTableSize,dwHashTableKey); - if (mpqOpenArc->lpBlockTable) DecryptData((LPBYTE)mpqOpenArc->lpBlockTable,sizeof(BLOCKTABLEENTRY) * mpqOpenArc->MpqHeader.dwBlockTableSize,dwBlockTableKey); - mpqOpenArc->lpFileName = mpqOpenArc->szFileName; - strncpy(mpqOpenArc->lpFileName,lpFileName,259); - if (FirstLastMpq[1]) FirstLastMpq[1]->lpNextArc = mpqOpenArc; - mpqOpenArc->lpNextArc = (MPQARCHIVE *)FirstLastMpq; - mpqOpenArc->lpPrevArc = (MPQARCHIVE *)FirstLastMpq[1]; - if (!FirstLastMpq[0]) { - mpqOpenArc->lpPrevArc = (MPQARCHIVE *)0xEAFC5E23; - FirstLastMpq[0] = mpqOpenArc; - } - FirstLastMpq[1] = mpqOpenArc; - mpqOpenArc->hFile = hFile; - mpqOpenArc->dwFlags1 = dwFlags1; - mpqOpenArc->dwPriority = dwPriority; - mpqOpenArc->lpLastReadFile = 0; - mpqOpenArc->dwUnk = 0; - mpqOpenArc->dwBlockSize = 512 << mpqOpenArc->MpqHeader.wBlockSize; - mpqOpenArc->lpLastReadBlock = 0; - mpqOpenArc->dwBufferSize = 0; - mpqOpenArc->dwMPQStart = dwMpqStart; - mpqOpenArc->lpMPQHeader = &mpqOpenArc->MpqHeader; - mpqOpenArc->dwReadOffset = flen; - mpqOpenArc->dwRefCount = 1; - mpqOpenArc->dwFlags = dwFlags2; - mpqOpenArc->dwExtraFlags = 0; + } + memcpy(lpnOpenMpq,lpOpenMpq,sizeof(MPQARCHIVE *) * dwOpenMpqCount); lpnOpenMpq[dwOpenMpqCount] = mpqOpenArc; if (lpOpenMpq) SFFree(lpOpenMpq); @@ -573,6 +563,7 @@ BOOL WINAPI MpqOpenArchiveEx(LPCSTR lpFileName, DWORD dwPriority, DWORD dwFlags, dwOpenMpqCount++; if (dwOpenMpqCount>1) SortOpenArchivesByPriority(); *hMPQ = (MPQHANDLE)mpqOpenArc; + return TRUE; } else { @@ -585,16 +576,14 @@ BOOL WINAPI MpqOpenArchiveEx(LPCSTR lpFileName, DWORD dwPriority, DWORD dwFlags, BOOL SFMPQAPI WINAPI SFileOpenFileAsArchive(MPQHANDLE hSourceMPQ, LPCSTR lpFileName, DWORD dwPriority, DWORD dwFlags, MPQHANDLE *hMPQ) { - DWORD flen,tsz; - if (!lpFileName || !hMPQ) { SetLastError(ERROR_INVALID_PARAMETER); - if (hMPQ) *hMPQ = 0; + if (hMPQ) *hMPQ = (MPQHANDLE)INVALID_HANDLE_VALUE; return FALSE; } + *hMPQ = (MPQHANDLE)INVALID_HANDLE_VALUE; if (!*lpFileName) { SetLastError(ERROR_INVALID_PARAMETER); - *hMPQ = 0; return FALSE; } @@ -609,105 +598,42 @@ BOOL SFMPQAPI WINAPI SFileOpenFileAsArchive(MPQHANDLE hSourceMPQ, LPCSTR lpFileN hFile = mpqArcFile.lpParentArc->hFile; MPQARCHIVE **lpnOpenMpq = (MPQARCHIVE **)SFAlloc(sizeof(MPQARCHIVE *) * (dwOpenMpqCount+1)); if (!lpnOpenMpq) { - *hMPQ = 0; return FALSE; } - DWORD dwMpqStart; MPQARCHIVE *mpqOpenArc; - dwMpqStart = mpqArcFile.lpBlockEntry->dwFileOffset; - flen = mpqArcFile.lpBlockEntry->dwFullSize; - dwMpqStart = FindMpqHeaderAtLocation(hFile,dwMpqStart,flen); - if (dwMpqStart==0xFFFFFFFF) { + UInt64 qwMpqStart = mpqArcFile.lpParentArc->qwMPQStart + MakeUInt64(mpqArcFile.lpBlockEntry->dwFileOffset, mpqArcFile.wFileOffsetHigh); + UInt64 flen = mpqArcFile.lpBlockEntry->dwFullSize; + qwMpqStart = SFileFindMpqHeaderEx(hFile, qwMpqStart, flen); + if (qwMpqStart == (UInt64)-1) { SFFree(lpnOpenMpq); SetLastError(MPQ_ERROR_MPQ_INVALID); - *hMPQ = 0; return FALSE; } mpqOpenArc = (MPQARCHIVE *)SFAlloc(sizeof(MPQARCHIVE)); if (!mpqOpenArc) { SFFree(lpnOpenMpq); - *hMPQ = 0; return FALSE; } - SetFilePointer(hFile,dwMpqStart,0,FILE_BEGIN); - if(ReadFile(hFile,&mpqOpenArc->MpqHeader,sizeof(MPQHEADER),&tsz,0)==0) { - SFFree(lpnOpenMpq); + + mpqOpenArc->hFile = hFile; + mpqOpenArc->qwMPQStart = qwMpqStart; + + if (!MpqReadExistingArchive(mpqOpenArc)) { + if (mpqOpenArc->lpBlockTable) SFFree(mpqOpenArc->lpBlockTable); + if (mpqOpenArc->lpHashTable) SFFree(mpqOpenArc->lpHashTable); SFFree(mpqOpenArc); - *hMPQ = 0; - return FALSE; - } - mpqOpenArc->lpHashTable = (HASHTABLEENTRY *)SFAlloc(sizeof(HASHTABLEENTRY) * mpqOpenArc->MpqHeader.dwHashTableSize); - if(!mpqOpenArc->lpHashTable) { SFFree(lpnOpenMpq); - SFFree(mpqOpenArc); - *hMPQ = 0; return FALSE; } - if (mpqOpenArc->MpqHeader.dwBlockTableSize!=0) { - mpqOpenArc->lpBlockTable = (BLOCKTABLEENTRY *)SFAlloc(sizeof(BLOCKTABLEENTRY) * mpqOpenArc->MpqHeader.dwBlockTableSize); - if(!mpqOpenArc->lpBlockTable) { - SFFree(mpqOpenArc->lpHashTable); - SFFree(lpnOpenMpq); - SFFree(mpqOpenArc); - *hMPQ = 0; - return FALSE; - } - } - SetFilePointer(hFile,dwMpqStart+mpqOpenArc->MpqHeader.dwHashTableOffset,0,FILE_BEGIN); - if(ReadFile(hFile,mpqOpenArc->lpHashTable,sizeof(HASHTABLEENTRY) * mpqOpenArc->MpqHeader.dwHashTableSize,&tsz,0)==0) { - if(mpqOpenArc->lpBlockTable) SFFree(mpqOpenArc->lpBlockTable); + + if (!MpqOpenArchiveInit(mpqOpenArc, lpFileName, dwPriority, 0, dwFlags, 1)) { + if (mpqOpenArc->lpBlockTable) SFFree(mpqOpenArc->lpBlockTable); SFFree(mpqOpenArc->lpHashTable); - SFFree(lpnOpenMpq); SFFree(mpqOpenArc); - *hMPQ = 0; - return FALSE; - } - if (mpqOpenArc->MpqHeader.dwBlockTableSize!=0) { - SetFilePointer(hFile,dwMpqStart+mpqOpenArc->MpqHeader.dwBlockTableOffset,0,FILE_BEGIN); - if(ReadFile(hFile,mpqOpenArc->lpBlockTable,sizeof(BLOCKTABLEENTRY) * mpqOpenArc->MpqHeader.dwBlockTableSize,&tsz,0)==0) { - SFFree(mpqOpenArc->lpBlockTable); - SFFree(mpqOpenArc->lpHashTable); - SFFree(lpnOpenMpq); - SFFree(mpqOpenArc); - *hMPQ = 0; - return FALSE; - } - } - /*mpqOpenArc->lpFileName = (char *)SFAlloc(strlen(lpFileName)+1); - if(!mpqOpenArc->lpFileName) { - if(mpqOpenArc->lpBlockTable) SFFree(mpqOpenArc->lpBlockTable); - SFFree(mpqOpenArc->lpHashTable); SFFree(lpnOpenMpq); - SFFree(mpqOpenArc); - *hMPQ = 0; return FALSE; - }*/ - DecryptData((LPBYTE)mpqOpenArc->lpHashTable,sizeof(HASHTABLEENTRY) * mpqOpenArc->MpqHeader.dwHashTableSize,dwHashTableKey); - if (mpqOpenArc->lpBlockTable) DecryptData((LPBYTE)mpqOpenArc->lpBlockTable,sizeof(BLOCKTABLEENTRY) * mpqOpenArc->MpqHeader.dwBlockTableSize,dwBlockTableKey); - mpqOpenArc->lpFileName = mpqOpenArc->szFileName; - strncpy(mpqOpenArc->lpFileName,lpFileName,259); - if (FirstLastMpq[1]) FirstLastMpq[1]->lpNextArc = mpqOpenArc; - mpqOpenArc->lpNextArc = (MPQARCHIVE *)FirstLastMpq; - mpqOpenArc->lpPrevArc = (MPQARCHIVE *)FirstLastMpq[1]; - if (!FirstLastMpq[0]) { - mpqOpenArc->lpPrevArc = (MPQARCHIVE *)0xEAFC5E23; - FirstLastMpq[0] = mpqOpenArc; - } - FirstLastMpq[1] = mpqOpenArc; - mpqOpenArc->hFile = hFile; - mpqOpenArc->dwFlags1 = 0; - mpqOpenArc->dwPriority = dwPriority; - mpqOpenArc->lpLastReadFile = 0; - mpqOpenArc->dwUnk = 0; - mpqOpenArc->dwBlockSize = 512 << mpqOpenArc->MpqHeader.wBlockSize; - mpqOpenArc->lpLastReadBlock = 0; - mpqOpenArc->dwBufferSize = 0; - mpqOpenArc->dwMPQStart = dwMpqStart; - mpqOpenArc->lpMPQHeader = &mpqOpenArc->MpqHeader; - mpqOpenArc->dwReadOffset = flen; - mpqOpenArc->dwRefCount = 1; - mpqOpenArc->dwFlags = dwFlags; - mpqOpenArc->dwExtraFlags = 1; + } + memcpy(lpnOpenMpq,lpOpenMpq,sizeof(MPQARCHIVE *) * dwOpenMpqCount); lpnOpenMpq[dwOpenMpqCount] = mpqOpenArc; if (lpOpenMpq) SFFree(lpOpenMpq); @@ -715,6 +641,7 @@ BOOL SFMPQAPI WINAPI SFileOpenFileAsArchive(MPQHANDLE hSourceMPQ, LPCSTR lpFileN dwOpenMpqCount++; if (dwOpenMpqCount>1) SortOpenArchivesByPriority(); *hMPQ = (MPQHANDLE)mpqOpenArc; + return TRUE; } else { @@ -958,6 +885,7 @@ BOOL SFMPQAPI WINAPI SFileOpenFileEx(MPQHANDLE hMPQ, LPCSTR lpFileName, DWORD dw mpqOpenFile->hFile = INVALID_HANDLE_VALUE; mpqOpenFile->lpHashEntry = (HASHTABLEENTRY *)hnFile; mpqOpenFile->lpBlockEntry = &((MPQARCHIVE *)hnMPQ)->lpBlockTable[mpqOpenFile->lpHashEntry->dwBlockTableIndex]; + mpqOpenFile->wFileOffsetHigh = ((MPQARCHIVE *)hnMPQ)->lpFileOffsetsHigh[mpqOpenFile->lpHashEntry->dwBlockTableIndex]; mpqOpenFile->lpParentArc->dwRefCount++; if (mpqOpenFile->lpBlockEntry->dwFlags&MAFA_ENCRYPT) { LPSTR lpOldNameBuffer = mpqOpenFile->lpFileName; @@ -1120,7 +1048,7 @@ DWORD SFMPQAPI WINAPI SFileGetFileInfo(MPQHANDLE hFile, DWORD dwInfoType) case SFILE_INFO_PRIORITY: return mpqOpenArc->dwPriority; case SFILE_INFO_HASH_INDEX: - return ((DWORD)mpqOpenFile->lpHashEntry-(DWORD)mpqOpenArc->lpHashTable)/sizeof(HASHTABLEENTRY); + return ((UIntPtr)mpqOpenFile->lpHashEntry-(UIntPtr)mpqOpenArc->lpHashTable)/sizeof(HASHTABLEENTRY); case SFILE_INFO_BLOCK_INDEX: return mpqOpenFile->lpHashEntry->dwBlockTableIndex; default: @@ -1133,15 +1061,15 @@ DWORD SFMPQAPI WINAPI SFileGetFileInfo(MPQHANDLE hFile, DWORD dwInfoType) case SFILE_INFO_TYPE: return SFILE_TYPE_FILE; case SFILE_INFO_SIZE: - return GetFileSize(mpqOpenFile->hFile,0); + return SFGetFileSize(mpqOpenFile->hFile); case SFILE_INFO_COMPRESSED_SIZE: - return GetFileSize(mpqOpenFile->hFile,0); + return SFGetFileSize(mpqOpenFile->hFile); #ifdef _WIN32 case SFILE_INFO_FLAGS: return GetFileAttributes(mpqOpenFile->lpFileName); #endif case SFILE_INFO_POSITION: - return SetFilePointer(mpqOpenFile->hFile,0,0,FILE_CURRENT); + return SFSetFilePointer(mpqOpenFile->hFile,0,FILE_CURRENT); default: SetLastError(ERROR_UNKNOWN_PROPERTY); return (DWORD)-1; @@ -1245,6 +1173,8 @@ BOOL SFMPQAPI WINAPI SFileReadFile(MPQHANDLE hFile,LPVOID lpBuffer,DWORD nNumber DWORD BlockIndex = mpqOpenFile->lpHashEntry->dwBlockTableIndex; if (mpqOpenFile->dwFilePointer+nNumberOfBytesToRead>mpqOpenArc->lpBlockTable[BlockIndex].dwFullSize) nNumberOfBytesToRead = mpqOpenArc->lpBlockTable[BlockIndex].dwFullSize-mpqOpenFile->dwFilePointer; DWORD blockSize = 512 << mpqOpenArc->MpqHeader.wBlockSize; + if (mpqOpenArc->lpBlockTable[BlockIndex].dwFlags & MAFA_SINGLEBLOCK) + blockSize = mpqOpenArc->lpBlockTable[BlockIndex].dwFullSize; DWORD dwBlockStart = mpqOpenFile->dwFilePointer - (mpqOpenFile->dwFilePointer % blockSize); DWORD blockNum = dwBlockStart / blockSize; DWORD nBlocks = (mpqOpenFile->dwFilePointer+nNumberOfBytesToRead) / blockSize; @@ -1262,12 +1192,18 @@ BOOL SFMPQAPI WINAPI SFileReadFile(MPQHANDLE hFile,LPVOID lpBuffer,DWORD nNumber if (lpOverlapped) lpOverlapped->InternalHigh = 0; return FALSE; } - void *blk16Buffer = SFAlloc(blockSize * 16); - if (!blk16Buffer) { - SFFree(blkBuffer); - if (lpNumberOfBytesRead) *lpNumberOfBytesRead = 0; - if (lpOverlapped) lpOverlapped->InternalHigh = 0; - return FALSE; + DWORD nBufferCount; + for (nBufferCount = 1; nBufferCount < nBlocks - blockNum && blockSize * nBufferCount < 65536; nBufferCount *= 2) {} + if (nBufferCount > nBlocks - blockNum) nBufferCount = nBlocks - blockNum; + void *blkLargeBuffer = NULL; + if (nBufferCount > 1) { + blkLargeBuffer = SFAlloc(blockSize * nBufferCount); + if (!blkLargeBuffer) { + SFFree(blkBuffer); + if (lpNumberOfBytesRead) *lpNumberOfBytesRead = 0; + if (lpOverlapped) lpOverlapped->InternalHigh = 0; + return FALSE; + } } DWORD dwCryptKey = mpqOpenFile->dwCryptKey; //if (mpqOpenArc->lpBlockTable[BlockIndex].dwFlags & MAFA_ENCRYPT) dwCryptKey = HashString(mpqOpenFile->lpFileName,HASH_KEY); @@ -1275,7 +1211,7 @@ BOOL SFMPQAPI WINAPI SFileReadFile(MPQHANDLE hFile,LPVOID lpBuffer,DWORD nNumber DWORD HeaderLength=0; if (memcmp(&mpqOpenArc->MpqHeader.dwMPQID,ID_BN3,4)==0) { - SetFilePointer(mpqOpenArc->hFile,mpqOpenArc->dwMPQStart+mpqOpenArc->lpBlockTable[BlockIndex].dwFileOffset,0,FILE_BEGIN); + SFSetFilePointer(mpqOpenArc->hFile, mpqOpenArc->qwMPQStart + MakeUInt64(mpqOpenArc->lpBlockTable[BlockIndex].dwFileOffset, mpqOpenArc->lpFileOffsetsHigh[BlockIndex]), FILE_BEGIN); ReadFile(mpqOpenArc->hFile,&HeaderLength,4,&nBytesRead,0); } DWORD i; @@ -1284,15 +1220,15 @@ BOOL SFMPQAPI WINAPI SFileReadFile(MPQHANDLE hFile,LPVOID lpBuffer,DWORD nNumber DWORD *dwBlockPtrTable = (DWORD *)SFAlloc((TotalBlocks+1)*4); if (!dwBlockPtrTable) { - SFFree(blk16Buffer); + if (blkLargeBuffer) SFFree(blkLargeBuffer); SFFree(blkBuffer); if (lpNumberOfBytesRead) *lpNumberOfBytesRead = 0; if (lpOverlapped) lpOverlapped->InternalHigh = 0; return FALSE; } - if ((mpqOpenArc->lpBlockTable[BlockIndex].dwFlags & MAFA_COMPRESS) || (mpqOpenArc->lpBlockTable[BlockIndex].dwFlags & MAFA_COMPRESS2)) + if (((mpqOpenArc->lpBlockTable[BlockIndex].dwFlags & MAFA_COMPRESS) || (mpqOpenArc->lpBlockTable[BlockIndex].dwFlags & MAFA_COMPRESS2)) && !(mpqOpenArc->lpBlockTable[BlockIndex].dwFlags & MAFA_SINGLEBLOCK)) { - SetFilePointer(mpqOpenArc->hFile,mpqOpenArc->dwMPQStart+mpqOpenArc->lpBlockTable[BlockIndex].dwFileOffset+HeaderLength,0,FILE_BEGIN); + SFSetFilePointer(mpqOpenArc->hFile, mpqOpenArc->qwMPQStart + MakeUInt64(mpqOpenArc->lpBlockTable[BlockIndex].dwFileOffset, mpqOpenArc->lpFileOffsetsHigh[BlockIndex]) + HeaderLength, FILE_BEGIN); ReadFile(mpqOpenArc->hFile,dwBlockPtrTable,(TotalBlocks+1)*4,&nBytesRead,0); if (mpqOpenArc->lpBlockTable[BlockIndex].dwFlags & MAFA_ENCRYPT) { DecryptData((LPBYTE)dwBlockPtrTable,(TotalBlocks+1)*4,dwCryptKey-1); @@ -1302,28 +1238,31 @@ BOOL SFMPQAPI WINAPI SFileReadFile(MPQHANDLE hFile,LPVOID lpBuffer,DWORD nNumber { for (i=0;ilpBlockTable[BlockIndex].dwFullSize; + else dwBlockPtrTable[i] = mpqOpenArc->lpBlockTable[BlockIndex].dwCompressedSize - HeaderLength; } } mpqOpenFile->lpdwBlockOffsets = dwBlockPtrTable; } - BYTE *compbuffer = (BYTE *)SFAlloc(blockSize+3); - if (!compbuffer) { - SFFree(blk16Buffer); - SFFree(blkBuffer); - if (lpNumberOfBytesRead) *lpNumberOfBytesRead = 0; - if (lpOverlapped) lpOverlapped->InternalHigh = 0; - return FALSE; + BYTE *compbuffer = NULL; + if ((mpqOpenArc->lpBlockTable[BlockIndex].dwFlags & MAFA_COMPRESS) || (mpqOpenArc->lpBlockTable[BlockIndex].dwFlags & MAFA_COMPRESS2)) { + compbuffer = (BYTE *)SFAlloc(blockSize+3); + if (!compbuffer) { + if (blkLargeBuffer) SFFree(blkLargeBuffer); + SFFree(blkBuffer); + if (lpNumberOfBytesRead) *lpNumberOfBytesRead = 0; + if (lpOverlapped) lpOverlapped->InternalHigh = 0; + return FALSE; + } } DWORD blk=0,blki=0; for (i=blockNum;ihFile,mpqOpenArc->dwMPQStart+mpqOpenArc->lpBlockTable[BlockIndex].dwFileOffset+HeaderLength+mpqOpenFile->lpdwBlockOffsets[i],0,FILE_BEGIN); + if (blk==0 && blkLargeBuffer) { + SFSetFilePointer(mpqOpenArc->hFile, mpqOpenArc->qwMPQStart + MakeUInt64(mpqOpenArc->lpBlockTable[BlockIndex].dwFileOffset, mpqOpenArc->lpFileOffsetsHigh[BlockIndex]) + HeaderLength + mpqOpenFile->lpdwBlockOffsets[i], FILE_BEGIN); blki=i; - if (i+16>nBlocks) { - if (ReadFile(mpqOpenArc->hFile,blk16Buffer,mpqOpenFile->lpdwBlockOffsets[nBlocks]-mpqOpenFile->lpdwBlockOffsets[i],&nBytesRead,0)==0) { - SFFree(compbuffer); - SFFree(blk16Buffer); + if (i+nBufferCount>nBlocks) { + if (ReadFile(mpqOpenArc->hFile,blkLargeBuffer,mpqOpenFile->lpdwBlockOffsets[nBlocks]-mpqOpenFile->lpdwBlockOffsets[i],&nBytesRead,0)==0) { + if (compbuffer) SFFree(compbuffer); + SFFree(blkLargeBuffer); SFFree(blkBuffer); if (lpNumberOfBytesRead) *lpNumberOfBytesRead = TotalBytesRead; if (lpOverlapped) lpOverlapped->InternalHigh = TotalBytesRead; @@ -1332,9 +1271,9 @@ BOOL SFMPQAPI WINAPI SFileReadFile(MPQHANDLE hFile,LPVOID lpBuffer,DWORD nNumber } else { - if (ReadFile(mpqOpenArc->hFile,blk16Buffer,mpqOpenFile->lpdwBlockOffsets[i+16]-mpqOpenFile->lpdwBlockOffsets[i],&nBytesRead,0)==0) { - SFFree(compbuffer); - SFFree(blk16Buffer); + if (ReadFile(mpqOpenArc->hFile,blkLargeBuffer,mpqOpenFile->lpdwBlockOffsets[i+nBufferCount]-mpqOpenFile->lpdwBlockOffsets[i],&nBytesRead,0)==0) { + if (compbuffer) SFFree(compbuffer); + SFFree(blkLargeBuffer); SFFree(blkBuffer); if (lpNumberOfBytesRead) *lpNumberOfBytesRead = TotalBytesRead; if (lpOverlapped) lpOverlapped->InternalHigh = TotalBytesRead; @@ -1342,7 +1281,20 @@ BOOL SFMPQAPI WINAPI SFileReadFile(MPQHANDLE hFile,LPVOID lpBuffer,DWORD nNumber } } } - memcpy(blkBuffer,((char *)blk16Buffer)+(mpqOpenFile->lpdwBlockOffsets[blki+blk]-mpqOpenFile->lpdwBlockOffsets[blki]),mpqOpenFile->lpdwBlockOffsets[i+1]-mpqOpenFile->lpdwBlockOffsets[i]); + if (blkLargeBuffer) { + memcpy(blkBuffer,((char *)blkLargeBuffer)+(mpqOpenFile->lpdwBlockOffsets[blki+blk]-mpqOpenFile->lpdwBlockOffsets[blki]),mpqOpenFile->lpdwBlockOffsets[i+1]-mpqOpenFile->lpdwBlockOffsets[i]); + } + else { + SFSetFilePointer(mpqOpenArc->hFile, mpqOpenArc->qwMPQStart + MakeUInt64(mpqOpenArc->lpBlockTable[BlockIndex].dwFileOffset, mpqOpenArc->lpFileOffsetsHigh[BlockIndex]) + HeaderLength + mpqOpenFile->lpdwBlockOffsets[i], FILE_BEGIN); + blki=i; + if (ReadFile(mpqOpenArc->hFile,blkBuffer,mpqOpenFile->lpdwBlockOffsets[i+1]-mpqOpenFile->lpdwBlockOffsets[i],&nBytesRead,0)==0) { + if (compbuffer) SFFree(compbuffer); + SFFree(blkBuffer); + if (lpNumberOfBytesRead) *lpNumberOfBytesRead = TotalBytesRead; + if (lpOverlapped) lpOverlapped->InternalHigh = TotalBytesRead; + return FALSE; + } + } if (mpqOpenArc->lpBlockTable[BlockIndex].dwFlags & MAFA_ENCRYPT) { DecryptData((LPBYTE)blkBuffer,mpqOpenFile->lpdwBlockOffsets[i+1]-mpqOpenFile->lpdwBlockOffsets[i],dwCryptKey+i); @@ -1414,10 +1366,10 @@ BOOL SFMPQAPI WINAPI SFileReadFile(MPQHANDLE hFile,LPVOID lpBuffer,DWORD nNumber nNumberOfBytesToRead-=nNumberOfBytesToRead; } } - blk = (blk+1) % 16; + blk = (blk+1) % nBufferCount; } - SFFree(compbuffer); - SFFree(blk16Buffer); + if (compbuffer) SFFree(compbuffer); + if (blkLargeBuffer) SFFree(blkLargeBuffer); SFFree(blkBuffer); if (lpNumberOfBytesRead) *lpNumberOfBytesRead = TotalBytesRead; if (lpOverlapped) lpOverlapped->InternalHigh = TotalBytesRead; @@ -1526,8 +1478,11 @@ BOOL SFMPQAPI WINAPI SFileListFiles(MPQHANDLE hMPQ, LPCSTR lpFileLists, FILELIST lpListBuffer[i].dwCompressedSize = mpqOpenArc->lpBlockTable[dwBlockIndex].dwCompressedSize; lpListBuffer[i].dwFullSize = mpqOpenArc->lpBlockTable[dwBlockIndex].dwFullSize; lpListBuffer[i].dwFlags = mpqOpenArc->lpBlockTable[dwBlockIndex].dwFlags; - lpListBuffer[i].dwFileExists=0xFFFFFFFF; - SetFilePointer(mpqOpenArc->hFile,mpqOpenArc->dwMPQStart+mpqOpenArc->lpBlockTable[dwBlockIndex].dwFileOffset+0x40,0,FILE_BEGIN); + if (dwFlags & SFILE_LIST_FLAG_UNKNOWN) + lpListBuffer[i].dwFileExists = 1; + else + lpListBuffer[i].dwFileExists=0xFFFFFFFF; + SFSetFilePointer(mpqOpenArc->hFile, mpqOpenArc->qwMPQStart + MakeUInt64(mpqOpenArc->lpBlockTable[dwBlockIndex].dwFileOffset, mpqOpenArc->lpFileOffsetsHigh[dwBlockIndex]) + 0x40, FILE_BEGIN); ReadFile(mpqOpenArc->hFile,lpListBuffer[i].szFileName,260,&tsz,0); if (mpqOpenArc->lpHashTable[i].dwNameHashA==HashString(lpListBuffer[i].szFileName,HASH_NAME_A) && mpqOpenArc->lpHashTable[i].dwNameHashB==HashString(lpListBuffer[i].szFileName,HASH_NAME_B)) { @@ -1537,6 +1492,10 @@ BOOL SFMPQAPI WINAPI SFileListFiles(MPQHANDLE hMPQ, LPCSTR lpFileLists, FILELIST } else { sprintf(lpListBuffer[i].szFileName,UNKNOWN_OUT,i); + if (dwFlags & SFILE_LIST_FLAG_UNKNOWN) { + lpListBuffer[i].dwFileExists |= 2; + } + if (dwFlags&SFILE_LIST_ONLY_KNOWN) { lpListBuffer[i].dwFileExists = 0; } @@ -1612,8 +1571,8 @@ BOOL SFMPQAPI WINAPI SFileListFiles(MPQHANDLE hMPQ, LPCSTR lpFileLists, FILELIST if (!(dwFlags&SFILE_LIST_MEMORY_LIST)) { hFile = CreateFile(lpNameBuffers[i],GENERIC_READ,FILE_SHARE_READ,0,OPEN_EXISTING,0,0); if (hFile!=INVALID_HANDLE_VALUE) { - fsz = GetFileSize(hFile,0); - SetFilePointer(hFile,0,0,FILE_BEGIN); + fsz = SFGetFileSize(hFile); + SFSetFilePointer(hFile,0,FILE_BEGIN); lpNameBuffers[i] = (char *)SFAlloc(fsz+1); ReadFile(hFile,lpNameBuffers[i],fsz,&tsz,0); CloseHandle(hFile); @@ -1690,7 +1649,10 @@ BOOL SFMPQAPI WINAPI SFileListFiles(MPQHANDLE hMPQ, LPCSTR lpFileLists, FILELIST lpListBuffer[i].dwCompressedSize = mpqOpenArc->lpBlockTable[dwBlockIndex].dwCompressedSize; lpListBuffer[i].dwFullSize = mpqOpenArc->lpBlockTable[dwBlockIndex].dwFullSize; lpListBuffer[i].dwFlags = mpqOpenArc->lpBlockTable[dwBlockIndex].dwFlags; - lpListBuffer[i].dwFileExists=0xFFFFFFFF; + if (dwFlags & SFILE_LIST_FLAG_UNKNOWN) + lpListBuffer[i].dwFileExists = 1; + else + lpListBuffer[i].dwFileExists=0xFFFFFFFF; for (j=0;jlpHashTable[i].dwNameHashA==lpdwNameHashA[j] && mpqOpenArc->lpHashTable[i].dwNameHashB==lpdwNameHashB[j]) { strncpy(lpListBuffer[i].szFileName,lpNames[j],260); @@ -1701,6 +1663,10 @@ BOOL SFMPQAPI WINAPI SFileListFiles(MPQHANDLE hMPQ, LPCSTR lpFileLists, FILELIST } if (j+1==dwTotalLines) { sprintf(lpListBuffer[i].szFileName,UNKNOWN_OUT,i); + if (dwFlags & SFILE_LIST_FLAG_UNKNOWN) { + lpListBuffer[i].dwFileExists |= 2; + } + if (dwFlags&SFILE_LIST_ONLY_KNOWN) { lpListBuffer[i].dwFileExists = 0; } @@ -1771,7 +1737,7 @@ BOOL SFMPQAPI WINAPI MpqAddFileToArchiveEx(MPQHANDLE hMPQ, LPCSTR lpSourceFileNa if (!hFile) return FALSE; HANDLE haFile = CreateFile(lpSourceFileName,GENERIC_READ,FILE_SHARE_READ,0,OPEN_EXISTING,0,0); if (haFile==INVALID_HANDLE_VALUE) return FALSE; - DWORD fsz = GetFileSize(haFile,0),tsz; + DWORD fsz = SFGetFileSize(haFile),tsz; DWORD ucfsz = fsz; BOOL IsBNcache = FALSE;char *buffer,*hbuffer; MPQARCHIVE *mpqOpenArc = (MPQARCHIVE *)hMPQ; @@ -1953,15 +1919,19 @@ BOOL SFMPQAPI WINAPI MpqAddFileToArchiveEx(MPQHANDLE hMPQ, LPCSTR lpSourceFileNa if ((hashEntry->dwBlockTableIndex&0xFFFFFFFE)==0xFFFFFFFE) { BLOCKTABLEENTRY *lpnBlockTable; - lpnBlockTable = (BLOCKTABLEENTRY *)SFAlloc(sizeof(BLOCKTABLEENTRY) * (mpqOpenArc->MpqHeader.dwBlockTableSize + 1)); + lpnBlockTable = (BLOCKTABLEENTRY *)SFAlloc((sizeof(BLOCKTABLEENTRY) + sizeof(UInt16)) * (mpqOpenArc->MpqHeader.dwBlockTableSize + 1)); if(!lpnBlockTable) { SFFree(buffer); return FALSE; } - if (mpqOpenArc->lpBlockTable) memcpy(lpnBlockTable,mpqOpenArc->lpBlockTable,sizeof(BLOCKTABLEENTRY) * mpqOpenArc->MpqHeader.dwBlockTableSize); + if (mpqOpenArc->lpBlockTable) { + memcpy(lpnBlockTable,mpqOpenArc->lpBlockTable,sizeof(BLOCKTABLEENTRY) * mpqOpenArc->MpqHeader.dwBlockTableSize); + memcpy(lpnBlockTable + mpqOpenArc->MpqHeader.dwBlockTableSize + 1, mpqOpenArc->lpFileOffsetsHigh, sizeof(UInt16) * mpqOpenArc->MpqHeader.dwBlockTableSize); + } mpqOpenArc->MpqHeader.dwBlockTableSize++; if (mpqOpenArc->lpBlockTable) SFFree(mpqOpenArc->lpBlockTable); mpqOpenArc->lpBlockTable = lpnBlockTable; + mpqOpenArc->lpFileOffsetsHigh = (UInt16 *)(mpqOpenArc->lpBlockTable + mpqOpenArc->MpqHeader.dwBlockTableSize); IsNewBlockEntry = TRUE; } DWORD BlockIndex = mpqOpenArc->MpqHeader.dwBlockTableSize - 1; @@ -2034,9 +2004,7 @@ BOOL SFMPQAPI WINAPI MpqAddFileToArchiveEx(MPQHANDLE hMPQ, LPCSTR lpSourceFileNa mpqOpenArc->lpBlockTable[BlockIndex].dwCompressedSize = fsz; mpqOpenArc->lpBlockTable[BlockIndex].dwFullSize = ucfsz; mpqOpenArc->lpBlockTable[BlockIndex].dwFlags = dwFlags|MAFA_EXISTS; - DWORD dwFileOffset = mpqOpenArc->lpBlockTable[BlockIndex].dwFileOffset; - SetFilePointer(mpqOpenArc->hFile,mpqOpenArc->dwMPQStart,0,FILE_BEGIN); - WriteFile(mpqOpenArc->hFile,&mpqOpenArc->MpqHeader,sizeof(MPQHEADER),&tsz,0); + MpqWriteHeaders(mpqOpenArc); if (dwFlags & MAFA_ENCRYPT) { DWORD dwCryptKey; if (dwFlags&MAFA_ENCRYPT) dwCryptKey = HashString(lpDestFileName,HASH_KEY); @@ -2056,37 +2024,11 @@ BOOL SFMPQAPI WINAPI MpqAddFileToArchiveEx(MPQHANDLE hMPQ, LPCSTR lpSourceFileNa } } SFFree(dwBlkpt); - SetFilePointer(mpqOpenArc->hFile,mpqOpenArc->dwMPQStart+dwFileOffset,0,FILE_BEGIN); + SFSetFilePointer(mpqOpenArc->hFile, mpqOpenArc->qwMPQStart + MakeUInt64(mpqOpenArc->lpBlockTable[BlockIndex].dwFileOffset, mpqOpenArc->lpFileOffsetsHigh[BlockIndex]), FILE_BEGIN); WriteFile(mpqOpenArc->hFile,buffer,fsz,&tsz,0); SFFree(buffer); - buffer = (char *)SFAlloc(sizeof(HASHTABLEENTRY) * mpqOpenArc->MpqHeader.dwHashTableSize); - if (buffer) { - memcpy(buffer,mpqOpenArc->lpHashTable,sizeof(HASHTABLEENTRY) * mpqOpenArc->MpqHeader.dwHashTableSize); - EncryptData((LPBYTE)buffer,sizeof(HASHTABLEENTRY) * mpqOpenArc->MpqHeader.dwHashTableSize,dwHashTableKey); - SetFilePointer(mpqOpenArc->hFile,mpqOpenArc->dwMPQStart+mpqOpenArc->MpqHeader.dwHashTableOffset,0,FILE_BEGIN); - WriteFile(mpqOpenArc->hFile,buffer,sizeof(HASHTABLEENTRY) * mpqOpenArc->MpqHeader.dwHashTableSize,&tsz,0); - SFFree(buffer); - } - else { - EncryptData((LPBYTE)mpqOpenArc->lpHashTable,sizeof(HASHTABLEENTRY) * mpqOpenArc->MpqHeader.dwHashTableSize,dwHashTableKey); - SetFilePointer(mpqOpenArc->hFile,mpqOpenArc->dwMPQStart+mpqOpenArc->MpqHeader.dwHashTableOffset,0,FILE_BEGIN); - WriteFile(mpqOpenArc->hFile,mpqOpenArc->lpHashTable,sizeof(HASHTABLEENTRY) * mpqOpenArc->MpqHeader.dwHashTableSize,&tsz,0); - DecryptData((LPBYTE)mpqOpenArc->lpHashTable,sizeof(HASHTABLEENTRY) * mpqOpenArc->MpqHeader.dwHashTableSize,dwHashTableKey); - } - buffer = (char *)SFAlloc(sizeof(BLOCKTABLEENTRY) * mpqOpenArc->MpqHeader.dwBlockTableSize); - if (buffer) { - memcpy(buffer,mpqOpenArc->lpBlockTable,sizeof(BLOCKTABLEENTRY) * mpqOpenArc->MpqHeader.dwBlockTableSize); - EncryptData((LPBYTE)buffer,sizeof(BLOCKTABLEENTRY) * mpqOpenArc->MpqHeader.dwBlockTableSize,dwBlockTableKey); - SetFilePointer(mpqOpenArc->hFile,mpqOpenArc->dwMPQStart+mpqOpenArc->MpqHeader.dwBlockTableOffset,0,FILE_BEGIN); - WriteFile(mpqOpenArc->hFile,buffer,sizeof(BLOCKTABLEENTRY) * mpqOpenArc->MpqHeader.dwBlockTableSize,&tsz,0); - SFFree(buffer); - } - else { - EncryptData((LPBYTE)mpqOpenArc->lpBlockTable,sizeof(BLOCKTABLEENTRY) * mpqOpenArc->MpqHeader.dwBlockTableSize,dwBlockTableKey); - SetFilePointer(mpqOpenArc->hFile,mpqOpenArc->dwMPQStart+mpqOpenArc->MpqHeader.dwBlockTableOffset,0,FILE_BEGIN); - WriteFile(mpqOpenArc->hFile,mpqOpenArc->lpBlockTable,sizeof(BLOCKTABLEENTRY) * mpqOpenArc->MpqHeader.dwBlockTableSize,&tsz,0); - DecryptData((LPBYTE)mpqOpenArc->lpBlockTable,sizeof(BLOCKTABLEENTRY) * mpqOpenArc->MpqHeader.dwBlockTableSize,dwBlockTableKey); - } + WriteHashTable(mpqOpenArc); + WriteBlockTable(mpqOpenArc); AddToInternalListing(hMPQ,lpDestFileName); return TRUE; @@ -2299,15 +2241,19 @@ BOOL SFMPQAPI WINAPI MpqAddFileFromBufferEx(MPQHANDLE hMPQ, LPVOID lpBuffer, DWO if ((hashEntry->dwBlockTableIndex&0xFFFFFFFE)==0xFFFFFFFE) { BLOCKTABLEENTRY *lpnBlockTable; - lpnBlockTable = (BLOCKTABLEENTRY *)SFAlloc(sizeof(BLOCKTABLEENTRY) * (mpqOpenArc->MpqHeader.dwBlockTableSize + 1)); - if(lpnBlockTable==0) { + lpnBlockTable = (BLOCKTABLEENTRY *)SFAlloc((sizeof(BLOCKTABLEENTRY) + sizeof(UInt16)) * (mpqOpenArc->MpqHeader.dwBlockTableSize + 1)); + if(!lpnBlockTable) { SFFree(buffer); return FALSE; } - if (mpqOpenArc->lpBlockTable!=0) memcpy(lpnBlockTable,mpqOpenArc->lpBlockTable,sizeof(BLOCKTABLEENTRY) * mpqOpenArc->MpqHeader.dwBlockTableSize); + if (mpqOpenArc->lpBlockTable) { + memcpy(lpnBlockTable,mpqOpenArc->lpBlockTable,sizeof(BLOCKTABLEENTRY) * mpqOpenArc->MpqHeader.dwBlockTableSize); + memcpy(lpnBlockTable + mpqOpenArc->MpqHeader.dwBlockTableSize + 1, mpqOpenArc->lpFileOffsetsHigh, sizeof(UInt16) * mpqOpenArc->MpqHeader.dwBlockTableSize); + } mpqOpenArc->MpqHeader.dwBlockTableSize++; - if (mpqOpenArc->lpBlockTable!=0) SFFree(mpqOpenArc->lpBlockTable); + if (mpqOpenArc->lpBlockTable) SFFree(mpqOpenArc->lpBlockTable); mpqOpenArc->lpBlockTable = lpnBlockTable; + mpqOpenArc->lpFileOffsetsHigh = (UInt16 *)(mpqOpenArc->lpBlockTable + mpqOpenArc->MpqHeader.dwBlockTableSize); IsNewBlockEntry = TRUE; } DWORD BlockIndex = mpqOpenArc->MpqHeader.dwBlockTableSize - 1; @@ -2379,9 +2325,7 @@ BOOL SFMPQAPI WINAPI MpqAddFileFromBufferEx(MPQHANDLE hMPQ, LPVOID lpBuffer, DWO mpqOpenArc->lpBlockTable[BlockIndex].dwCompressedSize = fsz; mpqOpenArc->lpBlockTable[BlockIndex].dwFullSize = ucfsz; mpqOpenArc->lpBlockTable[BlockIndex].dwFlags = dwFlags|MAFA_EXISTS; - DWORD dwFileOffset = mpqOpenArc->lpBlockTable[BlockIndex].dwFileOffset; - SetFilePointer(mpqOpenArc->hFile,mpqOpenArc->dwMPQStart,0,FILE_BEGIN); - WriteFile(mpqOpenArc->hFile,&mpqOpenArc->MpqHeader,sizeof(MPQHEADER),&tsz,0); + MpqWriteHeaders(mpqOpenArc); if (dwFlags & MAFA_ENCRYPT) { DWORD dwCryptKey; if (dwFlags&MAFA_ENCRYPT) dwCryptKey = HashString(lpFileName,HASH_KEY); @@ -2402,37 +2346,11 @@ BOOL SFMPQAPI WINAPI MpqAddFileFromBufferEx(MPQHANDLE hMPQ, LPVOID lpBuffer, DWO } } SFFree(dwBlkpt); - SetFilePointer(mpqOpenArc->hFile,mpqOpenArc->dwMPQStart+dwFileOffset,0,FILE_BEGIN); + SFSetFilePointer(mpqOpenArc->hFile, mpqOpenArc->qwMPQStart + MakeUInt64(mpqOpenArc->lpBlockTable[BlockIndex].dwFileOffset, mpqOpenArc->lpFileOffsetsHigh[BlockIndex]), FILE_BEGIN); WriteFile(mpqOpenArc->hFile,buffer,fsz,&tsz,0); SFFree(buffer); - buffer = (char *)SFAlloc(sizeof(HASHTABLEENTRY) * mpqOpenArc->MpqHeader.dwHashTableSize); - if (buffer!=0) { - memcpy(buffer,mpqOpenArc->lpHashTable,sizeof(HASHTABLEENTRY) * mpqOpenArc->MpqHeader.dwHashTableSize); - EncryptData((LPBYTE)buffer,sizeof(HASHTABLEENTRY) * mpqOpenArc->MpqHeader.dwHashTableSize,dwHashTableKey); - SetFilePointer(mpqOpenArc->hFile,mpqOpenArc->dwMPQStart+mpqOpenArc->MpqHeader.dwHashTableOffset,0,FILE_BEGIN); - WriteFile(mpqOpenArc->hFile,buffer,sizeof(HASHTABLEENTRY) * mpqOpenArc->MpqHeader.dwHashTableSize,&tsz,0); - SFFree(buffer); - } - else { - EncryptData((LPBYTE)mpqOpenArc->lpHashTable,sizeof(HASHTABLEENTRY) * mpqOpenArc->MpqHeader.dwHashTableSize,dwHashTableKey); - SetFilePointer(mpqOpenArc->hFile,mpqOpenArc->dwMPQStart+mpqOpenArc->MpqHeader.dwHashTableOffset,0,FILE_BEGIN); - WriteFile(mpqOpenArc->hFile,mpqOpenArc->lpHashTable,sizeof(HASHTABLEENTRY) * mpqOpenArc->MpqHeader.dwHashTableSize,&tsz,0); - DecryptData((LPBYTE)mpqOpenArc->lpHashTable,sizeof(HASHTABLEENTRY) * mpqOpenArc->MpqHeader.dwHashTableSize,dwHashTableKey); - } - buffer = (char *)SFAlloc(sizeof(BLOCKTABLEENTRY) * mpqOpenArc->MpqHeader.dwBlockTableSize); - if (buffer!=0) { - memcpy(buffer,mpqOpenArc->lpBlockTable,sizeof(BLOCKTABLEENTRY) * mpqOpenArc->MpqHeader.dwBlockTableSize); - EncryptData((LPBYTE)buffer,sizeof(BLOCKTABLEENTRY) * mpqOpenArc->MpqHeader.dwBlockTableSize,dwBlockTableKey); - SetFilePointer(mpqOpenArc->hFile,mpqOpenArc->dwMPQStart+mpqOpenArc->MpqHeader.dwBlockTableOffset,0,FILE_BEGIN); - WriteFile(mpqOpenArc->hFile,buffer,sizeof(BLOCKTABLEENTRY) * mpqOpenArc->MpqHeader.dwBlockTableSize,&tsz,0); - SFFree(buffer); - } - else { - EncryptData((LPBYTE)mpqOpenArc->lpBlockTable,sizeof(BLOCKTABLEENTRY) * mpqOpenArc->MpqHeader.dwBlockTableSize,dwBlockTableKey); - SetFilePointer(mpqOpenArc->hFile,mpqOpenArc->dwMPQStart+mpqOpenArc->MpqHeader.dwBlockTableOffset,0,FILE_BEGIN); - WriteFile(mpqOpenArc->hFile,mpqOpenArc->lpBlockTable,sizeof(BLOCKTABLEENTRY) * mpqOpenArc->MpqHeader.dwBlockTableSize,&tsz,0); - DecryptData((LPBYTE)mpqOpenArc->lpBlockTable,sizeof(BLOCKTABLEENTRY) * mpqOpenArc->MpqHeader.dwBlockTableSize,dwBlockTableKey); - } + WriteHashTable(mpqOpenArc); + WriteBlockTable(mpqOpenArc); AddToInternalListing(hMPQ,lpFileName); return TRUE; } @@ -2505,7 +2423,7 @@ BOOL SFMPQAPI WINAPI MpqRenameAndSetFileLocale(MPQHANDLE hMPQ, LPCSTR lpcOldFile DWORD HeaderLength=0; if (memcmp(&mpqOpenArc->MpqHeader.dwMPQID,ID_BN3,4)==0) { - SetFilePointer(mpqOpenArc->hFile,mpqOpenArc->dwMPQStart+mpqOpenArc->lpBlockTable[BlockIndex].dwFileOffset,0,FILE_BEGIN); + SFSetFilePointer(mpqOpenArc->hFile, mpqOpenArc->qwMPQStart + MakeUInt64(mpqOpenArc->lpBlockTable[BlockIndex].dwFileOffset, mpqOpenArc->lpFileOffsetsHigh[BlockIndex]), FILE_BEGIN); ReadFile(mpqOpenArc->hFile,&HeaderLength,4,&tsz,0); } @@ -2520,7 +2438,7 @@ BOOL SFMPQAPI WINAPI MpqRenameAndSetFileLocale(MPQHANDLE hMPQ, LPCSTR lpcOldFile DWORD i; if ((mpqOpenArc->lpBlockTable[BlockIndex].dwFlags & MAFA_COMPRESS)==MAFA_COMPRESS || (mpqOpenArc->lpBlockTable[BlockIndex].dwFlags & MAFA_COMPRESS2)==MAFA_COMPRESS2) { - SetFilePointer(mpqOpenArc->hFile,mpqOpenArc->dwMPQStart+mpqOpenArc->lpBlockTable[BlockIndex].dwFileOffset+HeaderLength,0,FILE_BEGIN); + SFSetFilePointer(mpqOpenArc->hFile, mpqOpenArc->qwMPQStart + MakeUInt64(mpqOpenArc->lpBlockTable[BlockIndex].dwFileOffset, mpqOpenArc->lpFileOffsetsHigh[BlockIndex]) + HeaderLength, FILE_BEGIN); ReadFile(mpqOpenArc->hFile,dwBlockPtrTable,(TotalBlocks+1)*4,&tsz,0); DecryptData((LPBYTE)dwBlockPtrTable,(TotalBlocks+1)*4,dwOldCryptKey-1); char *EncryptedTable = (char *)SFAlloc((TotalBlocks+1)*4); @@ -2530,7 +2448,7 @@ BOOL SFMPQAPI WINAPI MpqRenameAndSetFileLocale(MPQHANDLE hMPQ, LPCSTR lpcOldFile } memcpy(EncryptedTable,dwBlockPtrTable,(TotalBlocks+1)*4); EncryptData((LPBYTE)EncryptedTable,(TotalBlocks+1)*4,dwNewCryptKey-1); - SetFilePointer(mpqOpenArc->hFile,mpqOpenArc->dwMPQStart+mpqOpenArc->lpBlockTable[BlockIndex].dwFileOffset+HeaderLength,0,FILE_BEGIN); + SFSetFilePointer(mpqOpenArc->hFile, mpqOpenArc->qwMPQStart + MakeUInt64(mpqOpenArc->lpBlockTable[BlockIndex].dwFileOffset, mpqOpenArc->lpFileOffsetsHigh[BlockIndex]) + HeaderLength, FILE_BEGIN); WriteFile(mpqOpenArc->hFile,EncryptedTable,(TotalBlocks+1)*4,&tsz,0); SFFree(EncryptedTable); } @@ -2544,16 +2462,16 @@ BOOL SFMPQAPI WINAPI MpqRenameAndSetFileLocale(MPQHANDLE hMPQ, LPCSTR lpcOldFile char *blkBuffer = (char *)SFAlloc(blockSize); if (blkBuffer==0) { EncryptData((LPBYTE)dwBlockPtrTable,(TotalBlocks+1)*4,dwOldCryptKey-1); - SetFilePointer(mpqOpenArc->hFile,mpqOpenArc->dwMPQStart+mpqOpenArc->lpBlockTable[BlockIndex].dwFileOffset+HeaderLength,0,FILE_BEGIN); + SFSetFilePointer(mpqOpenArc->hFile, mpqOpenArc->qwMPQStart + MakeUInt64(mpqOpenArc->lpBlockTable[BlockIndex].dwFileOffset, mpqOpenArc->lpFileOffsetsHigh[BlockIndex]) + HeaderLength, FILE_BEGIN); WriteFile(mpqOpenArc->hFile,dwBlockPtrTable,(TotalBlocks+1)*4,&tsz,0); SFFree(dwBlockPtrTable); return FALSE; } for (i=0;ihFile,mpqOpenArc->dwMPQStart+mpqOpenArc->lpBlockTable[BlockIndex].dwFileOffset+HeaderLength+dwBlockPtrTable[i],0,FILE_BEGIN); + SFSetFilePointer(mpqOpenArc->hFile, mpqOpenArc->qwMPQStart + MakeUInt64(mpqOpenArc->lpBlockTable[BlockIndex].dwFileOffset, mpqOpenArc->lpFileOffsetsHigh[BlockIndex]) + HeaderLength + dwBlockPtrTable[i], FILE_BEGIN); if (ReadFile(mpqOpenArc->hFile,blkBuffer,dwBlockPtrTable[i+1]-dwBlockPtrTable[i],&tsz,0)==0) { EncryptData((LPBYTE)dwBlockPtrTable,(TotalBlocks+1)*4,dwOldCryptKey-1); - SetFilePointer(mpqOpenArc->hFile,mpqOpenArc->dwMPQStart+mpqOpenArc->lpBlockTable[BlockIndex].dwFileOffset+HeaderLength,0,FILE_BEGIN); + SFSetFilePointer(mpqOpenArc->hFile, mpqOpenArc->qwMPQStart + MakeUInt64(mpqOpenArc->lpBlockTable[BlockIndex].dwFileOffset, mpqOpenArc->lpFileOffsetsHigh[BlockIndex]) + HeaderLength, FILE_BEGIN); WriteFile(mpqOpenArc->hFile,dwBlockPtrTable,(TotalBlocks+1)*4,&tsz,0); SFFree(dwBlockPtrTable); SFFree(blkBuffer); @@ -2561,7 +2479,7 @@ BOOL SFMPQAPI WINAPI MpqRenameAndSetFileLocale(MPQHANDLE hMPQ, LPCSTR lpcOldFile } DecryptData((LPBYTE)blkBuffer,dwBlockPtrTable[i+1]-dwBlockPtrTable[i],dwOldCryptKey+i); EncryptData((LPBYTE)blkBuffer,dwBlockPtrTable[i+1]-dwBlockPtrTable[i],dwNewCryptKey+i); - SetFilePointer(mpqOpenArc->hFile,mpqOpenArc->dwMPQStart+mpqOpenArc->lpBlockTable[BlockIndex].dwFileOffset+HeaderLength+dwBlockPtrTable[i],0,FILE_BEGIN); + SFSetFilePointer(mpqOpenArc->hFile, mpqOpenArc->qwMPQStart + MakeUInt64(mpqOpenArc->lpBlockTable[BlockIndex].dwFileOffset, mpqOpenArc->lpFileOffsetsHigh[BlockIndex]) + HeaderLength + dwBlockPtrTable[i], FILE_BEGIN); WriteFile(mpqOpenArc->hFile,blkBuffer,dwBlockPtrTable[i+1]-dwBlockPtrTable[i],&tsz,0); } SFFree(dwBlockPtrTable); @@ -2573,20 +2491,7 @@ BOOL SFMPQAPI WINAPI MpqRenameAndSetFileLocale(MPQHANDLE hMPQ, LPCSTR lpcOldFile oldHashEntry->dwNameHashB = 0xFFFFFFFF; oldHashEntry->lcLocale = 0xFFFFFFFF; oldHashEntry->dwBlockTableIndex = 0xFFFFFFFE; - char *buffer = (char *)SFAlloc(sizeof(HASHTABLEENTRY) * mpqOpenArc->MpqHeader.dwHashTableSize); - if (buffer!=0) { - memcpy(buffer,mpqOpenArc->lpHashTable,sizeof(HASHTABLEENTRY) * mpqOpenArc->MpqHeader.dwHashTableSize); - EncryptData((LPBYTE)buffer,sizeof(HASHTABLEENTRY) * mpqOpenArc->MpqHeader.dwHashTableSize,dwHashTableKey); - SetFilePointer(mpqOpenArc->hFile,mpqOpenArc->dwMPQStart+mpqOpenArc->MpqHeader.dwHashTableOffset,0,FILE_BEGIN); - WriteFile(mpqOpenArc->hFile,buffer,sizeof(HASHTABLEENTRY) * mpqOpenArc->MpqHeader.dwHashTableSize,&tsz,0); - SFFree(buffer); - } - else { - EncryptData((LPBYTE)mpqOpenArc->lpHashTable,sizeof(HASHTABLEENTRY) * mpqOpenArc->MpqHeader.dwHashTableSize,dwHashTableKey); - SetFilePointer(mpqOpenArc->hFile,mpqOpenArc->dwMPQStart+mpqOpenArc->MpqHeader.dwHashTableOffset,0,FILE_BEGIN); - WriteFile(mpqOpenArc->hFile,mpqOpenArc->lpHashTable,sizeof(HASHTABLEENTRY) * mpqOpenArc->MpqHeader.dwHashTableSize,&tsz,0); - DecryptData((LPBYTE)mpqOpenArc->lpHashTable,sizeof(HASHTABLEENTRY) * mpqOpenArc->MpqHeader.dwHashTableSize,dwHashTableKey); - } + WriteHashTable(mpqOpenArc); } LCID dwOldLocale=LocaleID; LocaleID=nOldLocale; @@ -2626,22 +2531,7 @@ BOOL SFMPQAPI WINAPI MpqDeleteFileWithLocale(MPQHANDLE hMPQ, LPCSTR lpFileName, hashEntry->dwNameHashB = 0xFFFFFFFF; hashEntry->lcLocale = 0xFFFFFFFF; hashEntry->dwBlockTableIndex = 0xFFFFFFFE; - DWORD tsz; - char *buffer = (char *)SFAlloc(sizeof(HASHTABLEENTRY) * mpqOpenArc->MpqHeader.dwHashTableSize); - if (buffer!=0) { - memcpy(buffer,mpqOpenArc->lpHashTable,sizeof(HASHTABLEENTRY) * mpqOpenArc->MpqHeader.dwHashTableSize); - EncryptData((LPBYTE)buffer,sizeof(HASHTABLEENTRY) * mpqOpenArc->MpqHeader.dwHashTableSize,dwHashTableKey); - SetFilePointer(mpqOpenArc->hFile,mpqOpenArc->dwMPQStart+mpqOpenArc->MpqHeader.dwHashTableOffset,0,FILE_BEGIN); - - WriteFile(mpqOpenArc->hFile,buffer,sizeof(HASHTABLEENTRY) * mpqOpenArc->MpqHeader.dwHashTableSize,&tsz,0); - SFFree(buffer); - } - else { - EncryptData((LPBYTE)mpqOpenArc->lpHashTable,sizeof(HASHTABLEENTRY) * mpqOpenArc->MpqHeader.dwHashTableSize,dwHashTableKey); - SetFilePointer(mpqOpenArc->hFile,mpqOpenArc->dwMPQStart+mpqOpenArc->MpqHeader.dwHashTableOffset,0,FILE_BEGIN); - WriteFile(mpqOpenArc->hFile,mpqOpenArc->lpHashTable,sizeof(HASHTABLEENTRY) * mpqOpenArc->MpqHeader.dwHashTableSize,&tsz,0); - DecryptData((LPBYTE)mpqOpenArc->lpHashTable,sizeof(HASHTABLEENTRY) * mpqOpenArc->MpqHeader.dwHashTableSize,dwHashTableKey); - } + WriteHashTable(mpqOpenArc); LCID dwOldLocale=LocaleID; LocaleID=nLocale; RemoveFromInternalListing(hMPQ,lpFileName); @@ -2665,7 +2555,7 @@ BOOL SFMPQAPI WINAPI MpqCompactArchive(MPQHANDLE hMPQ) char *lpFileName = (char *)NewAlloc.Alloc(strlen(mpqOpenArc->lpFileName)+13); sprintf(lpFileName,"%s.compact",mpqOpenArc->lpFileName); HANDLE hFile = CreateFile(lpFileName,GENERIC_READ|GENERIC_WRITE,0,0,CREATE_NEW,0,0); - DWORD i; + UInt64 i; if (hFile==INVALID_HANDLE_VALUE) { for (i=0;i<10000;i++) { sprintf(lpFileName,"%s.compact.%04ld",mpqOpenArc->lpFileName,i); @@ -2675,7 +2565,8 @@ BOOL SFMPQAPI WINAPI MpqCompactArchive(MPQHANDLE hMPQ) } if (i==10000) return FALSE; } - DWORD dwLastOffset = sizeof(MPQHEADER),tsz; + UInt64 qwLastOffset = mpqOpenArc->dwHeaderSize; + DWORD tsz; char *buffer = (char *)SFAlloc(65536); if (buffer==0) { CloseHandle(hFile); @@ -2689,7 +2580,8 @@ BOOL SFMPQAPI WINAPI MpqCompactArchive(MPQHANDLE hMPQ) DeleteFile(lpFileName); return FALSE; } - BLOCKTABLEENTRY *lpBlockTable = (BLOCKTABLEENTRY *)SFAlloc(sizeof(BLOCKTABLEENTRY) * mpqOpenArc->MpqHeader.dwBlockTableSize); + BLOCKTABLEENTRY *lpBlockTable = (BLOCKTABLEENTRY *)SFAlloc((sizeof(BLOCKTABLEENTRY) + sizeof(UInt16)) * mpqOpenArc->MpqHeader.dwBlockTableSize); + UInt16 *lpdwFileOffsetsHigh = (UInt16 *)(lpBlockTable + mpqOpenArc->MpqHeader.dwBlockTableSize); if(mpqOpenArc->lpBlockTable!=0) { if (lpBlockTable==0) { SFFree(lpHashTable); @@ -2708,15 +2600,15 @@ BOOL SFMPQAPI WINAPI MpqCompactArchive(MPQHANDLE hMPQ) } if (jMpqHeader.dwHashTableSize) { memcpy(&lpBlockTable[i-nBlkOffset],&mpqOpenArc->lpBlockTable[i],sizeof(BLOCKTABLEENTRY)); - lpBlockTable[i-nBlkOffset].dwFileOffset = dwLastOffset; - dwLastOffset += mpqOpenArc->lpBlockTable[i].dwCompressedSize; + SplitUInt64(lpBlockTable[i-nBlkOffset].dwFileOffset, lpdwFileOffsetsHigh[i-nBlkOffset], qwLastOffset); + qwLastOffset += mpqOpenArc->lpBlockTable[i].dwCompressedSize; DWORD dwWritten=FALSE; if (mpqOpenArc->lpBlockTable[i].dwFlags&MAFA_ENCRYPT && mpqOpenArc->lpBlockTable[i].dwFlags&MAFA_MODCRYPTKEY && (mpqOpenArc->lpBlockTable[i].dwFlags&MAFA_COMPRESS || mpqOpenArc->lpBlockTable[i].dwFlags&MAFA_COMPRESS2)) { DWORD HeaderLength=0; if (memcmp(&mpqOpenArc->MpqHeader.dwMPQID,ID_BN3,4)==0) { - SetFilePointer(mpqOpenArc->hFile,mpqOpenArc->dwMPQStart+mpqOpenArc->lpBlockTable[i].dwFileOffset,0,FILE_BEGIN); + SFSetFilePointer(mpqOpenArc->hFile, mpqOpenArc->qwMPQStart + MakeUInt64(mpqOpenArc->lpBlockTable[i].dwFileOffset, mpqOpenArc->lpFileOffsetsHigh[i]), FILE_BEGIN); ReadFile(mpqOpenArc->hFile,&HeaderLength,4,&tsz,0); } DWORD blockSize = 512 << mpqOpenArc->MpqHeader.wBlockSize; @@ -2732,7 +2624,7 @@ BOOL SFMPQAPI WINAPI MpqCompactArchive(MPQHANDLE hMPQ) DeleteFile(lpFileName); return FALSE; } - SetFilePointer(mpqOpenArc->hFile,mpqOpenArc->dwMPQStart+mpqOpenArc->lpBlockTable[i].dwFileOffset+HeaderLength,0,FILE_BEGIN); + SFSetFilePointer(mpqOpenArc->hFile, mpqOpenArc->qwMPQStart + MakeUInt64(mpqOpenArc->lpBlockTable[i].dwFileOffset, mpqOpenArc->lpFileOffsetsHigh[i]) + HeaderLength, FILE_BEGIN); ReadFile(mpqOpenArc->hFile,dwBlockPtrTable,(TotalBlocks+1)*4,&tsz,0); DWORD dwOldCryptKey = DetectFileSeed(dwBlockPtrTable,(TotalBlocks+1)*4,blockSize); DWORD dwNewCryptKey = (dwOldCryptKey ^ mpqOpenArc->lpBlockTable[i].dwFullSize) - mpqOpenArc->lpBlockTable[i].dwFileOffset; @@ -2818,7 +2710,7 @@ BOOL SFMPQAPI WINAPI MpqCompactArchive(MPQHANDLE hMPQ) } memcpy(EncryptedTable,dwBlockPtrTable,(TotalBlocks+1)*4); EncryptData((LPBYTE)EncryptedTable,(TotalBlocks+1)*4,dwNewCryptKey-1); - SetFilePointer(hFile,lpBlockTable[i-nBlkOffset].dwFileOffset+HeaderLength,0,FILE_BEGIN); + SFSetFilePointer(hFile, MakeUInt64(lpBlockTable[i-nBlkOffset].dwFileOffset, lpdwFileOffsetsHigh[i-nBlkOffset]) + HeaderLength, FILE_BEGIN); WriteFile(hFile,EncryptedTable,(TotalBlocks+1)*4,&tsz,0); SFFree(EncryptedTable); char *blkBuffer = (char *)SFAlloc(blockSize); @@ -2832,7 +2724,7 @@ BOOL SFMPQAPI WINAPI MpqCompactArchive(MPQHANDLE hMPQ) return FALSE; } for (DWORD k=0;khFile,mpqOpenArc->dwMPQStart+mpqOpenArc->lpBlockTable[i].dwFileOffset+HeaderLength+dwBlockPtrTable[k],0,FILE_BEGIN); + SFSetFilePointer(mpqOpenArc->hFile, mpqOpenArc->qwMPQStart + MakeUInt64(mpqOpenArc->lpBlockTable[i].dwFileOffset, mpqOpenArc->lpFileOffsetsHigh[i]) + HeaderLength + dwBlockPtrTable[k], FILE_BEGIN); if (ReadFile(mpqOpenArc->hFile,blkBuffer,dwBlockPtrTable[k+1]-dwBlockPtrTable[k],&tsz,0)==0) { SFFree(dwBlockPtrTable); SFFree(blkBuffer); @@ -2845,7 +2737,7 @@ BOOL SFMPQAPI WINAPI MpqCompactArchive(MPQHANDLE hMPQ) } DecryptData((LPBYTE)blkBuffer,dwBlockPtrTable[k+1]-dwBlockPtrTable[k],dwOldCryptKey+k); EncryptData((LPBYTE)blkBuffer,dwBlockPtrTable[k+1]-dwBlockPtrTable[k],dwNewCryptKey+k); - SetFilePointer(hFile,lpBlockTable[i-nBlkOffset].dwFileOffset+HeaderLength+dwBlockPtrTable[k],0,FILE_BEGIN); + SFSetFilePointer(hFile, MakeUInt64(lpBlockTable[i-nBlkOffset].dwFileOffset, lpdwFileOffsetsHigh[i-nBlkOffset]) + HeaderLength + dwBlockPtrTable[k], FILE_BEGIN); WriteFile(hFile,blkBuffer,dwBlockPtrTable[k+1]-dwBlockPtrTable[k],&tsz,0); } SFFree(blkBuffer); @@ -2859,7 +2751,7 @@ BOOL SFMPQAPI WINAPI MpqCompactArchive(MPQHANDLE hMPQ) if (memcmp(&mpqOpenArc->MpqHeader.dwMPQID,ID_BN3,4)==0) { - SetFilePointer(mpqOpenArc->hFile,mpqOpenArc->dwMPQStart+mpqOpenArc->lpBlockTable[i].dwFileOffset,0,FILE_BEGIN); + SFSetFilePointer(mpqOpenArc->hFile, mpqOpenArc->qwMPQStart + MakeUInt64(mpqOpenArc->lpBlockTable[i].dwFileOffset, mpqOpenArc->lpFileOffsetsHigh[i]), FILE_BEGIN); ReadFile(mpqOpenArc->hFile,&HeaderLength,4,&tsz,0); } DWORD blockSize = 512 << mpqOpenArc->MpqHeader.wBlockSize; @@ -2944,7 +2836,7 @@ BOOL SFMPQAPI WINAPI MpqCompactArchive(MPQHANDLE hMPQ) return FALSE; } for (DWORD k=0;klpBlockTable[i].dwFullSize;k+=blockSize) { - SetFilePointer(mpqOpenArc->hFile,mpqOpenArc->dwMPQStart+mpqOpenArc->lpBlockTable[i].dwFileOffset+HeaderLength+k,0,FILE_BEGIN); + SFSetFilePointer(mpqOpenArc->hFile, mpqOpenArc->qwMPQStart + MakeUInt64(mpqOpenArc->lpBlockTable[i].dwFileOffset, mpqOpenArc->lpFileOffsetsHigh[i]) + HeaderLength + k, FILE_BEGIN); if (k+blockSize>mpqOpenArc->lpBlockTable[i].dwFullSize) blockSize = mpqOpenArc->lpBlockTable[i].dwFullSize % blockSize; if (ReadFile(mpqOpenArc->hFile,blkBuffer,blockSize,&tsz,0)==0) { SFFree(blkBuffer); @@ -2958,7 +2850,7 @@ BOOL SFMPQAPI WINAPI MpqCompactArchive(MPQHANDLE hMPQ) } DecryptData((LPBYTE)blkBuffer,blockSize,dwOldCryptKey+k); EncryptData((LPBYTE)blkBuffer,blockSize,dwNewCryptKey+k); - SetFilePointer(hFile,lpBlockTable[i-nBlkOffset].dwFileOffset+HeaderLength+k,0,FILE_BEGIN); + SFSetFilePointer(hFile, MakeUInt64(lpBlockTable[i-nBlkOffset].dwFileOffset, lpdwFileOffsetsHigh[i-nBlkOffset]) + HeaderLength + k, FILE_BEGIN); WriteFile(hFile,blkBuffer,blockSize,&tsz,0); } SFFree(blkBuffer); @@ -2968,8 +2860,8 @@ BOOL SFMPQAPI WINAPI MpqCompactArchive(MPQHANDLE hMPQ) if (dwWritten==FALSE) { ReadSize = 65536; for (j=0;jlpBlockTable[i].dwCompressedSize;j+=65536) { - SetFilePointer(mpqOpenArc->hFile,mpqOpenArc->dwMPQStart+mpqOpenArc->lpBlockTable[i].dwFileOffset+j,0,FILE_BEGIN); - SetFilePointer(hFile,lpBlockTable[i-nBlkOffset].dwFileOffset+j,0,FILE_BEGIN); + SFSetFilePointer(mpqOpenArc->hFile, mpqOpenArc->qwMPQStart + MakeUInt64(mpqOpenArc->lpBlockTable[i].dwFileOffset, mpqOpenArc->lpFileOffsetsHigh[i]) + j, FILE_BEGIN); + SFSetFilePointer(hFile, MakeUInt64(lpBlockTable[i-nBlkOffset].dwFileOffset, lpdwFileOffsetsHigh[i-nBlkOffset]) + j, FILE_BEGIN); if (j+65536>mpqOpenArc->lpBlockTable[i].dwCompressedSize) ReadSize = mpqOpenArc->lpBlockTable[i].dwCompressedSize-j; if (ReadFile(mpqOpenArc->hFile,buffer,ReadSize,&tsz,0)==0) { SFFree(lpBlockTable); @@ -2999,51 +2891,48 @@ BOOL SFMPQAPI WINAPI MpqCompactArchive(MPQHANDLE hMPQ) } } mpqOpenArc->MpqHeader.dwBlockTableSize -= nBlkOffset; - mpqOpenArc->MpqHeader.dwHashTableOffset = dwLastOffset; - dwLastOffset += mpqOpenArc->MpqHeader.dwHashTableSize * sizeof(HASHTABLEENTRY); - mpqOpenArc->MpqHeader.dwBlockTableOffset = dwLastOffset; - dwLastOffset += mpqOpenArc->MpqHeader.dwBlockTableSize * sizeof(BLOCKTABLEENTRY); - mpqOpenArc->MpqHeader.dwMPQSize = dwLastOffset; + SplitUInt64(mpqOpenArc->MpqHeader.dwHashTableOffset, mpqOpenArc->MpqHeader_Ex.wHashTableOffsetHigh, qwLastOffset); + qwLastOffset += mpqOpenArc->MpqHeader.dwHashTableSize * sizeof(HASHTABLEENTRY); + SplitUInt64(mpqOpenArc->MpqHeader.dwBlockTableOffset, mpqOpenArc->MpqHeader_Ex.wBlockTableOffsetHigh, qwLastOffset); + qwLastOffset += mpqOpenArc->MpqHeader.dwBlockTableSize * sizeof(BLOCKTABLEENTRY); + if (mpqOpenArc->MpqHeader_Ex.qwExtendedBlockOffsetTable) { + mpqOpenArc->MpqHeader_Ex.qwExtendedBlockOffsetTable = qwLastOffset; + qwLastOffset += mpqOpenArc->MpqHeader.dwBlockTableSize * sizeof(UInt16); + } + mpqOpenArc->MpqHeader.dwMPQSize = (UInt32)qwLastOffset; SFFree(mpqOpenArc->lpHashTable); mpqOpenArc->lpHashTable = lpHashTable; if(mpqOpenArc->lpBlockTable!=0) { SFFree(mpqOpenArc->lpBlockTable); - mpqOpenArc->lpBlockTable = (BLOCKTABLEENTRY *)SFAlloc(mpqOpenArc->MpqHeader.dwBlockTableSize * sizeof(BLOCKTABLEENTRY)); + mpqOpenArc->lpBlockTable = (BLOCKTABLEENTRY *)SFAlloc(mpqOpenArc->MpqHeader.dwBlockTableSize * (sizeof(BLOCKTABLEENTRY) + sizeof(UInt16))); + mpqOpenArc->lpFileOffsetsHigh = (UInt16 *)(mpqOpenArc->lpBlockTable + mpqOpenArc->MpqHeader.dwBlockTableSize); if (mpqOpenArc->lpBlockTable==0) { mpqOpenArc->lpBlockTable = lpBlockTable; + mpqOpenArc->lpFileOffsetsHigh = lpdwFileOffsetsHigh; } else { - memcpy(mpqOpenArc->lpBlockTable,lpBlockTable,mpqOpenArc->MpqHeader.dwBlockTableSize * sizeof(BLOCKTABLEENTRY)); + memcpy(mpqOpenArc->lpBlockTable, lpBlockTable, mpqOpenArc->MpqHeader.dwBlockTableSize * (sizeof(BLOCKTABLEENTRY) + sizeof(UInt16))); SFFree(lpBlockTable); } } - SetFilePointer(mpqOpenArc->hFile,mpqOpenArc->dwMPQStart+dwLastOffset,0,FILE_BEGIN); + SFSetFilePointer(mpqOpenArc->hFile, mpqOpenArc->qwMPQStart + qwLastOffset, FILE_BEGIN); SetEndOfFile(mpqOpenArc->hFile); - SetFilePointer(mpqOpenArc->hFile,mpqOpenArc->dwMPQStart,0,FILE_BEGIN); - mpqOpenArc->MpqHeader.dwHeaderSize = sizeof(MPQHEADER); - WriteFile(mpqOpenArc->hFile,&mpqOpenArc->MpqHeader,sizeof(MPQHEADER),&tsz,0); - dwLastOffset = sizeof(MPQHEADER); + MpqWriteHeaders(mpqOpenArc); + mpqOpenArc->MpqHeader.dwHeaderSize = mpqOpenArc->dwHeaderSize; + qwLastOffset = mpqOpenArc->dwHeaderSize; ReadSize = 65536; - for (i=dwLastOffset;iMpqHeader.dwHashTableOffset;i+=65536) { - SetFilePointer(mpqOpenArc->hFile,mpqOpenArc->dwMPQStart+i,0,FILE_BEGIN); - SetFilePointer(hFile,i,0,FILE_BEGIN); - if (i+65536>mpqOpenArc->MpqHeader.dwHashTableOffset) ReadSize = mpqOpenArc->MpqHeader.dwHashTableOffset-i; + for (i=qwLastOffset;iMpqHeader.dwHashTableOffset, mpqOpenArc->MpqHeader_Ex.wHashTableOffsetHigh);i+=65536) { + SFSetFilePointer(mpqOpenArc->hFile,mpqOpenArc->qwMPQStart+i,FILE_BEGIN); + SFSetFilePointer(hFile,i,FILE_BEGIN); + if (i+65536>MakeUInt64(mpqOpenArc->MpqHeader.dwHashTableOffset, mpqOpenArc->MpqHeader_Ex.wHashTableOffsetHigh)) ReadSize = MakeUInt64(mpqOpenArc->MpqHeader.dwHashTableOffset, mpqOpenArc->MpqHeader_Ex.wHashTableOffsetHigh)-i; ReadFile(hFile,buffer,ReadSize,&tsz,0); WriteFile(mpqOpenArc->hFile,buffer,ReadSize,&tsz,0); } SFFree(buffer); CloseHandle(hFile); DeleteFile(lpFileName); - EncryptData((BYTE *)mpqOpenArc->lpHashTable,mpqOpenArc->MpqHeader.dwHashTableSize * sizeof(HASHTABLEENTRY),dwHashTableKey); - SetFilePointer(mpqOpenArc->hFile,mpqOpenArc->dwMPQStart+mpqOpenArc->MpqHeader.dwHashTableOffset,0,FILE_BEGIN); - WriteFile(mpqOpenArc->hFile,mpqOpenArc->lpHashTable,mpqOpenArc->MpqHeader.dwHashTableSize * sizeof(HASHTABLEENTRY),&tsz,0); - DecryptData((BYTE *)mpqOpenArc->lpHashTable,mpqOpenArc->MpqHeader.dwHashTableSize * sizeof(HASHTABLEENTRY),dwHashTableKey); - if(mpqOpenArc->lpBlockTable!=0) { - EncryptData((BYTE *)mpqOpenArc->lpBlockTable,mpqOpenArc->MpqHeader.dwBlockTableSize * sizeof(BLOCKTABLEENTRY),dwBlockTableKey); - SetFilePointer(mpqOpenArc->hFile,mpqOpenArc->dwMPQStart+mpqOpenArc->MpqHeader.dwBlockTableOffset,0,FILE_BEGIN); - WriteFile(mpqOpenArc->hFile,mpqOpenArc->lpBlockTable,mpqOpenArc->MpqHeader.dwBlockTableSize * sizeof(BLOCKTABLEENTRY),&tsz,0); - DecryptData((BYTE *)mpqOpenArc->lpBlockTable,mpqOpenArc->MpqHeader.dwBlockTableSize * sizeof(BLOCKTABLEENTRY),dwBlockTableKey); - } + WriteHashTable(mpqOpenArc); + WriteBlockTable(mpqOpenArc); return TRUE; } @@ -3064,22 +2953,8 @@ BOOL SFMPQAPI WINAPI MpqSetFileLocale(MPQHANDLE hMPQ, LPCSTR lpFileName, LCID nO if (hashEntry==0) return FALSE; if (hashEntry->lcLocale!=nOldLocale) return FALSE; hashEntry->lcLocale = nNewLocale; - DWORD tsz; - char *buffer = (char *)SFAlloc(sizeof(HASHTABLEENTRY) * mpqOpenArc->MpqHeader.dwHashTableSize); - if (buffer!=0) { - memcpy(buffer,mpqOpenArc->lpHashTable,sizeof(HASHTABLEENTRY) * mpqOpenArc->MpqHeader.dwHashTableSize); - EncryptData((LPBYTE)buffer,sizeof(HASHTABLEENTRY) * mpqOpenArc->MpqHeader.dwHashTableSize,dwHashTableKey); - SetFilePointer(mpqOpenArc->hFile,mpqOpenArc->dwMPQStart+mpqOpenArc->MpqHeader.dwHashTableOffset,0,FILE_BEGIN); - WriteFile(mpqOpenArc->hFile,buffer,sizeof(HASHTABLEENTRY) * mpqOpenArc->MpqHeader.dwHashTableSize,&tsz,0); - SFFree(buffer); - } - else { - EncryptData((LPBYTE)mpqOpenArc->lpHashTable,sizeof(HASHTABLEENTRY) * mpqOpenArc->MpqHeader.dwHashTableSize,dwHashTableKey); - SetFilePointer(mpqOpenArc->hFile,mpqOpenArc->dwMPQStart+mpqOpenArc->MpqHeader.dwHashTableOffset,0,FILE_BEGIN); - WriteFile(mpqOpenArc->hFile,mpqOpenArc->lpHashTable,sizeof(HASHTABLEENTRY) * mpqOpenArc->MpqHeader.dwHashTableSize,&tsz,0); - DecryptData((LPBYTE)mpqOpenArc->lpHashTable,sizeof(HASHTABLEENTRY) * mpqOpenArc->MpqHeader.dwHashTableSize,dwHashTableKey); - } + WriteHashTable(mpqOpenArc); LCID dwOldLocale=LocaleID; LocaleID=nOldLocale; RemoveFromInternalListing(hMPQ,lpFileName); @@ -3090,18 +2965,42 @@ BOOL SFMPQAPI WINAPI MpqSetFileLocale(MPQHANDLE hMPQ, LPCSTR lpFileName, LCID nO return TRUE; } +BOOL SFMPQAPI WINAPI MpqCreateArchiveVersion(WORD wVersion) +{ + if (wVersion > 1) return FALSE; + + wCreationVersion = wVersion; + return TRUE; +} + DWORD SFMPQAPI WINAPI SFileFindMpqHeader(HANDLE hFile) { if (hFile == INVALID_HANDLE_VALUE) { SetLastError(ERROR_INVALID_PARAMETER); return 0xFFFFFFFF; } - DWORD FileLen = GetFileSize(hFile,0); + + DWORD dwHandleType = GetHandleType((MPQHANDLE)hFile); + if (dwHandleType == SFILE_TYPE_FILE) { + MPQFILE *mpqOpenFile = (MPQFILE *)hFile; + if (mpqOpenFile->hFile == INVALID_HANDLE_VALUE) { + return mpqOpenFile->lpParentArc->qwMPQStart; + } + else { + hFile = mpqOpenFile->hFile; + } + } + else if (dwHandleType == SFILE_TYPE_MPQ) { + return ((MPQARCHIVE *)hFile)->qwMPQStart; + } + + UInt64 FileLen = SFGetFileSize(hFile); + if (FileLen >= 0xFFFFFFFF) FileLen = 0xFFFFFFFE; char pbuf[sizeof(MPQHEADER)]; DWORD tsz; for (DWORD i=0;i= FileLen || qwStart + qwLength > FileLen) return (UInt64)-1; + if (qwLength == 0) qwLength = FileLen - qwStart; char pbuf[sizeof(MPQHEADER)]; DWORD tsz; - for (DWORD i=dwStart;idwStart+dwLength) tsz = (dwStart+dwLength)-i; - if (tszqwStart+qwLength) tsz = (qwStart+qwLength)-i; + if (tsz>= 2; - - while(dwLength-- > 0) - - { - seed += dwCryptTable[0x400 + (dwKey & 0xFF)]; - ch = *lpdwBuffer ^ (dwKey + seed); - - dwKey = ((~dwKey << 0x15) + 0x11111111) | (dwKey >> 0x0B); - seed = *lpdwBuffer + seed + (seed << 5) + 3; - - *lpdwBuffer++ = ch; - } - - return TRUE; -} - -BOOL DecryptData(LPBYTE lpbyBuffer, DWORD dwLength, DWORD dwKey) -{ - LPDWORD lpdwBuffer = (LPDWORD)lpbyBuffer; - DWORD seed = 0xEEEEEEEE; - DWORD ch; - - if (!lpbyBuffer) - return FALSE; - - // Round to DWORDs - dwLength >>= 2; - - while(dwLength-- > 0) - { - seed += dwCryptTable[0x400 + (dwKey & 0xFF)]; - ch = *lpdwBuffer ^ (dwKey + seed); - - dwKey = ((~dwKey << 0x15) + 0x11111111) | (dwKey >> 0x0B); - seed = ch + seed + (seed << 5) + 3; - - *lpdwBuffer++ = ch; - } - - return TRUE; -} - -//----------------------------------------------------------------------------- -// Functions tries to get file decryption key. The trick comes from block -// positions which are stored at the begin of each compressed file. We know the -// file size, that means we know number of blocks that means we know the first -// DWORD value in block position. And if we know encrypted and decrypted value, -// we can find the decryption key !!! -// -// hf - MPQ file handle -// block - DWORD array of block positions -// ch - Decrypted value of the first block pos - -static DWORD DetectFileSeed(DWORD * block, DWORD decrypted, DWORD blocksize) -{ - DWORD saveSeed1; - DWORD temp = *block ^ decrypted; // temp = seed1 + seed2 - // temp = seed1 + stormBuffer[0x400 + (seed1 & 0xFF)] + 0xEEEEEEEE - temp -= 0xEEEEEEEE; // temp = seed1 + stormBuffer[0x400 + (seed1 & 0xFF)] - - - for(int i = 0; i < 0x100; i++) // Try all 256 possibilities - { - DWORD seed1; - DWORD seed2 = 0xEEEEEEEE; - DWORD ch; - - // Try the first DWORD (We exactly know the value) - seed1 = temp - dwCryptTable[0x400 + i]; - seed2 += dwCryptTable[0x400 + (seed1 & 0xFF)]; - ch = block[0] ^ (seed1 + seed2); - - if(ch != decrypted) - continue; - - saveSeed1 = seed1 + 1; - - // If OK, continue and test the second value. We don't know exactly the value, - // but we know that the second one has a value less than or equal to the - // size of the block position table plus the block size - seed1 = ((~seed1 << 0x15) + 0x11111111) | (seed1 >> 0x0B); - seed2 = ch + seed2 + (seed2 << 5) + 3; - - seed2 += dwCryptTable[0x400 + (seed1 & 0xFF)]; - ch = block[1] ^ (seed1 + seed2); - - if(ch <= decrypted + blocksize) - return saveSeed1; - } - return 0; -} - DWORD DetectFileSeedEx(MPQARCHIVE * mpqOpenArc, HASHTABLEENTRY * lpHashEntry, LPCSTR * lplpFileName) { if (mpqOpenArc==0 || lpHashEntry==0) return 0; @@ -3766,7 +3479,7 @@ DWORD DetectFileSeedEx(MPQARCHIVE * mpqOpenArc, HASHTABLEENTRY * lpHashEntry, LP DWORD HeaderLength=0,tsz; if (memcmp(&mpqOpenArc->MpqHeader.dwMPQID,ID_BN3,4)==0) { - SetFilePointer(mpqOpenArc->hFile,mpqOpenArc->dwMPQStart+mpqOpenArc->lpBlockTable[dwBlockIndex].dwFileOffset,0,FILE_BEGIN); + SFSetFilePointer(mpqOpenArc->hFile, mpqOpenArc->qwMPQStart + MakeUInt64(mpqOpenArc->lpBlockTable[dwBlockIndex].dwFileOffset, mpqOpenArc->lpFileOffsetsHigh[dwBlockIndex]), FILE_BEGIN); ReadFile(mpqOpenArc->hFile,&HeaderLength,4,&tsz,0); } DWORD blockSize = 512 << mpqOpenArc->MpqHeader.wBlockSize; @@ -3776,7 +3489,7 @@ DWORD DetectFileSeedEx(MPQARCHIVE * mpqOpenArc, HASHTABLEENTRY * lpHashEntry, LP DWORD *dwBlockPtrTable = (DWORD *)SFAlloc((TotalBlocks+1)*4); if (dwBlockPtrTable==0) return 0; - SetFilePointer(mpqOpenArc->hFile,mpqOpenArc->dwMPQStart+mpqOpenArc->lpBlockTable[dwBlockIndex].dwFileOffset+HeaderLength,0,FILE_BEGIN); + SFSetFilePointer(mpqOpenArc->hFile, mpqOpenArc->qwMPQStart + MakeUInt64(mpqOpenArc->lpBlockTable[dwBlockIndex].dwFileOffset, mpqOpenArc->lpFileOffsetsHigh[dwBlockIndex]) + HeaderLength, FILE_BEGIN); ReadFile(mpqOpenArc->hFile,dwBlockPtrTable,(TotalBlocks+1)*4,&tsz,0); dwCryptKey = DetectFileSeed(dwBlockPtrTable,(TotalBlocks+1)*4,blockSize);