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.h141
1 files changed, 91 insertions, 50 deletions
diff --git a/dep/CascLib/src/CascCommon.h b/dep/CascLib/src/CascCommon.h
index b2f6a156e39..51b6689ec16 100644
--- a/dep/CascLib/src/CascCommon.h
+++ b/dep/CascLib/src/CascCommon.h
@@ -23,9 +23,9 @@
#include "CascPort.h"
#include "common/Common.h"
+#include "common/Map.h"
#include "common/FileStream.h"
#include "common/ListFile.h"
-#include "common/Map.h"
// Headers from LibTomCrypt
#include "libtomcrypt/src/headers/tomcrypt.h"
@@ -48,6 +48,20 @@
#define CASC_SEARCH_HAVE_NAME 0x0001 // Indicated that previous search found a name
+#define BLTE_HEADER_SIGNATURE 0x45544C42 // 'BLTE' header in the data files
+#define BLTE_HEADER_DELTA 0x1E // Distance of BLTE header from begin of the header area
+#define MAX_HEADER_AREA_SIZE 0x2A // Length of the file header area
+
+// File header area in the data.xxx:
+// BYTE HeaderHash[MD5_HASH_SIZE]; // MD5 of the frame array
+// DWORD dwFileSize; // Size of the file (see comment before CascGetFileSize for details)
+// BYTE SomeSize[4]; // Some size (big endian)
+// BYTE Padding[6]; // Padding (?)
+// DWORD dwSignature; // Must be "BLTE"
+// BYTE HeaderSizeAsBytes[4]; // Header size in bytes (big endian)
+// BYTE MustBe0F; // Must be 0x0F. Optional, only if HeaderSizeAsBytes != 0
+// BYTE FrameCount[3]; // Frame count (big endian). Optional, only if HeaderSizeAsBytes != 0
+
// 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)
@@ -57,16 +71,46 @@
#define CASC_PACKAGE_BUFFER 0x1000
//-----------------------------------------------------------------------------
-// Structures
+// On-disk structures
+
+typedef struct _FILE_LOCALE_BLOCK
+{
+ DWORD NumberOfFiles; // Number of entries
+ DWORD Flags;
+ DWORD Locales; // File locale mask (CASC_LOCALE_XXX)
+
+ // Followed by a block of 32-bit integers (count: NumberOfFiles)
+ // Followed by the MD5 and file name hash (count: NumberOfFiles)
+
+} FILE_LOCALE_BLOCK, *PFILE_LOCALE_BLOCK;
+
+typedef struct _FILE_ROOT_ENTRY
+{
+ DWORD EncodingKey[4]; // MD5 of the file
+ ULONGLONG FileNameHash; // Jenkins hash of the file name
+
+} FILE_ROOT_ENTRY, *PFILE_ROOT_ENTRY;
+
+typedef struct _ROOT_BLOCK_INFO
+{
+ 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
+class TMndxFindResult;
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];
+ BYTE FileOffsetBE[5]; // Index of data file and offset within (big endian).
+ BYTE FileSizeLE[4]; // Size occupied in the storage file (data.###). See comment before CascGetFileSize for details
} CASC_INDEX_ENTRY, *PCASC_INDEX_ENTRY;
typedef struct _CASC_MAPPING_TABLE
@@ -113,7 +157,7 @@ typedef struct _CASC_ENCODING_HEADER
typedef struct _CASC_ENCODING_ENTRY
{
USHORT KeyCount; // Number of subitems
- BYTE FileSizeBytes[4]; // File size as bytes (big-endian)
+ 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
@@ -132,29 +176,35 @@ typedef struct _CASC_ROOT_LOCALE_BLOCK
} 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
+{
+ 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
{
- 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
+ DWORD SumValue; // Sum value
+ DWORD Locales; // Locale flags of the file
+ DWORD EncodingKey[4]; // File encoding key (MD5)
} CASC_ROOT_ENTRY, *PCASC_ROOT_ENTRY;
-typedef struct _CASC_ROOT_KEY_INFO
+// Definition of the hash table for CASC root items
+typedef struct _CASC_ROOT_HASH_TABLE
{
- 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;
+ 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
-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;
+} CASC_ROOT_HASH_TABLE, *PCASC_ROOT_HASH_TABLE;
typedef struct _CASC_MNDX_INFO
{
@@ -174,8 +224,8 @@ typedef struct _CASC_MNDX_INFO
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;
+ PCASC_ROOT_ENTRY_MNDX pMndxEntries;
+ PCASC_ROOT_ENTRY_MNDX * ppValidEntries;
} CASC_MNDX_INFO, *PCASC_MNDX_INFO;
@@ -208,6 +258,7 @@ typedef struct _TCascStorage
DWORD dwRefCount; // Number of references
DWORD dwGameInfo; // Game type
DWORD dwBuildNumber; // Game build number
+ DWORD dwFileBeginDelta; // This is number of bytes to shift back from archive offset (from index entry) to actual begin of file data
QUERY_KEY CdnConfigKey;
QUERY_KEY CdnBuildKey;
@@ -239,9 +290,7 @@ typedef struct _TCascStorage
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
+ 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
@@ -258,9 +307,11 @@ typedef struct _TCascFile
DWORD ArchiveIndex; // Index of the archive (data.###)
DWORD HeaderOffset; // Offset of the BLTE header, relative to the begin of the archive
+ DWORD HeaderSize; // Length of the BLTE header
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
+ BYTE FrameArrayHash[MD5_HASH_SIZE]; // MD5 hash of the frame array
PCASC_FILE_FRAME pFrames; // Array of file frames
DWORD FrameCount; // Number of the file frames
@@ -270,9 +321,15 @@ typedef struct _TCascFile
DWORD CacheStart; // Starting offset in the cache
DWORD CacheEnd; // Ending offset in the cache
-} TCascFile;
+#ifdef CASCLIB_TEST // Extra fields for analyzing the file size problem
+ DWORD FileSize_RootEntry; // File size, from the root entry
+ DWORD FileSize_EncEntry; // File size, from the encoding entry
+ DWORD FileSize_IdxEntry; // File size, from the index entry
+ DWORD FileSize_HdrArea; // File size, as stated in the file header area
+ DWORD FileSize_FrameSum; // File size as sum of frame sizes
+#endif
-class TMndxFindResult;
+} TCascFile;
typedef struct _TCascSearch
{
@@ -284,8 +341,7 @@ typedef struct _TCascSearch
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 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
@@ -305,17 +361,10 @@ typedef struct _TCascSearch
//
#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_REALLOC(type, ptr, count) (type *)HeapReAlloc(GetProcessHeap(), 0, 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
@@ -336,7 +385,7 @@ ULONGLONG ConvertBytesToInteger_5(LPBYTE ValueAsBytes);
//-----------------------------------------------------------------------------
// Build configuration reading
-int LoadBuildConfiguration(TCascStorage * hs);
+int LoadBuildInfo(TCascStorage * hs);
//-----------------------------------------------------------------------------
// Internal file functions
@@ -344,31 +393,23 @@ int LoadBuildConfiguration(TCascStorage * hs);
TCascStorage * IsValidStorageHandle(HANDLE hStorage);
TCascFile * IsValidFileHandle(HANDLE hFile);
-PCASC_ROOT_ENTRY FindFirstRootEntry(TCascStorage * hs, const char * szFileName, size_t * PtrIndex);
+PCASC_ROOT_ENTRY FindRootEntry(TCascStorage * hs, const char * szFileName, DWORD * PtrTableIndex);
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
+// Dumping CASC data structures
#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 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 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__