diff options
Diffstat (limited to 'dep/CascLib/src/CascCommon.h')
-rw-r--r-- | dep/CascLib/src/CascCommon.h | 374 |
1 files changed, 374 insertions, 0 deletions
diff --git a/dep/CascLib/src/CascCommon.h b/dep/CascLib/src/CascCommon.h new file mode 100644 index 00000000000..b2f6a156e39 --- /dev/null +++ b/dep/CascLib/src/CascCommon.h @@ -0,0 +1,374 @@ +/*****************************************************************************/ +/* CascCommon.h Copyright (c) Ladislav Zezula 2014 */ +/*---------------------------------------------------------------------------*/ +/* Common functions for CascLib */ +/*---------------------------------------------------------------------------*/ +/* Date Ver Who Comment */ +/* -------- ---- --- ------- */ +/* 29.04.14 1.00 Lad The first version of CascCommon.h */ +/*****************************************************************************/ + +#ifndef __CASCCOMMON_H__ +#define __CASCCOMMON_H__ + +//----------------------------------------------------------------------------- +// Compression support + +// Include functions from zlib +#ifndef __SYS_ZLIB + #include "zlib/zlib.h" +#else + #include <zlib.h> +#endif + +#include "CascPort.h" +#include "common/Common.h" +#include "common/FileStream.h" +#include "common/ListFile.h" +#include "common/Map.h" + +// Headers from LibTomCrypt +#include "libtomcrypt/src/headers/tomcrypt.h" + +// For HashStringJenkins +#include "jenkins/lookup.h" + +//----------------------------------------------------------------------------- +// CascLib private defines + +#define CASC_GAME_HOTS 0x00010000 // Heroes of the Storm +#define CASC_GAME_WOW6 0x00020000 // World of Warcraft - Warlords of Draenor +#define CASC_GAME_MASK 0xFFFF0000 // Mask for getting game ID + +#define CASC_INDEX_COUNT 0x10 +#define CASC_FILE_KEY_SIZE 0x09 // Size of the file key +#define CASC_MAX_DATA_FILES 0x100 +#define CASC_MAX_MAR_FILES 3 // Maximum of 3 MAR files are supported +#define CASC_MNDX_SIGNATURE 0x58444E4D // 'MNDX' + +#define CASC_SEARCH_HAVE_NAME 0x0001 // Indicated that previous search found a name + +// Prevent problems with CRT "min" and "max" functions, +// as they are not defined on all platforms +#define CASCLIB_MIN(a, b) ((a < b) ? a : b) +#define CASCLIB_MAX(a, b) ((a > b) ? a : b) +#define CASCLIB_UNUSED(p) ((void)(p)) + +#define CASC_PACKAGE_BUFFER 0x1000 + +//----------------------------------------------------------------------------- +// Structures + +struct TFileStream; +struct _MAR_FILE; + +typedef struct _CASC_INDEX_ENTRY +{ + BYTE IndexKey[CASC_FILE_KEY_SIZE]; // The first 9 bytes of the encoding key + BYTE FileOffset[5]; // + BYTE FileSize[4]; +} CASC_INDEX_ENTRY, *PCASC_INDEX_ENTRY; + +typedef struct _CASC_MAPPING_TABLE +{ + TCHAR * szFileName; // Name of the key mapping file + LPBYTE pbFileData; // Pointer to the file data + DWORD cbFileData; // Length of the file data + BYTE ExtraBytes; // (?) Extra bytes in the key record + BYTE SpanSizeBytes; // Size of field with file size + BYTE SpanOffsBytes; // Size of field with file offset + BYTE KeyBytes; // Size of the file key + BYTE SegmentBits; // Number of bits for the file offset (rest is archive index) + ULONGLONG MaxFileOffset; + + PCASC_INDEX_ENTRY pIndexEntries; // Sorted array of index entries + DWORD nIndexEntries; // Number of index entries + +} CASC_MAPPING_TABLE, *PCASC_MAPPING_TABLE; + +typedef struct _CASC_FILE_FRAME +{ + DWORD FrameArchiveOffset; // Archive file pointer corresponding to the begin of the frame + DWORD FrameFileOffset; // File pointer corresponding to the begin of the frame + DWORD CompressedSize; // Compressed size of the file + DWORD FrameSize; // Size of the frame + BYTE md5[MD5_HASH_SIZE]; // MD5 hash of the file sector +} CASC_FILE_FRAME, *PCASC_FILE_FRAME; + +typedef struct _CASC_ENCODING_HEADER +{ + BYTE Magic[2]; // "EN" + BYTE field_2; + BYTE field_3; + BYTE field_4; + BYTE field_5[2]; + BYTE field_7[2]; + BYTE NumSegments[4]; // Number of entries (big endian) + BYTE field_D[4]; + BYTE field_11; + BYTE SegmentsPos[4]; // Offset of encoding segments + +} CASC_ENCODING_HEADER, *PCASC_ENCODING_HEADER; + +typedef struct _CASC_ENCODING_ENTRY +{ + USHORT KeyCount; // Number of subitems + BYTE FileSizeBytes[4]; // File size as bytes (big-endian) + BYTE EncodingKey[MD5_HASH_SIZE]; // File encoding key + + // Followed by the index keys + // (number of items = KeyCount) + // Followed by the index keys (number of items = KeyCount) +} CASC_ENCODING_ENTRY, *PCASC_ENCODING_ENTRY; + +typedef struct _CASC_ROOT_LOCALE_BLOCK +{ + DWORD NumberOfFiles; // Number of entries + DWORD Flags; + DWORD FileLocales; // File locales (CASC_LOCALE_XXX) + + // Followed by a block of 32-bit integers (count: NumberOfFiles) + // Followed by the MD5 and file name hash (count: NumberOfFiles) + +} CASC_ROOT_LOCALE_BLOCK, *PCASC_ROOT_LOCALE_BLOCK; + +typedef struct _CASC_ROOT_ENTRY +{ + BYTE EncodingKey[MD5_HASH_SIZE]; // File encoding key (MD5) + ULONGLONG FileNameHash; // Jenkins hash of the file name + DWORD Locales; // File locales (see CASC_LOCALE_XXX) + DWORD Flags; // File flags + +} CASC_ROOT_ENTRY, *PCASC_ROOT_ENTRY; + +typedef struct _CASC_ROOT_KEY_INFO +{ + BYTE EncodingKey[MD5_HASH_SIZE]; // Encoding key for the file, obtained from root info + ULONGLONG FileSize; // Size of the file, in bytes + BYTE Flags; // File flags +} CASC_ROOT_KEY_INFO, *PCASC_ROOT_KEY_INFO; + +typedef struct _CASC_MNDX_ENTRY +{ + DWORD Flags; // High 8 bits: Flags, low 24 bits: package index + BYTE EncodingKey[MD5_HASH_SIZE]; // Encoding key for the file + DWORD FileSize; // Size of the file, in bytes + +} CASC_MNDX_ENTRY, *PCASC_MNDX_ENTRY; + +typedef struct _CASC_MNDX_INFO +{ + bool bRootFileLoaded; // true if the root info file was properly loaded + BYTE RootFileName[MD5_HASH_SIZE]; // Name (aka MD5) of the root file + DWORD HeaderVersion; // Must be <= 2 + DWORD FormatVersion; + DWORD field_1C; + DWORD field_20; + DWORD MarInfoOffset; // Offset of the first MAR entry info + DWORD MarInfoCount; // Number of the MAR info entries + DWORD MarInfoSize; // Size of the MAR info entry + DWORD MndxEntriesOffset; + DWORD MndxEntriesTotal; // Total number of MNDX root entries + DWORD MndxEntriesValid; // Number of valid MNDX root entries + DWORD MndxEntrySize; // Size of one MNDX root entry + struct _MAR_FILE * pMarFile1; // File name list for the packages + struct _MAR_FILE * pMarFile2; // File name list for names stripped of package names + struct _MAR_FILE * pMarFile3; // File name list for complete names + PCASC_MNDX_ENTRY pMndxEntries; + PCASC_MNDX_ENTRY * ppValidEntries; + +} CASC_MNDX_INFO, *PCASC_MNDX_INFO; + +typedef struct _CASC_PACKAGE +{ + char * szFileName; // Pointer to file name + size_t nLength; // Length of the file name + +} CASC_PACKAGE, *PCASC_PACKAGE; + +typedef struct _CASC_PACKAGES +{ + char * szNameBuffer; // Pointer to the buffer for file names + size_t NameEntries; // Number of name entries in Names + size_t NameBufferUsed; // Number of bytes used in the name buffer + size_t NameBufferMax; // Total size of the name buffer + + CASC_PACKAGE Packages[1]; // List of packages + +} CASC_PACKAGES, *PCASC_PACKAGES; + +typedef struct _TCascStorage +{ + const char * szClassName; // "TCascStorage" + const TCHAR * szIndexFormat; // Format of the index file name + TCHAR * szRootPath; // This is the game directory + TCHAR * szDataPath; // This is the directory where data files are + TCHAR * szIndexPath; // This is the directory where index files are + TCHAR * szUrlPath; // URL to the Blizzard servers + DWORD dwRefCount; // Number of references + DWORD dwGameInfo; // Game type + DWORD dwBuildNumber; // Game build number + + QUERY_KEY CdnConfigKey; + QUERY_KEY CdnBuildKey; + + PQUERY_KEY pArchiveArray; // Array of the archives + QUERY_KEY ArchiveGroup; // Name of the group archive file + DWORD ArchiveCount; // Number of archives in the array + + PQUERY_KEY pPatchArchiveArray; // Array of the patch archives + QUERY_KEY PatchArchiveGroup; // Name of the patch group archive file + DWORD PatchArchiveCount; // Number of patch archives in the array + + QUERY_KEY RootKey; + QUERY_KEY PatchKey; + QUERY_KEY DownloadKey; + QUERY_KEY InstallKey; + + PQUERY_KEY pEncodingKeys; + QUERY_KEY EncodingKey; + QUERY_KEY EncodingEKey; + DWORD EncodingKeys; + + TFileStream * DataFileArray[CASC_MAX_DATA_FILES]; // Data file handles + + CASC_MAPPING_TABLE KeyMapping[CASC_INDEX_COUNT]; // Key mapping + PCASC_MAP pIndexEntryMap; // Map of index entries + + PCASC_ENCODING_HEADER pEncodingHeader; // The encoding file + PCASC_ENCODING_ENTRY * ppEncodingEntries; // Map of encoding entries + size_t nEncodingEntries; + + PCASC_ROOT_ENTRY * ppRootEntries; // Sorted array of root entries + PCASC_ROOT_ENTRY pRootEntries; // Linear array of root entries + size_t nRootEntries; // Number of root entries + + PCASC_MNDX_INFO pMndxInfo; // Used for storages which have MNDX/MAR file + PCASC_PACKAGES pPackages; // Linear list of present packages + +} TCascStorage; + +typedef struct _TCascFile +{ + TCascStorage * hs; // Pointer to storage structure + TFileStream * pStream; // An open data stream + const char * szClassName; // "TCascFile" + + DWORD FilePointer; // Current file pointer + + DWORD ArchiveIndex; // Index of the archive (data.###) + DWORD HeaderOffset; // Offset of the BLTE header, relative to the begin of the archive + DWORD FramesOffset; // Offset of the frame data, relative to the begin of the archive + DWORD CompressedSize; // Compressed size of the file (in bytes) + DWORD FileSize; // Size of file, in bytes + + PCASC_FILE_FRAME pFrames; // Array of file frames + DWORD FrameCount; // Number of the file frames + + LPBYTE pbFileCache; // Pointer to file cache + DWORD cbFileCache; // Size of the file cache + DWORD CacheStart; // Starting offset in the cache + DWORD CacheEnd; // Ending offset in the cache + +} TCascFile; + +class TMndxFindResult; + +typedef struct _TCascSearch +{ + TCascStorage * hs; // Pointer to the storage handle + const char * szClassName; + TCHAR * szListFile; + void * pCache; // Listfile cache + TMndxFindResult * pStruct1C; // Search structure for MNDX info + char * szMask; + char szFileName[MAX_PATH]; // Buffer for the file name + char szNormName[MAX_PATH]; // Buffer for normalized file name + ULONGLONG FileNameHash; // Name hash being searched right now + size_t RootIndex; // Root index of the previously found item + DWORD dwState; // Pointer to the state (0 = listfile, 1 = nameless, 2 = done) + BYTE BitArray[1]; // Bit array of already-reported files + +} TCascSearch; + +//----------------------------------------------------------------------------- +// Memory management +// +// We use our own macros for allocating/freeing memory. If you want +// to redefine them, please keep the following rules: +// +// - The memory allocation must return NULL if not enough memory +// (i.e not to throw exception) +// - The allocating function does not need to fill the allocated buffer with zeros +// - The reallocating function must support NULL as the previous block +// - Memory freeing function doesn't have to test the pointer to NULL +// + +#if defined(_MSC_VER) && defined(_DEBUG) +/* +void * DbgRealloc(void * ptr, size_t nSize); + +#define CASC_REALLOC(type, ptr, count) (type *)DbgRealloc(ptr, ((count) * sizeof(type))) +#define CASC_ALLOC(type, count) (type *)HeapAlloc(GetProcessHeap(), 0, ((count) * sizeof(type))) +#define CASC_FREE(ptr) HeapFree(GetProcessHeap(), 0, ptr) +*/ + +#define CASC_REALLOC(type, ptr, count) (type *)realloc(ptr, (count) * sizeof(type)) +#define CASC_ALLOC(type, count) (type *)malloc((count) * sizeof(type)) +#define CASC_FREE(ptr) free(ptr) + +#else + +#define CASC_REALLOC(type, ptr, count) (type *)realloc(ptr, (count) * sizeof(type)) +#define CASC_ALLOC(type, count) (type *)malloc((count) * sizeof(type)) +#define CASC_FREE(ptr) free(ptr) + +#endif + +//----------------------------------------------------------------------------- +// Big endian number manipulation + +DWORD ConvertBytesToInteger_3(LPBYTE ValueAsBytes); +DWORD ConvertBytesToInteger_4(LPBYTE ValueAsBytes); +DWORD ConvertBytesToInteger_4_LE(LPBYTE ValueAsBytes); +ULONGLONG ConvertBytesToInteger_5(LPBYTE ValueAsBytes); + +//----------------------------------------------------------------------------- +// Build configuration reading + +int LoadBuildConfiguration(TCascStorage * hs); + +//----------------------------------------------------------------------------- +// Internal file functions + +TCascStorage * IsValidStorageHandle(HANDLE hStorage); +TCascFile * IsValidFileHandle(HANDLE hFile); + +PCASC_ROOT_ENTRY FindFirstRootEntry(TCascStorage * hs, const char * szFileName, size_t * PtrIndex); +PCASC_ENCODING_ENTRY FindEncodingEntry(TCascStorage * hs, PQUERY_KEY pEncodingKey, size_t * PtrIndex); +PCASC_INDEX_ENTRY FindIndexEntry(TCascStorage * hs, PQUERY_KEY pIndexKey); + +int CascDecompress(void * pvOutBuffer, PDWORD pcbOutBuffer, void * pvInBuffer, DWORD cbInBuffer); + +//----------------------------------------------------------------------------- +// Dump data + +#ifdef _DEBUG +void CascDumpSparseArray(const char * szFileName, void * pvSparseArray); +void CascDumpNameFragTable(const char * szFileName, void * pvMarFile); +void CascDumpFileNames(const char * szFileName, void * pvMarFile); +void CascDumpMndxRoot(const char * szFileName, PCASC_MNDX_INFO pMndxInfo); +void CascDumpIndexEntries(const char * szFileName, TCascStorage * hs); +void CascDumpStorage(const char * szFileName, TCascStorage * hs, const TCHAR * szListFile); +void CascDumpFile(const char * szFileName, HANDLE hFile); +#else // _DEBUG +#define CascDumpSparseArray(n,a) /* */ +#define CascDumpNameFragTable(n, m) /* */ +#define CascDumpFileNames(n, m) /* */ +#define CascDumpMndxRoot(n,i) /* */ +#define CascDumpIndexEntries(n,h) /* */ +#define CascDumpStorage(n,h) /* */ +#define CascDumpFile(n,h) /* */ +#endif // _DEBUG + +#endif // __CASCCOMMON_H__ |