Browse Source

StormLib: Update to ladislav-zezula/StormLib@95fabe8c0936e013d8764858d6eaf17b6a774e12

pull/1455/head
Gleb Mazovetskiy 5 years ago committed by Anders Jenbo
parent
commit
7a77e88eb0
  1. 19
      3rdParty/StormLib/README
  2. 270
      3rdParty/StormLib/src/FileStream.cpp
  3. 2
      3rdParty/StormLib/src/FileStream.h
  4. 167
      3rdParty/StormLib/src/SBaseCommon.cpp
  5. 349
      3rdParty/StormLib/src/SBaseFileTable.cpp
  6. 38
      3rdParty/StormLib/src/SBaseSubTypes.cpp
  7. 2311
      3rdParty/StormLib/src/SCompression.cpp
  8. 2
      3rdParty/StormLib/src/SFileExtractFile.cpp
  9. 22
      3rdParty/StormLib/src/SFileFindFile.cpp
  10. 919
      3rdParty/StormLib/src/SFileGetFileInfo.cpp
  11. 1281
      3rdParty/StormLib/src/SFileOpenArchive.cpp
  12. 108
      3rdParty/StormLib/src/SFileOpenFileEx.cpp
  13. 1810
      3rdParty/StormLib/src/SFileReadFile.cpp
  14. 66
      3rdParty/StormLib/src/StormCommon.h
  15. 358
      3rdParty/StormLib/src/StormLib.h
  16. 897
      3rdParty/StormLib/src/StormPort.h

19
3rdParty/StormLib/README vendored

@ -1,13 +1,6 @@
This is a slightly modified version of ladislav-zezula/StormLib@4ad0bff21da0163917e1552960e6a43679586b89
Cosmetic changes:
* Remove all unused files.
* Comment out unnecessary bits with `#ifndef FULL`.
Implementation changes:
* Redefine `bool` to `BOOL`.
* Use STORMAPI instead of WINAPI for calling convention (and define it as nothing).
* Use external Storm error handling (`SErrGetLastError()` etc.)
* Convert pathnames to Unix-style slashes.
* Bugfixes, with comment: // BUGFIX (devilutionX)
* Fix missing header includes on macOS (devilutionX)
This is a slightly modified version of ladislav-zezula/StormLib@0a9057a09f083eb4791a55eb3d9538cea9822e37
Changes:
* Removed all files not used by DevilutionX.
* Comment out unnecessary bits with `#ifndef FULL`.

270
3rdParty/StormLib/src/FileStream.cpp vendored

@ -17,16 +17,6 @@
#include "StormLib.h"
#include "StormCommon.h"
#include "FileStream.h"
#ifdef __vita__
#include <psp2/rtc.h>
#define mmap(ptr, size, c, d, e, f) malloc(size)
#define munmap(ptr, size) free(ptr)
#define PROT_READ 0
#define MAP_PRIVATE 0
#endif
#ifdef _MSC_VER
#pragma comment(lib, "wininet.lib") // Internet functions for HTTP stream
@ -43,8 +33,7 @@
//-----------------------------------------------------------------------------
// Local functions - platform-specific functions
#ifdef FULL
#ifndef PLATFORM_WINDOWS
#ifndef STORMLIB_WINDOWS
static DWORD nLastError = ERROR_SUCCESS;
DWORD GetLastError()
@ -52,12 +41,11 @@ DWORD GetLastError()
return nLastError;
}
void SetLastError(DWORD nError)
void SetLastError(DWORD dwErrCode)
{
nLastError = nError;
nLastError = dwErrCode;
}
#endif
#endif
static DWORD StringToInt(const char * szString)
{
@ -65,13 +53,29 @@ static DWORD StringToInt(const char * szString)
while('0' <= szString[0] && szString[0] <= '9')
{
dwValue = (dwValue * 10) + (szString[0] - '9');
dwValue = (dwValue * 10) + (szString[0] - '0');
szString++;
}
return dwValue;
}
static void CreateNameWithSuffix(LPTSTR szBuffer, size_t cchMaxChars, LPCTSTR szName, unsigned int nValue)
{
LPTSTR szBufferEnd = szBuffer + cchMaxChars - 1;
// Copy the name
while(szBuffer < szBufferEnd && szName[0] != 0)
*szBuffer++ = *szName++;
// Append "."
if(szBuffer < szBufferEnd)
*szBuffer++ = '.';
// Append the number
IntToString(szBuffer, szBufferEnd - szBuffer + 1, nValue);
}
//-----------------------------------------------------------------------------
// Dummy init function
@ -85,7 +89,7 @@ static void BaseNone_Init(TFileStream *)
static bool BaseFile_Create(TFileStream * pStream)
{
#ifdef PLATFORM_WINDOWS
#ifdef STORMLIB_WINDOWS
{
DWORD dwWriteShare = (pStream->dwFlags & STREAM_FLAG_WRITE_SHARE) ? FILE_SHARE_WRITE : 0;
@ -101,15 +105,15 @@ static bool BaseFile_Create(TFileStream * pStream)
}
#endif
#if defined(PLATFORM_MAC) || defined(PLATFORM_LINUX) || defined(PLATFORM_HAIKU) || defined(PLATFORM_AMIGA) || defined(PLATFORM_SWITCH) || defined(PLATFORM_CTR) || defined(PLATFORM_VITA)
#if defined(STORMLIB_MAC) || defined(STORMLIB_LINUX)
{
intptr_t handle;
handle = open(pStream->szFileName, O_RDWR | O_CREAT | O_TRUNC | O_LARGEFILE, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
if(handle == -1)
{
pStream->Base.File.hFile = INVALID_HANDLE_VALUE;
nLastError = errno;
pStream->Base.File.hFile = INVALID_HANDLE_VALUE; // BUGFIX (devilutionX)
return false;
}
@ -125,7 +129,7 @@ static bool BaseFile_Create(TFileStream * pStream)
static bool BaseFile_Open(TFileStream * pStream, const TCHAR * szFileName, DWORD dwStreamFlags)
{
#ifdef PLATFORM_WINDOWS
#ifdef STORMLIB_WINDOWS
{
ULARGE_INTEGER FileSize;
DWORD dwWriteAccess = (dwStreamFlags & STREAM_FLAG_READ_ONLY) ? 0 : FILE_WRITE_DATA | FILE_APPEND_DATA | FILE_WRITE_ATTRIBUTES;
@ -151,7 +155,7 @@ static bool BaseFile_Open(TFileStream * pStream, const TCHAR * szFileName, DWORD
}
#endif
#if defined(PLATFORM_MAC) || defined(PLATFORM_LINUX) || defined(PLATFORM_HAIKU) || defined(PLATFORM_AMIGA) || defined(PLATFORM_SWITCH) || defined(PLATFORM_CTR) || defined(PLATFORM_VITA)
#if defined(STORMLIB_MAC) || defined(STORMLIB_LINUX)
{
struct stat64 fileinfo;
int oflag = (dwStreamFlags & STREAM_FLAG_READ_ONLY) ? O_RDONLY : O_RDWR;
@ -161,17 +165,17 @@ static bool BaseFile_Open(TFileStream * pStream, const TCHAR * szFileName, DWORD
handle = open(szFileName, oflag | O_LARGEFILE);
if(handle == -1)
{
pStream->Base.File.hFile = INVALID_HANDLE_VALUE;
nLastError = errno;
pStream->Base.File.hFile = INVALID_HANDLE_VALUE; // BUGFIX (devilutionX)
return false;
}
// Get the file size
if(fstat64(handle, &fileinfo) == -1)
{
pStream->Base.File.hFile = INVALID_HANDLE_VALUE;
nLastError = errno;
close(handle);
pStream->Base.File.hFile = INVALID_HANDLE_VALUE; // BUGFIX (devilutionX)
return false;
}
@ -198,7 +202,7 @@ static bool BaseFile_Read(
ULONGLONG ByteOffset = (pByteOffset != NULL) ? *pByteOffset : pStream->Base.File.FilePos;
DWORD dwBytesRead = 0; // Must be set by platform-specific code
#ifdef PLATFORM_WINDOWS
#ifdef STORMLIB_WINDOWS
{
// Note: StormLib no longer supports Windows 9x.
// Thus, we can use the OVERLAPPED structure to specify
@ -222,7 +226,7 @@ static bool BaseFile_Read(
}
#endif
#if defined(PLATFORM_MAC) || defined(PLATFORM_LINUX) || defined(PLATFORM_HAIKU) || defined(PLATFORM_AMIGA) || defined(PLATFORM_SWITCH) || defined(PLATFORM_CTR) || defined(PLATFORM_VITA)
#if defined(STORMLIB_MAC) || defined(STORMLIB_LINUX)
{
ssize_t bytes_read;
@ -269,7 +273,7 @@ static bool BaseFile_Write(TFileStream * pStream, ULONGLONG * pByteOffset, const
ULONGLONG ByteOffset = (pByteOffset != NULL) ? *pByteOffset : pStream->Base.File.FilePos;
DWORD dwBytesWritten = 0; // Must be set by platform-specific code
#ifdef PLATFORM_WINDOWS
#ifdef STORMLIB_WINDOWS
{
// Note: StormLib no longer supports Windows 9x.
// Thus, we can use the OVERLAPPED structure to specify
@ -293,7 +297,7 @@ static bool BaseFile_Write(TFileStream * pStream, ULONGLONG * pByteOffset, const
}
#endif
#if defined(PLATFORM_MAC) || defined(PLATFORM_LINUX) || defined(PLATFORM_HAIKU) || defined(PLATFORM_AMIGA) || defined(PLATFORM_SWITCH) || defined(PLATFORM_CTR) || defined(PLATFORM_VITA)
#if defined(STORMLIB_MAC) || defined(STORMLIB_LINUX)
{
ssize_t bytes_written;
@ -335,7 +339,7 @@ static bool BaseFile_Write(TFileStream * pStream, ULONGLONG * pByteOffset, const
*/
static bool BaseFile_Resize(TFileStream * pStream, ULONGLONG NewFileSize)
{
#ifdef PLATFORM_WINDOWS
#ifdef STORMLIB_WINDOWS
{
LONG FileSizeHi = (LONG)(NewFileSize >> 32);
LONG FileSizeLo;
@ -360,7 +364,7 @@ static bool BaseFile_Resize(TFileStream * pStream, ULONGLONG NewFileSize)
}
#endif
#if defined(PLATFORM_MAC) || defined(PLATFORM_LINUX) || defined(PLATFORM_HAIKU) || defined(PLATFORM_AMIGA) || defined(PLATFORM_SWITCH) || defined(PLATFORM_CTR) || defined(PLATFORM_VITA)
#if defined(STORMLIB_MAC) || defined(STORMLIB_LINUX)
{
if(ftruncate64((intptr_t)pStream->Base.File.hFile, (off64_t)NewFileSize) == -1)
{
@ -395,7 +399,7 @@ static bool BaseFile_GetPos(TFileStream * pStream, ULONGLONG * pByteOffset)
// Renames the file pointed by pStream so that it contains data from pNewStream
static bool BaseFile_Replace(TFileStream * pStream, TFileStream * pNewStream)
{
#ifdef PLATFORM_WINDOWS
#ifdef STORMLIB_WINDOWS
// Delete the original stream file. Don't check the result value,
// because if the file doesn't exist, it would fail
DeleteFile(pStream->szFileName);
@ -404,7 +408,7 @@ static bool BaseFile_Replace(TFileStream * pStream, TFileStream * pNewStream)
return (bool)MoveFile(pNewStream->szFileName, pStream->szFileName);
#endif
#if defined(PLATFORM_MAC) || defined(PLATFORM_LINUX) || defined(PLATFORM_HAIKU) || defined(PLATFORM_AMIGA) || defined(PLATFORM_SWITCH) || defined(PLATFORM_CTR) || defined(PLATFORM_VITA)
#if defined(STORMLIB_MAC) || defined(STORMLIB_LINUX)
// "rename" on Linux also works if the target file exists
if(rename(pNewStream->szFileName, pStream->szFileName) == -1)
{
@ -420,11 +424,11 @@ static void BaseFile_Close(TFileStream * pStream)
{
if(pStream->Base.File.hFile != INVALID_HANDLE_VALUE)
{
#ifdef PLATFORM_WINDOWS
#ifdef STORMLIB_WINDOWS
CloseHandle(pStream->Base.File.hFile);
#endif
#if defined(PLATFORM_MAC) || defined(PLATFORM_LINUX) || defined(PLATFORM_HAIKU) || defined(PLATFORM_AMIGA) || defined(PLATFORM_SWITCH) || defined(PLATFORM_CTR) || defined(PLATFORM_VITA)
#if defined(STORMLIB_MAC) || defined(STORMLIB_LINUX)
close((intptr_t)pStream->Base.File.hFile);
#endif
}
@ -449,61 +453,119 @@ static void BaseFile_Init(TFileStream * pStream)
//-----------------------------------------------------------------------------
// Local functions - base memory-mapped file support
static bool BaseMap_Open(TFileStream * pStream, const TCHAR * szFileName, DWORD dwStreamFlags)
#ifdef STORMLIB_WINDOWS
typedef struct _SECTION_BASIC_INFORMATION
{
PVOID BaseAddress;
ULONG Attributes;
LARGE_INTEGER Size;
} SECTION_BASIC_INFORMATION, *PSECTION_BASIC_INFORMATION;
typedef ULONG (WINAPI * NTQUERYSECTION)(
IN HANDLE SectionHandle,
IN ULONG SectionInformationClass,
OUT PVOID SectionInformation,
IN SIZE_T Length,
OUT PSIZE_T ResultLength);
static bool RetrieveFileMappingSize(HANDLE hSection, ULARGE_INTEGER & RefFileSize)
{
#ifdef PLATFORM_WINDOWS
SECTION_BASIC_INFORMATION BasicInfo = {0};
NTQUERYSECTION PfnQuerySection;
HMODULE hNtdll;
SIZE_T ReturnLength = 0;
if((hNtdll = GetModuleHandle(_T("ntdll.dll"))) != NULL)
{
PfnQuerySection = (NTQUERYSECTION)GetProcAddress(hNtdll, "NtQuerySection");
if(PfnQuerySection != NULL)
{
if(PfnQuerySection(hSection, 0, &BasicInfo, sizeof(SECTION_BASIC_INFORMATION), &ReturnLength) == 0)
{
RefFileSize.HighPart = BasicInfo.Size.HighPart;
RefFileSize.LowPart = BasicInfo.Size.LowPart;
return true;
}
}
}
ULARGE_INTEGER FileSize;
HANDLE hFile;
HANDLE hMap;
return false;
}
#endif
static bool BaseMap_Open(TFileStream * pStream, LPCTSTR szFileName, DWORD dwStreamFlags)
{
#ifdef STORMLIB_WINDOWS
ULARGE_INTEGER FileSize = {0};
HANDLE hFile = INVALID_HANDLE_VALUE;
HANDLE hMap = NULL;
bool bResult = false;
// Keep compiler happy
dwStreamFlags = dwStreamFlags;
// Open the file for read access
hFile = CreateFile(szFileName, FILE_READ_DATA, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
if(hFile != INVALID_HANDLE_VALUE)
// 1) Try to treat "szFileName" as a section name
hMap = OpenFileMapping(SECTION_QUERY | FILE_MAP_READ, FALSE, szFileName);
if(hMap != NULL)
{
// Retrieve file size. Don't allow mapping file of a zero size.
FileSize.LowPart = GetFileSize(hFile, &FileSize.HighPart);
if(FileSize.QuadPart != 0)
// Try to retrieve the size of the mapping
if(!RetrieveFileMappingSize(hMap, FileSize))
{
// Now create mapping object
hMap = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
if(hMap != NULL)
CloseHandle(hMap);
hMap = NULL;
}
}
// 2) Treat the name as file name
else
{
hFile = CreateFile(szFileName, FILE_READ_DATA, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
if(hFile != INVALID_HANDLE_VALUE)
{
// Retrieve file size. Don't allow mapping file of a zero size.
FileSize.LowPart = GetFileSize(hFile, &FileSize.HighPart);
if(FileSize.QuadPart != 0)
{
// Map the entire view into memory
// Note that this operation will fail if the file can't fit
// into usermode address space
pStream->Base.Map.pbFile = (LPBYTE)MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0);
if(pStream->Base.Map.pbFile != NULL)
{
// Retrieve file time
GetFileTime(hFile, NULL, NULL, (LPFILETIME)&pStream->Base.Map.FileTime);
// Now create file mapping over the file
hMap = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
}
}
}
// Retrieve file size and position
pStream->Base.Map.FileSize = FileSize.QuadPart;
pStream->Base.Map.FilePos = 0;
bResult = true;
}
// Did it succeed?
if(hMap != NULL)
{
// Map the entire view into memory
// Note that this operation will fail if the file can't fit
// into usermode address space
pStream->Base.Map.pbFile = (LPBYTE)MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0);
if(pStream->Base.Map.pbFile != NULL)
{
// Retrieve file time. If it's named section, put 0
if(hFile != INVALID_HANDLE_VALUE)
GetFileTime(hFile, NULL, NULL, (LPFILETIME)&pStream->Base.Map.FileTime);
// Close the map handle
CloseHandle(hMap);
}
// Retrieve file size and position
pStream->Base.Map.FileSize = FileSize.QuadPart;
pStream->Base.Map.FilePos = 0;
bResult = true;
}
// Close the file handle
CloseHandle(hFile);
// Close the map handle
CloseHandle(hMap);
}
// If the file is not there and is not available for random access,
// report error
if(bResult == false)
return false;
#endif
// Close the file handle
if(hFile != INVALID_HANDLE_VALUE)
CloseHandle(hFile);
// Return the result of the operation
return bResult;
#elif defined(STORMLIB_HAS_MMAP)
#if defined(PLATFORM_MAC) || defined(PLATFORM_LINUX) || defined(PLATFORM_HAIKU) || defined(PLATFORM_AMIGA) || defined(PLATFORM_SWITCH) || defined(PLATFORM_CTR) || defined(PLATFORM_VITA)
struct stat64 fileinfo;
intptr_t handle;
bool bResult = false;
@ -515,12 +577,7 @@ static bool BaseMap_Open(TFileStream * pStream, const TCHAR * szFileName, DWORD
// Get the file size
if(fstat64(handle, &fileinfo) != -1)
{
#if !defined(PLATFORM_AMIGA)
#if defined(PLATFORM_SWITCH) || defined(PLATFORM_CTR) || defined(PLATFORM_VITA)
pStream->Base.Map.pbFile = (LPBYTE)malloc((size_t)fileinfo.st_size);
#else
pStream->Base.Map.pbFile = (LPBYTE)mmap(NULL, (size_t)fileinfo.st_size, PROT_READ, MAP_PRIVATE, handle, 0);
#endif
if(pStream->Base.Map.pbFile != NULL)
{
// time_t is number of seconds since 1.1.1970, UTC.
@ -531,20 +588,21 @@ static bool BaseMap_Open(TFileStream * pStream, const TCHAR * szFileName, DWORD
pStream->Base.Map.FilePos = 0;
bResult = true;
}
#endif
}
close(handle);
}
// Did the mapping fail?
if(bResult == false)
{
nLastError = errno;
return false;
}
#endif
return bResult;
return true;
#else
// File mapping is not supported
return false;
#endif
}
static bool BaseMap_Read(
@ -573,18 +631,17 @@ static bool BaseMap_Read(
static void BaseMap_Close(TFileStream * pStream)
{
#ifdef PLATFORM_WINDOWS
#ifdef STORMLIB_WINDOWS
if(pStream->Base.Map.pbFile != NULL)
UnmapViewOfFile(pStream->Base.Map.pbFile);
#endif
#if (defined(PLATFORM_MAC) || defined(PLATFORM_LINUX) || defined(PLATFORM_HAIKU)) && !defined(PLATFORM_AMIGA) && !defined(PLATFORM_SWITCH) && !defined(PLATFORM_CTR) && !defined(PLATFORM_VITA)
//Todo(Amiga): Fix a proper solution for this
#elif defined(STORMLIB_HAS_MMAP)
if(pStream->Base.Map.pbFile != NULL)
munmap(pStream->Base.Map.pbFile, (size_t )pStream->Base.Map.FileSize);
#elif defined(PLATFORM_SWITCH) || defined(PLATFORM_CTR) || defined(PLATFORM_VITA)
if(pStream->Base.Map.pbFile != NULL)
free(pStream->Base.Map.pbFile);
#endif
pStream->Base.Map.pbFile = NULL;
@ -632,7 +689,7 @@ static const TCHAR * BaseHttp_ExtractServerName(const TCHAR * szFileName, TCHAR
static bool BaseHttp_Open(TFileStream * pStream, const TCHAR * szFileName, DWORD dwStreamFlags)
{
#ifdef PLATFORM_WINDOWS
#ifdef STORMLIB_WINDOWS
HINTERNET hRequest;
DWORD dwTemp = 0;
@ -677,6 +734,19 @@ static bool BaseHttp_Open(TFileStream * pStream, const TCHAR * szFileName, DWORD
DWORD dwFileSize = 0;
DWORD dwDataSize;
DWORD dwIndex = 0;
TCHAR StatusCode[0x08];
// Check if the file succeeded to open
dwDataSize = sizeof(StatusCode);
if(HttpQueryInfo(hRequest, HTTP_QUERY_STATUS_CODE, StatusCode, &dwDataSize, &dwIndex))
{
if(_tcscmp(StatusCode, _T("200")))
{
InternetCloseHandle(hRequest);
SetLastError(ERROR_FILE_NOT_FOUND);
return false;
}
}
// Check if the MPQ has Last Modified field
dwDataSize = sizeof(ULONGLONG);
@ -731,7 +801,7 @@ static bool BaseHttp_Read(
void * pvBuffer, // Pointer to data to be read
DWORD dwBytesToRead) // Number of bytes to read from the file
{
#ifdef PLATFORM_WINDOWS
#ifdef STORMLIB_WINDOWS
ULONGLONG ByteOffset = (pByteOffset != NULL) ? *pByteOffset : pStream->Base.Http.FilePos;
DWORD dwTotalBytesRead = 0;
@ -752,8 +822,8 @@ static bool BaseHttp_Read(
{
// Add range request to the HTTP headers
// http://www.clevercomponents.com/articles/article015/resuming.asp
_stprintf(szRangeRequest, _T("Range: bytes=%u-%u"), (unsigned int)dwStartOffset, (unsigned int)dwEndOffset);
HttpAddRequestHeaders(hRequest, szRangeRequest, 0xFFFFFFFF, HTTP_ADDREQ_FLAG_ADD_IF_NEW);
wsprintf(szRangeRequest, _T("Range: bytes=%u-%u"), (unsigned int)dwStartOffset, (unsigned int)dwEndOffset);
HttpAddRequestHeaders(hRequest, szRangeRequest, 0xFFFFFFFF, HTTP_ADDREQ_FLAG_ADD_IF_NEW);
// Send the request to the server
if(HttpSendRequest(hRequest, NULL, 0, NULL, 0))
@ -804,7 +874,7 @@ static bool BaseHttp_Read(
static void BaseHttp_Close(TFileStream * pStream)
{
#ifdef PLATFORM_WINDOWS
#ifdef STORMLIB_WINDOWS
if(pStream->Base.Http.hConnect != NULL)
InternetCloseHandle(pStream->Base.Http.hConnect);
pStream->Base.Http.hConnect = NULL;
@ -1006,7 +1076,7 @@ static void BlockStream_Close(TBlockStream * pStream)
static STREAM_INIT StreamBaseInit[4] =
{
BaseFile_Init,
BaseMap_Init,
BaseMap_Init,
BaseHttp_Init,
BaseNone_Init
};
@ -1690,7 +1760,7 @@ static void PartStream_Close(TBlockStream * pStream)
// Make sure that the header is properly BSWAPed
BSWAP_ARRAY32_UNSIGNED(&PartHeader, sizeof(PART_FILE_HEADER));
sprintf(PartHeader.GameBuildNumber, "%u", (unsigned int)pStream->BuildNumber);
IntToString(PartHeader.GameBuildNumber, _countof(PartHeader.GameBuildNumber), pStream->BuildNumber);
// Write the part header
pStream->BaseWrite(pStream, &ByteOffset, &PartHeader, sizeof(PART_FILE_HEADER));
@ -2049,7 +2119,7 @@ static bool MpqeStream_DetectFileKey(TEncryptedStream * pStream)
// Prepare they decryption key from game serial number
CreateKeyFromAuthCode(pStream->Key, AuthCodeArray[i]);
// Try to decrypt with the given key
// Try to decrypt with the given key
memcpy(FileHeader, EncryptedHeader, MPQE_CHUNK_SIZE);
DecryptFileChunk((LPDWORD)FileHeader, pStream->Key, ByteOffset, MPQE_CHUNK_SIZE);
@ -2275,7 +2345,7 @@ static TFileStream * Block4Stream_Open(const TCHAR * szFileName, DWORD dwStreamF
for(int nSuffix = 0; nSuffix < 30; nSuffix++)
{
// Open the n-th file
_stprintf(szNameBuff, _T("%s.%u"), pStream->szFileName, nSuffix);
CreateNameWithSuffix(szNameBuff, nNameLength + 4, pStream->szFileName, nSuffix);
if(!pStream->BaseOpen(pStream, szNameBuff, dwBaseFlags))
break;
@ -2305,7 +2375,7 @@ static TFileStream * Block4Stream_Open(const TCHAR * szFileName, DWORD dwStreamF
RemainderBlock = FileSize % (BLOCK4_BLOCK_SIZE + BLOCK4_HASH_SIZE);
BlockCount = FileSize / (BLOCK4_BLOCK_SIZE + BLOCK4_HASH_SIZE);
// Increment the stream size and number of blocks
// Increment the stream size and number of blocks
pStream->StreamSize += (BlockCount * BLOCK4_BLOCK_SIZE);
pStream->BlockCount += (DWORD)BlockCount;
@ -2839,7 +2909,7 @@ void FileStream_Close(TFileStream * pStream)
FileStream_Close(pStream->pMaster);
pStream->pMaster = NULL;
// Close the stream provider ...
// Close the stream provider
if(pStream->StreamClose != NULL)
pStream->StreamClose(pStream);

2
3rdParty/StormLib/src/FileStream.h vendored

@ -202,7 +202,7 @@ struct TBlockStream : public TFileStream
DWORD BlockCount; // Number of data blocks in the file
DWORD IsComplete; // If nonzero, no blocks are missing
DWORD IsModified; // nonzero if the bitmap has been modified
};
};
//-----------------------------------------------------------------------------
// Structure for encrypted stream

167
3rdParty/StormLib/src/SBaseCommon.cpp vendored

@ -20,7 +20,10 @@ char StormLibCopyright[] = "StormLib v " STORMLIB_VERSION_STRING " Copyright Lad
//-----------------------------------------------------------------------------
// Local variables
LCID lcFileLocale = LANG_NEUTRAL; // File locale
DWORD g_dwMpqSignature = ID_MPQ; // Marker for MPQ header
DWORD g_dwHashTableKey = MPQ_KEY_HASH_TABLE; // Key for hash table
DWORD g_dwBlockTableKey = MPQ_KEY_BLOCK_TABLE; // Key for block table
LCID g_lcFileLocale = LANG_NEUTRAL; // File locale
USHORT wPlatform = 0; // File platform
//-----------------------------------------------------------------------------
@ -95,11 +98,13 @@ unsigned char AsciiToUpperTable_Slash[256] =
//-----------------------------------------------------------------------------
// Safe string functions (for ANSI builds)
void StringCopy(char * szTarget, size_t cchTarget, const char * szSource)
char * StringCopy(char * szTarget, size_t cchTarget, const char * szSource)
{
size_t cchSource = 0;
if(cchTarget > 0)
{
size_t cchSource = strlen(szSource);
cchSource = strlen(szSource);
if(cchSource >= cchTarget)
cchSource = cchTarget - 1;
@ -107,6 +112,8 @@ void StringCopy(char * szTarget, size_t cchTarget, const char * szSource)
memcpy(szTarget, szSource, cchSource);
szTarget[cchSource] = 0;
}
return szTarget + cchSource;
}
void StringCat(char * szTarget, size_t cchTargetMax, const char * szSource)
@ -121,6 +128,26 @@ void StringCat(char * szTarget, size_t cchTargetMax, const char * szSource)
}
}
void StringCreatePseudoFileName(char * szBuffer, size_t cchMaxChars, unsigned int nIndex, const char * szExtension)
{
char * szBufferEnd = szBuffer + cchMaxChars;
// "File"
szBuffer = StringCopy(szBuffer, (szBufferEnd - szBuffer), "File");
// Number
szBuffer = IntToString(szBuffer, szBufferEnd - szBuffer + 1, nIndex, 8);
// Dot
if(szBuffer < szBufferEnd)
*szBuffer++ = '.';
// Extension
while(szExtension[0] == '.')
szExtension++;
StringCopy(szBuffer, (szBufferEnd - szBuffer), szExtension);
}
//-----------------------------------------------------------------------------
// Utility functions (UNICODE) only exist in the ANSI version of the library
// In ANSI builds, TCHAR = char, so we don't need these functions implemented
@ -217,14 +244,13 @@ void InitializeMpqCryptography()
}
}
#ifdef FULL
// Also register both MD5 and SHA1 hash algorithms
register_hash(&md5_desc);
register_hash(&sha1_desc);
// Use LibTomMath as support math library for LibTomCrypt
ltc_mp = ltm_desc;
#endif
// Don't do that again
bMpqCryptographyInitialized = true;
}
@ -339,8 +365,6 @@ DWORD GetNearestPowerOfTwo(DWORD dwFileCount)
return dwPowerOfTwo;
}
*/
#ifdef FULL
//-----------------------------------------------------------------------------
// Calculates a Jenkin's Encrypting and decrypting MPQ file data
@ -372,7 +396,6 @@ ULONGLONG HashStringJenkins(const char * szFileName)
// Combine those 2 together
return ((ULONGLONG)primary_hash << 0x20) | (ULONGLONG)secondary_hash;
}
#endif
//-----------------------------------------------------------------------------
// Default flags for (attributes) and (listfile)
@ -610,7 +633,7 @@ TMPQArchive * IsValidMpqHandle(HANDLE hMpq)
{
TMPQArchive * ha = (TMPQArchive *)hMpq;
return (ha != NULL && ha->pHeader != NULL && ha->pHeader->dwID == ID_MPQ) ? ha : NULL;
return (ha != NULL && ha->pHeader != NULL && ha->pHeader->dwID == g_dwMpqSignature) ? ha : NULL;
}
TMPQFile * IsValidFileHandle(HANDLE hFile)
@ -887,6 +910,7 @@ TMPQFile * CreateWritableHandle(TMPQArchive * ha, DWORD dwFileSize)
void * LoadMpqTable(
TMPQArchive * ha,
ULONGLONG ByteOffset,
LPBYTE pbTableHash,
DWORD dwCompressedSize,
DWORD dwTableSize,
DWORD dwKey,
@ -925,6 +949,7 @@ void * LoadMpqTable(
// On archives v 1.0, hash table and block table can go beyond EOF.
// Storm.dll reads as much as possible, then fills the missing part with zeros.
// Abused by Spazzler map protector which sets hash table size to 0x00100000
// Abused by NP_Protect in MPQs v4 as well
if(ha->pHeader->wFormatVersion == MPQ_FORMAT_VERSION_1)
{
// Cut the table size
@ -941,8 +966,21 @@ void * LoadMpqTable(
}
}
// If everything succeeded, read the raw table form the MPQ
// If everything succeeded, read the raw table from the MPQ
if(FileStream_Read(ha->pStream, &ByteOffset, pbToRead, dwBytesToRead))
{
// Verify the MD5 of the table, if present
if(!VerifyDataBlockHash(pbToRead, dwBytesToRead, pbTableHash))
{
nError = ERROR_FILE_CORRUPT;
}
}
else
{
nError = GetLastError();
}
if(nError == ERROR_SUCCESS)
{
// First of all, decrypt the table
if(dwKey != 0)
@ -965,10 +1003,6 @@ void * LoadMpqTable(
// Make sure that the table is properly byte-swapped
BSWAP_ARRAY32_UNSIGNED(pbMpqTable, dwTableSize);
}
else
{
nError = GetLastError();
}
// If read failed, free the table and return
if(nError != ERROR_SUCCESS)
@ -1320,7 +1354,7 @@ int AllocateSectorChecksums(TMPQFile * hf, bool bLoadFromFile)
RawFilePos = CalculateRawSectorOffset(hf, dwCrcOffset);
// Now read the table from the MPQ
hf->SectorChksums = (DWORD *)LoadMpqTable(ha, RawFilePos, dwCompressedSize, dwCrcSize, 0, NULL);
hf->SectorChksums = (DWORD *)LoadMpqTable(ha, RawFilePos, NULL, dwCompressedSize, dwCrcSize, 0, NULL);
if(hf->SectorChksums == NULL)
return ERROR_NOT_ENOUGH_MEMORY;
}
@ -1380,7 +1414,6 @@ int WriteSectorOffsets(TMPQFile * hf)
return ERROR_SUCCESS;
}
int WriteSectorChecksums(TMPQFile * hf)
{
TMPQArchive * ha = hf->ha;
@ -1611,10 +1644,8 @@ void FreeArchiveHandle(TMPQArchive *& ha)
if(ha->pHashTable != NULL)
STORM_FREE(ha->pHashTable);
#ifdef FULL
if(ha->pHetTable != NULL)
FreeHetTable(ha->pHetTable);
#endif
STORM_FREE(ha);
ha = NULL;
}
@ -1674,7 +1705,7 @@ bool IsValidMD5(LPBYTE pbMd5)
{
LPDWORD Md5 = (LPDWORD)pbMd5;
return (Md5[0] | Md5[1] | Md5[2] | Md5[3]) ? true : false;
return ((Md5 != NULL) && (Md5[0] | Md5[1] | Md5[2] | Md5[3])) ? true : false;
}
bool IsValidSignature(LPBYTE pbSignature)
@ -1691,127 +1722,81 @@ bool IsValidSignature(LPBYTE pbSignature)
bool VerifyDataBlockHash(void * pvDataBlock, DWORD cbDataBlock, LPBYTE expected_md5)
{
#ifdef FULL
hash_state md5_state;
BYTE md5_digest[MD5_DIGEST_SIZE];
bool bResult = true;
// Don't verify the block if the MD5 is not valid.
if(!IsValidMD5(expected_md5))
return true;
if(IsValidMD5(expected_md5))
{
// Calculate the MD5 of the data block
md5_init(&md5_state);
md5_process(&md5_state, (unsigned char *)pvDataBlock, cbDataBlock);
md5_done(&md5_state, md5_digest);
// Calculate the MD5 of the data block
md5_init(&md5_state);
md5_process(&md5_state, (unsigned char *)pvDataBlock, cbDataBlock);
md5_done(&md5_state, md5_digest);
// Does the MD5's match?
bResult = (memcmp(md5_digest, expected_md5, MD5_DIGEST_SIZE) == 0);
}
// Does the MD5's match?
return (memcmp(md5_digest, expected_md5, MD5_DIGEST_SIZE) == 0);
#else
assert(0);
return false;
#endif
return bResult;
}
void CalculateDataBlockHash(void * pvDataBlock, DWORD cbDataBlock, LPBYTE md5_hash)
{
#ifdef FULL
hash_state md5_state;
md5_init(&md5_state);
md5_process(&md5_state, (unsigned char *)pvDataBlock, cbDataBlock);
md5_done(&md5_state, md5_hash);
#else
assert(0);
#endif
}
//-----------------------------------------------------------------------------
// Swapping functions
#if !defined(PLATFORM_LITTLE_ENDIAN)
//
// Note that those functions are implemented for Mac operating system,
// as this is the only supported platform that uses big endian.
//
#ifndef STORMLIB_LITTLE_ENDIAN
#if defined(PLATFORM_MAC)
// Swaps a signed 16-bit integer
int16_t SwapInt16(uint16_t data)
int16_t SwapInt16(uint16_t val)
{
return (int16_t)CFSwapInt16(data);
return (val << 8) | ((val >> 8) & 0xFF);
}
// Swaps an unsigned 16-bit integer
uint16_t SwapUInt16(uint16_t data)
{
return CFSwapInt16(data);
}
// Swaps signed 32-bit integer
int32_t SwapInt32(uint32_t data)
{
return (int32_t)CFSwapInt32(data);
}
// Swaps an unsigned 32-bit integer
uint32_t SwapUInt32(uint32_t data)
{
return CFSwapInt32(data);
}
// Swaps signed 64-bit integer
int64_t SwapInt64(int64_t data)
{
return (int64_t)CFSwapInt64(data);
}
// Swaps an unsigned 64-bit integer
uint64_t SwapUInt64(uint64_t data)
{
return CFSwapInt64(data);
}
#else
//! Byte swap unsigned short
uint16_t SwapUInt16( uint16_t val )
uint16_t SwapUInt16(uint16_t val)
{
return (val << 8) | (val >> 8 );
}
//! Byte swap short
int16_t SwapInt16( int16_t val )
// Swaps a signed 32-bit integer
int32_t SwapInt32(uint32_t val)
{
return (val << 8) | ((val >> 8) & 0xFF);
val = ((val << 8) & 0xFF00FF00) | ((val >> 8) & 0xFF00FF );
return (val << 16) | ((val >> 16) & 0xFFFF);
}
//! Byte swap unsigned int
uint32_t SwapUInt32( uint32_t val )
// Swaps an unsigned 32-bit integer
uint32_t SwapUInt32(uint32_t val)
{
val = ((val << 8) & 0xFF00FF00 ) | ((val >> 8) & 0xFF00FF );
return (val << 16) | (val >> 16);
}
//! Byte swap int
int32_t SwapInt32( int32_t val )
{
val = ((val << 8) & 0xFF00FF00) | ((val >> 8) & 0xFF00FF );
return (val << 16) | ((val >> 16) & 0xFFFF);
}
int64_t SwapInt64( int64_t val )
// Swaps a signed 64-bit integer
int64_t SwapInt64(uint64_t val)
{
val = ((val << 8) & 0xFF00FF00FF00FF00ULL ) | ((val >> 8) & 0x00FF00FF00FF00FFULL );
val = ((val << 16) & 0xFFFF0000FFFF0000ULL ) | ((val >> 16) & 0x0000FFFF0000FFFFULL );
return (val << 32) | ((val >> 32) & 0xFFFFFFFFULL);
}
uint64_t SwapUInt64( uint64_t val )
// Swaps an unsigned 64-bit integer
uint64_t SwapUInt64(uint64_t val)
{
val = ((val << 8) & 0xFF00FF00FF00FF00ULL ) | ((val >> 8) & 0x00FF00FF00FF00FFULL );
val = ((val << 16) & 0xFFFF0000FFFF0000ULL ) | ((val >> 16) & 0x0000FFFF0000FFFFULL );
return (val << 32) | (val >> 32);
}
#endif
// Swaps array of unsigned 16-bit integers
void ConvertUInt16Buffer(void * ptr, size_t length)
@ -1895,4 +1880,4 @@ void ConvertTMPQHeader(void *header, uint16_t version)
}
}
#endif // PLATFORM_LITTLE_ENDIAN
#endif // STORMLIB_LITTLE_ENDIAN

349
3rdParty/StormLib/src/SBaseFileTable.cpp vendored

@ -57,19 +57,33 @@ static DWORD GetNecessaryBitCount(ULONGLONG MaxValue)
}
//-----------------------------------------------------------------------------
// Support functions for BIT_ARRAY
// Implementation of the TMPQBits struct
static USHORT SetBitsMask[] = {0x00, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF};
struct TMPQBits
{
static TMPQBits * Create(DWORD NumberOfBits, BYTE FillValue);
void GetBits(unsigned int nBitPosition, unsigned int nBitLength, void * pvBuffer, int nResultSize);
void SetBits(unsigned int nBitPosition, unsigned int nBitLength, void * pvBuffer, int nResultSize);
static const USHORT SetBitsMask[]; // Bit mask for each number of bits (0-8)
DWORD NumberOfBytes; // Total number of bytes in "Elements"
DWORD NumberOfBits; // Total number of bits that are available
BYTE Elements[1]; // Array of elements (variable length)
};
const USHORT TMPQBits::SetBitsMask[] = {0x00, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF};
static TBitArray * CreateBitArray(
TMPQBits * TMPQBits::Create(
DWORD NumberOfBits,
BYTE FillValue)
{
TBitArray * pBitArray;
size_t nSize = sizeof(TBitArray) + (NumberOfBits + 7) / 8;
TMPQBits * pBitArray;
size_t nSize = sizeof(TMPQBits) + (NumberOfBits + 7) / 8;
// Allocate the bit array
pBitArray = (TBitArray *)STORM_ALLOC(BYTE, nSize);
pBitArray = (TMPQBits *)STORM_ALLOC(BYTE, nSize);
if(pBitArray != NULL)
{
memset(pBitArray, FillValue, nSize);
@ -80,8 +94,7 @@ static TBitArray * CreateBitArray(
return pBitArray;
}
void GetBits(
TBitArray * pArray,
void TMPQBits::GetBits(
unsigned int nBitPosition,
unsigned int nBitLength,
void * pvBuffer,
@ -103,7 +116,7 @@ void GetBits(
assert(pbBuffer[i] == 0);
#endif
#ifndef PLATFORM_LITTLE_ENDIAN
#ifndef STORMLIB_LITTLE_ENDIAN
// Adjust the buffer pointer for big endian platforms
pbBuffer += (nResultByteSize - 1);
#endif
@ -114,14 +127,14 @@ void GetBits(
// Is the current position in the Elements byte-aligned?
if(nBitOffset != 0)
{
BitBuffer = (unsigned char)((pArray->Elements[nBytePosition0] >> nBitOffset) | (pArray->Elements[nBytePosition1] << (0x08 - nBitOffset)));
BitBuffer = (unsigned char)((Elements[nBytePosition0] >> nBitOffset) | (Elements[nBytePosition1] << (0x08 - nBitOffset)));
}
else
{
BitBuffer = pArray->Elements[nBytePosition0];
BitBuffer = Elements[nBytePosition0];
}
#ifdef PLATFORM_LITTLE_ENDIAN
#ifdef STORMLIB_LITTLE_ENDIAN
*pbBuffer++ = BitBuffer;
#else
*pbBuffer-- = BitBuffer;
@ -137,17 +150,16 @@ void GetBits(
nBitLength = (nBitLength & 0x07);
if(nBitLength != 0)
{
*pbBuffer = (unsigned char)(pArray->Elements[nBytePosition0] >> nBitOffset);
*pbBuffer = (unsigned char)(Elements[nBytePosition0] >> nBitOffset);
if(nBitLength > (8 - nBitOffset))
*pbBuffer = (unsigned char)((pArray->Elements[nBytePosition1] << (8 - nBitOffset)) | (pArray->Elements[nBytePosition0] >> nBitOffset));
*pbBuffer = (unsigned char)((Elements[nBytePosition1] << (8 - nBitOffset)) | (Elements[nBytePosition0] >> nBitOffset));
*pbBuffer &= (0x01 << nBitLength) - 1;
}
}
void SetBits(
TBitArray * pArray,
void TMPQBits::SetBits(
unsigned int nBitPosition,
unsigned int nBitLength,
void * pvBuffer,
@ -163,7 +175,7 @@ void SetBits(
// Keep compiler happy for platforms where nResultByteSize is not used
nResultByteSize = nResultByteSize;
#ifndef PLATFORM_LITTLE_ENDIAN
#ifndef STORMLIB_LITTLE_ENDIAN
// Adjust the buffer pointer for big endian platforms
pbBuffer += (nResultByteSize - 1);
#endif
@ -172,7 +184,7 @@ void SetBits(
while(nBitLength > 8)
{
// Reload the bit buffer
#ifdef PLATFORM_LITTLE_ENDIAN
#ifdef STORMLIB_LITTLE_ENDIAN
OneByte = *pbBuffer++;
#else
OneByte = *pbBuffer--;
@ -182,7 +194,7 @@ void SetBits(
AndMask = (AndMask >> 0x08) | (0x00FF << nBitOffset);
// Update the byte in the array
pArray->Elements[nBytePosition] = (BYTE)((pArray->Elements[nBytePosition] & ~AndMask) | BitBuffer);
Elements[nBytePosition] = (BYTE)((Elements[nBytePosition] & ~AndMask) | BitBuffer);
// Move byte positions and lengths
nBytePosition++;
@ -199,7 +211,7 @@ void SetBits(
AndMask = (AndMask >> 0x08) | (SetBitsMask[nBitLength] << nBitOffset);
// Update the byte in the array
pArray->Elements[nBytePosition] = (BYTE)((pArray->Elements[nBytePosition] & ~AndMask) | BitBuffer);
Elements[nBytePosition] = (BYTE)((Elements[nBytePosition] & ~AndMask) | BitBuffer);
// Update the next byte, if needed
if(AndMask & 0xFF00)
@ -208,14 +220,56 @@ void SetBits(
BitBuffer >>= 0x08;
AndMask >>= 0x08;
pArray->Elements[nBytePosition] = (BYTE)((pArray->Elements[nBytePosition] & ~AndMask) | BitBuffer);
Elements[nBytePosition] = (BYTE)((Elements[nBytePosition] & ~AndMask) | BitBuffer);
}
}
}
void GetMPQBits(TMPQBits * pBits, unsigned int nBitPosition, unsigned int nBitLength, void * pvBuffer, int nResultByteSize)
{
pBits->GetBits(nBitPosition, nBitLength, pvBuffer, nResultByteSize);
}
//-----------------------------------------------------------------------------
// Support for MPQ header
static bool VerifyTablePosition64(
ULONGLONG MpqOffset, // Position of the MPQ header
ULONGLONG TableOffset, // Position of the MPQ table, relative to MPQ header
ULONGLONG TableSize, // Size of the MPQ table, in bytes
ULONGLONG FileSize) // Size of the entire file, in bytes
{
if(TableOffset != 0)
{
// Verify overflows
if((MpqOffset + TableOffset) < MpqOffset)
return false;
if((MpqOffset + TableOffset + TableSize) < MpqOffset)
return false;
// Verify sizes
if(TableOffset >= FileSize || TableSize >= FileSize)
return false;
if((MpqOffset + TableOffset) >= FileSize)
return false;
if((MpqOffset + TableOffset + TableSize) >= FileSize)
return false;
}
return true;
}
static bool VerifyTableTandemPositions(
ULONGLONG MpqOffset, // Position of the MPQ header
ULONGLONG TableOffset1, // 1st table: Position, relative to MPQ header
ULONGLONG TableSize1, // 1st table: Size in bytes
ULONGLONG TableOffset2, // 2nd table: Position, relative to MPQ header
ULONGLONG TableSize2, // 2nd table: Size in bytes
ULONGLONG FileSize) // Size of the entire file, in bytes
{
return VerifyTablePosition64(MpqOffset, TableOffset1, TableSize1, FileSize) &&
VerifyTablePosition64(MpqOffset, TableOffset2, TableSize2, FileSize);
}
static ULONGLONG DetermineArchiveSize_V1(
TMPQArchive * ha,
TMPQHeader * pHeader,
@ -288,6 +342,45 @@ static ULONGLONG DetermineArchiveSize_V2(
return (EndOfMpq - MpqOffset);
}
static ULONGLONG DetermineArchiveSize_V4(
TMPQHeader * pHeader,
ULONGLONG /* MpqOffset */,
ULONGLONG /* FileSize */)
{
ULONGLONG ArchiveSize = 0;
ULONGLONG EndOfTable;
// This could only be called for MPQs version 4
assert(pHeader->wFormatVersion == MPQ_FORMAT_VERSION_4);
// Check position of BET table, if correct
if((pHeader->BetTablePos64 >> 0x20) == 0 && (pHeader->BetTableSize64 >> 0x20) == 0)
{
EndOfTable = pHeader->BetTablePos64 + pHeader->BetTableSize64;
if(EndOfTable > ArchiveSize)
ArchiveSize = EndOfTable;
}
// Check position of HET table, if correct
if((pHeader->HetTablePos64 >> 0x20) == 0 && (pHeader->HetTableSize64 >> 0x20) == 0)
{
EndOfTable = pHeader->HetTablePos64 + pHeader->HetTableSize64;
if(EndOfTable > ArchiveSize)
ArchiveSize = EndOfTable;
}
EndOfTable = pHeader->dwHashTablePos + pHeader->dwHashTableSize * sizeof(TMPQHash);
if(EndOfTable > ArchiveSize)
ArchiveSize = EndOfTable;
EndOfTable = pHeader->dwBlockTablePos + pHeader->dwBlockTableSize * sizeof(TMPQBlock);
if(EndOfTable > ArchiveSize)
ArchiveSize = EndOfTable;
// Return the calculated archive size
return ArchiveSize;
}
ULONGLONG FileOffsetFromMpqOffset(TMPQArchive * ha, ULONGLONG MpqOffset)
{
if(ha->pHeader->wFormatVersion == MPQ_FORMAT_VERSION_1)
@ -336,24 +429,30 @@ ULONGLONG CalculateRawSectorOffset(
// This function converts the MPQ header so it always looks like version 4
int ConvertMpqHeaderToFormat4(
TMPQArchive * ha,
ULONGLONG MpqOffset,
ULONGLONG ByteOffset,
ULONGLONG FileSize,
DWORD dwFlags,
bool bIsWarcraft3Map)
MTYPE MapType)
{
TMPQHeader * pHeader = (TMPQHeader *)ha->HeaderData;
ULONGLONG BlockTablePos64 = 0;
ULONGLONG HashTablePos64 = 0;
ULONGLONG BlockTableMask = (ULONGLONG)-1;
ULONGLONG ByteOffset;
ULONGLONG MaxOffset;
USHORT wFormatVersion = BSWAP_INT16_UNSIGNED(pHeader->wFormatVersion);
bool bHashBlockOffsetOK = false;
bool bHetBetOffsetOK = false;
int nError = ERROR_SUCCESS;
// If version 1.0 is forced, then the format version is forced to be 1.0
// Reason: Storm.dll in Warcraft III ignores format version value
if((dwFlags & MPQ_OPEN_FORCE_MPQ_V1) || bIsWarcraft3Map)
if((MapType == MapTypeWarcraft3) || (dwFlags & MPQ_OPEN_FORCE_MPQ_V1))
wFormatVersion = MPQ_FORMAT_VERSION_1;
// Don't accept format 3 for Starcraft II maps
if((MapType == MapTypeStarcraft2) && (pHeader->wFormatVersion > MPQ_FORMAT_VERSION_2))
wFormatVersion = MPQ_FORMAT_VERSION_4;
// Format-specific fixes
switch(wFormatVersion)
{
@ -396,16 +495,24 @@ int ConvertMpqHeaderToFormat4(
// Block table position must be calculated as 32-bit value
// Note: BOBA protector puts block table before the MPQ header, so it is negative
BlockTablePos64 = (ULONGLONG)((DWORD)MpqOffset + pHeader->dwBlockTablePos);
BlockTablePos64 = (ULONGLONG)((DWORD)ByteOffset + pHeader->dwBlockTablePos);
BlockTableMask = 0xFFFFFFF0;
// Determine the archive size on malformed MPQs
if(ha->dwFlags & MPQ_FLAG_MALFORMED)
{
// Calculate the archive size
pHeader->ArchiveSize64 = DetermineArchiveSize_V1(ha, pHeader, MpqOffset, FileSize);
pHeader->ArchiveSize64 = DetermineArchiveSize_V1(ha, pHeader, ByteOffset, FileSize);
pHeader->dwArchiveSize = (DWORD)pHeader->ArchiveSize64;
}
// EWIX_v8_7.w3x: TMPQHeader::dwBlockTableSize = 0x00319601
// Size of TFileTable goes to ~200MB, so we artificially cut it
if(BlockTablePos64 + (pHeader->dwBlockTableSize * sizeof(TMPQBlock)) > FileSize)
{
pHeader->dwBlockTableSize = (DWORD)((FileSize - BlockTablePos64) / sizeof(TMPQBlock));
pHeader->BlockTableSize64 = pHeader->dwBlockTableSize * sizeof(TMPQBlock);
}
break;
case MPQ_FORMAT_VERSION_2:
@ -447,7 +554,7 @@ int ConvertMpqHeaderToFormat4(
assert(pHeader->BlockTableSize64 <= (pHeader->dwBlockTableSize * sizeof(TMPQBlock)));
// Determine real archive size
pHeader->ArchiveSize64 = DetermineArchiveSize_V2(pHeader, MpqOffset, FileSize);
pHeader->ArchiveSize64 = DetermineArchiveSize_V2(pHeader, ByteOffset, FileSize);
// Calculate the size of the hi-block table
pHeader->HiBlockTableSize64 = pHeader->ArchiveSize64 - pHeader->HiBlockTablePos64;
@ -456,7 +563,7 @@ int ConvertMpqHeaderToFormat4(
else
{
// Determine real archive size
pHeader->ArchiveSize64 = DetermineArchiveSize_V2(pHeader, MpqOffset, FileSize);
pHeader->ArchiveSize64 = DetermineArchiveSize_V2(pHeader, ByteOffset, FileSize);
// Calculate size of the block table
pHeader->BlockTableSize64 = pHeader->ArchiveSize64 - BlockTablePos64;
@ -470,7 +577,7 @@ int ConvertMpqHeaderToFormat4(
}
// Add the MPQ Offset
BlockTablePos64 += MpqOffset;
BlockTablePos64 += ByteOffset;
break;
case MPQ_FORMAT_VERSION_3:
@ -499,45 +606,45 @@ int ConvertMpqHeaderToFormat4(
memset((LPBYTE)pHeader + MPQ_HEADER_SIZE_V3, 0, sizeof(TMPQHeader) - MPQ_HEADER_SIZE_V3);
BlockTablePos64 = MAKE_OFFSET64(pHeader->wBlockTablePosHi, pHeader->dwBlockTablePos);
HashTablePos64 = MAKE_OFFSET64(pHeader->wHashTablePosHi, pHeader->dwHashTablePos);
ByteOffset = pHeader->ArchiveSize64;
MaxOffset = pHeader->ArchiveSize64;
// Size of the hi-block table
if(pHeader->HiBlockTablePos64)
{
pHeader->HiBlockTableSize64 = ByteOffset - pHeader->HiBlockTablePos64;
ByteOffset = pHeader->HiBlockTablePos64;
pHeader->HiBlockTableSize64 = MaxOffset - pHeader->HiBlockTablePos64;
MaxOffset = pHeader->HiBlockTablePos64;
}
// Size of the block table
if(BlockTablePos64)
{
pHeader->BlockTableSize64 = ByteOffset - BlockTablePos64;
ByteOffset = BlockTablePos64;
pHeader->BlockTableSize64 = MaxOffset - BlockTablePos64;
MaxOffset = BlockTablePos64;
}
// Size of the hash table
if(HashTablePos64)
{
pHeader->HashTableSize64 = ByteOffset - HashTablePos64;
ByteOffset = HashTablePos64;
pHeader->HashTableSize64 = MaxOffset - HashTablePos64;
MaxOffset = HashTablePos64;
}
// Size of the BET table
if(pHeader->BetTablePos64)
{
pHeader->BetTableSize64 = ByteOffset - pHeader->BetTablePos64;
ByteOffset = pHeader->BetTablePos64;
pHeader->BetTableSize64 = MaxOffset - pHeader->BetTablePos64;
MaxOffset = pHeader->BetTablePos64;
}
// Size of the HET table
if(pHeader->HetTablePos64)
{
pHeader->HetTableSize64 = ByteOffset - pHeader->HetTablePos64;
// ByteOffset = pHeader->HetTablePos64;
pHeader->HetTableSize64 = MaxOffset - pHeader->HetTablePos64;
// MaxOffset = pHeader->HetTablePos64;
}
// Add the MPQ Offset
BlockTablePos64 += MpqOffset;
BlockTablePos64 += ByteOffset;
break;
case MPQ_FORMAT_VERSION_4:
@ -545,11 +652,52 @@ int ConvertMpqHeaderToFormat4(
// Verify header MD5. Header MD5 is calculated from the MPQ header since the 'MPQ\x1A'
// signature until the position of header MD5 at offset 0xC0
BSWAP_TMPQHEADER(pHeader, MPQ_FORMAT_VERSION_4);
// Apparently, Starcraft II only accepts MPQ headers where the MPQ header hash matches
// If MD5 doesn't match, we ignore this offset. We also ignore it if there's no MD5 at all
if(!IsValidMD5(pHeader->MD5_MpqHeader))
return ERROR_FAKE_MPQ_HEADER;
if(!VerifyDataBlockHash(pHeader, MPQ_HEADER_SIZE_V4 - MD5_DIGEST_SIZE, pHeader->MD5_MpqHeader))
nError = ERROR_FILE_CORRUPT;
return ERROR_FAKE_MPQ_HEADER;
// HiBlockTable must be 0 for archives under 4GB
if((pHeader->ArchiveSize64 >> 0x20) == 0 && pHeader->HiBlockTablePos64 != 0)
return ERROR_FAKE_MPQ_HEADER;
// Is the "HET&BET" table tandem OK?
bHetBetOffsetOK = VerifyTableTandemPositions(ByteOffset,
pHeader->HetTablePos64, pHeader->HetTableSize64,
pHeader->BetTablePos64, pHeader->BetTableSize64,
FileSize);
// Is the "Hash&Block" table tandem OK?
bHashBlockOffsetOK = VerifyTableTandemPositions(ByteOffset,
pHeader->dwHashTablePos, pHeader->HashTableSize64,
pHeader->dwBlockTablePos, pHeader->BlockTableSize64,
FileSize);
// At least one pair must be OK
if(bHetBetOffsetOK == false && bHashBlockOffsetOK == false)
return ERROR_FAKE_MPQ_HEADER;
// Check for malformed MPQs
if(pHeader->wFormatVersion != MPQ_FORMAT_VERSION_4 || (ByteOffset + pHeader->ArchiveSize64) != FileSize || (ByteOffset + pHeader->HiBlockTablePos64) >= FileSize)
{
pHeader->wFormatVersion = MPQ_FORMAT_VERSION_4;
pHeader->dwHeaderSize = MPQ_HEADER_SIZE_V4;
ha->dwFlags |= MPQ_FLAG_MALFORMED;
}
// Recalculate archive size
if(ha->dwFlags & MPQ_FLAG_MALFORMED)
{
// Calculate the archive size
pHeader->ArchiveSize64 = DetermineArchiveSize_V4(pHeader, ByteOffset, FileSize);
pHeader->dwArchiveSize = (DWORD)pHeader->ArchiveSize64;
}
// Calculate the block table position
BlockTablePos64 = MpqOffset + MAKE_OFFSET64(pHeader->wBlockTablePosHi, pHeader->dwBlockTablePos);
BlockTablePos64 = ByteOffset + MAKE_OFFSET64(pHeader->wBlockTablePosHi, pHeader->dwBlockTablePos);
break;
default:
@ -565,13 +713,13 @@ int ConvertMpqHeaderToFormat4(
}
// Calculate the block table position
BlockTablePos64 = MpqOffset + MAKE_OFFSET64(pHeader->wBlockTablePosHi, pHeader->dwBlockTablePos);
BlockTablePos64 = ByteOffset + MAKE_OFFSET64(pHeader->wBlockTablePosHi, pHeader->dwBlockTablePos);
break;
}
// Handle case when block table is placed before the MPQ header
// Used by BOBA protector
if(BlockTablePos64 < MpqOffset)
if(BlockTablePos64 < ByteOffset)
ha->dwFlags |= MPQ_FLAG_MALFORMED;
return nError;
}
@ -1170,7 +1318,6 @@ static int SaveExtTable(
return nError;
}
#ifdef FULL
//-----------------------------------------------------------------------------
// Support for HET table
@ -1236,7 +1383,7 @@ TMPQHetTable * CreateHetTable(DWORD dwEntryCount, DWORD dwTotalCount, DWORD dwNa
memset(pHetTable->pNameHashes, 0, dwTotalCount);
// Allocate the bit array for file indexes
pHetTable->pBetIndexes = CreateBitArray(dwTotalCount * pHetTable->dwIndexSizeTotal, 0xFF);
pHetTable->pBetIndexes = TMPQBits::Create(dwTotalCount * pHetTable->dwIndexSizeTotal, 0xFF);
if(pHetTable->pBetIndexes != NULL)
{
// Initialize the HET table from the source data (if given)
@ -1284,7 +1431,7 @@ static int InsertHetEntry(TMPQHetTable * pHetTable, ULONGLONG FileNameHash, DWOR
pHetTable->pNameHashes[Index] = NameHash1;
// Set the entry in the file index table
SetBits(pHetTable->pBetIndexes, pHetTable->dwIndexSizeTotal * Index,
pHetTable->pBetIndexes->SetBits(pHetTable->dwIndexSizeTotal * Index,
pHetTable->dwIndexSize,
&dwFileIndex,
4);
@ -1317,7 +1464,7 @@ static TMPQHetTable * TranslateHetTable(TMPQHetHeader * pHetHeader)
if(pHetHeader->ExtHdr.dwDataSize >= (sizeof(TMPQHetHeader) - sizeof(TMPQExtHeader)))
{
// Verify the size of the table in the header
if(pHetHeader->dwTableSize == pHetHeader->ExtHdr.dwDataSize)
if(pHetHeader->ExtHdr.dwDataSize >= pHetHeader->dwTableSize)
{
// The size of the HET table must be sum of header, hash and index table size
assert((sizeof(TMPQHetHeader) - sizeof(TMPQExtHeader) + pHetHeader->dwTotalCount + pHetHeader->dwIndexTableSize) == pHetHeader->dwTableSize);
@ -1390,7 +1537,6 @@ static TMPQExtHeader * TranslateHetTable(TMPQHetTable * pHetTable, ULONGLONG * p
return (TMPQExtHeader *)pbLinearTable;
}
static DWORD GetFileIndex_Het(TMPQArchive * ha, const char * szFileName)
{
TMPQHetTable * pHetTable = ha->pHetTable;
@ -1427,7 +1573,7 @@ static DWORD GetFileIndex_Het(TMPQArchive * ha, const char * szFileName)
DWORD dwFileIndex = 0;
// Get the file index
GetBits(pHetTable->pBetIndexes, pHetTable->dwIndexSizeTotal * Index,
pHetTable->pBetIndexes->GetBits(pHetTable->dwIndexSizeTotal * Index,
pHetTable->dwIndexSize,
&dwFileIndex,
sizeof(DWORD));
@ -1588,10 +1734,11 @@ static TMPQBetTable * TranslateBetTable(
if(pBetHeader->ExtHdr.dwDataSize >= (sizeof(TMPQBetHeader) - sizeof(TMPQExtHeader)))
{
// Verify the size of the table in the header
if(pBetHeader->dwTableSize == pBetHeader->ExtHdr.dwDataSize)
if(pBetHeader->ExtHdr.dwDataSize >= pBetHeader->dwTableSize)
{
// The number of entries in the BET table must be the same like number of entries in the block table
assert(pBetHeader->dwEntryCount == ha->pHeader->dwBlockTableSize);
// Note: Ignored if there is no block table
//assert(pBetHeader->dwEntryCount == ha->pHeader->dwBlockTableSize);
assert(pBetHeader->dwEntryCount <= ha->dwMaxFileCount);
// The number of entries in the BET table must be the same like number of entries in the HET table
@ -1636,7 +1783,7 @@ static TMPQBetTable * TranslateBetTable(
}
// Load the bit-based file table
pBetTable->pFileTable = CreateBitArray(pBetTable->dwTableEntrySize * pBetHeader->dwEntryCount, 0);
pBetTable->pFileTable = TMPQBits::Create(pBetTable->dwTableEntrySize * pBetHeader->dwEntryCount, 0);
if(pBetTable->pFileTable != NULL)
{
LengthInBytes = (pBetTable->pFileTable->NumberOfBits + 7) / 8;
@ -1650,7 +1797,7 @@ static TMPQBetTable * TranslateBetTable(
pBetTable->dwBitCount_NameHash2 = pBetHeader->dwBitCount_NameHash2;
// Create and load the array of BET hashes
pBetTable->pNameHashes = CreateBitArray(pBetTable->dwBitTotal_NameHash2 * pBetHeader->dwEntryCount, 0);
pBetTable->pNameHashes = TMPQBits::Create(pBetTable->dwBitTotal_NameHash2 * pBetHeader->dwEntryCount, 0);
if(pBetTable->pNameHashes != NULL)
{
LengthInBytes = (pBetTable->pNameHashes->NumberOfBits + 7) / 8;
@ -1675,7 +1822,7 @@ TMPQExtHeader * TranslateBetTable(
TMPQBetHeader BetHeader;
TFileEntry * pFileTableEnd = ha->pFileTable + ha->dwFileTableSize;
TFileEntry * pFileEntry;
TBitArray * pBitArray = NULL;
TMPQBits * pBitArray = NULL;
LPBYTE pbLinearTable = NULL;
LPBYTE pbTrgData;
DWORD LengthInBytes;
@ -1695,7 +1842,7 @@ TMPQExtHeader * TranslateBetTable(
pbTrgData = (LPBYTE)(pBetHeader + 1);
// Save the bit-based block table
pBitArray = CreateBitArray(BetHeader.dwEntryCount * BetHeader.dwTableEntrySize, 0);
pBitArray = TMPQBits::Create(BetHeader.dwEntryCount * BetHeader.dwTableEntrySize, 0);
if(pBitArray != NULL)
{
DWORD dwFlagIndex = 0;
@ -1710,22 +1857,22 @@ TMPQExtHeader * TranslateBetTable(
//
// Save the byte offset
SetBits(pBitArray, nBitOffset + BetHeader.dwBitIndex_FilePos,
pBitArray->SetBits(nBitOffset + BetHeader.dwBitIndex_FilePos,
BetHeader.dwBitCount_FilePos,
&pFileEntry->ByteOffset,
8);
SetBits(pBitArray, nBitOffset + BetHeader.dwBitIndex_FileSize,
pBitArray->SetBits(nBitOffset + BetHeader.dwBitIndex_FileSize,
BetHeader.dwBitCount_FileSize,
&pFileEntry->dwFileSize,
4);
SetBits(pBitArray, nBitOffset + BetHeader.dwBitIndex_CmpSize,
pBitArray->SetBits(nBitOffset + BetHeader.dwBitIndex_CmpSize,
BetHeader.dwBitCount_CmpSize,
&pFileEntry->dwCmpSize,
4);
// Save the flag index
dwFlagIndex = GetFileFlagIndex(FlagArray, pFileEntry->dwFlags);
SetBits(pBitArray, nBitOffset + BetHeader.dwBitIndex_FlagIndex,
pBitArray->SetBits(nBitOffset + BetHeader.dwBitIndex_FlagIndex,
BetHeader.dwBitCount_FlagIndex,
&dwFlagIndex,
4);
@ -1750,7 +1897,7 @@ TMPQExtHeader * TranslateBetTable(
}
// Create bit array for name hashes
pBitArray = CreateBitArray(BetHeader.dwBitTotal_NameHash2 * BetHeader.dwEntryCount, 0);
pBitArray = TMPQBits::Create(BetHeader.dwBitTotal_NameHash2 * BetHeader.dwEntryCount, 0);
if(pBitArray != NULL)
{
DWORD dwFileIndex = 0;
@ -1758,7 +1905,7 @@ TMPQExtHeader * TranslateBetTable(
for(pFileEntry = ha->pFileTable; pFileEntry < pFileTableEnd; pFileEntry++)
{
// Insert the name hash to the bit array
SetBits(pBitArray, BetHeader.dwBitTotal_NameHash2 * dwFileIndex,
pBitArray->SetBits(BetHeader.dwBitTotal_NameHash2 * dwFileIndex,
BetHeader.dwBitCount_NameHash2,
&pFileEntry->FileNameHash,
8);
@ -1802,7 +1949,6 @@ void FreeBetTable(TMPQBetTable * pBetTable)
STORM_FREE(pBetTable);
}
}
#endif
//-----------------------------------------------------------------------------
// Support for file table
@ -1826,7 +1972,6 @@ TFileEntry * GetFileEntryLocale2(TMPQArchive * ha, const char * szFileName, LCID
}
}
#ifdef FULL
// If we have HET table in the MPQ, try to find the file in HET table
if(ha->pHetTable != NULL)
{
@ -1834,7 +1979,6 @@ TFileEntry * GetFileEntryLocale2(TMPQArchive * ha, const char * szFileName, LCID
if(dwFileIndex != HASH_ENTRY_FREE)
return ha->pFileTable + dwFileIndex;
}
#endif
// Not found
return NULL;
@ -1862,7 +2006,6 @@ TFileEntry * GetFileEntryExact(TMPQArchive * ha, const char * szFileName, LCID l
}
}
#ifdef FULL
// If we have HET table in the MPQ, try to find the file in HET table
if(ha->pHetTable != NULL)
{
@ -1874,7 +2017,6 @@ TFileEntry * GetFileEntryExact(TMPQArchive * ha, const char * szFileName, LCID l
return ha->pFileTable + dwFileIndex;
}
}
#endif
// Not found
return NULL;
@ -1901,7 +2043,6 @@ void AllocateFileName(TMPQArchive * ha, TFileEntry * pFileEntry, const char * sz
strcpy(pFileEntry->szFileName, szFileName);
}
#ifdef FULL
// We also need to create the file name hash
if(ha->pHetTable != NULL)
{
@ -1910,7 +2051,6 @@ void AllocateFileName(TMPQArchive * ha, TFileEntry * pFileEntry, const char * sz
pFileEntry->FileNameHash = (HashStringJenkins(szFileName) & AndMask64) | OrMask64;
}
#endif
}
TFileEntry * AllocateFileEntry(TMPQArchive * ha, const char * szFileName, LCID lcLocale, LPDWORD PtrHashIndex)
@ -1972,14 +2112,12 @@ TFileEntry * AllocateFileEntry(TMPQArchive * ha, const char * szFileName, LCID l
PtrHashIndex[0] = (DWORD)(pHash - ha->pHashTable);
}
#ifdef FULL
// If the archive has a HET table, just do some checks
// Note: Don't bother modifying the HET table. It will be rebuilt from scratch after, anyway
if(ha->pHetTable != NULL)
{
assert(GetFileIndex_Het(ha, szFileName) == HASH_ENTRY_FREE);
}
#endif
// Return the free table entry
return pFreeEntry;
@ -2072,10 +2210,10 @@ int DeleteFileEntry(TMPQArchive * ha, TMPQFile * hf)
return ERROR_SUCCESS;
}
DWORD InvalidateInternalFile(TMPQArchive * ha, const char * szFileName, DWORD dwFlagNone, DWORD dwFlagNew)
DWORD InvalidateInternalFile(TMPQArchive * ha, const char * szFileName, DWORD dwFlagNone, DWORD dwFlagNew, DWORD dwForceAddTheFile = 0)
{
TMPQFile * hf = NULL;
DWORD dwFileFlags = 0;
DWORD dwFileFlags = MPQ_FILE_DEFAULT_INTERNAL;
int nError = ERROR_FILE_NOT_FOUND;
// Open the file from the MPQ
@ -2087,17 +2225,25 @@ DWORD InvalidateInternalFile(TMPQArchive * ha, const char * szFileName, DWORD dw
// Delete the file entry
nError = DeleteFileEntry(ha, hf);
if(nError == ERROR_SUCCESS)
{
ha->dwFlags |= dwFlagNew;
ha->dwReservedFiles++;
}
dwForceAddTheFile = 1;
// Free the file entry
// Close the file
FreeFileHandle(hf);
}
// If the deletion failed, set the "none" flag
ha->dwFlags |= (nError != ERROR_SUCCESS) ? dwFlagNone : 0;
// Are we going to add the file?
if(dwForceAddTheFile)
{
ha->dwFlags |= dwFlagNew;
ha->dwReservedFiles++;
}
else
{
ha->dwFlags |= dwFlagNone;
dwFileFlags = 0;
}
// Return the intended file flags
return dwFileFlags;
}
@ -2115,7 +2261,7 @@ void InvalidateInternalFiles(TMPQArchive * ha)
// Invalidate the (listfile), if not done yet
if((ha->dwFlags & (MPQ_FLAG_LISTFILE_NONE | MPQ_FLAG_LISTFILE_NEW)) == 0)
{
ha->dwFileFlags1 = InvalidateInternalFile(ha, LISTFILE_NAME, MPQ_FLAG_LISTFILE_NONE, MPQ_FLAG_LISTFILE_NEW);
ha->dwFileFlags1 = InvalidateInternalFile(ha, LISTFILE_NAME, MPQ_FLAG_LISTFILE_NONE, MPQ_FLAG_LISTFILE_NEW, (ha->dwFlags & MPQ_FLAG_LISTFILE_FORCE));
}
// Invalidate the (attributes), if not done yet
@ -2192,7 +2338,7 @@ static TMPQHash * LoadHashTable(TMPQArchive * ha)
dwCmpSize = (DWORD)pHeader->HashTableSize64;
// Read, decrypt and uncompress the hash table
pHashTable = (TMPQHash *)LoadMpqTable(ha, ByteOffset, dwCmpSize, dwTableSize, MPQ_KEY_HASH_TABLE, &bHashTableIsCut);
pHashTable = (TMPQHash *)LoadMpqTable(ha, ByteOffset, pHeader->MD5_HashTable, dwCmpSize, dwTableSize, g_dwHashTableKey, &bHashTableIsCut);
// DumpHashTable(pHashTable, pHeader->dwHashTableSize);
// If the hash table was cut, we can/have to defragment it
@ -2209,7 +2355,7 @@ static TMPQHash * LoadHashTable(TMPQArchive * ha)
break;
}
// Remember the size of the hash table
// Return the loaded hash table
return pHashTable;
}
@ -2253,7 +2399,7 @@ TMPQBlock * LoadBlockTable(TMPQArchive * ha, bool /* bDontFixEntries */)
dwCmpSize = (DWORD)pHeader->BlockTableSize64;
// Read, decrypt and uncompress the block table
pBlockTable = (TMPQBlock * )LoadMpqTable(ha, ByteOffset, dwCmpSize, dwTableSize, MPQ_KEY_BLOCK_TABLE, &bBlockTableIsCut);
pBlockTable = (TMPQBlock * )LoadMpqTable(ha, ByteOffset, NULL, dwCmpSize, dwTableSize, g_dwBlockTableKey, &bBlockTableIsCut);
// If the block table was cut, we need to remember it
if(pBlockTable != NULL && bBlockTableIsCut)
@ -2274,7 +2420,6 @@ TMPQBlock * LoadBlockTable(TMPQArchive * ha, bool /* bDontFixEntries */)
return pBlockTable;
}
#ifdef FULL
TMPQHetTable * LoadHetTable(TMPQArchive * ha)
{
TMPQExtHeader * pExtTable;
@ -2282,7 +2427,7 @@ TMPQHetTable * LoadHetTable(TMPQArchive * ha)
TMPQHeader * pHeader = ha->pHeader;
// If the HET table position is not 0, we expect the table to be present
if(pHeader->HetTablePos64 != 0 && pHeader->HetTableSize64 != 0)
if(pHeader->HetTablePos64 && pHeader->HetTableSize64)
{
// Attempt to load the HET table (Hash Extended Table)
pExtTable = LoadExtTable(ha, pHeader->HetTablePos64, (size_t)pHeader->HetTableSize64, HET_TABLE_SIGNATURE, MPQ_KEY_HASH_TABLE);
@ -2304,7 +2449,7 @@ TMPQBetTable * LoadBetTable(TMPQArchive * ha)
TMPQHeader * pHeader = ha->pHeader;
// If the BET table position is not 0, we expect the table to be present
if(pHeader->BetTablePos64 != 0 && pHeader->BetTableSize64 != 0)
if(pHeader->BetTablePos64 && pHeader->BetTableSize64)
{
// Attempt to load the HET table (Hash Extended Table)
pExtTable = LoadExtTable(ha, pHeader->BetTablePos64, (size_t)pHeader->BetTableSize64, BET_TABLE_SIGNATURE, MPQ_KEY_BLOCK_TABLE);
@ -2319,7 +2464,6 @@ TMPQBetTable * LoadBetTable(TMPQArchive * ha)
return pBetTable;
}
#endif
int LoadAnyHashTable(TMPQArchive * ha)
{
@ -2329,12 +2473,13 @@ int LoadAnyHashTable(TMPQArchive * ha)
if(pHeader->dwHashTableSize == 0 && pHeader->HetTableSize64 == 0)
return CreateHashTable(ha, HASH_TABLE_SIZE_DEFAULT);
#ifdef FULL
// Try to load HET table
if(pHeader->HetTablePos64 != 0)
ha->pHetTable = LoadHetTable(ha);
#endif
// Try to load classic hash table
// Note that we load the classic hash table even when HET table exists,
// because if the MPQ gets modified and saved, hash table must be there
if(pHeader->dwHashTableSize)
ha->pHashTable = LoadHashTable(ha);
@ -2419,13 +2564,12 @@ static int BuildFileTable_Classic(TMPQArchive * ha)
return nError;
}
#ifdef FULL
static int BuildFileTable_HetBet(TMPQArchive * ha)
{
TMPQHetTable * pHetTable = ha->pHetTable;
TMPQBetTable * pBetTable;
TFileEntry * pFileEntry = ha->pFileTable;
TBitArray * pBitArray;
TMPQBits * pBitArray;
DWORD dwBitPosition = 0;
DWORD i;
int nError = ERROR_FILE_CORRUPT;
@ -2451,7 +2595,7 @@ static int BuildFileTable_HetBet(TMPQArchive * ha)
if(pHetTable->pNameHashes[i] != HET_ENTRY_FREE)
{
// Load the index to the BET table
GetBits(pHetTable->pBetIndexes, pHetTable->dwIndexSizeTotal * i,
pHetTable->pBetIndexes->GetBits(pHetTable->dwIndexSizeTotal * i,
pHetTable->dwIndexSize,
&dwFileIndex,
4);
@ -2462,7 +2606,7 @@ static int BuildFileTable_HetBet(TMPQArchive * ha)
ULONGLONG NameHash2 = 0;
// Load the BET hash
GetBits(pBetTable->pNameHashes, pBetTable->dwBitTotal_NameHash2 * dwFileIndex,
pBetTable->pNameHashes->GetBits(pBetTable->dwBitTotal_NameHash2 * dwFileIndex,
pBetTable->dwBitCount_NameHash2,
&NameHash2,
8);
@ -2482,19 +2626,19 @@ static int BuildFileTable_HetBet(TMPQArchive * ha)
DWORD dwFlagIndex = 0;
// Read the file position
GetBits(pBitArray, dwBitPosition + pBetTable->dwBitIndex_FilePos,
pBitArray->GetBits(dwBitPosition + pBetTable->dwBitIndex_FilePos,
pBetTable->dwBitCount_FilePos,
&pFileEntry->ByteOffset,
8);
// Read the file size
GetBits(pBitArray, dwBitPosition + pBetTable->dwBitIndex_FileSize,
pBitArray->GetBits(dwBitPosition + pBetTable->dwBitIndex_FileSize,
pBetTable->dwBitCount_FileSize,
&pFileEntry->dwFileSize,
4);
// Read the compressed size
GetBits(pBitArray, dwBitPosition + pBetTable->dwBitIndex_CmpSize,
pBitArray->GetBits(dwBitPosition + pBetTable->dwBitIndex_CmpSize,
pBetTable->dwBitCount_CmpSize,
&pFileEntry->dwCmpSize,
4);
@ -2503,7 +2647,7 @@ static int BuildFileTable_HetBet(TMPQArchive * ha)
// Read the flag index
if(pBetTable->dwFlagCount != 0)
{
GetBits(pBitArray, dwBitPosition + pBetTable->dwBitIndex_FlagIndex,
pBitArray->GetBits(dwBitPosition + pBetTable->dwBitIndex_FlagIndex,
pBetTable->dwBitCount_FlagIndex,
&dwFlagIndex,
4);
@ -2530,7 +2674,6 @@ static int BuildFileTable_HetBet(TMPQArchive * ha)
return nError;
}
#endif
int BuildFileTable(TMPQArchive * ha)
{
@ -2554,7 +2697,6 @@ int BuildFileTable(TMPQArchive * ha)
memset(ha->pFileTable, 0, dwFileTableSize * sizeof(TFileEntry));
ha->dwFileTableSize = dwFileTableSize;
#ifdef FULL
// If we have HET table, we load file table from the BET table
// Note: If BET table is corrupt or missing, we set the archive as read only
if(ha->pHetTable != NULL)
@ -2564,7 +2706,6 @@ int BuildFileTable(TMPQArchive * ha)
else
bFileTableCreated = true;
}
#endif
// If we have hash table, we load the file table from the block table
// Note: If block table is corrupt or missing, we set the archive as read only
@ -2600,7 +2741,6 @@ void UpdateBlockTableSize(TMPQArchive * ha)
}
*/
#ifdef FULL
// Defragment the file table so it does not contain any gaps
int DefragmentFileTable(TMPQArchive * ha)
{
@ -2959,4 +3099,3 @@ int SaveMPQTables(TMPQArchive * ha)
STORM_FREE(pHiBlockTable);
return nError;
}
#endif

38
3rdParty/StormLib/src/SBaseSubTypes.cpp vendored

@ -21,24 +21,24 @@
typedef struct _TSQPHeader
{
// The ID_MPQ ('MPQ\x1A') signature
DWORD dwID;
DWORD dwID;
// Size of the archive header
DWORD dwHeaderSize;
DWORD dwHeaderSize;
// 32-bit size of MPQ archive
DWORD dwArchiveSize;
// Offset to the beginning of the hash table, relative to the beginning of the archive.
DWORD dwHashTablePos;
// Offset to the beginning of the block table, relative to the beginning of the archive.
DWORD dwBlockTablePos;
// Number of entries in the hash table. Must be a power of two, and must be less than 2^16 for
// the original MoPaQ format, or less than 2^20 for the Burning Crusade format.
DWORD dwHashTableSize;
// Number of entries in the block table
DWORD dwBlockTableSize;
@ -66,7 +66,7 @@ typedef struct _TSQPHash
// The hash of the file path, using method A.
DWORD dwName1;
// The hash of the file path, using method B.
DWORD dwName2;
@ -76,16 +76,16 @@ typedef struct _TSQPBlock
{
// Offset of the beginning of the file, relative to the beginning of the archive.
DWORD dwFilePos;
// Flags for the file. See MPQ_FILE_XXXX constants
DWORD dwFlags;
DWORD dwFlags;
// Compressed file size
DWORD dwCSize;
// Uncompressed file size
DWORD dwFSize;
DWORD dwFSize;
} TSQPBlock;
//-----------------------------------------------------------------------------
@ -131,7 +131,7 @@ int ConvertSqpHeaderToFormat4(
Header.wSectorSize = BSWAP_INT16_UNSIGNED(pSqpHeader->wSectorSize);
// Verify the SQP header
if(Header.dwID == ID_MPQ && Header.dwHeaderSize == sizeof(TSQPHeader) && Header.dwArchiveSize == FileSize)
if(Header.dwID == g_dwMpqSignature && Header.dwHeaderSize == sizeof(TSQPHeader) && Header.dwArchiveSize == FileSize)
{
// Check for fixed values of version and sector size
if(Header.wFormatVersion == MPQ_FORMAT_VERSION_1 && Header.wSectorSize == 3)
@ -143,7 +143,7 @@ int ConvertSqpHeaderToFormat4(
// Copy the converted MPQ header back
memcpy(ha->HeaderData, &Header, sizeof(TMPQHeader));
// Mark this file as SQP file
ha->pfnHashString = HashStringSlash;
ha->dwFlags |= MPQ_FLAG_READ_ONLY;
@ -292,13 +292,13 @@ typedef struct _TMPKHeader
{
// The ID_MPK ('MPK\x1A') signature
DWORD dwID;
// Contains '2000'
DWORD dwVersion;
// 32-bit size of the archive
DWORD dwArchiveSize;
// Size of the archive header
DWORD dwHeaderSize;
@ -315,7 +315,7 @@ typedef struct _TMPKHash
{
// The hash of the file path, using method A.
DWORD dwName1;
// The hash of the file path, using method B.
DWORD dwName2;
@ -334,7 +334,7 @@ typedef struct _TMPKHash
typedef struct _TMPKBlock
{
DWORD dwFlags; // 0x1121 - Compressed , 0x1120 - Not compressed
DWORD dwFlags; // 0x1121 - Compressed , 0x1120 - Not compressed
DWORD dwFilePos; // Offset of the beginning of the file, relative to the beginning of the archive.
DWORD dwFSize; // Uncompressed file size
DWORD dwCSize; // Compressed file size
@ -414,7 +414,7 @@ int ConvertMpkHeaderToFormat4(
if(Header.dwID == ID_MPK && Header.dwHeaderSize == sizeof(TMPKHeader) && Header.dwArchiveSize == (DWORD)FileSize)
{
// The header ID must be ID_MPQ
Header.dwID = ID_MPQ;
Header.dwID = g_dwMpqSignature;
Header.wFormatVersion = MPQ_FORMAT_VERSION_1;
Header.wSectorSize = 3;

2311
3rdParty/StormLib/src/SCompression.cpp vendored

File diff suppressed because it is too large Load Diff

2
3rdParty/StormLib/src/SFileExtractFile.cpp vendored

@ -12,7 +12,7 @@
#include "StormLib.h"
#include "StormCommon.h"
bool STORMAPI SFileExtractFile(HANDLE hMpq, const char * szToExtract, const TCHAR * szExtracted, DWORD dwSearchScope)
bool WINAPI SFileExtractFile(HANDLE hMpq, const char * szToExtract, const TCHAR * szExtracted, DWORD dwSearchScope)
{
TFileStream * pLocalFile = NULL;
HANDLE hMpqFile = NULL;

22
3rdParty/StormLib/src/SFileFindFile.cpp vendored

@ -39,7 +39,7 @@ static TMPQSearch * IsValidSearchHandle(HANDLE hFind)
return NULL;
}
bool CheckWildCard(const char * szString, const char * szWildCard)
bool SFileCheckWildCard(const char * szString, const char * szWildCard)
{
const char * szWildCardPtr;
@ -71,7 +71,7 @@ bool CheckWildCard(const char * szString, const char * szWildCard)
if(AsciiToUpperTable[szWildCardPtr[0]] == AsciiToUpperTable[szString[0]])
{
if(CheckWildCard(szString, szWildCardPtr))
if(SFileCheckWildCard(szString, szWildCardPtr))
return true;
}
}
@ -222,6 +222,10 @@ static bool DoMPQSearch_FileEntry(
// Is it a file but not a patch file?
if((pFileEntry->dwFlags & hs->dwFlagMask) == MPQ_FILE_EXISTS)
{
// Ignore fake files which are not compressed but have size higher than the archive
if ((pFileEntry->dwFlags & MPQ_FILE_COMPRESS_MASK) == 0 && (pFileEntry->dwFileSize > ha->FileSize))
return false;
// Now we have to check if this file was not enumerated before
if(!FileWasFoundBefore(ha, hs, pFileEntry))
{
@ -234,13 +238,15 @@ static bool DoMPQSearch_FileEntry(
// Prepare the block index
dwBlockIndex = (DWORD)(pFileEntry - ha->pFileTable);
if(dwBlockIndex == 569)
szNameBuff[0] = 'F';
// Get the file name. If it's not known, we will create pseudo-name
szFileName = pFileEntry->szFileName;
if(szFileName == NULL)
{
// Open the file by its pseudo-name.
sprintf(szNameBuff, "File%08u.xxx", (unsigned int)dwBlockIndex);
StringCreatePseudoFileName(szNameBuff, _countof(szNameBuff), dwBlockIndex, "xxx");
if(SFileOpenFileEx((HANDLE)hs->ha, szNameBuff, SFILE_OPEN_BASE_FILE, &hFile))
{
SFileGetFileName(hFile, szNameBuff);
@ -253,7 +259,7 @@ static bool DoMPQSearch_FileEntry(
if(szFileName != NULL)
{
// Check the file name against the wildcard
if(CheckWildCard(szFileName + nPrefixLength, hs->szSearchMask))
if(SFileCheckWildCard(szFileName + nPrefixLength, hs->szSearchMask))
{
// Fill the found entry. hash entry and block index are taken from the base MPQ
lpFindFileData->dwHashIndex = HASH_ENTRY_FREE;
@ -378,7 +384,7 @@ static void FreeMPQSearch(TMPQSearch *& hs)
//-----------------------------------------------------------------------------
// Public functions
HANDLE STORMAPI SFileFindFirstFile(HANDLE hMpq, const char * szMask, SFILE_FIND_DATA * lpFindFileData, const TCHAR * szListFile)
HANDLE WINAPI SFileFindFirstFile(HANDLE hMpq, const char * szMask, SFILE_FIND_DATA * lpFindFileData, const TCHAR * szListFile)
{
TMPQArchive * ha = (TMPQArchive *)hMpq;
TMPQSearch * hs = NULL;
@ -391,13 +397,11 @@ HANDLE STORMAPI SFileFindFirstFile(HANDLE hMpq, const char * szMask, SFILE_FIND_
if(szMask == NULL || lpFindFileData == NULL)
nError = ERROR_INVALID_PARAMETER;
#ifdef FULL
// Include the listfile into the MPQ's internal listfile
// Note that if the listfile name is NULL, do nothing because the
// internal listfile is always included.
if(nError == ERROR_SUCCESS && szListFile != NULL && *szListFile != 0)
nError = SFileAddListFile((HANDLE)ha, szListFile);
#endif
// Allocate the structure for MPQ search
if(nError == ERROR_SUCCESS)
@ -446,7 +450,7 @@ HANDLE STORMAPI SFileFindFirstFile(HANDLE hMpq, const char * szMask, SFILE_FIND_
return (HANDLE)hs;
}
bool STORMAPI SFileFindNextFile(HANDLE hFind, SFILE_FIND_DATA * lpFindFileData)
bool WINAPI SFileFindNextFile(HANDLE hFind, SFILE_FIND_DATA * lpFindFileData)
{
TMPQSearch * hs = IsValidSearchHandle(hFind);
int nError = ERROR_SUCCESS;
@ -465,7 +469,7 @@ bool STORMAPI SFileFindNextFile(HANDLE hFind, SFILE_FIND_DATA * lpFindFileData)
return (nError == ERROR_SUCCESS);
}
bool STORMAPI SFileFindClose(HANDLE hFind)
bool WINAPI SFileFindClose(HANDLE hFind)
{
TMPQSearch * hs = IsValidSearchHandle(hFind);

919
3rdParty/StormLib/src/SFileGetFileInfo.cpp vendored

File diff suppressed because it is too large Load Diff

1281
3rdParty/StormLib/src/SFileOpenArchive.cpp vendored

File diff suppressed because it is too large Load Diff

108
3rdParty/StormLib/src/SFileOpenFileEx.cpp vendored

@ -124,37 +124,38 @@ bool OpenPatchedFile(HANDLE hMpq, const char * szFileName, HANDLE * PtrFile)
}
// If we couldn't find the base file in any of the patches, it doesn't exist
if((ha = haBase) == NULL)
if((ha = haBase) != NULL)
{
SetLastError(ERROR_FILE_NOT_FOUND);
return false;
}
// Now open the base file
if(SFileOpenFileEx((HANDLE)ha, GetPatchFileName(ha, szFileName, szNameBuffer), SFILE_OPEN_BASE_FILE, (HANDLE *)&hfBase))
{
// The file must be a base file, i.e. without MPQ_FILE_PATCH_FILE
assert((hfBase->pFileEntry->dwFlags & MPQ_FILE_PATCH_FILE) == 0);
hf = hfBase;
// Now open all patches and attach them on top of the base file
for(ha = ha->haPatch; ha != NULL; ha = ha->haPatch)
// Now open the base file
if(SFileOpenFileEx((HANDLE)ha, GetPatchFileName(ha, szFileName, szNameBuffer), SFILE_OPEN_BASE_FILE, (HANDLE *)&hfBase))
{
// Prepare the file name with a correct prefix
if(SFileOpenFileEx((HANDLE)ha, GetPatchFileName(ha, szFileName, szNameBuffer), SFILE_OPEN_BASE_FILE, &hPatchFile))
// The file must be a base file, i.e. without MPQ_FILE_PATCH_FILE
assert((hfBase->pFileEntry->dwFlags & MPQ_FILE_PATCH_FILE) == 0);
hf = hfBase;
// Now open all patches and attach them on top of the base file
for(ha = ha->haPatch; ha != NULL; ha = ha->haPatch)
{
// Remember the new version
hfPatch = (TMPQFile *)hPatchFile;
// Prepare the file name with a correct prefix
if(SFileOpenFileEx((HANDLE)ha, GetPatchFileName(ha, szFileName, szNameBuffer), SFILE_OPEN_BASE_FILE, &hPatchFile))
{
// Remember the new version
hfPatch = (TMPQFile *)hPatchFile;
// We should not find patch file
assert((hfPatch->pFileEntry->dwFlags & MPQ_FILE_PATCH_FILE) != 0);
// We should not find patch file
assert((hfPatch->pFileEntry->dwFlags & MPQ_FILE_PATCH_FILE) != 0);
// Attach the patch to the base file
hf->hfPatch = hfPatch;
hf = hfPatch;
// Attach the patch to the base file
hf->hfPatch = hfPatch;
hf = hfPatch;
}
}
}
}
else
{
SetLastError(ERROR_FILE_NOT_FOUND);
}
// Give the updated base MPQ
if(PtrFile != NULL)
@ -167,12 +168,12 @@ bool OpenPatchedFile(HANDLE hMpq, const char * szFileName, HANDLE * PtrFile)
/*****************************************************************************/
//-----------------------------------------------------------------------------
// SFileEnumLocales enums all locale versions within MPQ.
// SFileEnumLocales enums all locale versions within MPQ.
// Functions fills all available language identifiers on a file into the buffer
// pointed by plcLocales. There must be enough entries to copy the localed,
// otherwise the function returns ERROR_INSUFFICIENT_BUFFER.
int STORMAPI SFileEnumLocales(
int WINAPI SFileEnumLocales(
HANDLE hMpq,
const char * szFileName,
LCID * PtrLocales,
@ -197,7 +198,7 @@ int STORMAPI SFileEnumLocales(
return ERROR_INVALID_PARAMETER;
if(IsPseudoFileName(szFileName, &dwFileIndex))
return ERROR_INVALID_PARAMETER;
// Keep compiler happy
dwMaxLocales = PtrMaxLocales[0];
dwSearchScope = dwSearchScope;
@ -228,7 +229,7 @@ int STORMAPI SFileEnumLocales(
// dwSearchScope - Where to search
// PtrFile - Pointer to store opened file handle
bool STORMAPI SFileOpenFileEx(HANDLE hMpq, const char * szFileName, DWORD dwSearchScope, HANDLE * PtrFile)
bool WINAPI SFileOpenFileEx(HANDLE hMpq, const char * szFileName, DWORD dwSearchScope, HANDLE * PtrFile)
{
TMPQArchive * ha = IsValidMpqHandle(hMpq);
TFileEntry * pFileEntry = NULL;
@ -258,11 +259,11 @@ bool STORMAPI SFileOpenFileEx(HANDLE hMpq, const char * szFileName, DWORD dwSear
case SFILE_OPEN_FROM_MPQ:
case SFILE_OPEN_BASE_FILE:
case SFILE_OPEN_CHECK_EXISTS:
// If this MPQ has no patches, open the file from this MPQ directly
if(ha->haPatch == NULL || dwSearchScope == SFILE_OPEN_BASE_FILE)
{
pFileEntry = GetFileEntryLocale2(ha, szFileName, lcFileLocale, &dwHashIndex);
pFileEntry = GetFileEntryLocale2(ha, szFileName, g_lcFileLocale, &dwHashIndex);
}
// If this MPQ is a patched archive, open the file as patched
@ -283,7 +284,7 @@ bool STORMAPI SFileOpenFileEx(HANDLE hMpq, const char * szFileName, DWORD dwSear
case SFILE_OPEN_LOCAL_FILE:
// Open a local file
return OpenLocalFile(szFileName, PtrFile);
return OpenLocalFile(szFileName, PtrFile);
default:
@ -296,24 +297,45 @@ bool STORMAPI SFileOpenFileEx(HANDLE hMpq, const char * szFileName, DWORD dwSear
// Check whether the file really exists in the MPQ
if(nError == ERROR_SUCCESS)
{
if(pFileEntry == NULL || (pFileEntry->dwFlags & MPQ_FILE_EXISTS) == 0)
// If we didn't find the file, try to open it using pseudo file name ("File
if (pFileEntry == NULL || (pFileEntry->dwFlags & MPQ_FILE_EXISTS) == 0)
{
// Check the pseudo-file name
if((bOpenByIndex = IsPseudoFileName(szFileName, &dwFileIndex)) == true)
// Check the pseudo-file name ("File00000001.ext")
if ((bOpenByIndex = IsPseudoFileName(szFileName, &dwFileIndex)) == true)
{
// Get the file entry for the file
if(dwFileIndex < ha->dwFileTableSize)
if (dwFileIndex < ha->dwFileTableSize)
{
pFileEntry = ha->pFileTable + dwFileIndex;
}
}
nError = ERROR_FILE_NOT_FOUND;
// Still not found?
if (pFileEntry == NULL)
{
nError = ERROR_FILE_NOT_FOUND;
}
}
// Ignore unknown loading flags (example: MPQ_2016_v1_WME4_4.w3x)
// if(pFileEntry != NULL && pFileEntry->dwFlags & ~MPQ_FILE_VALID_FLAGS)
// nError = ERROR_NOT_SUPPORTED;
// Perform some checks of invalid files
if (pFileEntry != NULL)
{
// MPQ protectors use insanely amount of fake files, often with very high size.
// We won't open any files whose compressed size is bigger than archive size
// If the file is not compressed, its size cannot be bigger than archive size
if ((pFileEntry->dwFlags & MPQ_FILE_COMPRESS_MASK) == 0 && (pFileEntry->dwFileSize > ha->FileSize))
{
nError = ERROR_FILE_CORRUPT;
pFileEntry = NULL;
}
// Ignore unknown loading flags (example: MPQ_2016_v1_WME4_4.w3x)
// if(pFileEntry->dwFlags & ~MPQ_FILE_VALID_FLAGS)
// {
// nError = ERROR_NOT_SUPPORTED;
// pFileEntry = NULL;
// }
}
}
// Did the caller just wanted to know if the file exists?
@ -358,7 +380,7 @@ bool STORMAPI SFileOpenFileEx(HANDLE hMpq, const char * szFileName, DWORD dwSear
// Give the file entry
if(PtrFile != NULL)
*PtrFile = hf;
PtrFile[0] = hf;
// Return error code
if(nError != ERROR_SUCCESS)
@ -372,18 +394,18 @@ bool STORMAPI SFileOpenFileEx(HANDLE hMpq, const char * szFileName, DWORD dwSear
// hMpq - Handle of opened MPQ archive
// szFileName - Name of file to look for
bool STORMAPI SFileHasFile(HANDLE hMpq, const char * szFileName)
bool WINAPI SFileHasFile(HANDLE hMpq, const char * szFileName)
{
return SFileOpenFileEx(hMpq, szFileName, SFILE_OPEN_CHECK_EXISTS, NULL);
}
//-----------------------------------------------------------------------------
// bool STORMAPI SFileCloseFile(HANDLE hFile);
// bool WINAPI SFileCloseFile(HANDLE hFile);
bool STORMAPI SFileCloseFile(HANDLE hFile)
bool WINAPI SFileCloseFile(HANDLE hFile)
{
TMPQFile * hf = (TMPQFile *)hFile;
if(!IsValidFileHandle(hFile))
{
SetLastError(ERROR_INVALID_HANDLE);

1810
3rdParty/StormLib/src/SFileReadFile.cpp vendored

File diff suppressed because it is too large Load Diff

66
3rdParty/StormLib/src/StormCommon.h vendored

@ -18,9 +18,8 @@
// Compression support
// Include functions from Pkware Data Compression Library
#include "../../PKWare/pkware.h"
#include "pklib/pklib.h"
#ifdef FULL
// Include functions from Huffmann compression
#include "huffman/huff.h"
@ -56,7 +55,6 @@
// For HashStringJenkins
#include "jenkins/lookup.h"
#endif
//-----------------------------------------------------------------------------
// StormLib private defines
@ -72,6 +70,18 @@
// Macro for building 64-bit file offset from two 32-bit
#define MAKE_OFFSET64(hi, lo) (((ULONGLONG)hi << 32) | (ULONGLONG)lo)
//-----------------------------------------------------------------------------
// MTYPE definition - specifies what kind of MPQ is the map type
typedef enum _MTYPE
{
MapTypeNotChecked, // The map type was not checked yet
MapTypeNotRecognized, // The file does not seems to be a map
MapTypeAviFile, // The file is actually an AVI file (Warcraft III cinematics)
MapTypeWarcraft3, // The file is a Warcraft III map
MapTypeStarcraft2 // The file is a Starcraft II map
} MTYPE, *PMTYPE;
//-----------------------------------------------------------------------------
// MPQ signature information
@ -124,7 +134,10 @@ typedef struct _MPQ_SIGNATURE_INFO
//-----------------------------------------------------------------------------
// StormLib internal global variables
extern LCID lcFileLocale; // Preferred file locale
extern DWORD g_dwMpqSignature; // Marker for MPQ header
extern DWORD g_dwHashTableKey; // Key for hash table
extern DWORD g_dwBlockTableKey; // Key for block table
extern LCID g_lcFileLocale; // Preferred file locale
//-----------------------------------------------------------------------------
// Conversion to uppercase/lowercase (and "/" to "\")
@ -135,8 +148,46 @@ extern unsigned char AsciiToUpperTable[256];
//-----------------------------------------------------------------------------
// Safe string functions
void StringCopy(char * szTarget, size_t cchTarget, const char * szSource);
template <typename XCHAR, typename XINT>
XCHAR * IntToString(XCHAR * szBuffer, size_t cchMaxChars, XINT nValue, size_t nDigitCount = 0)
{
XCHAR * szBufferEnd = szBuffer + cchMaxChars - 1;
XCHAR szNumberRev[0x20];
size_t nLength = 0;
// Always put the first digit
szNumberRev[nLength++] = (XCHAR)(nValue % 10) + '0';
nValue /= 10;
// Continue as long as we have non-zero
while(nValue != 0)
{
szNumberRev[nLength++] = (XCHAR)(nValue % 10) + '0';
nValue /= 10;
}
// Fill zeros, if needed
while(szBuffer < szBufferEnd && nLength < nDigitCount)
{
*szBuffer++ = '0';
nDigitCount--;
}
// Fill the buffer
while(szBuffer < szBufferEnd && nLength > 0)
{
nLength--;
*szBuffer++ = szNumberRev[nLength];
}
// Terminate the number with zeros
szBuffer[0] = 0;
return szBuffer;
}
char * StringCopy(char * szTarget, size_t cchTarget, const char * szSource);
void StringCat(char * szTarget, size_t cchTargetMax, const char * szSource);
void StringCreatePseudoFileName(char * szBuffer, size_t cchMaxChars, unsigned int nIndex, const char * szExtension);
#ifdef _UNICODE
void StringCopy(TCHAR * szTarget, size_t cchTarget, const char * szSource);
@ -191,7 +242,7 @@ TMPQFile * IsValidFileHandle(HANDLE hFile);
ULONGLONG FileOffsetFromMpqOffset(TMPQArchive * ha, ULONGLONG MpqOffset);
ULONGLONG CalculateRawSectorOffset(TMPQFile * hf, DWORD dwSectorOffset);
int ConvertMpqHeaderToFormat4(TMPQArchive * ha, ULONGLONG MpqOffset, ULONGLONG FileSize, DWORD dwFlags, bool bIsWarcraft3Map);
int ConvertMpqHeaderToFormat4(TMPQArchive * ha, ULONGLONG MpqOffset, ULONGLONG FileSize, DWORD dwFlags, MTYPE MapType);
bool IsValidHashEntry(TMPQArchive * ha, TMPQHash * pHash);
@ -263,7 +314,7 @@ int SCompDecompressMpk(void * pvOutBuffer, int * pcbOutBuffer, void * pvInBuffer
TMPQFile * CreateFileHandle(TMPQArchive * ha, TFileEntry * pFileEntry);
TMPQFile * CreateWritableHandle(TMPQArchive * ha, DWORD dwFileSize);
void * LoadMpqTable(TMPQArchive * ha, ULONGLONG ByteOffset, DWORD dwCompressedSize, DWORD dwRealSize, DWORD dwKey, bool * pbTableIsCut);
void * LoadMpqTable(TMPQArchive * ha, ULONGLONG ByteOffset, LPBYTE pbTableHash, DWORD dwCompressedSize, DWORD dwRealSize, DWORD dwKey, bool * pbTableIsCut);
int AllocateSectorBuffer(TMPQFile * hf);
int AllocatePatchInfo(TMPQFile * hf, bool bLoadFromFile);
int AllocateSectorOffsets(TMPQFile * hf, bool bLoadFromFile);
@ -299,7 +350,6 @@ void Patch_Finalize(TMPQPatcher * pPatcher);
//-----------------------------------------------------------------------------
// Utility functions
bool CheckWildCard(const char * szString, const char * szWildCard);
bool IsInternalMpqFileName(const char * szFileName);
template <typename XCHAR>

358
3rdParty/StormLib/src/StormLib.h vendored

@ -79,9 +79,9 @@
#define __STORMLIB_H__
#ifdef _MSC_VER
#pragma warning(disable:4668) // 'XXX' is not defined as a preprocessor macro, replacing with '0' for '#if/#elif'
#pragma warning(disable:4668) // 'XXX' is not defined as a preprocessor macro, replacing with '0' for '#if/#elif'
#pragma warning(disable:4820) // 'XXX' : '2' bytes padding added after data member 'XXX::yyy'
#endif
#endif
#include "StormPort.h"
@ -94,7 +94,7 @@ extern "C" {
//
// The library type is encoded in the library name as the following
// StormLibXYZ.lib
//
//
// X - D for Debug version, R for Release version
// Y - A for ANSI version, U for Unicode version
// Z - S for static-linked CRT library, D for multithreaded DLL CRT library
@ -105,32 +105,34 @@ extern "C" {
#endif
#if defined(_MSC_VER) && !defined(STORMLIB_NO_AUTO_LINK)
#ifdef _DEBUG // DEBUG VERSIONS
#ifndef _UNICODE
#ifdef _DLL
#pragma comment(lib, "StormLibDAD.lib") // Debug Ansi CRT-DLL version
#else
#pragma comment(lib, "StormLibDAS.lib") // Debug Ansi CRT-LIB version
#endif
#else
#ifdef _DLL
#pragma comment(lib, "StormLibDUD.lib") // Debug Unicode CRT-DLL version
#else
#pragma comment(lib, "StormLibDUS.lib") // Debug Unicode CRT-LIB version
#endif
#endif
#else // RELEASE VERSIONS
#ifndef _UNICODE
#ifdef _DLL
#pragma comment(lib, "StormLibRAD.lib") // Release Ansi CRT-DLL version
#else
#pragma comment(lib, "StormLibRAS.lib") // Release Ansi CRT-LIB version
#ifndef WDK_BUILD
#ifdef _DEBUG // DEBUG VERSIONS
#ifndef _UNICODE
#ifdef _DLL
#pragma comment(lib, "StormLibDAD.lib") // Debug Ansi CRT-DLL version
#else
#pragma comment(lib, "StormLibDAS.lib") // Debug Ansi CRT-LIB version
#endif
#else
#ifdef _DLL
#pragma comment(lib, "StormLibDUD.lib") // Debug Unicode CRT-DLL version
#else
#pragma comment(lib, "StormLibDUS.lib") // Debug Unicode CRT-LIB version
#endif
#endif
#else
#ifdef _DLL
#pragma comment(lib, "StormLibRUD.lib") // Release Unicode CRT-DLL version
#else
#pragma comment(lib, "StormLibRUS.lib") // Release Unicode CRT-LIB version
#else // RELEASE VERSIONS
#ifndef _UNICODE
#ifdef _DLL
#pragma comment(lib, "StormLibRAD.lib") // Release Ansi CRT-DLL version
#else
#pragma comment(lib, "StormLibRAS.lib") // Release Ansi CRT-LIB version
#endif
#else
#ifdef _DLL
#pragma comment(lib, "StormLibRUD.lib") // Release Unicode CRT-DLL version
#else
#pragma comment(lib, "StormLibRUS.lib") // Release Unicode CRT-LIB version
#endif
#endif
#endif
#endif
@ -140,8 +142,8 @@ extern "C" {
//-----------------------------------------------------------------------------
// Defines
#define STORMLIB_VERSION 0x0916 // Current version of StormLib (9.21)
#define STORMLIB_VERSION_STRING "9.22" // String version of StormLib version
#define STORMLIB_VERSION 0x0917 // Current version of StormLib (9.23)
#define STORMLIB_VERSION_STRING "9.23" // String version of StormLib version
#define ID_MPQ 0x1A51504D // MPQ archive header ID ('MPQ\x1A')
#define ID_MPQ_USERDATA 0x1B51504D // MPQ userdata entry ('MPQ\x1B')
@ -156,6 +158,7 @@ extern "C" {
#define ERROR_FILE_INCOMPLETE 10006 // The required file part is missing
#define ERROR_UNKNOWN_FILE_NAMES 10007 // A name of at least one file is unknown
#define ERROR_CANT_FIND_PATCH_PREFIX 10008 // StormLib was unable to find patch prefix for the patches
#define ERROR_FAKE_MPQ_HEADER 10009 // The header at this position is fake header
// Values for SFileCreateArchive
#define HASH_TABLE_SIZE_MIN 0x00000004 // Verified: If there is 1 file, hash table size is 4
@ -181,7 +184,7 @@ extern "C" {
#define SFILE_OPEN_ANY_LOCALE 0xFFFFFFFE // Reserved for StormLib internal use
#define SFILE_OPEN_LOCAL_FILE 0xFFFFFFFF // Open a local file
// Flags for TMPQArchive::dwFlags
// Flags for TMPQArchive::dwFlags. Used internally
#define MPQ_FLAG_READ_ONLY 0x00000001 // If set, the MPQ has been open for read-only access
#define MPQ_FLAG_CHANGED 0x00000002 // If set, the MPQ tables have been changed
#define MPQ_FLAG_MALFORMED 0x00000004 // Malformed data structure detected (W3M map protectors)
@ -193,10 +196,11 @@ extern "C" {
#define MPQ_FLAG_WAR3_MAP 0x00000100 // If set, this MPQ is a map for Warcraft III
#define MPQ_FLAG_LISTFILE_NONE 0x00000200 // Set when no (listfile) was found in InvalidateInternalFiles
#define MPQ_FLAG_LISTFILE_NEW 0x00000400 // Set when (listfile) invalidated by InvalidateInternalFiles
#define MPQ_FLAG_ATTRIBUTES_NONE 0x00000800 // Set when no (attributes) was found in InvalidateInternalFiles
#define MPQ_FLAG_ATTRIBUTES_NEW 0x00001000 // Set when (attributes) invalidated by InvalidateInternalFiles
#define MPQ_FLAG_SIGNATURE_NONE 0x00002000 // Set when no (signature) was found in InvalidateInternalFiles
#define MPQ_FLAG_SIGNATURE_NEW 0x00004000 // Set when (signature) invalidated by InvalidateInternalFiles
#define MPQ_FLAG_LISTFILE_FORCE 0x00000800 // Save updated listfile on exit
#define MPQ_FLAG_ATTRIBUTES_NONE 0x00001000 // Set when no (attributes) was found in InvalidateInternalFiles
#define MPQ_FLAG_ATTRIBUTES_NEW 0x00002000 // Set when (attributes) invalidated by InvalidateInternalFiles
#define MPQ_FLAG_SIGNATURE_NONE 0x00004000 // Set when no (signature) was found in InvalidateInternalFiles
#define MPQ_FLAG_SIGNATURE_NEW 0x00008000 // Set when (signature) invalidated by InvalidateInternalFiles
// Values for TMPQArchive::dwSubType
#define MPQ_SUBTYPE_MPQ 0x00000000 // The file is a MPQ file (Blizzard games)
@ -211,7 +215,7 @@ extern "C" {
// Flags for SFileAddFile
#define MPQ_FILE_IMPLODE 0x00000100 // Implode method (By PKWARE Data Compression Library)
#define MPQ_FILE_COMPRESS 0x00000200 // Compress methods (By multiple methods)
#define MPQ_FILE_ENCRYPTED 0x00010000 // Indicates whether file is encrypted
#define MPQ_FILE_ENCRYPTED 0x00010000 // Indicates whether file is encrypted
#define MPQ_FILE_FIX_KEY 0x00020000 // File decryption key has to be fixed
#define MPQ_FILE_PATCH_FILE 0x00100000 // The file is a patch file. Raw file data begin with TPatchInfo structure
#define MPQ_FILE_SINGLE_UNIT 0x01000000 // File is stored as a single unit, rather than split into sectors (Thx, Quantam)
@ -283,7 +287,7 @@ extern "C" {
#define PATCH_METADATA_NAME "(patch_metadata)"
#define MPQ_FORMAT_VERSION_1 0 // Up to The Burning Crusade
#define MPQ_FORMAT_VERSION_2 1 // The Burning Crusade and newer
#define MPQ_FORMAT_VERSION_2 1 // The Burning Crusade and newer
#define MPQ_FORMAT_VERSION_3 2 // WoW Cataclysm Beta
#define MPQ_FORMAT_VERSION_4 3 // WoW Cataclysm and newer
@ -322,6 +326,7 @@ extern "C" {
#define MPQ_OPEN_FORCE_MPQ_V1 0x00080000 // Always open the archive as MPQ v 1.00, ignore the "wFormatVersion" variable in the header
#define MPQ_OPEN_CHECK_SECTOR_CRC 0x00100000 // On files with MPQ_FILE_SECTOR_CRC, the CRC will be checked when reading file
#define MPQ_OPEN_PATCH 0x00200000 // This archive is a patch MPQ. Used internally.
#define MPQ_OPEN_FORCE_LISTFILE 0x00400000 // Force add listfile even if there is none at the moment of opening
#define MPQ_OPEN_READ_ONLY STREAM_FLAG_READ_ONLY
// Flags for SFileCreateArchive
@ -377,7 +382,7 @@ extern "C" {
#define ERROR_WEAK_SIGNATURE_ERROR 3 // There is a weak signature but sign check failed
#define ERROR_STRONG_SIGNATURE_OK 4 // There is a strong signature and sign check passed
#define ERROR_STRONG_SIGNATURE_ERROR 5 // There is a strong signature but sign check failed
#ifndef MD5_DIGEST_SIZE
#define MD5_DIGEST_SIZE 0x10
#endif
@ -469,25 +474,13 @@ typedef enum _SFileInfoClass
#define CCB_COPYING_NON_MPQ_DATA 3 // Copying non-MPQ data: No params used
#define CCB_COMPACTING_FILES 4 // Compacting archive (dwParam1 = current, dwParam2 = total)
#define CCB_CLOSING_ARCHIVE 5 // Closing archive: No params used
typedef void (STORMAPI * SFILE_DOWNLOAD_CALLBACK)(void * pvUserData, ULONGLONG ByteOffset, DWORD dwTotalBytes);
typedef void (STORMAPI * SFILE_ADDFILE_CALLBACK)(void * pvUserData, DWORD dwBytesWritten, DWORD dwTotalBytes, bool bFinalCall);
typedef void (STORMAPI * SFILE_COMPACT_CALLBACK)(void * pvUserData, DWORD dwWorkType, ULONGLONG BytesProcessed, ULONGLONG TotalBytes);
typedef struct TFileStream TFileStream;
//-----------------------------------------------------------------------------
// Structure for bit arrays used for HET and BET tables
typedef struct _TBitArray
{
DWORD NumberOfBytes; // Total number of bytes in "Elements"
DWORD NumberOfBits; // Total number of bits that are available
BYTE Elements[1]; // Array of elements (variable length)
} TBitArray;
typedef void (WINAPI * SFILE_DOWNLOAD_CALLBACK)(void * pvUserData, ULONGLONG ByteOffset, DWORD dwTotalBytes);
typedef void (WINAPI * SFILE_ADDFILE_CALLBACK)(void * pvUserData, DWORD dwBytesWritten, DWORD dwTotalBytes, bool bFinalCall);
typedef void (WINAPI * SFILE_COMPACT_CALLBACK)(void * pvUserData, DWORD dwWorkType, ULONGLONG BytesProcessed, ULONGLONG TotalBytes);
void GetBits(TBitArray * array, unsigned int nBitPosition, unsigned int nBitLength, void * pvBuffer, int nResultSize);
void SetBits(TBitArray * array, unsigned int nBitPosition, unsigned int nBitLength, void * pvBuffer, int nResultSize);
struct TFileStream;
struct TMPQBits;
//-----------------------------------------------------------------------------
// Structures related to MPQ format
@ -552,14 +545,14 @@ typedef struct _TMPQHeader
// Offset to the beginning of the hash table, relative to the beginning of the archive.
DWORD dwHashTablePos;
// Offset to the beginning of the block table, relative to the beginning of the archive.
DWORD dwBlockTablePos;
// Number of entries in the hash table. Must be a power of two, and must be less than 2^16 for
// the original MoPaQ format, or less than 2^20 for the Burning Crusade format.
DWORD dwHashTableSize;
// Number of entries in the block table
DWORD dwBlockTableSize;
@ -604,7 +597,7 @@ typedef struct _TMPQHeader
// Size of raw data chunk to calculate MD5.
// MD5 of each data chunk follows the raw file data.
DWORD dwRawChunkSize;
DWORD dwRawChunkSize;
// MD5 of MPQ tables
unsigned char MD5_BlockTable[MD5_DIGEST_SIZE]; // MD5 of the block table before decryption
@ -621,11 +614,11 @@ typedef struct _TMPQHash
{
// The hash of the file path, using method A.
DWORD dwName1;
// The hash of the file path, using method B.
DWORD dwName2;
#ifdef PLATFORM_LITTLE_ENDIAN
#ifdef STORMLIB_LITTLE_ENDIAN
// The language of the file. This is a Windows LANGID data type, and uses the same values.
// 0 indicates the default language (American English), or that the file is language-neutral.
@ -658,16 +651,16 @@ typedef struct _TMPQBlock
{
// Offset of the beginning of the file, relative to the beginning of the archive.
DWORD dwFilePos;
// Compressed file size
DWORD dwCSize;
// Only valid if the block is a file; otherwise meaningless, and should be 0.
// If the file is compressed, this is the size of the uncompressed file data.
DWORD dwFSize;
DWORD dwFSize;
// Flags for the file. See MPQ_FILE_XXXX constants
DWORD dwFlags;
DWORD dwFlags;
} TMPQBlock;
// Patch file information, preceding the sector offset table
@ -714,14 +707,14 @@ typedef struct _TMPQHetHeader
{
TMPQExtHeader ExtHdr;
DWORD dwTableSize; // Size of the entire HET table, including HET_TABLE_HEADER (in bytes)
DWORD dwEntryCount; // Number of occupied entries in the HET table
DWORD dwTotalCount; // Total number of entries in the HET table
DWORD dwNameHashBitSize; // Size of the name hash entry (in bits)
DWORD dwIndexSizeTotal; // Total size of file index (in bits)
DWORD dwIndexSizeExtra; // Extra bits in the file index
DWORD dwIndexSize; // Effective size of the file index (in bits)
DWORD dwIndexTableSize; // Size of the block index subtable (in bytes)
DWORD dwTableSize; // Size of the entire HET table, including HET_TABLE_HEADER (in bytes)
DWORD dwEntryCount; // Number of occupied entries in the HET table
DWORD dwTotalCount; // Total number of entries in the HET table
DWORD dwNameHashBitSize; // Size of the name hash entry (in bits)
DWORD dwIndexSizeTotal; // Total size of file index (in bits)
DWORD dwIndexSizeExtra; // Extra bits in the file index
DWORD dwIndexSize; // Effective size of the file index (in bits)
DWORD dwIndexTableSize; // Size of the block index subtable (in bytes)
} TMPQHetHeader;
@ -730,32 +723,32 @@ typedef struct _TMPQBetHeader
{
TMPQExtHeader ExtHdr;
DWORD dwTableSize; // Size of the entire BET table, including the header (in bytes)
DWORD dwEntryCount; // Number of entries in the BET table. Must match HET_TABLE_HEADER::dwEntryCount
DWORD dwTableSize; // Size of the entire BET table, including the header (in bytes)
DWORD dwEntryCount; // Number of entries in the BET table. Must match HET_TABLE_HEADER::dwEntryCount
DWORD dwUnknown08;
DWORD dwTableEntrySize; // Size of one table entry (in bits)
DWORD dwBitIndex_FilePos; // Bit index of the file position (within the entry record)
DWORD dwBitIndex_FileSize; // Bit index of the file size (within the entry record)
DWORD dwBitIndex_CmpSize; // Bit index of the compressed size (within the entry record)
DWORD dwBitIndex_FlagIndex; // Bit index of the flag index (within the entry record)
DWORD dwBitIndex_Unknown; // Bit index of the ??? (within the entry record)
DWORD dwBitCount_FilePos; // Bit size of file position (in the entry record)
DWORD dwBitCount_FileSize; // Bit size of file size (in the entry record)
DWORD dwBitCount_CmpSize; // Bit size of compressed file size (in the entry record)
DWORD dwBitCount_FlagIndex; // Bit size of flags index (in the entry record)
DWORD dwBitCount_Unknown; // Bit size of ??? (in the entry record)
DWORD dwBitTotal_NameHash2; // Total bit size of the NameHash2
DWORD dwBitExtra_NameHash2; // Extra bits in the NameHash2
DWORD dwBitCount_NameHash2; // Effective size of NameHash2 (in bits)
DWORD dwNameHashArraySize; // Size of NameHash2 table, in bytes
DWORD dwFlagCount; // Number of flags in the following array
DWORD dwTableEntrySize; // Size of one table entry (in bits)
DWORD dwBitIndex_FilePos; // Bit index of the file position (within the entry record)
DWORD dwBitIndex_FileSize; // Bit index of the file size (within the entry record)
DWORD dwBitIndex_CmpSize; // Bit index of the compressed size (within the entry record)
DWORD dwBitIndex_FlagIndex; // Bit index of the flag index (within the entry record)
DWORD dwBitIndex_Unknown; // Bit index of the ??? (within the entry record)
DWORD dwBitCount_FilePos; // Bit size of file position (in the entry record)
DWORD dwBitCount_FileSize; // Bit size of file size (in the entry record)
DWORD dwBitCount_CmpSize; // Bit size of compressed file size (in the entry record)
DWORD dwBitCount_FlagIndex; // Bit size of flags index (in the entry record)
DWORD dwBitCount_Unknown; // Bit size of ??? (in the entry record)
DWORD dwBitTotal_NameHash2; // Total bit size of the NameHash2
DWORD dwBitExtra_NameHash2; // Extra bits in the NameHash2
DWORD dwBitCount_NameHash2; // Effective size of NameHash2 (in bits)
DWORD dwNameHashArraySize; // Size of NameHash2 table, in bytes
DWORD dwFlagCount; // Number of flags in the following array
} TMPQBetHeader;
// Structure for parsed HET table
typedef struct _TMPQHetTable
{
TBitArray * pBetIndexes; // Bit array of FileIndex values
TMPQBits * pBetIndexes; // Bit array of FileIndex values
LPBYTE pNameHashes; // Array of NameHash1 values (NameHash1 = upper 8 bits of FileName hashe)
ULONGLONG AndMask64; // AND mask used for calculating file name hash
ULONGLONG OrMask64; // OR mask used for setting the highest bit of the file name hash
@ -771,8 +764,8 @@ typedef struct _TMPQHetTable
// Structure for parsed BET table
typedef struct _TMPQBetTable
{
TBitArray * pNameHashes; // Array of NameHash2 entries (lower 24 bits of FileName hash)
TBitArray * pFileTable; // Bit-based file table
TMPQBits * pNameHashes; // Array of NameHash2 entries (lower 24 bits of FileName hash)
TMPQBits * pFileTable; // Bit-based file table
LPDWORD pFileFlags; // Array of file flags
DWORD dwTableEntrySize; // Size of one table entry, in bits
@ -832,7 +825,7 @@ typedef struct _TMPQArchive
TMPQHetTable * pHetTable; // HET table
TFileEntry * pFileTable; // File table
HASH_STRING pfnHashString; // Hashing function that will convert the file name into hash
TMPQUserData UserData; // MPQ user data. Valid only when ID_MPQ_USERDATA has been found
DWORD HeaderData[MPQ_HEADER_DWORDS]; // Storage for MPQ header
@ -856,7 +849,7 @@ typedef struct _TMPQArchive
ULONGLONG CompactBytesProcessed; // Amount of bytes that have been processed during a particular compact call
ULONGLONG CompactTotalBytes; // Total amount of bytes to be compacted
void * pvCompactUserData; // User data thats passed to the callback
} TMPQArchive;
} TMPQArchive;
// File handle structure
typedef struct _TMPQFile
@ -931,11 +924,24 @@ typedef struct _SFILE_CREATE_MPQ
} SFILE_CREATE_MPQ, *PSFILE_CREATE_MPQ;
typedef struct _SFILE_MARKERS
{
DWORD dwSize; // Size of this structure, in bytes
DWORD dwSignature; // Alternate MPQ header marker
const char * szHashTableKey; // Replacement for "(hash table)"
const char * szBlockTableKey; // Replacement for "(block table)"
} SFILE_MARKERS, *PSFILE_MARKERS;
//-----------------------------------------------------------------------------
// TMPQBits support - functions
void GetMPQBits(TMPQBits * pBits, unsigned int nBitPosition, unsigned int nBitLength, void * pvBuffer, int nResultByteSize);
//-----------------------------------------------------------------------------
// Stream support - functions
// Structure used by FileStream_GetBitmap
typedef struct _TStreamBitmap
struct TStreamBitmap
{
ULONGLONG StreamSize; // Size of the stream, in bytes
DWORD BitmapSize; // Size of the block map, in bytes
@ -944,8 +950,7 @@ typedef struct _TStreamBitmap
DWORD IsComplete; // Nonzero if the file is complete
// Followed by the BYTE array, each bit means availability of one block
} TStreamBitmap;
};
// UNICODE versions of the file access functions
TFileStream * FileStream_CreateFile(const TCHAR * szFileName, DWORD dwStreamFlags);
@ -955,7 +960,7 @@ size_t FileStream_Prefix(const TCHAR * szFileName, DWORD * pdwProvider);
bool FileStream_SetCallback(TFileStream * pStream, SFILE_DOWNLOAD_CALLBACK pfnCallback, void * pvUserData);
bool FileStream_GetBitmap(TFileStream * pStream, void * pvBitmap, DWORD cbBitmap, LPDWORD pcbLengthNeeded);
bool FileStream_GetBitmap(TFileStream * pStream, void * pvBitmap, DWORD cbBitmap, DWORD * pcbLengthNeeded);
bool FileStream_Read(TFileStream * pStream, ULONGLONG * pByteOffset, void * pvBuffer, DWORD dwBytesToRead);
bool FileStream_Write(TFileStream * pStream, ULONGLONG * pByteOffset, const void * pvBuffer, DWORD dwBytesToWrite);
bool FileStream_SetSize(TFileStream * pStream, ULONGLONG NewFileSize);
@ -970,151 +975,144 @@ void FileStream_Close(TFileStream * pStream);
// Functions prototypes for Storm.dll
// Typedefs for functions exported by Storm.dll
typedef LCID (STORMAPI * SFILESETLOCALE)(LCID);
typedef bool (STORMAPI * SFILEOPENARCHIVE)(const char *, DWORD, DWORD, HANDLE *);
typedef bool (STORMAPI * SFILECLOSEARCHIVE)(HANDLE);
typedef bool (STORMAPI * SFILEOPENFILEEX)(HANDLE, const char *, DWORD, HANDLE *);
typedef bool (STORMAPI * SFILECLOSEFILE)(HANDLE);
typedef DWORD (STORMAPI * SFILEGETFILESIZE)(HANDLE, LPDWORD);
typedef DWORD (STORMAPI * SFILESETFILEPOINTER)(HANDLE, LONG, LONG *, DWORD);
typedef bool (STORMAPI * SFILEREADFILE)(HANDLE, void *, DWORD, LPDWORD, LPOVERLAPPED);
typedef LCID (WINAPI * SFILESETLOCALE)(LCID);
typedef bool (WINAPI * SFILEOPENARCHIVE)(const char *, DWORD, DWORD, HANDLE *);
typedef bool (WINAPI * SFILECLOSEARCHIVE)(HANDLE);
typedef bool (WINAPI * SFILEOPENFILEEX)(HANDLE, const char *, DWORD, HANDLE *);
typedef bool (WINAPI * SFILECLOSEFILE)(HANDLE);
typedef DWORD (WINAPI * SFILEGETFILESIZE)(HANDLE, LPDWORD);
typedef DWORD (WINAPI * SFILESETFILEPOINTER)(HANDLE, LONG, LONG *, DWORD);
typedef bool (WINAPI * SFILEREADFILE)(HANDLE, void *, DWORD, LPDWORD, LPOVERLAPPED);
//-----------------------------------------------------------------------------
// Functions for manipulation with StormLib global flags
LCID STORMAPI SFileGetLocale();
LCID STORMAPI SFileSetLocale(LCID lcNewLocale);
// Alternate marker support. This is for MPQs masked as DLLs (*.asi), which
// patch Storm.dll at runtime. Call before SFileOpenArchive
bool WINAPI SFileSetArchiveMarkers(PSFILE_MARKERS pMarkers);
// Call before SFileOpenFileEx
LCID WINAPI SFileGetLocale();
LCID WINAPI SFileSetLocale(LCID lcNewLocale);
//-----------------------------------------------------------------------------
// Functions for archive manipulation
bool STORMAPI SFileOpenArchive(const TCHAR * szMpqName, DWORD dwPriority, DWORD dwFlags, HANDLE * phMpq);
bool STORMAPI SFileCreateArchive(const TCHAR * szMpqName, DWORD dwCreateFlags, DWORD dwMaxFileCount, HANDLE * phMpq);
bool STORMAPI SFileCreateArchive2(const TCHAR * szMpqName, PSFILE_CREATE_MPQ pCreateInfo, HANDLE * phMpq);
bool WINAPI SFileOpenArchive(const TCHAR * szMpqName, DWORD dwPriority, DWORD dwFlags, HANDLE * phMpq);
bool WINAPI SFileCreateArchive(const TCHAR * szMpqName, DWORD dwCreateFlags, DWORD dwMaxFileCount, HANDLE * phMpq);
bool WINAPI SFileCreateArchive2(const TCHAR * szMpqName, PSFILE_CREATE_MPQ pCreateInfo, HANDLE * phMpq);
bool STORMAPI SFileSetDownloadCallback(HANDLE hMpq, SFILE_DOWNLOAD_CALLBACK DownloadCB, void * pvUserData);
bool STORMAPI SFileFlushArchive(HANDLE hMpq);
bool STORMAPI SFileCloseArchive(HANDLE hMpq);
bool WINAPI SFileSetDownloadCallback(HANDLE hMpq, SFILE_DOWNLOAD_CALLBACK DownloadCB, void * pvUserData);
bool WINAPI SFileFlushArchive(HANDLE hMpq);
bool WINAPI SFileCloseArchive(HANDLE hMpq);
// Adds another listfile into MPQ. The currently added listfile(s) remain,
// so you can use this API to combining more listfiles.
// Note that this function is internally called by SFileFindFirstFile
int STORMAPI SFileAddListFile(HANDLE hMpq, const TCHAR * szListFile);
int WINAPI SFileAddListFile(HANDLE hMpq, const TCHAR * szListFile);
// Archive compacting
bool STORMAPI SFileSetCompactCallback(HANDLE hMpq, SFILE_COMPACT_CALLBACK CompactCB, void * pvUserData);
bool STORMAPI SFileCompactArchive(HANDLE hMpq, const TCHAR * szListFile, bool bReserved);
bool WINAPI SFileSetCompactCallback(HANDLE hMpq, SFILE_COMPACT_CALLBACK CompactCB, void * pvUserData);
bool WINAPI SFileCompactArchive(HANDLE hMpq, const TCHAR * szListFile, bool bReserved);
// Changing the maximum file count
DWORD STORMAPI SFileGetMaxFileCount(HANDLE hMpq);
bool STORMAPI SFileSetMaxFileCount(HANDLE hMpq, DWORD dwMaxFileCount);
DWORD WINAPI SFileGetMaxFileCount(HANDLE hMpq);
bool WINAPI SFileSetMaxFileCount(HANDLE hMpq, DWORD dwMaxFileCount);
// Changing (attributes) file
DWORD STORMAPI SFileGetAttributes(HANDLE hMpq);
bool STORMAPI SFileSetAttributes(HANDLE hMpq, DWORD dwFlags);
bool STORMAPI SFileUpdateFileAttributes(HANDLE hMpq, const char * szFileName);
DWORD WINAPI SFileGetAttributes(HANDLE hMpq);
bool WINAPI SFileSetAttributes(HANDLE hMpq, DWORD dwFlags);
bool WINAPI SFileUpdateFileAttributes(HANDLE hMpq, const char * szFileName);
//-----------------------------------------------------------------------------
// Functions for manipulation with patch archives
bool STORMAPI SFileOpenPatchArchive(HANDLE hMpq, const TCHAR * szPatchMpqName, const char * szPatchPathPrefix, DWORD dwFlags);
bool STORMAPI SFileIsPatchedArchive(HANDLE hMpq);
bool WINAPI SFileOpenPatchArchive(HANDLE hMpq, const TCHAR * szPatchMpqName, const char * szPatchPathPrefix, DWORD dwFlags);
bool WINAPI SFileIsPatchedArchive(HANDLE hMpq);
//-----------------------------------------------------------------------------
// Functions for file manipulation
// Reading from MPQ file
bool STORMAPI SFileHasFile(HANDLE hMpq, const char * szFileName);
bool STORMAPI SFileOpenFileEx(HANDLE hMpq, const char * szFileName, DWORD dwSearchScope, HANDLE * phFile);
DWORD STORMAPI SFileGetFileSize(HANDLE hFile, LPDWORD pdwFileSizeHigh);
DWORD STORMAPI SFileSetFilePointer(HANDLE hFile, LONG lFilePos, LONG * plFilePosHigh, DWORD dwMoveMethod);
bool STORMAPI SFileReadFile(HANDLE hFile, void * lpBuffer, DWORD dwToRead, LPDWORD pdwRead, LPOVERLAPPED lpOverlapped);
bool STORMAPI SFileCloseFile(HANDLE hFile);
bool WINAPI SFileHasFile(HANDLE hMpq, const char * szFileName);
bool WINAPI SFileOpenFileEx(HANDLE hMpq, const char * szFileName, DWORD dwSearchScope, HANDLE * phFile);
DWORD WINAPI SFileGetFileSize(HANDLE hFile, LPDWORD pdwFileSizeHigh);
DWORD WINAPI SFileSetFilePointer(HANDLE hFile, LONG lFilePos, LONG * plFilePosHigh, DWORD dwMoveMethod);
bool WINAPI SFileReadFile(HANDLE hFile, void * lpBuffer, DWORD dwToRead, LPDWORD pdwRead, LPOVERLAPPED lpOverlapped);
bool WINAPI SFileCloseFile(HANDLE hFile);
// Retrieving info about a file in the archive
bool STORMAPI SFileGetFileInfo(HANDLE hMpqOrFile, SFileInfoClass InfoClass, void * pvFileInfo, DWORD cbFileInfo, LPDWORD pcbLengthNeeded);
bool STORMAPI SFileGetFileName(HANDLE hFile, char * szFileName);
bool STORMAPI SFileFreeFileInfo(void * pvFileInfo, SFileInfoClass InfoClass);
bool WINAPI SFileGetFileInfo(HANDLE hMpqOrFile, SFileInfoClass InfoClass, void * pvFileInfo, DWORD cbFileInfo, LPDWORD pcbLengthNeeded);
bool WINAPI SFileGetFileName(HANDLE hFile, char * szFileName);
bool WINAPI SFileFreeFileInfo(void * pvFileInfo, SFileInfoClass InfoClass);
// High-level extract function
bool STORMAPI SFileExtractFile(HANDLE hMpq, const char * szToExtract, const TCHAR * szExtracted, DWORD dwSearchScope);
bool WINAPI SFileExtractFile(HANDLE hMpq, const char * szToExtract, const TCHAR * szExtracted, DWORD dwSearchScope);
//-----------------------------------------------------------------------------
// Functions for file and archive verification
// Generates file CRC32
bool STORMAPI SFileGetFileChecksums(HANDLE hMpq, const char * szFileName, LPDWORD pdwCrc32, char * pMD5);
bool WINAPI SFileGetFileChecksums(HANDLE hMpq, const char * szFileName, LPDWORD pdwCrc32, char * pMD5);
// Verifies file against its checksums stored in (attributes) attributes (depending on dwFlags).
// For dwFlags, use one or more of MPQ_ATTRIBUTE_MD5
DWORD STORMAPI SFileVerifyFile(HANDLE hMpq, const char * szFileName, DWORD dwFlags);
DWORD WINAPI SFileVerifyFile(HANDLE hMpq, const char * szFileName, DWORD dwFlags);
// Verifies raw data of the archive. Only works for MPQs version 4 or newer
int STORMAPI SFileVerifyRawData(HANDLE hMpq, DWORD dwWhatToVerify, const char * szFileName);
int WINAPI SFileVerifyRawData(HANDLE hMpq, DWORD dwWhatToVerify, const char * szFileName);
// Verifies the signature, if present
bool STORMAPI SFileSignArchive(HANDLE hMpq, DWORD dwSignatureType);
DWORD STORMAPI SFileVerifyArchive(HANDLE hMpq);
bool WINAPI SFileSignArchive(HANDLE hMpq, DWORD dwSignatureType);
DWORD WINAPI SFileVerifyArchive(HANDLE hMpq);
//-----------------------------------------------------------------------------
// Functions for file searching
HANDLE STORMAPI SFileFindFirstFile(HANDLE hMpq, const char * szMask, SFILE_FIND_DATA * lpFindFileData, const TCHAR * szListFile);
bool STORMAPI SFileFindNextFile(HANDLE hFind, SFILE_FIND_DATA * lpFindFileData);
bool STORMAPI SFileFindClose(HANDLE hFind);
HANDLE WINAPI SFileFindFirstFile(HANDLE hMpq, const char * szMask, SFILE_FIND_DATA * lpFindFileData, const TCHAR * szListFile);
bool WINAPI SFileFindNextFile(HANDLE hFind, SFILE_FIND_DATA * lpFindFileData);
bool WINAPI SFileFindClose(HANDLE hFind);
HANDLE STORMAPI SListFileFindFirstFile(HANDLE hMpq, const TCHAR * szListFile, const char * szMask, SFILE_FIND_DATA * lpFindFileData);
bool STORMAPI SListFileFindNextFile(HANDLE hFind, SFILE_FIND_DATA * lpFindFileData);
bool STORMAPI SListFileFindClose(HANDLE hFind);
HANDLE WINAPI SListFileFindFirstFile(HANDLE hMpq, const TCHAR * szListFile, const char * szMask, SFILE_FIND_DATA * lpFindFileData);
bool WINAPI SListFileFindNextFile(HANDLE hFind, SFILE_FIND_DATA * lpFindFileData);
bool WINAPI SListFileFindClose(HANDLE hFind);
// Locale support
int STORMAPI SFileEnumLocales(HANDLE hMpq, const char * szFileName, LCID * plcLocales, LPDWORD pdwMaxLocales, DWORD dwSearchScope);
int WINAPI SFileEnumLocales(HANDLE hMpq, const char * szFileName, LCID * plcLocales, LPDWORD pdwMaxLocales, DWORD dwSearchScope);
//-----------------------------------------------------------------------------
// Support for adding files to the MPQ
bool STORMAPI SFileCreateFile(HANDLE hMpq, const char * szArchivedName, ULONGLONG FileTime, DWORD dwFileSize, LCID lcLocale, DWORD dwFlags, HANDLE * phFile);
bool STORMAPI SFileWriteFile(HANDLE hFile, const void * pvData, DWORD dwSize, DWORD dwCompression);
bool STORMAPI SFileFinishFile(HANDLE hFile);
bool WINAPI SFileCreateFile(HANDLE hMpq, const char * szArchivedName, ULONGLONG FileTime, DWORD dwFileSize, LCID lcLocale, DWORD dwFlags, HANDLE * phFile);
bool WINAPI SFileWriteFile(HANDLE hFile, const void * pvData, DWORD dwSize, DWORD dwCompression);
bool WINAPI SFileFinishFile(HANDLE hFile);
bool STORMAPI SFileAddFileEx(HANDLE hMpq, const TCHAR * szFileName, const char * szArchivedName, DWORD dwFlags, DWORD dwCompression, DWORD dwCompressionNext = MPQ_COMPRESSION_NEXT_SAME);
bool STORMAPI SFileAddFile(HANDLE hMpq, const TCHAR * szFileName, const char * szArchivedName, DWORD dwFlags);
bool STORMAPI SFileAddWave(HANDLE hMpq, const TCHAR * szFileName, const char * szArchivedName, DWORD dwFlags, DWORD dwQuality);
bool STORMAPI SFileRemoveFile(HANDLE hMpq, const char * szFileName, DWORD dwSearchScope);
bool STORMAPI SFileRenameFile(HANDLE hMpq, const char * szOldFileName, const char * szNewFileName);
bool STORMAPI SFileSetFileLocale(HANDLE hFile, LCID lcNewLocale);
bool STORMAPI SFileSetDataCompression(DWORD DataCompression);
bool WINAPI SFileAddFileEx(HANDLE hMpq, const TCHAR * szFileName, const char * szArchivedName, DWORD dwFlags, DWORD dwCompression, DWORD dwCompressionNext = MPQ_COMPRESSION_NEXT_SAME);
bool WINAPI SFileAddFile(HANDLE hMpq, const TCHAR * szFileName, const char * szArchivedName, DWORD dwFlags);
bool WINAPI SFileAddWave(HANDLE hMpq, const TCHAR * szFileName, const char * szArchivedName, DWORD dwFlags, DWORD dwQuality);
bool WINAPI SFileRemoveFile(HANDLE hMpq, const char * szFileName, DWORD dwSearchScope);
bool WINAPI SFileRenameFile(HANDLE hMpq, const char * szOldFileName, const char * szNewFileName);
bool WINAPI SFileSetFileLocale(HANDLE hFile, LCID lcNewLocale);
bool WINAPI SFileSetDataCompression(DWORD DataCompression);
bool STORMAPI SFileSetAddFileCallback(HANDLE hMpq, SFILE_ADDFILE_CALLBACK AddFileCB, void * pvUserData);
bool WINAPI SFileSetAddFileCallback(HANDLE hMpq, SFILE_ADDFILE_CALLBACK AddFileCB, void * pvUserData);
//-----------------------------------------------------------------------------
// Compression and decompression
int STORMAPI SCompImplode (void * pvOutBuffer, int * pcbOutBuffer, void * pvInBuffer, int cbInBuffer);
int STORMAPI SCompExplode (void * pvOutBuffer, int * pcbOutBuffer, void * pvInBuffer, int cbInBuffer);
int STORMAPI SCompCompress (void * pvOutBuffer, int * pcbOutBuffer, void * pvInBuffer, int cbInBuffer, unsigned uCompressionMask, int nCmpType, int nCmpLevel);
int STORMAPI SCompDecompress (void * pvOutBuffer, int * pcbOutBuffer, void * pvInBuffer, int cbInBuffer);
int STORMAPI SCompDecompress2(void * pvOutBuffer, int * pcbOutBuffer, void * pvInBuffer, int cbInBuffer);
int WINAPI SCompImplode (void * pvOutBuffer, int * pcbOutBuffer, void * pvInBuffer, int cbInBuffer);
int WINAPI SCompExplode (void * pvOutBuffer, int * pcbOutBuffer, void * pvInBuffer, int cbInBuffer);
int WINAPI SCompCompress (void * pvOutBuffer, int * pcbOutBuffer, void * pvInBuffer, int cbInBuffer, unsigned uCompressionMask, int nCmpType, int nCmpLevel);
int WINAPI SCompDecompress (void * pvOutBuffer, int * pcbOutBuffer, void * pvInBuffer, int cbInBuffer);
int WINAPI SCompDecompress2(void * pvOutBuffer, int * pcbOutBuffer, void * pvInBuffer, int cbInBuffer);
//-----------------------------------------------------------------------------
// Non-Windows support for SetLastError/GetLastError
#ifdef FULL
#ifndef PLATFORM_WINDOWS
void SetLastError(DWORD err);
DWORD GetLastError();
#endif
#else
extern DWORD nLastError;
DWORD STORMAPI SErrGetLastError();
void STORMAPI SErrSetLastError(DWORD dwErrCode);
#ifndef STORMLIB_WINDOWS
#define SetLastError SErrSetLastError
#define GetLastError SErrGetLastError
void SetLastError(DWORD dwErrCode);
DWORD GetLastError();
#endif

897
3rdParty/StormLib/src/StormPort.h vendored

@ -1,438 +1,461 @@
/*****************************************************************************/
/* StormPort.h Copyright (c) Marko Friedemann 2001 */
/*---------------------------------------------------------------------------*/
/* Portability module for the StormLib library. Contains a wrapper symbols */
/* to make the compilation under Linux work */
/* */
/* Author: Marko Friedemann <marko.friedemann@bmx-chemnitz.de> */
/* Created at: Mon Jan 29 18:26:01 CEST 2001 */
/* Computer: whiplash.flachland-chemnitz.de */
/* System: Linux 2.4.0 on i686 */
/* */
/* Author: Sam Wilkins <swilkins1337@gmail.com> */
/* System: Mac OS X and port to big endian processor */
/* */
/*---------------------------------------------------------------------------*/
/* Date Ver Who Comment */
/* -------- ---- --- ------- */
/* 29.01.01 1.00 Mar Created */
/* 24.03.03 1.01 Lad Some cosmetic changes */
/* 12.11.03 1.02 Dan Macintosh compatibility */
/* 24.07.04 1.03 Sam Mac OS X compatibility */
/* 22.11.06 1.04 Sam Mac OS X compatibility (for StormLib 6.0) */
/* 31.12.06 1.05 XPinguin Full GNU/Linux compatibility */
/* 17.10.12 1.05 Lad Moved error codes so they don't overlap with errno.h */
/*****************************************************************************/
#ifndef __STORMPORT_H__
#define __STORMPORT_H__
#define STORMAPI
#ifndef __cplusplus
#define bool char
#define true 1
#define false 0
#endif
//-----------------------------------------------------------------------------
// Defines for Windows
#if !defined(PLATFORM_DEFINED) && defined(_WIN32)
// In MSVC 8.0, there are some functions declared as deprecated.
#if _MSC_VER >= 1400
#define _CRT_SECURE_NO_DEPRECATE
#define _CRT_NON_CONFORMING_SWPRINTFS
#endif
#include <tchar.h>
#include <assert.h>
#include <ctype.h>
#include <stdio.h>
// Suppress definitions of `min` and `max` macros by <windows.h>:
#define NOMINMAX 1
#include <windows.h>
#include <wininet.h>
#define PLATFORM_LITTLE_ENDIAN
#ifdef _WIN64
#define PLATFORM_64BIT
#else
#define PLATFORM_32BIT
#endif
#define PLATFORM_WINDOWS
#define PLATFORM_DEFINED // The platform is known now
#endif
//-----------------------------------------------------------------------------
// Defines for Mac
#if !defined(PLATFORM_DEFINED) && defined(__APPLE__) // Mac BSD API
// Macintosh
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <assert.h>
#include <errno.h>
// Support for PowerPC on Mac OS X
#if (__ppc__ == 1) || (__POWERPC__ == 1) || (_ARCH_PPC == 1)
#include <stdint.h>
#include <CoreFoundation/CFByteOrder.h>
#endif
#define PKEXPORT
#define __SYS_ZLIB
#define __SYS_BZLIB
#ifndef __BIG_ENDIAN__
#define PLATFORM_LITTLE_ENDIAN
#endif
#define PLATFORM_MAC
#define PLATFORM_DEFINED // The platform is known now
#endif
#if !defined(PLATFORM_DEFINED) && defined(__HAIKU__)
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <ctype.h>
#include <assert.h>
#include <errno.h>
#ifndef __BIG_ENDIAN__
#define PLATFORM_LITTLE_ENDIAN
#endif
#define PLATFORM_HAIKU
#define PLATFORM_DEFINED // The platform is known now
#endif
#if !defined(PLATFORM_DEFINED) && defined(__AMIGA__)
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <ctype.h>
#include <assert.h>
#include <errno.h>
#define PLATFORM_AMIGA
#define PLATFORM_DEFINED
#endif
#if !defined(PLATFORM_DEFINED) && defined(__SWITCH__)
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <strings.h>
#include <ctype.h>
#include <assert.h>
#include <errno.h>
#ifndef __BIG_ENDIAN__
#define PLATFORM_LITTLE_ENDIAN
#endif
#define PLATFORM_SWITCH
#define PLATFORM_DEFINED
#endif
#if !defined(PLATFORM_DEFINED) && defined(__3DS__)
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <strings.h>
#include <ctype.h>
#include <assert.h>
#include <errno.h>
#define PLATFORM_LITTLE_ENDIAN
#define PLATFORM_CTR
#define PLATFORM_DEFINED
#endif
#if !defined(PLATFORM_DEFINED) && defined(__vita__)
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <strings.h>
#include <ctype.h>
#include <assert.h>
#include <errno.h>
#ifndef __BIG_ENDIAN__
#define PLATFORM_LITTLE_ENDIAN
#endif
#define PLATFORM_VITA
#define PLATFORM_DEFINED
#endif
//-----------------------------------------------------------------------------
// Assumption: we are not on Windows nor Macintosh, so this must be linux *grin*
#if !defined(PLATFORM_DEFINED)
#include <sys/types.h>
#include <sys/stat.h>
#ifndef __vita__
#include <sys/mman.h>
/*****************************************************************************/
/* StormPort.h Copyright (c) Marko Friedemann 2001 */
/*---------------------------------------------------------------------------*/
/* Portability module for the StormLib library. Contains a wrapper symbols */
/* to make the compilation under Linux work */
/* */
/* Author: Marko Friedemann <marko.friedemann@bmx-chemnitz.de> */
/* Created at: Mon Jan 29 18:26:01 CEST 2001 */
/* Computer: whiplash.flachland-chemnitz.de */
/* System: Linux 2.4.0 on i686 */
/* */
/* Author: Sam Wilkins <swilkins1337@gmail.com> */
/* System: Mac OS X and port to big endian processor */
/* */
/*---------------------------------------------------------------------------*/
/* Date Ver Who Comment */
/* -------- ---- --- ------- */
/* 29.01.01 1.00 Mar Created */
/* 24.03.03 1.01 Lad Some cosmetic changes */
/* 12.11.03 1.02 Dan Macintosh compatibility */
/* 24.07.04 1.03 Sam Mac OS X compatibility */
/* 22.11.06 1.04 Sam Mac OS X compatibility (for StormLib 6.0) */
/* 31.12.06 1.05 XPinguin Full GNU/Linux compatibility */
/* 17.10.12 1.05 Lad Moved error codes so they don't overlap with errno.h */
/*****************************************************************************/
#ifndef __STORMPORT_H__
#define __STORMPORT_H__
#ifndef __cplusplus
#define bool char
#define true 1
#define false 0
#endif
//-----------------------------------------------------------------------------
// Defines for Windows
#if !defined(STORMLIB_PLATFORM_DEFINED) && defined(_WIN32)
// In MSVC 8.0, there are some functions declared as deprecated.
#if _MSC_VER >= 1400
#define _CRT_SECURE_NO_DEPRECATE
#define _CRT_NON_CONFORMING_SWPRINTFS
#endif
#include <fcntl.h>
#include <unistd.h>
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <strings.h>
#include <ctype.h>
#include <assert.h>
#include <errno.h>
#ifndef __BIG_ENDIAN__
#define PLATFORM_LITTLE_ENDIAN
#endif
#define PLATFORM_LINUX
#define PLATFORM_DEFINED
#endif
//-----------------------------------------------------------------------------
// Definition of Windows-specific types for non-Windows platforms
#ifndef PLATFORM_WINDOWS
#if __LP64__
#define PLATFORM_64BIT
#else
#define PLATFORM_32BIT
#endif
// Typedefs for ANSI C
typedef unsigned char BYTE;
typedef int LONG;
typedef unsigned short USHORT;
typedef unsigned int DWORD;
typedef unsigned long DWORD_PTR;
typedef long LONG_PTR;
typedef long INT_PTR;
typedef long long LONGLONG;
typedef unsigned long long ULONGLONG;
typedef void * HANDLE;
typedef void * LPOVERLAPPED; // Unsupported on Linux and Mac
typedef char TCHAR;
typedef unsigned int LCID;
typedef LONG * PLONG;
typedef DWORD * LPDWORD;
typedef BYTE * LPBYTE;
typedef const char * LPCTSTR;
typedef const char * LPCSTR;
typedef char * LPTSTR;
typedef char * LPSTR;
#ifdef PLATFORM_32BIT
#define _LZMA_UINT32_IS_ULONG
#endif
// Some Windows-specific defines
#ifndef MAX_PATH
#define MAX_PATH 1024
#endif
#ifndef _countof
#define _countof(x) (sizeof(x) / sizeof(x[0]))
#endif
#define WINAPI __attribute__((stdcall))
#define FILE_BEGIN SEEK_SET
#define FILE_CURRENT SEEK_CUR
#define FILE_END SEEK_END
#define _T(x) x
#define _tcslen strlen
#define _tcscpy strcpy
#define _tcscat strcat
#define _tcschr strchr
#define _tcsrchr strrchr
#define _tcsstr strstr
#define _tcsnicmp strncasecmp
#define _tprintf printf
#define _stprintf sprintf
#define _tremove remove
#define _tmain main
#define _stricmp strcasecmp
#define _strnicmp strncasecmp
#define _tcsicmp strcasecmp
#define _tcsnicmp strncasecmp
#endif // !PLATFORM_WINDOWS
// 64-bit calls are supplied by "normal" calls on Mac
#if defined(PLATFORM_MAC) || defined(PLATFORM_HAIKU) || defined(PLATFORM_AMIGA) || defined(PLATFORM_SWITCH) || defined(PLATFORM_CTR) || defined(PLATFORM_VITA)
#define stat64 stat
#define fstat64 fstat
#define lseek64 lseek
#define ftruncate64 ftruncate
#define off64_t off_t
#define O_LARGEFILE 0
#endif
// Platform-specific error codes for UNIX-based platforms
#if defined(PLATFORM_MAC) || defined(PLATFORM_LINUX) || defined(PLATFORM_HAIKU) || defined(PLATFORM_AMIGA) || defined(PLATFORM_SWITCH) || defined(PLATFORM_CTR) || defined(PLATFORM_VITA)
#define ERROR_SUCCESS 0
#define ERROR_FILE_NOT_FOUND ENOENT
#define ERROR_ACCESS_DENIED EPERM
#define ERROR_INVALID_HANDLE EBADF
#define ERROR_NOT_ENOUGH_MEMORY ENOMEM
#define ERROR_NOT_SUPPORTED ENOTSUP
#define ERROR_INVALID_PARAMETER EINVAL
#define ERROR_NEGATIVE_SEEK EINVAL
#define ERROR_DISK_FULL ENOSPC
#define ERROR_ALREADY_EXISTS EEXIST
#define ERROR_INSUFFICIENT_BUFFER ENOBUFS
#define ERROR_BAD_FORMAT 1000 // No such error code under Linux
#define ERROR_NO_MORE_FILES 1001 // No such error code under Linux
#define ERROR_HANDLE_EOF 1002 // No such error code under Linux
#define ERROR_CAN_NOT_COMPLETE 1003 // No such error code under Linux
#define ERROR_FILE_CORRUPT 1004 // No such error code under Linux
#endif
//-----------------------------------------------------------------------------
// Swapping functions
#ifdef PLATFORM_LITTLE_ENDIAN
#define BSWAP_INT16_UNSIGNED(a) (a)
#define BSWAP_INT16_SIGNED(a) (a)
#define BSWAP_INT32_UNSIGNED(a) (a)
#define BSWAP_INT32_SIGNED(a) (a)
#define BSWAP_INT64_SIGNED(a) (a)
#define BSWAP_INT64_UNSIGNED(a) (a)
#define BSWAP_ARRAY16_UNSIGNED(a,b) {}
#define BSWAP_ARRAY32_UNSIGNED(a,b) {}
#define BSWAP_ARRAY64_UNSIGNED(a,b) {}
#define BSWAP_PART_HEADER(a) {}
#define BSWAP_TMPQHEADER(a,b) {}
#define BSWAP_TMPKHEADER(a) {}
#else
#ifdef __cplusplus
extern "C" {
#endif
int16_t SwapInt16(uint16_t);
uint16_t SwapUInt16(uint16_t);
int32_t SwapInt32(uint32_t);
uint32_t SwapUInt32(uint32_t);
int64_t SwapInt64(uint64_t);
uint64_t SwapUInt64(uint64_t);
void ConvertUInt16Buffer(void * ptr, size_t length);
void ConvertUInt32Buffer(void * ptr, size_t length);
void ConvertUInt64Buffer(void * ptr, size_t length);
void ConvertTMPQUserData(void *userData);
void ConvertTMPQHeader(void *header, uint16_t wPart);
void ConvertTMPKHeader(void *header);
#ifdef __cplusplus
}
#endif
#define BSWAP_INT16_SIGNED(a) SwapInt16((a))
#define BSWAP_INT16_UNSIGNED(a) SwapUInt16((a))
#define BSWAP_INT32_SIGNED(a) SwapInt32((a))
#define BSWAP_INT32_UNSIGNED(a) SwapUInt32((a))
#define BSWAP_INT64_SIGNED(a) SwapInt64((a))
#define BSWAP_INT64_UNSIGNED(a) SwapUInt64((a))
#define BSWAP_ARRAY16_UNSIGNED(a,b) ConvertUInt16Buffer((a),(b))
#define BSWAP_ARRAY32_UNSIGNED(a,b) ConvertUInt32Buffer((a),(b))
#define BSWAP_ARRAY64_UNSIGNED(a,b) ConvertUInt64Buffer((a),(b))
#define BSWAP_TMPQHEADER(a,b) ConvertTMPQHeader((a),(b))
#define BSWAP_TMPKHEADER(a) ConvertTMPKHeader((a))
#endif
//-----------------------------------------------------------------------------
// Macro for deprecated symbols
/*
#ifdef _MSC_VER
#if _MSC_FULL_VER >= 140050320
#define STORMLIB_DEPRECATED(_Text) __declspec(deprecated(_Text))
#else
#define STORMLIB_DEPRECATED(_Text) __declspec(deprecated)
#endif
#else
#ifdef __GNUC__
#define STORMLIB_DEPRECATED(_Text) __attribute__((deprecated))
#else
#define STORMLIB_DEPRECATED(_Text) __attribute__((deprecated(_Text)))
#endif
#endif
// When a flag is deprecated, use this macro
#ifndef _STORMLIB_NO_DEPRECATE
#define STORMLIB_DEPRECATED_FLAG(type, oldflag, newflag) \
const STORMLIB_DEPRECATED(#oldflag " is deprecated. Use " #newflag ". To supress this warning, define _STORMLIB_NO_DEPRECATE") static type oldflag = (type)newflag;
#else
#define STORMLIB_DEPRECATED_FLAG(type, oldflag, newflag) static type oldflag = (type)newflag;
#endif
*/
//
// MINIWIN changes
//
#define bool int
#endif // __STORMPORT_H__
#include <tchar.h>
#include <assert.h>
#include <ctype.h>
#include <stdio.h>
// Suppress definitions of `min` and `max` macros by <windows.h>:
#define NOMINMAX 1
#include <windows.h>
#include <wininet.h>
#define STORMLIB_LITTLE_ENDIAN
#ifdef _WIN64
#define STORMLIB_64BIT
#else
#define STORMLIB_32BIT
#endif
#define STORMLIB_CDECL __cdecl
#define STORMLIB_WINDOWS
#define STORMLIB_PLATFORM_DEFINED // The platform is known now
#endif
//-----------------------------------------------------------------------------
// Defines for Mac
#if !defined(STORMLIB_PLATFORM_DEFINED) && defined(__APPLE__) // Mac BSD API
// Macintosh
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <assert.h>
#include <errno.h>
// Support for PowerPC on Max OS X
#if (__ppc__ == 1) || (__POWERPC__ == 1) || (_ARCH_PPC == 1)
#include <stdint.h>
#include <CoreFoundation/CFByteOrder.h>
#endif
#define PKEXPORT
#define __SYS_ZLIB
#define __SYS_BZLIB
#ifndef __BIG_ENDIAN__
#define STORMLIB_LITTLE_ENDIAN
#endif
#define STORMLIB_MAC
#define STORMLIB_HAS_MMAP // Indicate that we have mmap support
#define STORMLIB_PLATFORM_DEFINED // The platform is known now
#endif
//-----------------------------------------------------------------------------
// Defines for HAIKU platform
#if !defined(STORMLIB_PLATFORM_DEFINED) && defined(__HAIKU__)
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <ctype.h>
#include <assert.h>
#include <errno.h>
#ifndef __BIG_ENDIAN__
#define STORMLIB_LITTLE_ENDIAN
#endif
#define STORMLIB_MAC // Use Mac compatible code
#define STORMLIB_HAIKU
#define STORMLIB_PLATFORM_DEFINED // The platform is known now
#endif
//-----------------------------------------------------------------------------
// Defines for AMIGA platform
#if !defined(STORMLIB_PLATFORM_DEFINED) && defined(__AMIGA__)
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <ctype.h>
#include <assert.h>
#include <errno.h>
#ifndef __BIG_ENDIAN__
#define STORMLIB_LITTLE_ENDIAN
#endif
#define STORMLIB_MAC // Use Mac compatible code
#define STORMLIB_AMIGA
#define STORMLIB_PLATFORM_DEFINED
#endif
//-----------------------------------------------------------------------------
// Defines for Switch platform
#if !defined(STORMLIB_PLATFORM_DEFINED) && defined(__SWITCH__)
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <strings.h>
#include <ctype.h>
#include <assert.h>
#include <errno.h>
#ifndef __BIG_ENDIAN__
#define STORMLIB_LITTLE_ENDIAN
#endif
#define STORMLIB_MAC // Use Mac compatible code
#define STORMLIB_SWITCH
#define STORMLIB_PLATFORM_DEFINED
#endif
//-----------------------------------------------------------------------------
// Defines for 3DS platform
#if !defined(STORMLIB_PLATFORM_DEFINED) && defined(__3DS__)
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <strings.h>
#include <ctype.h>
#include <assert.h>
#include <errno.h>
#define STORMLIB_LITTLE_ENDIAN
#define STORMLIB_MAC // Use Mac compatible code
#define STORMLIB_CTR
#define STORMLIB_PLATFORM_DEFINED
#endif
//-----------------------------------------------------------------------------
// Defines for Vita platform
#if !defined(STORMLIB_PLATFORM_DEFINED) && defined(__vita__)
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <strings.h>
#include <ctype.h>
#include <assert.h>
#include <errno.h>
#ifndef __BIG_ENDIAN__
#define STORMLIB_LITTLE_ENDIAN
#endif
#define STORMLIB_MAC // Use Mac compatible code
#define STORMLIB_VITA
#define STORMLIB_PLATFORM_DEFINED
#endif
//-----------------------------------------------------------------------------
// Assumption: If the platform is not defined, this must be Linux *grin*
#if !defined(STORMLIB_PLATFORM_DEFINED)
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <strings.h>
#include <ctype.h>
#include <assert.h>
#include <errno.h>
#ifndef __BIG_ENDIAN__
#define STORMLIB_LITTLE_ENDIAN
#endif
#define STORMLIB_LINUX
#define STORMLIB_HAS_MMAP // Indicate that we have mmap support
#define STORMLIB_PLATFORM_DEFINED
#endif
//-----------------------------------------------------------------------------
// Definition of Windows-specific types for non-Windows platforms
#ifndef STORMLIB_WINDOWS
#if __LP64__
#define STORMLIB_64BIT
#else
#define STORMLIB_32BIT
#endif
// __cdecl meand nothing on non-Windows
#define STORMLIB_CDECL /* */
// Typedefs for ANSI C
typedef unsigned char BYTE;
typedef unsigned short USHORT;
typedef int LONG;
typedef unsigned int DWORD;
typedef unsigned long DWORD_PTR;
typedef long LONG_PTR;
typedef long INT_PTR;
typedef long long LONGLONG;
typedef unsigned long long ULONGLONG;
typedef void * HANDLE;
typedef void * LPOVERLAPPED; // Unsupported on Linux and Mac
typedef char TCHAR;
typedef unsigned int LCID;
typedef LONG * PLONG;
typedef DWORD * LPDWORD;
typedef BYTE * LPBYTE;
typedef const char * LPCTSTR;
typedef const char * LPCSTR;
typedef char * LPTSTR;
typedef char * LPSTR;
#ifdef STORMLIB_32BIT
#define _LZMA_UINT32_IS_ULONG
#endif
// Some Windows-specific defines
#ifndef MAX_PATH
#define MAX_PATH 1024
#endif
#define WINAPI
#define FILE_BEGIN SEEK_SET
#define FILE_CURRENT SEEK_CUR
#define FILE_END SEEK_END
#define _T(x) x
#define _tcslen strlen
#define _tcscpy strcpy
#define _tcscat strcat
#define _tcschr strchr
#define _tcsrchr strrchr
#define _tcsstr strstr
#define _tcsnicmp strncasecmp
#define _tprintf printf
#define _stprintf sprintf
#define _tremove remove
#define _tmain main
#define _stricmp strcasecmp
#define _strnicmp strncasecmp
#define _tcsicmp strcasecmp
#define _tcsnicmp strncasecmp
#endif // !STORMLIB_WINDOWS
// 64-bit calls are supplied by "normal" calls on Mac
#if defined(STORMLIB_MAC)
#define stat64 stat
#define fstat64 fstat
#define lseek64 lseek
#define ftruncate64 ftruncate
#define off64_t off_t
#define O_LARGEFILE 0
#endif
// Platform-specific error codes for UNIX-based platforms
#if defined(STORMLIB_MAC) || defined(STORMLIB_LINUX)
#define ERROR_SUCCESS 0
#define ERROR_FILE_NOT_FOUND ENOENT
#define ERROR_ACCESS_DENIED EPERM
#define ERROR_INVALID_HANDLE EBADF
#define ERROR_NOT_ENOUGH_MEMORY ENOMEM
#define ERROR_NOT_SUPPORTED ENOTSUP
#define ERROR_INVALID_PARAMETER EINVAL
#define ERROR_NEGATIVE_SEEK ESPIPE
#define ERROR_DISK_FULL ENOSPC
#define ERROR_ALREADY_EXISTS EEXIST
#define ERROR_INSUFFICIENT_BUFFER ENOBUFS
#define ERROR_BAD_FORMAT 1000 // No such error code under Linux
#define ERROR_NO_MORE_FILES 1001 // No such error code under Linux
#define ERROR_HANDLE_EOF 1002 // No such error code under Linux
#define ERROR_CAN_NOT_COMPLETE 1003 // No such error code under Linux
#define ERROR_FILE_CORRUPT 1004 // No such error code under Linux
#endif
#ifndef _countof
#define _countof(x) (sizeof(x) / sizeof(x[0]))
#endif
//-----------------------------------------------------------------------------
// Swapping functions
#ifdef STORMLIB_LITTLE_ENDIAN
#define BSWAP_INT16_UNSIGNED(a) (a)
#define BSWAP_INT16_SIGNED(a) (a)
#define BSWAP_INT32_UNSIGNED(a) (a)
#define BSWAP_INT32_SIGNED(a) (a)
#define BSWAP_INT64_SIGNED(a) (a)
#define BSWAP_INT64_UNSIGNED(a) (a)
#define BSWAP_ARRAY16_UNSIGNED(a,b) {}
#define BSWAP_ARRAY32_UNSIGNED(a,b) {}
#define BSWAP_ARRAY64_UNSIGNED(a,b) {}
#define BSWAP_PART_HEADER(a) {}
#define BSWAP_TMPQHEADER(a,b) {}
#define BSWAP_TMPKHEADER(a) {}
#else
#ifdef __cplusplus
extern "C" {
#endif
int16_t SwapInt16(uint16_t);
uint16_t SwapUInt16(uint16_t);
int32_t SwapInt32(uint32_t);
uint32_t SwapUInt32(uint32_t);
int64_t SwapInt64(uint64_t);
uint64_t SwapUInt64(uint64_t);
void ConvertUInt16Buffer(void * ptr, size_t length);
void ConvertUInt32Buffer(void * ptr, size_t length);
void ConvertUInt64Buffer(void * ptr, size_t length);
void ConvertTMPQUserData(void *userData);
void ConvertTMPQHeader(void *header, uint16_t wPart);
void ConvertTMPKHeader(void *header);
#ifdef __cplusplus
}
#endif
#define BSWAP_INT16_SIGNED(a) SwapInt16((a))
#define BSWAP_INT16_UNSIGNED(a) SwapUInt16((a))
#define BSWAP_INT32_SIGNED(a) SwapInt32((a))
#define BSWAP_INT32_UNSIGNED(a) SwapUInt32((a))
#define BSWAP_INT64_SIGNED(a) SwapInt64((a))
#define BSWAP_INT64_UNSIGNED(a) SwapUInt64((a))
#define BSWAP_ARRAY16_UNSIGNED(a,b) ConvertUInt16Buffer((a),(b))
#define BSWAP_ARRAY32_UNSIGNED(a,b) ConvertUInt32Buffer((a),(b))
#define BSWAP_ARRAY64_UNSIGNED(a,b) ConvertUInt64Buffer((a),(b))
#define BSWAP_TMPQHEADER(a,b) ConvertTMPQHeader((a),(b))
#define BSWAP_TMPKHEADER(a) ConvertTMPKHeader((a))
#endif
//-----------------------------------------------------------------------------
// Macro for deprecated symbols
/*
#ifdef _MSC_VER
#if _MSC_FULL_VER >= 140050320
#define STORMLIB_DEPRECATED(_Text) __declspec(deprecated(_Text))
#else
#define STORMLIB_DEPRECATED(_Text) __declspec(deprecated)
#endif
#else
#ifdef __GNUC__
#define STORMLIB_DEPRECATED(_Text) __attribute__((deprecated))
#else
#define STORMLIB_DEPRECATED(_Text) __attribute__((deprecated(_Text)))
#endif
#endif
// When a flag is deprecated, use this macro
#ifndef _STORMLIB_NO_DEPRECATE
#define STORMLIB_DEPRECATED_FLAG(type, oldflag, newflag) \
const STORMLIB_DEPRECATED(#oldflag " is deprecated. Use " #newflag ". To supress this warning, define _STORMLIB_NO_DEPRECATE") static type oldflag = (type)newflag;
#else
#define STORMLIB_DEPRECATED_FLAG(type, oldflag, newflag) static type oldflag = (type)newflag;
#endif
*/
#endif // __STORMPORT_H__

Loading…
Cancel
Save