X-Git-Url: https://sfsrealm.hopto.org/projects/?a=blobdiff_plain;f=SFmpqapi.cpp;h=628d29fb2bfd204a9e8f391fc8a5610e3694a23b;hb=259ebaeb9ff628fe0086c2cf93daadbc03b9391f;hp=a0d5a13991c63c51249f1cdce8d5c5afd5eba114;hpb=7214af3eb69acdaef221c1846157ed07438bd0c1;p=SFmpqapi.git diff --git a/SFmpqapi.cpp b/SFmpqapi.cpp index a0d5a13..628d29f 100644 --- a/SFmpqapi.cpp +++ b/SFmpqapi.cpp @@ -13,6 +13,7 @@ #include "../SComp/SComp.h" +#include "SFmpqInternal.h" #include "MpqCrypt.h" #include "MpqHashTable.h" #include "MpqBlockTable.h" @@ -53,6 +54,7 @@ SFMPQLIBMODULE::~SFMPQLIBMODULE() #endif LCID LocaleID = 0; +WORD wCreationVersion = 0; BOOL SFMpqInit = FALSE; HINSTANCE hStorm = 0; #ifdef _USRDLL @@ -101,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; @@ -113,7 +112,7 @@ void LoadStorm(); void FreeStorm(); 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); @@ -287,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; } @@ -318,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; @@ -329,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; @@ -356,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 (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 = SFGetFileSize(hFile); mpqOpenArc = (MPQARCHIVE *)SFAlloc(sizeof(MPQARCHIVE)); if (!mpqOpenArc) { SFFree(lpnOpenMpq); CloseHandle(hFile); - *hMPQ = 0; return FALSE; } - SFSetFilePointer(hFile,dwMpqStart,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; - } - } - SFSetFilePointer(hFile,dwMpqStart+mpqOpenArc->MpqHeader.dwHashTableOffset,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) { - SFSetFilePointer(hFile,dwMpqStart+mpqOpenArc->MpqHeader.dwBlockTableOffset,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); @@ -526,6 +563,7 @@ BOOL WINAPI MpqOpenArchiveEx(LPCSTR lpFileName, DWORD dwPriority, DWORD dwFlags, dwOpenMpqCount++; if (dwOpenMpqCount>1) SortOpenArchivesByPriority(); *hMPQ = (MPQHANDLE)mpqOpenArc; + return TRUE; } else { @@ -538,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; } @@ -562,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; } - SFSetFilePointer(hFile,dwMpqStart,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; - } - } - SFSetFilePointer(hFile,dwMpqStart+mpqOpenArc->MpqHeader.dwHashTableOffset,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) { - SFSetFilePointer(hFile,dwMpqStart+mpqOpenArc->MpqHeader.dwBlockTableOffset,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); @@ -668,6 +641,7 @@ BOOL SFMPQAPI WINAPI SFileOpenFileAsArchive(MPQHANDLE hSourceMPQ, LPCSTR lpFileN dwOpenMpqCount++; if (dwOpenMpqCount>1) SortOpenArchivesByPriority(); *hMPQ = (MPQHANDLE)mpqOpenArc; + return TRUE; } else { @@ -911,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; @@ -1073,7 +1048,7 @@ DWORD SFMPQAPI WINAPI SFileGetFileInfo(MPQHANDLE hFile, DWORD dwInfoType) case SFILE_INFO_PRIORITY: return mpqOpenArc->dwPriority; case SFILE_INFO_HASH_INDEX: - return ((INT_PTR)mpqOpenFile->lpHashEntry-(INT_PTR)mpqOpenArc->lpHashTable)/sizeof(HASHTABLEENTRY); + return ((UIntPtr)mpqOpenFile->lpHashEntry-(UIntPtr)mpqOpenArc->lpHashTable)/sizeof(HASHTABLEENTRY); case SFILE_INFO_BLOCK_INDEX: return mpqOpenFile->lpHashEntry->dwBlockTableIndex; default: @@ -1198,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; @@ -1215,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); @@ -1228,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) { - SFSetFilePointer(mpqOpenArc->hFile,mpqOpenArc->dwMPQStart+mpqOpenArc->lpBlockTable[BlockIndex].dwFileOffset,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; @@ -1237,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)) { - SFSetFilePointer(mpqOpenArc->hFile,mpqOpenArc->dwMPQStart+mpqOpenArc->lpBlockTable[BlockIndex].dwFileOffset+HeaderLength,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); @@ -1255,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],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; @@ -1285,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; @@ -1295,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); @@ -1367,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; @@ -1483,7 +1482,7 @@ BOOL SFMPQAPI WINAPI SFileListFiles(MPQHANDLE hMPQ, LPCSTR lpFileLists, FILELIST lpListBuffer[i].dwFileExists = 1; else lpListBuffer[i].dwFileExists=0xFFFFFFFF; - SFSetFilePointer(mpqOpenArc->hFile,mpqOpenArc->dwMPQStart+mpqOpenArc->lpBlockTable[dwBlockIndex].dwFileOffset+0x40,FILE_BEGIN); + 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)) { @@ -1920,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; @@ -2001,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; - SFSetFilePointer(mpqOpenArc->hFile,mpqOpenArc->dwMPQStart,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); @@ -2023,7 +2024,7 @@ BOOL SFMPQAPI WINAPI MpqAddFileToArchiveEx(MPQHANDLE hMPQ, LPCSTR lpSourceFileNa } } SFFree(dwBlkpt); - SFSetFilePointer(mpqOpenArc->hFile,mpqOpenArc->dwMPQStart+dwFileOffset,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); WriteHashTable(mpqOpenArc); @@ -2240,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; @@ -2320,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; - SFSetFilePointer(mpqOpenArc->hFile,mpqOpenArc->dwMPQStart,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); @@ -2343,7 +2346,7 @@ BOOL SFMPQAPI WINAPI MpqAddFileFromBufferEx(MPQHANDLE hMPQ, LPVOID lpBuffer, DWO } } SFFree(dwBlkpt); - SFSetFilePointer(mpqOpenArc->hFile,mpqOpenArc->dwMPQStart+dwFileOffset,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); WriteHashTable(mpqOpenArc); @@ -2420,7 +2423,7 @@ BOOL SFMPQAPI WINAPI MpqRenameAndSetFileLocale(MPQHANDLE hMPQ, LPCSTR lpcOldFile DWORD HeaderLength=0; if (memcmp(&mpqOpenArc->MpqHeader.dwMPQID,ID_BN3,4)==0) { - SFSetFilePointer(mpqOpenArc->hFile,mpqOpenArc->dwMPQStart+mpqOpenArc->lpBlockTable[BlockIndex].dwFileOffset,FILE_BEGIN); + SFSetFilePointer(mpqOpenArc->hFile, mpqOpenArc->qwMPQStart + MakeUInt64(mpqOpenArc->lpBlockTable[BlockIndex].dwFileOffset, mpqOpenArc->lpFileOffsetsHigh[BlockIndex]), FILE_BEGIN); ReadFile(mpqOpenArc->hFile,&HeaderLength,4,&tsz,0); } @@ -2435,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) { - SFSetFilePointer(mpqOpenArc->hFile,mpqOpenArc->dwMPQStart+mpqOpenArc->lpBlockTable[BlockIndex].dwFileOffset+HeaderLength,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); @@ -2445,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); - SFSetFilePointer(mpqOpenArc->hFile,mpqOpenArc->dwMPQStart+mpqOpenArc->lpBlockTable[BlockIndex].dwFileOffset+HeaderLength,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); } @@ -2459,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); - SFSetFilePointer(mpqOpenArc->hFile,mpqOpenArc->dwMPQStart+mpqOpenArc->lpBlockTable[BlockIndex].dwFileOffset+HeaderLength,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],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); - SFSetFilePointer(mpqOpenArc->hFile,mpqOpenArc->dwMPQStart+mpqOpenArc->lpBlockTable[BlockIndex].dwFileOffset+HeaderLength,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); @@ -2476,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); - SFSetFilePointer(mpqOpenArc->hFile,mpqOpenArc->dwMPQStart+mpqOpenArc->lpBlockTable[BlockIndex].dwFileOffset+HeaderLength+dwBlockPtrTable[i],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); @@ -2552,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); @@ -2562,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); @@ -2576,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); @@ -2595,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) { - SFSetFilePointer(mpqOpenArc->hFile,mpqOpenArc->dwMPQStart+mpqOpenArc->lpBlockTable[i].dwFileOffset,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; @@ -2619,7 +2624,7 @@ BOOL SFMPQAPI WINAPI MpqCompactArchive(MPQHANDLE hMPQ) DeleteFile(lpFileName); return FALSE; } - SFSetFilePointer(mpqOpenArc->hFile,mpqOpenArc->dwMPQStart+mpqOpenArc->lpBlockTable[i].dwFileOffset+HeaderLength,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; @@ -2705,7 +2710,7 @@ BOOL SFMPQAPI WINAPI MpqCompactArchive(MPQHANDLE hMPQ) } memcpy(EncryptedTable,dwBlockPtrTable,(TotalBlocks+1)*4); EncryptData((LPBYTE)EncryptedTable,(TotalBlocks+1)*4,dwNewCryptKey-1); - SFSetFilePointer(hFile,lpBlockTable[i-nBlkOffset].dwFileOffset+HeaderLength,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); @@ -2719,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],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); @@ -2732,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); - SFSetFilePointer(hFile,lpBlockTable[i-nBlkOffset].dwFileOffset+HeaderLength+dwBlockPtrTable[k],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); @@ -2746,7 +2751,7 @@ BOOL SFMPQAPI WINAPI MpqCompactArchive(MPQHANDLE hMPQ) if (memcmp(&mpqOpenArc->MpqHeader.dwMPQID,ID_BN3,4)==0) { - SFSetFilePointer(mpqOpenArc->hFile,mpqOpenArc->dwMPQStart+mpqOpenArc->lpBlockTable[i].dwFileOffset,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; @@ -2831,7 +2836,7 @@ BOOL SFMPQAPI WINAPI MpqCompactArchive(MPQHANDLE hMPQ) return FALSE; } for (DWORD k=0;klpBlockTable[i].dwFullSize;k+=blockSize) { - SFSetFilePointer(mpqOpenArc->hFile,mpqOpenArc->dwMPQStart+mpqOpenArc->lpBlockTable[i].dwFileOffset+HeaderLength+k,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); @@ -2845,7 +2850,7 @@ BOOL SFMPQAPI WINAPI MpqCompactArchive(MPQHANDLE hMPQ) } DecryptData((LPBYTE)blkBuffer,blockSize,dwOldCryptKey+k); EncryptData((LPBYTE)blkBuffer,blockSize,dwNewCryptKey+k); - SFSetFilePointer(hFile,lpBlockTable[i-nBlkOffset].dwFileOffset+HeaderLength+k,FILE_BEGIN); + SFSetFilePointer(hFile, MakeUInt64(lpBlockTable[i-nBlkOffset].dwFileOffset, lpdwFileOffsetsHigh[i-nBlkOffset]) + HeaderLength + k, FILE_BEGIN); WriteFile(hFile,blkBuffer,blockSize,&tsz,0); } SFFree(blkBuffer); @@ -2855,8 +2860,8 @@ BOOL SFMPQAPI WINAPI MpqCompactArchive(MPQHANDLE hMPQ) if (dwWritten==FALSE) { ReadSize = 65536; for (j=0;jlpBlockTable[i].dwCompressedSize;j+=65536) { - SFSetFilePointer(mpqOpenArc->hFile,mpqOpenArc->dwMPQStart+mpqOpenArc->lpBlockTable[i].dwFileOffset+j,FILE_BEGIN); - SFSetFilePointer(hFile,lpBlockTable[i-nBlkOffset].dwFileOffset+j,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); @@ -2886,35 +2891,40 @@ 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); } } - SFSetFilePointer(mpqOpenArc->hFile,mpqOpenArc->dwMPQStart+dwLastOffset,FILE_BEGIN); + SFSetFilePointer(mpqOpenArc->hFile, mpqOpenArc->qwMPQStart + qwLastOffset, FILE_BEGIN); SetEndOfFile(mpqOpenArc->hFile); - SFSetFilePointer(mpqOpenArc->hFile,mpqOpenArc->dwMPQStart,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) { - SFSetFilePointer(mpqOpenArc->hFile,mpqOpenArc->dwMPQStart+i,FILE_BEGIN); + 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>mpqOpenArc->MpqHeader.dwHashTableOffset) ReadSize = mpqOpenArc->MpqHeader.dwHashTableOffset-i; + 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); } @@ -2955,13 +2965,37 @@ 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 = SFGetFileSize(hFile); + + 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 (tszMpqHeader.dwMPQID,ID_BN3,4)==0) { - SFSetFilePointer(mpqOpenArc->hFile,mpqOpenArc->dwMPQStart+mpqOpenArc->lpBlockTable[dwBlockIndex].dwFileOffset,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; @@ -3452,7 +3489,7 @@ DWORD DetectFileSeedEx(MPQARCHIVE * mpqOpenArc, HASHTABLEENTRY * lpHashEntry, LP DWORD *dwBlockPtrTable = (DWORD *)SFAlloc((TotalBlocks+1)*4); if (dwBlockPtrTable==0) return 0; - SFSetFilePointer(mpqOpenArc->hFile,mpqOpenArc->dwMPQStart+mpqOpenArc->lpBlockTable[dwBlockIndex].dwFileOffset+HeaderLength,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);