aboutsummaryrefslogtreecommitdiff
path: root/dep/CascLib/src/CascCommon.h
diff options
context:
space:
mode:
Diffstat (limited to 'dep/CascLib/src/CascCommon.h')
-rw-r--r--dep/CascLib/src/CascCommon.h251
1 files changed, 96 insertions, 155 deletions
diff --git a/dep/CascLib/src/CascCommon.h b/dep/CascLib/src/CascCommon.h
index 7a2b4071dc6..42e158bfcb2 100644
--- a/dep/CascLib/src/CascCommon.h
+++ b/dep/CascLib/src/CascCommon.h
@@ -23,9 +23,13 @@
#include "CascPort.h"
#include "common/Common.h"
+#include "common/DynamicArray.h"
#include "common/Map.h"
#include "common/FileStream.h"
+#include "common/Directory.h"
#include "common/ListFile.h"
+#include "common/DumpContext.h"
+#include "common/RootHandler.h"
// Headers from LibTomCrypt
#include "libtomcrypt/src/headers/tomcrypt.h"
@@ -36,16 +40,17 @@
//-----------------------------------------------------------------------------
// 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_DIABLO3 0x00030000 // Diablo 3 Since PTR 2.2.0
-#define CASC_GAME_MASK 0xFFFF0000 // Mask for getting game ID
+#define CASC_GAME_HOTS 0x00010000 // Heroes of the Storm
+#define CASC_GAME_WOW6 0x00020000 // World of Warcraft - Warlords of Draenor
+#define CASC_GAME_DIABLO3 0x00030000 // Diablo 3 since PTR 2.2.0
+#define CASC_GAME_OVERWATCH 0x00040000 // Overwatch since PTR 24919
+#define CASC_GAME_STARCRAFT2 0x00050000 // Starcraft II - Legacy of the Void, since build 38996
+#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_EXTRA_FILES 0x20 // Number of extra entries to be reserved for additionally inserted files
#define CASC_SEARCH_HAVE_NAME 0x0001 // Indicated that previous search found a name
@@ -71,41 +76,28 @@
#define CASC_PACKAGE_BUFFER 0x1000
-//-----------------------------------------------------------------------------
-// On-disk structures
-
-typedef struct _FILE_LOCALE_BLOCK
-{
- DWORD NumberOfFiles; // Number of entries
- DWORD Flags;
- DWORD Locales; // File locale mask (CASC_LOCALE_XXX)
+#ifndef _maxchars
+#define _maxchars(buff) ((sizeof(buff) / sizeof(buff[0])) - 1)
+#endif
- // Followed by a block of 32-bit integers (count: NumberOfFiles)
- // Followed by the MD5 and file name hash (count: NumberOfFiles)
+//-----------------------------------------------------------------------------
+// In-memory structures
+// See http://pxr.dk/wowdev/wiki/index.php?title=CASC for more information
-} FILE_LOCALE_BLOCK, *PFILE_LOCALE_BLOCK;
+struct TFileStream;
-typedef struct _FILE_ROOT_ENTRY
+typedef enum _CBLD_TYPE
{
- DWORD EncodingKey[4]; // MD5 of the file
- ULONGLONG FileNameHash; // Jenkins hash of the file name
-
-} FILE_ROOT_ENTRY, *PFILE_ROOT_ENTRY;
+ CascBuildNone = 0, // No build type found
+ CascBuildInfo, // .build.info
+ CascBuildDb, // .build.db (older storages)
+} CBLD_TYPE, *PCBLD_TYPE;
-typedef struct _ROOT_BLOCK_INFO
+typedef struct _ENCODING_KEY
{
- PFILE_LOCALE_BLOCK pLocaleBlockHdr; // Pointer to the locale block
- PDWORD pInt32Array; // Pointer to the array of 32-bit integers
- PFILE_ROOT_ENTRY pRootEntries;
-
-} ROOT_BLOCK_INFO, *PROOT_BLOCK_INFO;
-
-//-----------------------------------------------------------------------------
-// In-memory structures
+ BYTE Value[MD5_HASH_SIZE]; // MD5 of the file
-class TMndxFindResult;
-struct TFileStream;
-struct _MAR_FILE;
+} ENCODING_KEY, *PENCODING_KEY;
typedef struct _CASC_INDEX_ENTRY
{
@@ -140,25 +132,34 @@ typedef struct _CASC_FILE_FRAME
BYTE md5[MD5_HASH_SIZE]; // MD5 hash of the file sector
} CASC_FILE_FRAME, *PCASC_FILE_FRAME;
+// The encoding file is in the form of:
+// * File header
+// * String block #1
+// * Table A header
+// * Table A entries
+// * Table B header
+// * Table B entries
+// * String block #2
+// http://pxr.dk/wowdev/wiki/index.php?title=CASC#Key_CASC_Files
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 Version; // Expected to be 1 by CascLib
+ BYTE ChecksumSizeA; // The length of the checksums in Encoding Table
+ BYTE ChecksumSizeB; // The length of the checksums in Encoding Layout Table
+ BYTE Flags_TableA[2]; // Flags for Encoding Table
+ BYTE Flags_TableB[2]; // Flags for Encoding Layout Table
+ BYTE Entries_TableA[4]; // Number of segments in Encoding Table (big endian)
+ BYTE Entries_TableB[4]; // Number of segments in Encoding Layout Table (big endian)
BYTE field_11;
- BYTE SegmentsPos[4]; // Offset of encoding segments
+ BYTE Size_StringTable1[4]; // Size of the string block #1
} CASC_ENCODING_HEADER, *PCASC_ENCODING_HEADER;
typedef struct _CASC_ENCODING_ENTRY
{
- USHORT KeyCount; // Number of subitems
- BYTE FileSizeBE[4]; // Compressed file size (header area + frame headers + compressed frames), in bytes
+ USHORT KeyCount; // Number of index keys
+ BYTE FileSizeBE[4]; // Compressed file size (header area + frame headers + compressed frames), in bytes
BYTE EncodingKey[MD5_HASH_SIZE]; // File encoding key
// Followed by the index keys
@@ -166,87 +167,21 @@ typedef struct _CASC_ENCODING_ENTRY
// 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;
-
-// Root file entry for CASC storages with MNDX root file (Heroes of the Storm)
-// Corresponds to the in-file structure
-typedef struct _CASC_ROOT_ENTRY_MNDX
+// A version of CASC_ENCODING_ENTRY with one index key
+typedef struct _CASC_ENCODING_ENTRY_1
{
- DWORD Flags; // High 8 bits: Flags, low 24 bits: package index
- BYTE EncodingKey[MD5_HASH_SIZE]; // Encoding key for the file
- DWORD FileSize; // Uncompressed file size, in bytes
-
-} CASC_ROOT_ENTRY_MNDX, *PCASC_ROOT_ENTRY_MNDX;
-
-// Root file entry for CASC storages without MNDX root file (World of Warcraft 6.0+)
-// Does not match to the in-file structure of the root entry
-typedef struct _CASC_ROOT_ENTRY
-{
- ULONGLONG FileNameHash; // Jenkins hash of the file name
- DWORD SumValue; // Sum value
- DWORD Locales; // Locale flags of the file
- DWORD EncodingKey[4]; // File encoding key (MD5)
-
-} CASC_ROOT_ENTRY, *PCASC_ROOT_ENTRY;
-
-// Definition of the hash table for CASC root items
-typedef struct _CASC_ROOT_HASH_TABLE
-{
- PCASC_ROOT_ENTRY TablePtr; // Pointer to the CASC root table
- DWORD TableSize; // Total size of the root table
- DWORD ItemCount; // Number of items currently in the table
-
-} CASC_ROOT_HASH_TABLE, *PCASC_ROOT_HASH_TABLE;
-
-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_ROOT_ENTRY_MNDX pMndxEntries;
- PCASC_ROOT_ENTRY_MNDX * 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;
+ USHORT KeyCount; // Number of index keys
+ BYTE FileSizeBE[4]; // Compressed file size (header area + frame headers + compressed frames), in bytes
+ BYTE EncodingKey[MD5_HASH_SIZE]; // File encoding key
+ BYTE IndexKey[MD5_HASH_SIZE]; // File index key
-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_ENCODING_ENTRY_1, *PCASC_ENCODING_ENTRY_1;
- CASC_PACKAGE Packages[1]; // List of packages
+#define GET_INDEX_KEY(pEncodingEntry) (pEncodingEntry->EncodingKey + MD5_HASH_SIZE)
+#define FAKE_ENCODING_ENTRY_SIZE (sizeof(CASC_ENCODING_ENTRY) + MD5_HASH_SIZE)
-} CASC_PACKAGES, *PCASC_PACKAGES;
+//-----------------------------------------------------------------------------
+// Structures for CASC storage and CASC file
typedef struct _TCascStorage
{
@@ -254,6 +189,7 @@ typedef struct _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 * szBuildFile; // Build file name (.build.info or .build.db)
TCHAR * szIndexPath; // This is the directory where index files are
TCHAR * szUrlPath; // URL to the Blizzard servers
DWORD dwRefCount; // Number of references
@@ -262,40 +198,29 @@ typedef struct _TCascStorage
DWORD dwFileBeginDelta; // This is number of bytes to shift back from archive offset (from index entry) to actual begin of file data
DWORD dwDefaultLocale; // Default locale, read from ".build.info"
+ CBLD_TYPE BuildFileType; // Type of the build file
+
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 ArchivesGroup; // Key array of the "archive-group"
+ QUERY_KEY ArchivesKey; // Key array of the "archives"
+ QUERY_KEY PatchArchivesKey; // Key array of the "patch-archives"
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;
+ QUERY_KEY EncodingFile; // Content of the ENCODING file
+ PCASC_MAP pEncodingMap; // Map of encoding entries
+ DYNAMIC_ARRAY ExtraEntries; // Extra encoding entries
- CASC_ROOT_HASH_TABLE RootTable; // Hash table for the root entries
-
- PCASC_MNDX_INFO pMndxInfo; // Used for storages which have MNDX/MAR file
- PCASC_PACKAGES pPackages; // Linear list of present packages
+ TRootHandler * pRootHandler; // Common handler for various ROOT file formats
} TCascStorage;
@@ -336,16 +261,19 @@ typedef struct _TCascFile
typedef struct _TCascSearch
{
TCascStorage * hs; // Pointer to the storage handle
- const char * szClassName;
- TCHAR * szListFile;
+ const char * szClassName; // Contains "TCascSearch"
+ TCHAR * szListFile; // Name of the listfile
void * pCache; // Listfile cache
- TMndxFindResult * pStruct1C; // Search structure for MNDX info
- char * szMask;
+ char * szMask; // Search mask
char szFileName[MAX_PATH]; // Buffer for the file name
- char szNormName[MAX_PATH]; // Buffer for normalized file name
- DWORD 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
+
+ // Provider-specific data
+ void * pRootContext; // Root-specific search context
+ size_t IndexLevel1; // Root-specific search context
+ size_t IndexLevel2; // Root-specific search context
+ DWORD dwState; // Pointer to the search state (0 = listfile, 1 = nameless, 2 = done)
+
+ BYTE BitArray[1]; // Bit array of encoding keys. Set for each entry that has already been reported
} TCascSearch;
@@ -384,10 +312,15 @@ DWORD ConvertBytesToInteger_4(LPBYTE ValueAsBytes);
DWORD ConvertBytesToInteger_4_LE(LPBYTE ValueAsBytes);
ULONGLONG ConvertBytesToInteger_5(LPBYTE ValueAsBytes);
+void ConvertIntegerToBytes_4(DWORD Value, LPBYTE ValueAsBytes);
+void FreeCascBlob(PQUERY_KEY pQueryKey);
+
//-----------------------------------------------------------------------------
-// Build configuration reading
+// Text file parsing (CascFiles.cpp)
int LoadBuildInfo(TCascStorage * hs);
+int CheckGameDirectory(TCascStorage * hs, TCHAR * szDirectory);
+int ParseRootFileLine(const char * szLinePtr, const char * szLineEnd, PQUERY_KEY pEncodingKey, char * szFileName, size_t nMaxChars);
//-----------------------------------------------------------------------------
// Internal file functions
@@ -395,11 +328,20 @@ int LoadBuildInfo(TCascStorage * hs);
TCascStorage * IsValidStorageHandle(HANDLE hStorage);
TCascFile * IsValidFileHandle(HANDLE hFile);
-PCASC_ROOT_ENTRY FindRootEntry(TCascStorage * hs, const char * szFileName, DWORD * PtrTableIndex);
-PCASC_ENCODING_ENTRY FindEncodingEntry(TCascStorage * hs, PQUERY_KEY pEncodingKey, size_t * PtrIndex);
+PCASC_ENCODING_ENTRY FindEncodingEntry(TCascStorage * hs, PQUERY_KEY pEncodingKey, PDWORD PtrIndex);
PCASC_INDEX_ENTRY FindIndexEntry(TCascStorage * hs, PQUERY_KEY pIndexKey);
-int CascDecompress(void * pvOutBuffer, PDWORD pcbOutBuffer, void * pvInBuffer, DWORD cbInBuffer);
+int CascDecompress(LPBYTE pvOutBuffer, PDWORD pcbOutBuffer, LPBYTE pvInBuffer, DWORD cbInBuffer);
+int CascDecrypt (LPBYTE pbOutBuffer, PDWORD pcbOutBuffer, LPBYTE pbInBuffer, DWORD cbInBuffer, DWORD dwFrameIndex);
+int CascDirectCopy(LPBYTE pbOutBuffer, PDWORD pcbOutBuffer, LPBYTE pbInBuffer, DWORD cbInBuffer);
+
+//-----------------------------------------------------------------------------
+// Support for ROOT file
+
+int RootHandler_CreateMNDX(TCascStorage * hs, LPBYTE pbRootFile, DWORD cbRootFile);
+int RootHandler_CreateDiablo3(TCascStorage * hs, LPBYTE pbRootFile, DWORD cbRootFile);
+int RootHandler_CreateOverwatch(TCascStorage * hs, LPBYTE pbRootFile, DWORD cbRootFile);
+int RootHandler_CreateWoW6(TCascStorage * hs, LPBYTE pbRootFile, DWORD cbRootFile, DWORD dwLocaleMask);
//-----------------------------------------------------------------------------
// Dumping CASC data structures
@@ -409,8 +351,7 @@ void CascDumpSparseArray(const char * szFileName, void * pvSparseArray);
void CascDumpNameFragTable(const char * szFileName, void * pvMarFile);
void CascDumpFileNames(const char * szFileName, void * pvMarFile);
void CascDumpIndexEntries(const char * szFileName, TCascStorage * hs);
-void CascDumpMndxRoot(const char * szFileName, PCASC_MNDX_INFO pMndxInfo);
-void CascDumpRootFile(TCascStorage * hs, LPBYTE pbRootFile, DWORD cbRootFile, const char * szFormat, const TCHAR * szListFile, int nDumpLevel);
+void CascDumpEncodingEntry(TCascStorage * hs, TDumpContext * dc, PCASC_ENCODING_ENTRY pEncodingEntry, int nDumpLevel);
void CascDumpFile(const char * szFileName, HANDLE hFile);
#endif // _DEBUG