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 [Mon, 14 Mar 2011 12:22:19 +0000 (06:22 -0600)]
1  2 
SFmpqapi.cpp

diff --combined SFmpqapi.cpp
@@@ -13,7 -13,6 +13,7 @@@
  
  #include "../SComp/SComp.h"
  
 +#include "SFmpqInternal.h"
  #include "MpqCrypt.h"
  #include "MpqHashTable.h"
  #include "MpqBlockTable.h"
@@@ -54,7 -53,6 +54,7 @@@ SFMPQLIBMODULE::~SFMPQLIBMODULE(
  #endif
  
  LCID LocaleID = 0;
 +WORD wCreationVersion = 0;
  BOOL SFMpqInit = FALSE;
  HINSTANCE hStorm = 0;
  #ifdef _USRDLL
@@@ -112,7 -110,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);
@@@ -286,155 -284,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 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 flen,tsz;
 +      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;i<mpqOpenArc->MpqHeader.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;
        }
  
        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;
        if (dwFlags2 & MOAU_READ_ONLY) {
                if (!(dwFlags2 & MOAU_OPEN_EXISTING)) {
                        SetLastError(MPQ_ERROR_BAD_OPEN_MODE);
 -                      *hMPQ = 0;
                        return FALSE;
                }
                dwAccessFlags = GENERIC_READ;
        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;i<dwMaximumFilesInArchive;i*=2) {}
 -                      dwMaximumFilesInArchive = i;
 +
 +                      mpqOpenArc->hFile = 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);
                dwOpenMpqCount++;
                if (dwOpenMpqCount>1) SortOpenArchivesByPriority();
                *hMPQ = (MPQHANDLE)mpqOpenArc;
 +
                return TRUE;
        }
        else {
  
  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;
        }
  
                hFile = mpqArcFile.lpParentArc->hFile;
                MPQARCHIVE **lpnOpenMpq = (MPQARCHIVE **)SFAlloc(sizeof(MPQARCHIVE *) * (dwOpenMpqCount+1));
                if (!lpnOpenMpq) {
 -                      *hMPQ = 0;
                        return FALSE;
                }
 -              DWORD dwMpqStart;
                MPQARCHIVE *mpqOpenArc;
 -              dwMpqStart = mpqArcFile.lpParentArc->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);
                dwOpenMpqCount++;
                if (dwOpenMpqCount>1) SortOpenArchivesByPriority();
                *hMPQ = (MPQHANDLE)mpqOpenArc;
 +
                return TRUE;
        }
        else {
@@@ -885,7 -908,6 +885,7 @@@ BOOL SFMPQAPI WINAPI SFileOpenFileEx(MP
                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;
@@@ -1102,7 -1124,7 +1102,7 @@@ DWORD SFMPQAPI WINAPI SFileGetFileInfo(
        return (DWORD)-1;
  }
  
- DWORD SFMPQAPI WINAPI SFileSetFilePointer(MPQHANDLE hFile, long lDistanceToMove, PLONG lplDistanceToMoveHigh, DWORD dwMoveMethod)
+ DWORD SFMPQAPI WINAPI SFileSetFilePointer(MPQHANDLE hFile, LONG lDistanceToMove, PLONG lplDistanceToMoveHigh, DWORD dwMoveMethod)
  {
        if (!hFile) {
                SetLastError(ERROR_INVALID_PARAMETER);
@@@ -1154,7 -1176,7 +1154,7 @@@ BOOL SFMPQAPI WINAPI SFileReadFile(MPQH
        }
        if (lpOverlapped)
                if (lpOverlapped->Internal || lpOverlapped->InternalHigh || lpOverlapped->Offset || lpOverlapped->OffsetHigh || lpOverlapped->hEvent)
-                       SFileSetFilePointer(hFile,lpOverlapped->Offset,(long *)&lpOverlapped->OffsetHigh,FILE_BEGIN);
+                       SFileSetFilePointer(hFile,lpOverlapped->Offset,(LONG *)&lpOverlapped->OffsetHigh,FILE_BEGIN);
        if (nNumberOfBytesToRead==0) {
                if (lpNumberOfBytesRead) *lpNumberOfBytesRead = 0;
                if (lpOverlapped) lpOverlapped->InternalHigh = 0;
        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;
                }
                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);
        DWORD blk=0,blki=0;
        for (i=blockNum;i<nBlocks;i++) {
                if (blk==0 && blkLargeBuffer) {
 -                      SFSetFilePointer(mpqOpenArc->hFile,mpqOpenArc->dwMPQStart+mpqOpenArc->lpBlockTable[BlockIndex].dwFileOffset+HeaderLength+mpqOpenFile->lpdwBlockOffsets[i],FILE_BEGIN);
 +                      SFSetFilePointer(mpqOpenArc->hFile, mpqOpenArc->qwMPQStart + MakeUInt64(mpqOpenArc->lpBlockTable[BlockIndex].dwFileOffset, mpqOpenArc->lpFileOffsetsHigh[BlockIndex]) + HeaderLength + mpqOpenFile->lpdwBlockOffsets[i], FILE_BEGIN);
                        blki=i;
                        if (i+nBufferCount>nBlocks) {
                                if (ReadFile(mpqOpenArc->hFile,blkLargeBuffer,mpqOpenFile->lpdwBlockOffsets[nBlocks]-mpqOpenFile->lpdwBlockOffsets[i],&nBytesRead,0)==0) {
                        memcpy(blkBuffer,((char *)blkLargeBuffer)+(mpqOpenFile->lpdwBlockOffsets[blki+blk]-mpqOpenFile->lpdwBlockOffsets[blki]),mpqOpenFile->lpdwBlockOffsets[i+1]-mpqOpenFile->lpdwBlockOffsets[i]);
                }
                else {
 -                      SFSetFilePointer(mpqOpenArc->hFile,mpqOpenArc->dwMPQStart+mpqOpenArc->lpBlockTable[BlockIndex].dwFileOffset+HeaderLength+mpqOpenFile->lpdwBlockOffsets[i],FILE_BEGIN);
 +                      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);
@@@ -1482,7 -1504,7 +1482,7 @@@ BOOL SFMPQAPI WINAPI SFileListFiles(MPQ
                                        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)) {
@@@ -1919,19 -1941,15 +1919,19 @@@ BOOL SFMPQAPI WINAPI MpqAddFileToArchiv
        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;
        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);
                }
        }
        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);
@@@ -2241,19 -2261,15 +2241,19 @@@ BOOL SFMPQAPI WINAPI MpqAddFileFromBuff
        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;
        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);
                }
        }
        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);
@@@ -2423,7 -2441,7 +2423,7 @@@ BOOL SFMPQAPI WINAPI MpqRenameAndSetFil
                        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);
  
                        }
                        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);
                                }
                                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);
                        }
                        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;i<TotalBlocks;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);
                                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);
                                }
                                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);
@@@ -2555,7 -2573,7 +2555,7 @@@ BOOL SFMPQAPI WINAPI MpqCompactArchive(
        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);
                }
                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);
                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);
                }
                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 + MakeUInt64(mpqOpenArc->lpBlockTable[i].dwFileOffset, mpqOpenArc->lpFileOffsetsHigh[i]), FILE_BEGIN);
                                        ReadFile(mpqOpenArc->hFile,&HeaderLength,4,&tsz,0);
                                }
                                DWORD blockSize = 512 << mpqOpenArc->MpqHeader.wBlockSize;
                                        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;
                                        }
                                        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);
                                                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 + 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);
                                                }
                                                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);
                                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;
                                                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 + 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);
                                                }
                                                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);
                        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(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);
                }
        }
        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;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);
        }
@@@ -2965,37 -2976,13 +2965,37 @@@ BOOL SFMPQAPI WINAPI MpqSetFileLocale(M
        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;i+=512)
        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
                        return i;
                }
        }
 -      return 0xFFFFFFFF;
 +      return (UInt64)-1;
  }
  
  DWORD GetFullPath(LPCSTR lpFileName, char *lpBuffer, DWORD dwBufferLength)
@@@ -3479,7 -3463,7 +3479,7 @@@ DWORD DetectFileSeedEx(MPQARCHIVE * mpq
                        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 + MakeUInt64(mpqOpenArc->lpBlockTable[dwBlockIndex].dwFileOffset, mpqOpenArc->lpFileOffsetsHigh[dwBlockIndex]), FILE_BEGIN);
                                ReadFile(mpqOpenArc->hFile,&HeaderLength,4,&tsz,0);
                        }
                        DWORD blockSize = 512 << mpqOpenArc->MpqHeader.wBlockSize;
                        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);