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, 4 Jul 2010 23:01:31 +0000 (17:01 -0600)]
Resolved conflicts:
SFmpqapi.cpp

1  2 
SFmpqapi.cpp
SFmpqapi.h

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
@@@ -103,9 -101,6 +103,6 @@@ MPQFILE * FirstLastFile[2] = {0,0}
  
  char StormBasePath[MAX_PATH+1];
  
- #define UNSUPPORTED_COMPRESSION   (0xFF ^ (0x40 | 0x80 | 0x01 | 0x02 | 0x08 | 0x10))
- #define UNSUPPORTED_DECOMPRESSION (0xFF ^ (0x40 | 0x80 | 0x01 | 0x02 | 0x08 | 0x10))
  typedef BOOL (WINAPI* funcSCompCompress)(LPVOID lpvDestinationMem, LPDWORD lpdwCompressedSize, LPVOID lpvSourceMem, DWORD dwDecompressedSize, DWORD dwCompressionType, DWORD dwCompressionSubType, DWORD dwWAVQuality);
  typedef BOOL (WINAPI* funcSCompDecompress)(LPVOID lpvDestinationMem, LPDWORD lpdwDecompressedSize, LPVOID lpvSourceMem, DWORD dwCompressedSize);
  funcSCompCompress stormSCompCompress = 0;
@@@ -115,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);
@@@ -289,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 {
@@@ -888,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;
@@@ -1176,6 -1195,8 +1173,8 @@@ BOOL SFMPQAPI WINAPI SFileReadFile(MPQH
        DWORD BlockIndex = mpqOpenFile->lpHashEntry->dwBlockTableIndex;
        if (mpqOpenFile->dwFilePointer+nNumberOfBytesToRead>mpqOpenArc->lpBlockTable[BlockIndex].dwFullSize) nNumberOfBytesToRead = mpqOpenArc->lpBlockTable[BlockIndex].dwFullSize-mpqOpenFile->dwFilePointer;
        DWORD blockSize = 512 << mpqOpenArc->MpqHeader.wBlockSize;
+       if (mpqOpenArc->lpBlockTable[BlockIndex].dwFlags & MAFA_SINGLEBLOCK)
+               blockSize = mpqOpenArc->lpBlockTable[BlockIndex].dwFullSize;
        DWORD dwBlockStart = mpqOpenFile->dwFilePointer - (mpqOpenFile->dwFilePointer % blockSize);
      DWORD blockNum = dwBlockStart / blockSize;
      DWORD nBlocks  = (mpqOpenFile->dwFilePointer+nNumberOfBytesToRead) / blockSize;
                if (lpOverlapped) lpOverlapped->InternalHigh = 0;
                return FALSE;
        }
-       void *blk16Buffer = SFAlloc(blockSize * 16);
-       if (!blk16Buffer) {
-               SFFree(blkBuffer);
-               if (lpNumberOfBytesRead) *lpNumberOfBytesRead = 0;
-               if (lpOverlapped) lpOverlapped->InternalHigh = 0;
-               return FALSE;
+       DWORD nBufferCount;
+       for (nBufferCount = 1; nBufferCount < nBlocks - blockNum && blockSize * nBufferCount < 65536; nBufferCount *= 2) {}
+       if (nBufferCount > nBlocks - blockNum) nBufferCount = nBlocks - blockNum;
+       void *blkLargeBuffer = NULL;
+       if (nBufferCount > 1) {
+               blkLargeBuffer = SFAlloc(blockSize * nBufferCount);
+               if (!blkLargeBuffer) {
+                       SFFree(blkBuffer);
+                       if (lpNumberOfBytesRead) *lpNumberOfBytesRead = 0;
+                       if (lpOverlapped) lpOverlapped->InternalHigh = 0;
+                       return FALSE;
+               }
        }
        DWORD dwCryptKey = mpqOpenFile->dwCryptKey;
        //if (mpqOpenArc->lpBlockTable[BlockIndex].dwFlags & MAFA_ENCRYPT) dwCryptKey = HashString(mpqOpenFile->lpFileName,HASH_KEY);
        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;
                DWORD *dwBlockPtrTable = (DWORD *)SFAlloc((TotalBlocks+1)*4);
                if (!dwBlockPtrTable) {
  
-                       SFFree(blk16Buffer);
+                       if (blkLargeBuffer) SFFree(blkLargeBuffer);
                        SFFree(blkBuffer);
                        if (lpNumberOfBytesRead) *lpNumberOfBytesRead = 0;
                        if (lpOverlapped) lpOverlapped->InternalHigh = 0;
                        return FALSE;
                }
-               if ((mpqOpenArc->lpBlockTable[BlockIndex].dwFlags & MAFA_COMPRESS) || (mpqOpenArc->lpBlockTable[BlockIndex].dwFlags & MAFA_COMPRESS2))
+               if (((mpqOpenArc->lpBlockTable[BlockIndex].dwFlags & MAFA_COMPRESS) || (mpqOpenArc->lpBlockTable[BlockIndex].dwFlags & MAFA_COMPRESS2)) && !(mpqOpenArc->lpBlockTable[BlockIndex].dwFlags & MAFA_SINGLEBLOCK))
                {
 -                      SFSetFilePointer(mpqOpenArc->hFile,mpqOpenArc->dwMPQStart+mpqOpenArc->lpBlockTable[BlockIndex].dwFileOffset+HeaderLength,FILE_BEGIN);
 +                      SFSetFilePointer(mpqOpenArc->hFile, mpqOpenArc->qwMPQStart + MakeUInt64(mpqOpenArc->lpBlockTable[BlockIndex].dwFileOffset, mpqOpenArc->lpFileOffsetsHigh[BlockIndex]) + HeaderLength, FILE_BEGIN);
                        ReadFile(mpqOpenArc->hFile,dwBlockPtrTable,(TotalBlocks+1)*4,&nBytesRead,0);
                        if (mpqOpenArc->lpBlockTable[BlockIndex].dwFlags & MAFA_ENCRYPT) {
                                DecryptData((LPBYTE)dwBlockPtrTable,(TotalBlocks+1)*4,dwCryptKey-1);
                {
                        for (i=0;i<TotalBlocks+1;i++) {
                                if (i<TotalBlocks) dwBlockPtrTable[i] = i * blockSize;
-                               else dwBlockPtrTable[i] = mpqOpenArc->lpBlockTable[BlockIndex].dwFullSize;
+                               else dwBlockPtrTable[i] = mpqOpenArc->lpBlockTable[BlockIndex].dwCompressedSize - HeaderLength;
                        }
                }
                mpqOpenFile->lpdwBlockOffsets = dwBlockPtrTable;
        }
-       BYTE *compbuffer = (BYTE *)SFAlloc(blockSize+3);
-       if (!compbuffer) {
-               SFFree(blk16Buffer);
-               SFFree(blkBuffer);
-               if (lpNumberOfBytesRead) *lpNumberOfBytesRead = 0;
-               if (lpOverlapped) lpOverlapped->InternalHigh = 0;
-               return FALSE;
+       BYTE *compbuffer = NULL;
+       if ((mpqOpenArc->lpBlockTable[BlockIndex].dwFlags & MAFA_COMPRESS) || (mpqOpenArc->lpBlockTable[BlockIndex].dwFlags & MAFA_COMPRESS2)) {
+               compbuffer = (BYTE *)SFAlloc(blockSize+3);
+               if (!compbuffer) {
+                       if (blkLargeBuffer) SFFree(blkLargeBuffer);
+                       SFFree(blkBuffer);
+                       if (lpNumberOfBytesRead) *lpNumberOfBytesRead = 0;
+                       if (lpOverlapped) lpOverlapped->InternalHigh = 0;
+                       return FALSE;
+               }
        }
        DWORD blk=0,blki=0;
        for (i=blockNum;i<nBlocks;i++) {
-               if (blk==0) {
+               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+16>nBlocks) {
-                               if (ReadFile(mpqOpenArc->hFile,blk16Buffer,mpqOpenFile->lpdwBlockOffsets[nBlocks]-mpqOpenFile->lpdwBlockOffsets[i],&nBytesRead,0)==0) {
-                                       SFFree(compbuffer);
-                                       SFFree(blk16Buffer);
+                       if (i+nBufferCount>nBlocks) {
+                               if (ReadFile(mpqOpenArc->hFile,blkLargeBuffer,mpqOpenFile->lpdwBlockOffsets[nBlocks]-mpqOpenFile->lpdwBlockOffsets[i],&nBytesRead,0)==0) {
+                                       if (compbuffer) SFFree(compbuffer);
+                                       SFFree(blkLargeBuffer);
                                        SFFree(blkBuffer);
                                        if (lpNumberOfBytesRead) *lpNumberOfBytesRead = TotalBytesRead;
                                        if (lpOverlapped) lpOverlapped->InternalHigh = TotalBytesRead;
  
                        }
                        else {
-                               if (ReadFile(mpqOpenArc->hFile,blk16Buffer,mpqOpenFile->lpdwBlockOffsets[i+16]-mpqOpenFile->lpdwBlockOffsets[i],&nBytesRead,0)==0) {
-                                       SFFree(compbuffer);
-                                       SFFree(blk16Buffer);
+                               if (ReadFile(mpqOpenArc->hFile,blkLargeBuffer,mpqOpenFile->lpdwBlockOffsets[i+nBufferCount]-mpqOpenFile->lpdwBlockOffsets[i],&nBytesRead,0)==0) {
+                                       if (compbuffer) SFFree(compbuffer);
+                                       SFFree(blkLargeBuffer);
                                        SFFree(blkBuffer);
                                        if (lpNumberOfBytesRead) *lpNumberOfBytesRead = TotalBytesRead;
                                        if (lpOverlapped) lpOverlapped->InternalHigh = TotalBytesRead;
                                }
                        }
                }
-               memcpy(blkBuffer,((char *)blk16Buffer)+(mpqOpenFile->lpdwBlockOffsets[blki+blk]-mpqOpenFile->lpdwBlockOffsets[blki]),mpqOpenFile->lpdwBlockOffsets[i+1]-mpqOpenFile->lpdwBlockOffsets[i]);
+               if (blkLargeBuffer) {
+                       memcpy(blkBuffer,((char *)blkLargeBuffer)+(mpqOpenFile->lpdwBlockOffsets[blki+blk]-mpqOpenFile->lpdwBlockOffsets[blki]),mpqOpenFile->lpdwBlockOffsets[i+1]-mpqOpenFile->lpdwBlockOffsets[i]);
+               }
+               else {
 -                      SFSetFilePointer(mpqOpenArc->hFile,mpqOpenArc->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);
+                               SFFree(blkBuffer);
+                               if (lpNumberOfBytesRead) *lpNumberOfBytesRead = TotalBytesRead;
+                               if (lpOverlapped) lpOverlapped->InternalHigh = TotalBytesRead;
+                               return FALSE;
+                       }
+               }
                if (mpqOpenArc->lpBlockTable[BlockIndex].dwFlags & MAFA_ENCRYPT)
                {
                        DecryptData((LPBYTE)blkBuffer,mpqOpenFile->lpdwBlockOffsets[i+1]-mpqOpenFile->lpdwBlockOffsets[i],dwCryptKey+i);
                                nNumberOfBytesToRead-=nNumberOfBytesToRead;
                        }
                }
-               blk = (blk+1) % 16;
+               blk = (blk+1) % nBufferCount;
        }
-       SFFree(compbuffer);
-       SFFree(blk16Buffer);
+       if (compbuffer) SFFree(compbuffer);
+       if (blkLargeBuffer) SFFree(blkLargeBuffer);
        SFFree(blkBuffer);
        if (lpNumberOfBytesRead) *lpNumberOfBytesRead = TotalBytesRead;
        if (lpOverlapped) lpOverlapped->InternalHigh = TotalBytesRead;
@@@ -1461,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)) {
@@@ -1898,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);
@@@ -2220,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);
@@@ -2402,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);
@@@ -2534,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);
        }
@@@ -2944,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)
@@@ -3458,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);
  
diff --combined SFmpqapi.h
@@@ -1,6 -1,6 +1,6 @@@
  /*
  
-   ShadowFlare MPQ API Library. (c) ShadowFlare Software 2002-2009
+   ShadowFlare MPQ API Library. (c) ShadowFlare Software 2002-2010
    License information for this code is in license.txt and
    included in this file at the end of this comment.
  
  
    License information:
  
-   Copyright (c) 2002-2009, ShadowFlare <blakflare@hotmail.com>
+   Copyright (c) 2002-2010, ShadowFlare <blakflare@hotmail.com>
    All rights reserved.
  
    Redistribution and use in source and binary forms, with or without
@@@ -230,6 -230,7 +230,7 @@@ long SFMPQAPI __inline SFMpqCompareVers
  // MpqAddFileToArchive flags
  #define MAFA_EXISTS           0x80000000 //This flag will be added if not present
  #define MAFA_UNKNOWN40000000  0x40000000 //Unknown flag
+ #define MAFA_SINGLEBLOCK      0x01000000 //File is stored as a single unit rather than being split by the block size
  #define MAFA_MODCRYPTKEY      0x00020000 //Used with MAFA_ENCRYPT. Uses an encryption key based on file position and size
  #define MAFA_ENCRYPT          0x00010000 //Encrypts the file. The file is still accessible when using this, so the use of this has depreciated
  #define MAFA_COMPRESS         0x00000200 //File is to be compressed when added. This is used for most of the compression methods
@@@ -306,8 -307,9 +307,8 @@@ struct FILELISTENTRY 
        char szFileName[260];
  };
  
 -struct MPQARCHIVE;
 -struct MPQFILE;
  struct MPQHEADER;
 +struct MPQHEADER_EX;
  struct BLOCKTABLEENTRY;
  struct HASHTABLEENTRY;
  
@@@ -315,7 -317,7 +316,7 @@@ struct MPQHEADER 
        DWORD dwMPQID; //"MPQ\x1A" for mpq's, "BN3\x1A" for bncache.dat
        DWORD dwHeaderSize; // Size of this header
        DWORD dwMPQSize; //The size of the mpq archive
 -      WORD wUnused0C; // Seems to always be 0
 +      WORD wVersion; // 0 for original format, 1 for large archive
        WORD wBlockSize; // Size of blocks in files equals 512 << wBlockSize
        DWORD dwHashTableOffset; // Offset to hash table
        DWORD dwBlockTableOffset; // Offset to block table
        DWORD dwBlockTableSize; // Number of entries in block table
  };
  
 -#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;
 -};
 -
 -//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;
 +// Large archive format only
 +struct MPQHEADER_EX {
 +      UINT64 qwExtendedBlockOffsetTable; // Offset to table containing upper 16 bits of block offsets
 +      WORD wHashTableOffsetHigh; // High 16 bits of the hash table offset for large archives
 +      WORD wBlockTableOffsetHigh; // High 16 bits of the block table offset for large archives
  };
  
 -#include <pshpack1.h>
 -
  struct BLOCKTABLEENTRY {
        DWORD dwFileOffset; // Offset to file
        DWORD dwCompressedSize; // Compressed size of file
@@@ -396,7 -452,6 +397,7 @@@ BOOL      SFMPQAPI WINAPI MpqAddWaveFro
  BOOL      SFMPQAPI WINAPI MpqRenameAndSetFileLocale(MPQHANDLE hMPQ, LPCSTR lpcOldFileName, LPCSTR lpcNewFileName, LCID nOldLocale, LCID nNewLocale);
  BOOL      SFMPQAPI WINAPI MpqDeleteFileWithLocale(MPQHANDLE hMPQ, LPCSTR lpFileName, LCID nLocale);
  BOOL      SFMPQAPI WINAPI MpqSetFileLocale(MPQHANDLE hMPQ, LPCSTR lpFileName, LCID nOldLocale, LCID nNewLocale);
 +BOOL      SFMPQAPI WINAPI MpqCreateArchiveVersion(WORD wVersion);
  
  // These functions do nothing.  They are only provided for
  // compatibility with MPQ extractors that use storm.