Current News
Archived News
Search News
Discussion Forum


Old Forum
Install Programs More Downloads...
Troubleshooting
Source Code
Format Specs.
Misc. Information
Non-SF Stuff
Links




ShadowFlare [Sun, 3 Jan 2010 08:31:07 +0000 (01:31 -0700)]
MpqBlockTable.cpp
MpqHashTable.cpp
SFTypes.h
SFUtil.cpp
SFUtil.h
SFmpqInternal.h [new file with mode: 0644]
SFmpqapi.cpp
SFmpqapi.h
SFmpqapi.vcproj

index 650acc1..e351f05 100644 (file)
@@ -2,6 +2,7 @@
 
 #include <windows.h>
 #include "SFmpqapi.h"
+#include "SFmpqInternal.h"
 #include "SFUtil.h"
 #include "MpqCrypt.h"
 
@@ -16,13 +17,13 @@ BOOL WriteBlockTable(MPQARCHIVE *mpqOpenArc)
        if (buffer) {
                memcpy(buffer,mpqOpenArc->lpBlockTable,sizeof(BLOCKTABLEENTRY) * mpqOpenArc->MpqHeader.dwBlockTableSize);
                EncryptData((LPBYTE)buffer,sizeof(BLOCKTABLEENTRY) * mpqOpenArc->MpqHeader.dwBlockTableSize,dwBlockTableKey);
-               SFSetFilePointer(mpqOpenArc->hFile,mpqOpenArc->dwMPQStart+mpqOpenArc->MpqHeader.dwBlockTableOffset,FILE_BEGIN);
+               SFSetFilePointer(mpqOpenArc->hFile, mpqOpenArc->qwMPQStart + mpqOpenArc->MpqHeader.dwBlockTableOffset + ((UINT64)mpqOpenArc->MpqHeader_Ex.wBlockTableOffsetHigh << 32), 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);
-               SFSetFilePointer(mpqOpenArc->hFile,mpqOpenArc->dwMPQStart+mpqOpenArc->MpqHeader.dwBlockTableOffset,FILE_BEGIN);
+               SFSetFilePointer(mpqOpenArc->hFile, mpqOpenArc->qwMPQStart + mpqOpenArc->MpqHeader.dwBlockTableOffset + ((UINT64)mpqOpenArc->MpqHeader_Ex.wBlockTableOffsetHigh << 32), FILE_BEGIN);
                WriteFile(mpqOpenArc->hFile,mpqOpenArc->lpBlockTable,sizeof(BLOCKTABLEENTRY) * mpqOpenArc->MpqHeader.dwBlockTableSize,&tsz,0);
                DecryptData((LPBYTE)mpqOpenArc->lpBlockTable,sizeof(BLOCKTABLEENTRY) * mpqOpenArc->MpqHeader.dwBlockTableSize,dwBlockTableKey);
        }
index 90072c1..625746c 100644 (file)
@@ -2,6 +2,7 @@
 
 #include <windows.h>
 #include "SFmpqapi.h"
+#include "SFmpqInternal.h"
 #include "SFUtil.h"
 #include "MpqCrypt.h"
 
@@ -13,13 +14,13 @@ BOOL WriteHashTable(MPQARCHIVE *mpqOpenArc)
        if (buffer) {
                memcpy(buffer,mpqOpenArc->lpHashTable,sizeof(HASHTABLEENTRY) * mpqOpenArc->MpqHeader.dwHashTableSize);
                EncryptData((LPBYTE)buffer,sizeof(HASHTABLEENTRY) * mpqOpenArc->MpqHeader.dwHashTableSize,dwHashTableKey);
-               SFSetFilePointer(mpqOpenArc->hFile,mpqOpenArc->dwMPQStart+mpqOpenArc->MpqHeader.dwHashTableOffset,FILE_BEGIN);
+               SFSetFilePointer(mpqOpenArc->hFile, mpqOpenArc->qwMPQStart + mpqOpenArc->MpqHeader.dwHashTableOffset + ((UINT64)mpqOpenArc->MpqHeader_Ex.wHashTableOffsetHigh << 32), 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);
-               SFSetFilePointer(mpqOpenArc->hFile,mpqOpenArc->dwMPQStart+mpqOpenArc->MpqHeader.dwHashTableOffset,FILE_BEGIN);
+               SFSetFilePointer(mpqOpenArc->hFile, mpqOpenArc->qwMPQStart + mpqOpenArc->MpqHeader.dwHashTableOffset + ((UINT64)mpqOpenArc->MpqHeader_Ex.wHashTableOffsetHigh << 32), FILE_BEGIN);
                WriteFile(mpqOpenArc->hFile,mpqOpenArc->lpHashTable,sizeof(HASHTABLEENTRY) * mpqOpenArc->MpqHeader.dwHashTableSize,&tsz,0);
                DecryptData((LPBYTE)mpqOpenArc->lpHashTable,sizeof(HASHTABLEENTRY) * mpqOpenArc->MpqHeader.dwHashTableSize,dwHashTableKey);
        }
index 5758b9a..f58bfba 100644 (file)
--- a/SFTypes.h
+++ b/SFTypes.h
@@ -56,5 +56,11 @@ union IntConv {
        UInt64 ui64;
 };
 
+#define SplitUInt64(L_Low, L_High, R) \
+       L_Low = (UInt32)(R); \
+       L_High = (UInt32)((R) >> 32);
+
+#define MakeUInt64(R_Low, R_High) ((UInt64)(R_Low) + (UInt64)((R_High) << 32))
+
 #endif // #ifndef SFTYPES_INCLUDED
 
index 76d2228..c2b01cf 100644 (file)
@@ -36,7 +36,7 @@ void WINAPI SFFree(LPVOID lpvMemory)
        if (lpvMemory) free(lpvMemory);
 }
 
-Int64 SFGetFileSize(HANDLE hFile)
+UInt64 SFGetFileSize(HANDLE hFile)
 {
        IntConv FileSize;
 
@@ -46,26 +46,26 @@ Int64 SFGetFileSize(HANDLE hFile)
 
        if (FileSize.ui32[0] == INVALID_FILE_SIZE) {
                if (::GetLastError() != NO_ERROR)
-                       return -1;
+                       return (UInt64)-1;
        }
 
-       return FileSize.i64;
+       return FileSize.ui64;
 }
 
-Int64 SFSetFilePointer(HANDLE hFile, Int64 nDistance, UInt32 dwMoveMethod)
+UInt64 SFSetFilePointer(HANDLE hFile, Int64 nDistance, UInt32 dwMoveMethod)
 {
        IntConv FilePos;
 
        FilePos.i64 = nDistance;
 
-       FilePos.i32[0] = ::SetFilePointer(hFile, FilePos.i32[0], &FilePos.i32[1], dwMoveMethod);
+       FilePos.ui32[0] = ::SetFilePointer(hFile, FilePos.i32[0], &FilePos.i32[1], dwMoveMethod);
 
-       if (FilePos.i32[0] == INVALID_SET_FILE_POINTER) {
+       if (FilePos.ui32[0] == INVALID_SET_FILE_POINTER) {
                if (::GetLastError() != NO_ERROR)
-                       return -1;
+                       return (UInt64)-1;
        }
 
-       return FilePos.i64;
+       return FilePos.ui64;
 }
 
 size_t strlnlen(const char *strline)
index 7325d46..f87e409 100644 (file)
--- a/SFUtil.h
+++ b/SFUtil.h
@@ -9,8 +9,8 @@
 LPVOID WINAPI SFAlloc(DWORD dwSize);
 void WINAPI SFFree(LPVOID lpvMemory);
 void WINAPI SFMemZero(LPVOID lpvDestination, DWORD dwLength);
-Int64 SFGetFileSize(HANDLE hFile);
-Int64 SFSetFilePointer(HANDLE hFile, Int64 nDistance, UInt32 dwMoveMethod);
+UInt64 SFGetFileSize(HANDLE hFile);
+UInt64 SFSetFilePointer(HANDLE hFile, Int64 nDistance, UInt32 dwMoveMethod);
 size_t strlnlen(const char *strline);
 char *nextline(const char *strline);
 
diff --git a/SFmpqInternal.h b/SFmpqInternal.h
new file mode 100644 (file)
index 0000000..6ae0e3c
--- /dev/null
@@ -0,0 +1,72 @@
+// License information for this code is in license.txt
+
+#ifndef SFMPQ_INTERNAL_INCLUDED
+#define SFMPQ_INTERNAL_INCLUDED
+
+#include <windows.h>
+#include "SFmpqapi.h"
+
+struct MPQARCHIVE;
+struct MPQFILE;
+
+//Archive handles are typecasted to this struct internally to access
+//this data.  This struct is based on Storm's internal struct for
+//archive handles.
+struct MPQARCHIVE {
+       // Arranged according to priority with lowest priority first
+       MPQARCHIVE * lpNextArc; //0// Pointer to the next MPQARCHIVE struct. Pointer to addresses of first and last archives if last archive
+       MPQARCHIVE * lpPrevArc; //4// Pointer to the previous MPQARCHIVE struct. 0xEAFC5E23 if first archive
+       char szFileName[260]; //8// Filename of the archive
+       HANDLE hFile; //10C// The archive's file handle
+       DWORD dwFlags1; //110// Some flags, bit 0 seems to be set when opening an archive from a hard drive if bit 1 in the flags for SFileOpenArchive is set, bit 1 (0 based) seems to be set when opening an archive from a CD
+       DWORD dwPriority; //114// Priority of the archive set when calling SFileOpenArchive
+       MPQFILE * lpLastReadFile; //118// Pointer to the last read file's MPQFILE struct. This is cleared when finished reading a block
+       DWORD dwUnk; //11C// Seems to always be 0
+       DWORD dwBlockSize; //120// Size of file blocks in bytes
+       BYTE * lpLastReadBlock; //124// Pointer to the read buffer for archive. This is cleared when finished reading a block
+       DWORD dwBufferSize; //128// Size of the read buffer for archive. This is cleared when finished reading a block
+       UINT64 qwMPQStart; //12C// The starting offset of the archive
+       UINT64 qwMPQEnd; //130// The ending offset of the archive
+       MPQHEADER * lpMPQHeader; //134// Pointer to the archive header
+       BLOCKTABLEENTRY * lpBlockTable; //138// Pointer to the start of the block table
+       HASHTABLEENTRY * lpHashTable; //13C// Pointer to the start of the hash table
+       UINT64 qwReadOffset; //140// Offset to the data for a file
+       DWORD dwRefCount; //144// Count of references to this open archive.  This is incremented for each file opened from the archive, and decremented for each file closed
+       // Extra struct members used by SFmpq
+       MPQHEADER MpqHeader;
+       DWORD dwFlags; //The only flags that should be changed are MOAU_MAINTAIN_LISTFILE and MOAU_MAINTAIN_ATTRIBUTES, changing any others can have unpredictable effects
+       LPSTR lpFileName;
+       DWORD dwExtraFlags;
+       MPQHEADER_EX MpqHeader_Ex;
+       DWORD dwHeaderSize;
+       WORD * lpFileOffsetsHigh;
+};
+
+//Handles to files in the archive are typecasted to this struct
+//internally to access this data.  This struct is based on
+//Storm's internal struct for file handles.
+struct MPQFILE {
+       MPQFILE * lpNextFile; //0// Pointer to the next MPQFILE struct. Pointer to addresses of first and last files if last file
+       MPQFILE * lpPrevFile; //4// Pointer to the previous MPQFILE struct. 0xEAFC5E13 if first file
+       char szFileName[260]; //8// Filename of the file
+       HANDLE hFile; //10C// Always INVALID_HANDLE_VALUE for files in MPQ archives. For files not in MPQ archives, this is the file handle for the file and the rest of this struct is filled with zeros except for dwRefCount
+       MPQARCHIVE * lpParentArc; //110// Pointer to the MPQARCHIVE struct of the archive in which the file is contained
+       BLOCKTABLEENTRY * lpBlockEntry; //114// Pointer to the file's block table entry
+       DWORD dwCryptKey; //118// Decryption key for the file
+       DWORD dwFilePointer; //11C// Position of file pointer in the file
+       DWORD dwUnk; //120// Seems to always be 0
+       DWORD dwBlockCount; //124// Number of blocks in file
+       DWORD * lpdwBlockOffsets; //128// Offsets to blocks in file. There are 1 more of these than the number of blocks. The values for this are set after the first read
+       DWORD dwReadStarted; //12C// Set to 1 after first read
+       BOOL bStreaming; //130// 1 when streaming a WAVE
+       BYTE * lpLastReadBlock; //134// Pointer to the read buffer for file. This starts at the position specified in the last SFileSetFilePointer call. This is cleared when SFileSetFilePointer is called or when finished reading the block
+       DWORD dwBytesRead; //138// Total bytes read from the current block in the open file. This is cleared when SFileSetFilePointer is called or when finished reading the block
+       DWORD dwBufferSize; //13C// Size of the read buffer for file. This is cleared when SFileSetFilePointer is called or when finished reading the block
+       DWORD dwRefCount; //140// Count of references to this open file
+       // Extra struct members used by SFmpq
+       HASHTABLEENTRY *lpHashEntry;
+       LPSTR lpFileName;
+       WORD wFileOffsetHigh;
+};
+
+#endif // #ifndef SFMPQ_INTERNAL_INCLUDED
index e89bf42..c09d3cc 100644 (file)
@@ -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
@@ -113,7 +115,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);
@@ -289,7 +291,8 @@ void SFMPQAPI WINAPI AboutSFMpq()
 
 BOOL WINAPI MpqOpenArchiveEx(LPCSTR lpFileName, DWORD dwPriority, DWORD dwFlags, MPQHANDLE *hMPQ, DWORD dwFlags2, DWORD dwMaximumFilesInArchive, DWORD dwBlockSize)
 {
-       DWORD flen,tsz;
+       UInt64 flen;
+       DWORD tsz;
 
        if (!lpFileName || !hMPQ) {
                SetLastError(ERROR_INVALID_PARAMETER);
@@ -361,11 +364,11 @@ BOOL WINAPI MpqOpenArchiveEx(LPCSTR lpFileName, DWORD dwPriority, DWORD dwFlags,
                        *hMPQ = 0;
                        return FALSE;
                }
-               DWORD dwMpqStart;
+               UInt64 qwMpqStart;
                MPQARCHIVE *mpqOpenArc;
                if (SFGetFileSize(hFile)==0 && !(dwFlags2 & MOAU_READ_ONLY))
                {
-                       dwMpqStart = 0;
+                       qwMpqStart = 0;
                        mpqOpenArc = (MPQARCHIVE *)SFAlloc(sizeof(MPQARCHIVE));
                        if (!mpqOpenArc) {
                                SFFree(lpnOpenMpq);
@@ -375,7 +378,13 @@ BOOL WINAPI MpqOpenArchiveEx(LPCSTR lpFileName, DWORD dwPriority, DWORD dwFlags,
                        }
                        memcpy(&mpqOpenArc->MpqHeader.dwMPQID,ID_MPQ,4);
                        mpqOpenArc->MpqHeader.dwHeaderSize = sizeof(MPQHEADER);
-                       mpqOpenArc->MpqHeader.wVersion = 0;
+                       mpqOpenArc->MpqHeader.wVersion = wCreationVersion;
+
+                       if (mpqOpenArc->MpqHeader.wVersion == 0)
+                               mpqOpenArc->MpqHeader.dwHeaderSize = sizeof(MPQHEADER);
+                       else
+                               mpqOpenArc->MpqHeader.dwHeaderSize = sizeof(MPQHEADER) + sizeof(MPQHEADER_EX);
+
                        if (dwBlockSize & 0xFFFF0000)
                                mpqOpenArc->MpqHeader.wBlockSize = DEFAULT_BLOCK_SIZE;
                        else
@@ -387,6 +396,9 @@ BOOL WINAPI MpqOpenArchiveEx(LPCSTR lpFileName, DWORD dwPriority, DWORD dwFlags,
                        mpqOpenArc->MpqHeader.dwBlockTableSize = 0;
                        mpqOpenArc->MpqHeader.dwHashTableOffset = mpqOpenArc->MpqHeader.dwHeaderSize;
                        mpqOpenArc->MpqHeader.dwBlockTableOffset = mpqOpenArc->MpqHeader.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->MpqHeader.dwHeaderSize + mpqOpenArc->MpqHeader.dwHashTableSize * sizeof(HASHTABLEENTRY);
                        if(WriteFile(hFile,&mpqOpenArc->MpqHeader,mpqOpenArc->MpqHeader.dwHeaderSize,&tsz,0)==0) {
                                SFFree(lpnOpenMpq);
@@ -417,8 +429,8 @@ BOOL WINAPI MpqOpenArchiveEx(LPCSTR lpFileName, DWORD dwPriority, DWORD dwFlags,
                }
                else
                {
-                       dwMpqStart = SFileFindMpqHeader(hFile);
-                       if (dwMpqStart==0xFFFFFFFF) {
+                       qwMpqStart = SFileFindMpqHeaderEx(hFile);
+                       if (qwMpqStart == (UInt64)-1) {
                                SFFree(lpnOpenMpq);
                                CloseHandle(hFile);
                                SetLastError(MPQ_ERROR_MPQ_INVALID);
@@ -433,7 +445,7 @@ BOOL WINAPI MpqOpenArchiveEx(LPCSTR lpFileName, DWORD dwPriority, DWORD dwFlags,
                                *hMPQ = 0;
                                return FALSE;
                        }
-                       SFSetFilePointer(hFile,dwMpqStart,FILE_BEGIN);
+                       SFSetFilePointer(hFile, qwMpqStart, FILE_BEGIN);
                        if(ReadFile(hFile,&mpqOpenArc->MpqHeader,sizeof(MPQHEADER),&tsz,0)==0) {
                                SFFree(lpnOpenMpq);
                                SFFree(mpqOpenArc);
@@ -441,6 +453,16 @@ BOOL WINAPI MpqOpenArchiveEx(LPCSTR lpFileName, DWORD dwPriority, DWORD dwFlags,
                                *hMPQ = 0;
                                return FALSE;
                        }
+
+                       if (mpqOpenArc->MpqHeader.wVersion > 0) {
+                               ReadFile(hFile, &mpqOpenArc->MpqHeader_Ex, sizeof(MPQHEADER_EX), &tsz, 0);
+                               mpqOpenArc->dwHeaderSize = sizeof(MPQHEADER) + sizeof(MPQHEADER_EX);
+                       }
+                       else {
+                               memset(&mpqOpenArc->MpqHeader_Ex, 0, sizeof(MPQHEADER_EX));
+                               mpqOpenArc->dwHeaderSize = sizeof(MPQHEADER);
+                       }
+
                        mpqOpenArc->lpHashTable = (HASHTABLEENTRY *)SFAlloc(sizeof(HASHTABLEENTRY) * mpqOpenArc->MpqHeader.dwHashTableSize);
                        if(!mpqOpenArc->lpHashTable) {
                                SFFree(lpnOpenMpq);
@@ -450,7 +472,8 @@ BOOL WINAPI MpqOpenArchiveEx(LPCSTR lpFileName, DWORD dwPriority, DWORD dwFlags,
                                return FALSE;
                        }
                        if (mpqOpenArc->MpqHeader.dwBlockTableSize!=0) {
-                               mpqOpenArc->lpBlockTable = (BLOCKTABLEENTRY *)SFAlloc(sizeof(BLOCKTABLEENTRY) * 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) {
                                        SFFree(mpqOpenArc->lpHashTable);
                                        SFFree(lpnOpenMpq);
@@ -460,7 +483,7 @@ BOOL WINAPI MpqOpenArchiveEx(LPCSTR lpFileName, DWORD dwPriority, DWORD dwFlags,
                                        return FALSE;
                                }
                        }
-                       SFSetFilePointer(hFile,dwMpqStart+mpqOpenArc->MpqHeader.dwHashTableOffset,FILE_BEGIN);
+                       SFSetFilePointer(hFile, qwMpqStart + mpqOpenArc->MpqHeader.dwHashTableOffset + ((UINT64)mpqOpenArc->MpqHeader_Ex.wHashTableOffsetHigh << 32), FILE_BEGIN);
                        if(ReadFile(hFile,mpqOpenArc->lpHashTable,sizeof(HASHTABLEENTRY) * mpqOpenArc->MpqHeader.dwHashTableSize,&tsz,0)==0) {
                                if(mpqOpenArc->lpBlockTable) SFFree(mpqOpenArc->lpBlockTable);
                                SFFree(mpqOpenArc->lpHashTable);
@@ -471,7 +494,7 @@ BOOL WINAPI MpqOpenArchiveEx(LPCSTR lpFileName, DWORD dwPriority, DWORD dwFlags,
                                return FALSE;
                        }
                        if (mpqOpenArc->MpqHeader.dwBlockTableSize!=0) {
-                               SFSetFilePointer(hFile,dwMpqStart+mpqOpenArc->MpqHeader.dwBlockTableOffset,FILE_BEGIN);
+                               SFSetFilePointer(hFile, qwMpqStart + mpqOpenArc->MpqHeader.dwBlockTableOffset + ((UINT64)mpqOpenArc->MpqHeader_Ex.wBlockTableOffsetHigh << 32), FILE_BEGIN);
                                if(ReadFile(hFile,mpqOpenArc->lpBlockTable,sizeof(BLOCKTABLEENTRY) * mpqOpenArc->MpqHeader.dwBlockTableSize,&tsz,0)==0) {
                                        SFFree(mpqOpenArc->lpBlockTable);
                                        SFFree(mpqOpenArc->lpHashTable);
@@ -481,6 +504,11 @@ BOOL WINAPI MpqOpenArchiveEx(LPCSTR lpFileName, DWORD dwPriority, DWORD dwFlags,
                                        *hMPQ = 0;
                                        return FALSE;
                                }
+
+                               if (mpqOpenArc->MpqHeader_Ex.qwExtendedBlockOffsetTable) {
+                                       SFSetFilePointer(hFile, qwMpqStart + mpqOpenArc->MpqHeader_Ex.qwExtendedBlockOffsetTable, FILE_BEGIN);
+                                       ReadFile(hFile, mpqOpenArc->lpFileOffsetsHigh, sizeof(WORD) * mpqOpenArc->MpqHeader.dwBlockTableSize, &tsz, 0);
+                               }
                        }
                }
                /*mpqOpenArc->lpFileName = (char *)SFAlloc(strlen(lpFileName)+1);
@@ -513,9 +541,9 @@ BOOL WINAPI MpqOpenArchiveEx(LPCSTR lpFileName, DWORD dwPriority, DWORD dwFlags,
                mpqOpenArc->dwBlockSize = 512 << mpqOpenArc->MpqHeader.wBlockSize;
                mpqOpenArc->lpLastReadBlock = 0;
                mpqOpenArc->dwBufferSize = 0;
-               mpqOpenArc->dwMPQStart = dwMpqStart;
+               mpqOpenArc->qwMPQStart = qwMpqStart;
                mpqOpenArc->lpMPQHeader = &mpqOpenArc->MpqHeader;
-               mpqOpenArc->dwReadOffset = flen;
+               mpqOpenArc->qwReadOffset = flen;
                mpqOpenArc->dwRefCount = 1;
                mpqOpenArc->dwFlags = dwFlags2;
                mpqOpenArc->dwExtraFlags = 0;
@@ -565,12 +593,12 @@ BOOL SFMPQAPI WINAPI SFileOpenFileAsArchive(MPQHANDLE hSourceMPQ, LPCSTR lpFileN
                        *hMPQ = 0;
                        return FALSE;
                }
-               DWORD dwMpqStart;
+               UInt64 qwMpqStart;
                MPQARCHIVE *mpqOpenArc;
-               dwMpqStart = mpqArcFile.lpBlockEntry->dwFileOffset;
+               qwMpqStart = mpqArcFile.lpParentArc->qwMPQStart + mpqArcFile.lpBlockEntry->dwFileOffset + ((UInt64)mpqArcFile.wFileOffsetHigh << 32);
                flen = mpqArcFile.lpBlockEntry->dwFullSize;
-               dwMpqStart = FindMpqHeaderAtLocation(hFile,dwMpqStart,flen);
-               if (dwMpqStart==0xFFFFFFFF) {
+               qwMpqStart = SFileFindMpqHeaderEx(hFile, qwMpqStart, flen);
+               if (qwMpqStart == (UInt64)-1) {
                        SFFree(lpnOpenMpq);
                        SetLastError(MPQ_ERROR_MPQ_INVALID);
                        *hMPQ = 0;
@@ -582,7 +610,7 @@ BOOL SFMPQAPI WINAPI SFileOpenFileAsArchive(MPQHANDLE hSourceMPQ, LPCSTR lpFileN
                        *hMPQ = 0;
                        return FALSE;
                }
-               SFSetFilePointer(hFile,dwMpqStart,FILE_BEGIN);
+               SFSetFilePointer(hFile, qwMpqStart, FILE_BEGIN);
                if(ReadFile(hFile,&mpqOpenArc->MpqHeader,sizeof(MPQHEADER),&tsz,0)==0) {
                        SFFree(lpnOpenMpq);
                        SFFree(mpqOpenArc);
@@ -606,7 +634,7 @@ BOOL SFMPQAPI WINAPI SFileOpenFileAsArchive(MPQHANDLE hSourceMPQ, LPCSTR lpFileN
                                return FALSE;
                        }
                }
-               SFSetFilePointer(hFile,dwMpqStart+mpqOpenArc->MpqHeader.dwHashTableOffset,FILE_BEGIN);
+               SFSetFilePointer(hFile, qwMpqStart + mpqOpenArc->MpqHeader.dwHashTableOffset + ((UINT64)mpqOpenArc->MpqHeader_Ex.wHashTableOffsetHigh << 32), FILE_BEGIN);
                if(ReadFile(hFile,mpqOpenArc->lpHashTable,sizeof(HASHTABLEENTRY) * mpqOpenArc->MpqHeader.dwHashTableSize,&tsz,0)==0) {
                        if(mpqOpenArc->lpBlockTable) SFFree(mpqOpenArc->lpBlockTable);
                        SFFree(mpqOpenArc->lpHashTable);
@@ -616,7 +644,7 @@ BOOL SFMPQAPI WINAPI SFileOpenFileAsArchive(MPQHANDLE hSourceMPQ, LPCSTR lpFileN
                        return FALSE;
                }
                if (mpqOpenArc->MpqHeader.dwBlockTableSize!=0) {
-                       SFSetFilePointer(hFile,dwMpqStart+mpqOpenArc->MpqHeader.dwBlockTableOffset,FILE_BEGIN);
+                       SFSetFilePointer(hFile, qwMpqStart + mpqOpenArc->MpqHeader.dwBlockTableOffset + ((UINT64)mpqOpenArc->MpqHeader_Ex.wBlockTableOffsetHigh << 32), FILE_BEGIN);
                        if(ReadFile(hFile,mpqOpenArc->lpBlockTable,sizeof(BLOCKTABLEENTRY) * mpqOpenArc->MpqHeader.dwBlockTableSize,&tsz,0)==0) {
                                SFFree(mpqOpenArc->lpBlockTable);
                                SFFree(mpqOpenArc->lpHashTable);
@@ -655,9 +683,9 @@ BOOL SFMPQAPI WINAPI SFileOpenFileAsArchive(MPQHANDLE hSourceMPQ, LPCSTR lpFileN
                mpqOpenArc->dwBlockSize = 512 << mpqOpenArc->MpqHeader.wBlockSize;
                mpqOpenArc->lpLastReadBlock = 0;
                mpqOpenArc->dwBufferSize = 0;
-               mpqOpenArc->dwMPQStart = dwMpqStart;
+               mpqOpenArc->qwMPQStart = qwMpqStart;
                mpqOpenArc->lpMPQHeader = &mpqOpenArc->MpqHeader;
-               mpqOpenArc->dwReadOffset = flen;
+               mpqOpenArc->qwReadOffset = flen;
                mpqOpenArc->dwRefCount = 1;
                mpqOpenArc->dwFlags = dwFlags;
                mpqOpenArc->dwExtraFlags = 1;
@@ -1228,7 +1256,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 + mpqOpenArc->lpBlockTable[BlockIndex].dwFileOffset + ((UInt64)mpqOpenFile->wFileOffsetHigh << 32), FILE_BEGIN);
                ReadFile(mpqOpenArc->hFile,&HeaderLength,4,&nBytesRead,0);
        }
        DWORD i;
@@ -1245,7 +1273,7 @@ BOOL SFMPQAPI WINAPI SFileReadFile(MPQHANDLE hFile,LPVOID lpBuffer,DWORD nNumber
                }
                if ((mpqOpenArc->lpBlockTable[BlockIndex].dwFlags & MAFA_COMPRESS) || (mpqOpenArc->lpBlockTable[BlockIndex].dwFlags & MAFA_COMPRESS2))
                {
-                       SFSetFilePointer(mpqOpenArc->hFile,mpqOpenArc->dwMPQStart+mpqOpenArc->lpBlockTable[BlockIndex].dwFileOffset+HeaderLength,FILE_BEGIN);
+                       SFSetFilePointer(mpqOpenArc->hFile, mpqOpenArc->qwMPQStart + mpqOpenArc->lpBlockTable[BlockIndex].dwFileOffset + ((UInt64)mpqOpenFile->wFileOffsetHigh << 32) + 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);
@@ -1271,7 +1299,7 @@ BOOL SFMPQAPI WINAPI SFileReadFile(MPQHANDLE hFile,LPVOID lpBuffer,DWORD nNumber
        DWORD blk=0,blki=0;
        for (i=blockNum;i<nBlocks;i++) {
                if (blk==0) {
-                       SFSetFilePointer(mpqOpenArc->hFile,mpqOpenArc->dwMPQStart+mpqOpenArc->lpBlockTable[BlockIndex].dwFileOffset+HeaderLength+mpqOpenFile->lpdwBlockOffsets[i],FILE_BEGIN);
+                       SFSetFilePointer(mpqOpenArc->hFile, mpqOpenArc->qwMPQStart + mpqOpenArc->lpBlockTable[BlockIndex].dwFileOffset + ((UInt64)mpqOpenFile->wFileOffsetHigh << 32) + 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) {
@@ -1483,7 +1511,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 + mpqOpenArc->lpBlockTable[dwBlockIndex].dwFileOffset + ((UInt64)mpqOpenArc->lpFileOffsetsHigh[dwBlockIndex] << 32) + 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)) {
@@ -2002,8 +2030,8 @@ BOOL SFMPQAPI WINAPI MpqAddFileToArchiveEx(MPQHANDLE hMPQ, LPCSTR lpSourceFileNa
        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);
+       SFSetFilePointer(mpqOpenArc->hFile, mpqOpenArc->qwMPQStart, FILE_BEGIN);
+       WriteFile(mpqOpenArc->hFile,&mpqOpenArc->MpqHeader,mpqOpenArc->dwHeaderSize,&tsz,0);
        if (dwFlags & MAFA_ENCRYPT) {
                DWORD dwCryptKey;
                if (dwFlags&MAFA_ENCRYPT) dwCryptKey = HashString(lpDestFileName,HASH_KEY);
@@ -2023,7 +2051,7 @@ BOOL SFMPQAPI WINAPI MpqAddFileToArchiveEx(MPQHANDLE hMPQ, LPCSTR lpSourceFileNa
                }
        }
        SFFree(dwBlkpt);
-       SFSetFilePointer(mpqOpenArc->hFile,mpqOpenArc->dwMPQStart+dwFileOffset,FILE_BEGIN);
+       SFSetFilePointer(mpqOpenArc->hFile, mpqOpenArc->qwMPQStart + dwFileOffset, FILE_BEGIN);
        WriteFile(mpqOpenArc->hFile,buffer,fsz,&tsz,0);
        SFFree(buffer);
        WriteHashTable(mpqOpenArc);
@@ -2321,8 +2349,8 @@ BOOL SFMPQAPI WINAPI MpqAddFileFromBufferEx(MPQHANDLE hMPQ, LPVOID lpBuffer, DWO
        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);
+       SFSetFilePointer(mpqOpenArc->hFile, mpqOpenArc->qwMPQStart, FILE_BEGIN);
+       WriteFile(mpqOpenArc->hFile,&mpqOpenArc->MpqHeader,mpqOpenArc->dwHeaderSize,&tsz,0);
        if (dwFlags & MAFA_ENCRYPT) {
                DWORD dwCryptKey;
                if (dwFlags&MAFA_ENCRYPT) dwCryptKey = HashString(lpFileName,HASH_KEY);
@@ -2343,7 +2371,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 + dwFileOffset, FILE_BEGIN);
        WriteFile(mpqOpenArc->hFile,buffer,fsz,&tsz,0);
        SFFree(buffer);
        WriteHashTable(mpqOpenArc);
@@ -2420,7 +2448,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 + mpqOpenArc->lpBlockTable[BlockIndex].dwFileOffset + ((UInt64)mpqOpenArc->lpFileOffsetsHigh[BlockIndex] << 32), FILE_BEGIN);
                                ReadFile(mpqOpenArc->hFile,&HeaderLength,4,&tsz,0);
 
                        }
@@ -2435,7 +2463,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 + mpqOpenArc->lpBlockTable[BlockIndex].dwFileOffset + ((UInt64)mpqOpenArc->lpFileOffsetsHigh[BlockIndex] << 32) + 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 +2473,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 + mpqOpenArc->lpBlockTable[BlockIndex].dwFileOffset + ((UInt64)mpqOpenArc->lpFileOffsetsHigh[BlockIndex] << 32) + HeaderLength, FILE_BEGIN);
                                WriteFile(mpqOpenArc->hFile,EncryptedTable,(TotalBlocks+1)*4,&tsz,0);
                                SFFree(EncryptedTable);
                        }
@@ -2459,16 +2487,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 + mpqOpenArc->lpBlockTable[BlockIndex].dwFileOffset + ((UInt64)mpqOpenArc->lpFileOffsetsHigh[BlockIndex] << 32) + HeaderLength, FILE_BEGIN);
                                WriteFile(mpqOpenArc->hFile,dwBlockPtrTable,(TotalBlocks+1)*4,&tsz,0);
                                SFFree(dwBlockPtrTable);
                                return FALSE;
                        }
                        for (i=0;i<TotalBlocks;i++) {
-                               SFSetFilePointer(mpqOpenArc->hFile,mpqOpenArc->dwMPQStart+mpqOpenArc->lpBlockTable[BlockIndex].dwFileOffset+HeaderLength+dwBlockPtrTable[i],FILE_BEGIN);
+                               SFSetFilePointer(mpqOpenArc->hFile, mpqOpenArc->qwMPQStart + mpqOpenArc->lpBlockTable[BlockIndex].dwFileOffset + ((UInt64)mpqOpenArc->lpFileOffsetsHigh[BlockIndex] << 32) + 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 + mpqOpenArc->lpBlockTable[BlockIndex].dwFileOffset + ((UInt64)mpqOpenArc->lpFileOffsetsHigh[BlockIndex] << 32) + HeaderLength, FILE_BEGIN);
                                        WriteFile(mpqOpenArc->hFile,dwBlockPtrTable,(TotalBlocks+1)*4,&tsz,0);
                                        SFFree(dwBlockPtrTable);
                                        SFFree(blkBuffer);
@@ -2476,7 +2504,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 + mpqOpenArc->lpBlockTable[BlockIndex].dwFileOffset + ((UInt64)mpqOpenArc->lpFileOffsetsHigh[BlockIndex] << 32) + HeaderLength + dwBlockPtrTable[i], FILE_BEGIN);
                                WriteFile(mpqOpenArc->hFile,blkBuffer,dwBlockPtrTable[i+1]-dwBlockPtrTable[i],&tsz,0);
                        }
                        SFFree(dwBlockPtrTable);
@@ -2552,7 +2580,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 +2590,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 +2605,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 +2625,15 @@ BOOL SFMPQAPI WINAPI MpqCompactArchive(MPQHANDLE hMPQ)
                }
                if (j<mpqOpenArc->MpqHeader.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 + mpqOpenArc->lpBlockTable[i].dwFileOffset + ((UInt64)mpqOpenArc->lpFileOffsetsHigh[i] << 32), FILE_BEGIN);
                                        ReadFile(mpqOpenArc->hFile,&HeaderLength,4,&tsz,0);
                                }
                                DWORD blockSize = 512 << mpqOpenArc->MpqHeader.wBlockSize;
@@ -2619,7 +2649,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 + mpqOpenArc->lpBlockTable[i].dwFileOffset + ((UInt64)mpqOpenArc->lpFileOffsetsHigh[i] << 32) + 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;
@@ -2719,7 +2749,7 @@ BOOL SFMPQAPI WINAPI MpqCompactArchive(MPQHANDLE hMPQ)
                                                return FALSE;
                                        }
                                        for (DWORD k=0;k<TotalBlocks;k++) {
-                                               SFSetFilePointer(mpqOpenArc->hFile,mpqOpenArc->dwMPQStart+mpqOpenArc->lpBlockTable[i].dwFileOffset+HeaderLength+dwBlockPtrTable[k],FILE_BEGIN);
+                                               SFSetFilePointer(mpqOpenArc->hFile, mpqOpenArc->qwMPQStart + mpqOpenArc->lpBlockTable[i].dwFileOffset + ((UInt64)mpqOpenArc->lpFileOffsetsHigh[i] << 32) + HeaderLength + dwBlockPtrTable[k], FILE_BEGIN);
                                                if (ReadFile(mpqOpenArc->hFile,blkBuffer,dwBlockPtrTable[k+1]-dwBlockPtrTable[k],&tsz,0)==0) {
                                                        SFFree(dwBlockPtrTable);
                                                        SFFree(blkBuffer);
@@ -2746,7 +2776,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 + mpqOpenArc->lpBlockTable[i].dwFileOffset + ((UInt64)mpqOpenArc->lpFileOffsetsHigh[i] << 32), FILE_BEGIN);
                                        ReadFile(mpqOpenArc->hFile,&HeaderLength,4,&tsz,0);
                                }
                                DWORD blockSize = 512 << mpqOpenArc->MpqHeader.wBlockSize;
@@ -2831,7 +2861,7 @@ BOOL SFMPQAPI WINAPI MpqCompactArchive(MPQHANDLE hMPQ)
                                                return FALSE;
                                        }
                                        for (DWORD k=0;k<mpqOpenArc->lpBlockTable[i].dwFullSize;k+=blockSize) {
-                                               SFSetFilePointer(mpqOpenArc->hFile,mpqOpenArc->dwMPQStart+mpqOpenArc->lpBlockTable[i].dwFileOffset+HeaderLength+k,FILE_BEGIN);
+                                               SFSetFilePointer(mpqOpenArc->hFile, mpqOpenArc->qwMPQStart + mpqOpenArc->lpBlockTable[i].dwFileOffset + ((UInt64)mpqOpenArc->lpFileOffsetsHigh[i] << 32) + 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);
@@ -2855,7 +2885,7 @@ BOOL SFMPQAPI WINAPI MpqCompactArchive(MPQHANDLE hMPQ)
                        if (dwWritten==FALSE) {
                                ReadSize = 65536;
                                for (j=0;j<mpqOpenArc->lpBlockTable[i].dwCompressedSize;j+=65536) {
-                                       SFSetFilePointer(mpqOpenArc->hFile,mpqOpenArc->dwMPQStart+mpqOpenArc->lpBlockTable[i].dwFileOffset+j,FILE_BEGIN);
+                                       SFSetFilePointer(mpqOpenArc->hFile, mpqOpenArc->qwMPQStart + mpqOpenArc->lpBlockTable[i].dwFileOffset + ((UInt64)mpqOpenArc->lpFileOffsetsHigh[i] << 32) + j, FILE_BEGIN);
                                        SFSetFilePointer(hFile,lpBlockTable[i-nBlkOffset].dwFileOffset+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) {
@@ -2886,11 +2916,11 @@ 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);
+       mpqOpenArc->MpqHeader.dwMPQSize = (UInt32)qwLastOffset;
        SFFree(mpqOpenArc->lpHashTable);
        mpqOpenArc->lpHashTable = lpHashTable;
        if(mpqOpenArc->lpBlockTable!=0) {
@@ -2904,17 +2934,17 @@ BOOL SFMPQAPI WINAPI MpqCompactArchive(MPQHANDLE hMPQ)
                        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);
+       SFSetFilePointer(mpqOpenArc->hFile,mpqOpenArc->qwMPQStart,FILE_BEGIN);
+       mpqOpenArc->MpqHeader.dwHeaderSize = mpqOpenArc->dwHeaderSize;
+       WriteFile(mpqOpenArc->hFile,&mpqOpenArc->MpqHeader,mpqOpenArc->dwHeaderSize,&tsz,0);
+       qwLastOffset = mpqOpenArc->dwHeaderSize;
        ReadSize = 65536;
-       for (i=dwLastOffset;i<mpqOpenArc->MpqHeader.dwHashTableOffset;i+=65536) {
-               SFSetFilePointer(mpqOpenArc->hFile,mpqOpenArc->dwMPQStart+i,FILE_BEGIN);
+       for (i=qwLastOffset;i<MakeUInt64(mpqOpenArc->MpqHeader.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);
        }
@@ -2983,20 +3013,23 @@ DWORD SFMPQAPI WINAPI SFileFindMpqHeader(HANDLE hFile)
        return 0xFFFFFFFF;
 }
 
-DWORD WINAPI FindMpqHeaderAtLocation(HANDLE hFile, DWORD dwStart, DWORD dwLength)
+UInt64 WINAPI SFileFindMpqHeaderEx(HANDLE hFile, UInt64 qwStart, UInt64 qwLength)
 {
        if (hFile == INVALID_HANDLE_VALUE) {
                SetLastError(ERROR_INVALID_PARAMETER);
-               return 0xFFFFFFFF;
+               return (UInt64)-1;
        }
+       UInt64 FileLen = SFGetFileSize(hFile);
+       if (FileLen == (UInt64)-1 || qwStart >= FileLen || qwStart + qwLength > FileLen) return (UInt64)-1;
+       if (qwLength == 0) qwLength = FileLen - qwStart;
        char pbuf[sizeof(MPQHEADER)];
        DWORD tsz;
-       for (DWORD i=dwStart;i<dwStart+dwLength;i+=512)
+       for (UInt64 i=qwStart;i<qwStart+qwLength && i<FileLen;i+=512)
        {
                SFSetFilePointer(hFile,i,FILE_BEGIN);
-               if (ReadFile(hFile,pbuf,sizeof(MPQHEADER),&tsz,0)==0) return 0xFFFFFFFF;
-               if (i+tsz>dwStart+dwLength) tsz = (dwStart+dwLength)-i;
-               if (tsz<sizeof(MPQHEADER)) return 0xFFFFFFFF;
+               if (ReadFile(hFile,pbuf,sizeof(MPQHEADER),&tsz,0)==0) return (UInt64)-1;
+               if (i+tsz>qwStart+qwLength) tsz = (qwStart+qwLength)-i;
+               if (tsz<sizeof(MPQHEADER)) return (UInt64)-1;
                if (memcmp(pbuf,ID_MPQ,4)==0 || memcmp(pbuf,ID_BN3,4)==0)
                {
                        // Storm no longer does this, so mpq api shouldn't either
@@ -3008,7 +3041,7 @@ DWORD WINAPI FindMpqHeaderAtLocation(HANDLE hFile, DWORD dwStart, DWORD dwLength
                        return i;
                }
        }
-       return 0xFFFFFFFF;
+       return (UInt64)-1;
 }
 
 DWORD GetFullPath(LPCSTR lpFileName, char *lpBuffer, DWORD dwBufferLength)
@@ -3442,7 +3475,7 @@ DWORD DetectFileSeedEx(MPQARCHIVE * mpqOpenArc, HASHTABLEENTRY * lpHashEntry, LP
                        DWORD HeaderLength=0,tsz;
                        if (memcmp(&mpqOpenArc->MpqHeader.dwMPQID,ID_BN3,4)==0)
                        {
-                               SFSetFilePointer(mpqOpenArc->hFile,mpqOpenArc->dwMPQStart+mpqOpenArc->lpBlockTable[dwBlockIndex].dwFileOffset,FILE_BEGIN);
+                               SFSetFilePointer(mpqOpenArc->hFile, mpqOpenArc->qwMPQStart + mpqOpenArc->lpBlockTable[dwBlockIndex].dwFileOffset + ((UInt64)mpqOpenArc->lpFileOffsetsHigh[dwBlockIndex] << 32), FILE_BEGIN);
                                ReadFile(mpqOpenArc->hFile,&HeaderLength,4,&tsz,0);
                        }
                        DWORD blockSize = 512 << mpqOpenArc->MpqHeader.wBlockSize;
@@ -3452,7 +3485,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 + mpqOpenArc->lpBlockTable[dwBlockIndex].dwFileOffset + ((UInt64)mpqOpenArc->lpFileOffsetsHigh[dwBlockIndex] << 32) + HeaderLength, FILE_BEGIN);
                        ReadFile(mpqOpenArc->hFile,dwBlockPtrTable,(TotalBlocks+1)*4,&tsz,0);
                        dwCryptKey = DetectFileSeed(dwBlockPtrTable,(TotalBlocks+1)*4,blockSize);
 
index 768bff4..f9ce2db 100644 (file)
@@ -306,8 +306,6 @@ struct FILELISTENTRY {
        char szFileName[260];
 };
 
-struct MPQARCHIVE;
-struct MPQFILE;
 struct MPQHEADER;
 struct MPQHEADER_EX;
 struct BLOCKTABLEENTRY;
@@ -332,70 +330,6 @@ struct MPQHEADER_EX {
        WORD wBlockTableOffsetHigh; // High 16 bits of the block table offset for large archives
 };
 
-#include <poppack.h>
-
-//Archive handles may be typecasted to this struct so you can access
-//some of the archive's properties and the decrypted hash table and
-//block table directly.  This struct is based on Storm's internal
-//struct for archive handles.
-struct MPQARCHIVE {
-       // Arranged according to priority with lowest priority first
-       MPQARCHIVE * lpNextArc; //0// Pointer to the next MPQARCHIVE struct. Pointer to addresses of first and last archives if last archive
-       MPQARCHIVE * lpPrevArc; //4// Pointer to the previous MPQARCHIVE struct. 0xEAFC5E23 if first archive
-       char szFileName[260]; //8// Filename of the archive
-       HANDLE hFile; //10C// The archive's file handle
-       DWORD dwFlags1; //110// Some flags, bit 0 seems to be set when opening an archive from a hard drive if bit 1 in the flags for SFileOpenArchive is set, bit 1 (0 based) seems to be set when opening an archive from a CD
-       DWORD dwPriority; //114// Priority of the archive set when calling SFileOpenArchive
-       MPQFILE * lpLastReadFile; //118// Pointer to the last read file's MPQFILE struct. This is cleared when finished reading a block
-       DWORD dwUnk; //11C// Seems to always be 0
-       DWORD dwBlockSize; //120// Size of file blocks in bytes
-       BYTE * lpLastReadBlock; //124// Pointer to the read buffer for archive. This is cleared when finished reading a block
-       DWORD dwBufferSize; //128// Size of the read buffer for archive. This is cleared when finished reading a block
-       DWORD dwMPQStart; //12C// The starting offset of the archive
-       DWORD dwMPQEnd; //130// The ending offset of the archive
-       MPQHEADER * lpMPQHeader; //134// Pointer to the archive header
-       BLOCKTABLEENTRY * lpBlockTable; //138// Pointer to the start of the block table
-       HASHTABLEENTRY * lpHashTable; //13C// Pointer to the start of the hash table
-       DWORD dwReadOffset; //140// Offset to the data for a file
-       DWORD dwRefCount; //144// Count of references to this open archive.  This is incremented for each file opened from the archive, and decremented for each file closed
-       // Extra struct members used by SFmpq
-       MPQHEADER MpqHeader;
-       DWORD dwFlags; //The only flags that should be changed are MOAU_MAINTAIN_LISTFILE and MOAU_MAINTAIN_ATTRIBUTES, changing any others can have unpredictable effects
-       LPSTR lpFileName;
-       DWORD dwExtraFlags;
-       MPQHEADER_EX MpqHeader_Ex;
-       WORD * lpFileOffsetsHigh;
-};
-
-//Handles to files in the archive may be typecasted to this struct
-//so you can access some of the file's properties directly.  This
-//struct is based on Storm's internal struct for file handles.
-struct MPQFILE {
-       MPQFILE * lpNextFile; //0// Pointer to the next MPQFILE struct. Pointer to addresses of first and last files if last file
-       MPQFILE * lpPrevFile; //4// Pointer to the previous MPQFILE struct. 0xEAFC5E13 if first file
-       char szFileName[260]; //8// Filename of the file
-       HANDLE hFile; //10C// Always INVALID_HANDLE_VALUE for files in MPQ archives. For files not in MPQ archives, this is the file handle for the file and the rest of this struct is filled with zeros except for dwRefCount
-       MPQARCHIVE * lpParentArc; //110// Pointer to the MPQARCHIVE struct of the archive in which the file is contained
-       BLOCKTABLEENTRY * lpBlockEntry; //114// Pointer to the file's block table entry
-       DWORD dwCryptKey; //118// Decryption key for the file
-       DWORD dwFilePointer; //11C// Position of file pointer in the file
-       DWORD dwUnk; //120// Seems to always be 0
-       DWORD dwBlockCount; //124// Number of blocks in file
-       DWORD * lpdwBlockOffsets; //128// Offsets to blocks in file. There are 1 more of these than the number of blocks. The values for this are set after the first read
-       DWORD dwReadStarted; //12C// Set to 1 after first read
-       BOOL bStreaming; //130// 1 when streaming a WAVE
-       BYTE * lpLastReadBlock; //134// Pointer to the read buffer for file. This starts at the position specified in the last SFileSetFilePointer call. This is cleared when SFileSetFilePointer is called or when finished reading the block
-       DWORD dwBytesRead; //138// Total bytes read from the current block in the open file. This is cleared when SFileSetFilePointer is called or when finished reading the block
-       DWORD dwBufferSize; //13C// Size of the read buffer for file. This is cleared when SFileSetFilePointer is called or when finished reading the block
-       DWORD dwRefCount; //140// Count of references to this open file
-       // Extra struct members used by SFmpq
-       HASHTABLEENTRY *lpHashEntry;
-       LPSTR lpFileName;
-       WORD wFileOffsetHigh;
-};
-
-#include <pshpack1.h>
-
 struct BLOCKTABLEENTRY {
        DWORD dwFileOffset; // Offset to file
        DWORD dwCompressedSize; // Compressed size of file
index 2e6c6c2..5dce539 100644 (file)
                                RelativePath="SFmpqapi.h"\r
                                >\r
                        </File>\r
+                       <File\r
+                               RelativePath=".\SFmpqInternal.h"\r
+                               >\r
+                       </File>\r
                        <File\r
                                RelativePath=".\SFTypes.h"\r
                                >\r