aboutsummaryrefslogtreecommitdiff
path: root/dep/CascLib/src/CascCommon.h
diff options
context:
space:
mode:
authorShauren <shauren.trinity@gmail.com>2019-06-06 16:48:21 +0200
committerShauren <shauren.trinity@gmail.com>2019-06-08 17:09:24 +0200
commitfc330fd8ff0115804d9c4b53a1f810c00dd63de9 (patch)
treecfa10998fed66779834bf0b7a9b8b799d33d91d4 /dep/CascLib/src/CascCommon.h
parent82c7b6c5688495d90c4ee5995a4ff74039348296 (diff)
Dep/CascLib: Update to ladislav-zezula/CascLib@a1197edf0b3bd4d52c3f39be7fa7b44bb0b98012
Diffstat (limited to 'dep/CascLib/src/CascCommon.h')
-rw-r--r--dep/CascLib/src/CascCommon.h554
1 files changed, 327 insertions, 227 deletions
diff --git a/dep/CascLib/src/CascCommon.h b/dep/CascLib/src/CascCommon.h
index e38094171b8..3ce527061c2 100644
--- a/dep/CascLib/src/CascCommon.h
+++ b/dep/CascLib/src/CascCommon.h
@@ -23,341 +23,441 @@
#include "CascPort.h"
#include "common/Common.h"
-#include "common/DynamicArray.h"
+#include "common/Array.h"
#include "common/Map.h"
+#include "common/FileTree.h"
#include "common/FileStream.h"
#include "common/Directory.h"
#include "common/ListFile.h"
-#include "common/DumpContext.h"
+#include "common/Csv.h"
#include "common/RootHandler.h"
-// Headers from LibTomCrypt
-#include "libtomcrypt/src/headers/tomcrypt.h"
+// Headers from Alexander Peslyak's MD5 implementation
+#include "md5/md5.h"
// For HashStringJenkins
#include "jenkins/lookup.h"
+// On-disk CASC structures
+#include "CascStructs.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_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_STARCRAFT1 0x00060000 // Starcraft 1 (remastered)
-#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_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
-
-#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.nnn:
-// 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)
-#define CASCLIB_MAX(a, b) ((a > b) ? a : b)
-#define CASCLIB_UNUSED(p) ((void)(p))
-
-#define CASC_PACKAGE_BUFFER 0x1000
-
-#ifndef _maxchars
-#define _maxchars(buff) ((sizeof(buff) / sizeof(buff[0])) - 1)
+#ifdef _DEBUG
+#define BREAK_ON_XKEY3(CKey, v0, v1, v2) if(CKey[0] == v0 && CKey[1] == v1 && CKey[2] == v2) { __debugbreak(); }
+#define BREAKIF(condition) if(condition) { __debugbreak(); }
+#else
+#define BREAK_ON_XKEY3(CKey, v0, v1, v2) { /* NOTHING */ }
+#define BREAKIF(condition) { /* NOTHING */ }
#endif
//-----------------------------------------------------------------------------
// In-memory structures
-// See http://pxr.dk/wowdev/wiki/index.php?title=CASC for more information
-
-struct TFileStream;
typedef enum _CBLD_TYPE
{
CascBuildNone = 0, // No build type found
CascBuildInfo, // .build.info
CascBuildDb, // .build.db (older storages)
+ CascVersionsDb // versions (downloaded online)
} CBLD_TYPE, *PCBLD_TYPE;
-typedef struct _ENCODING_KEY
+// Tag file entry, loaded from the DOWNLOAD file
+typedef struct _CASC_TAG_ENTRY
{
- BYTE Value[MD5_HASH_SIZE]; // MD5 of the file
+ USHORT HashType; // Hash type
+ char TagName[1]; // Tag name. Variable length.
+} CASC_TAG_ENTRY, *PCASC_TAG_ENTRY;
-} ENCODING_KEY, *PENCODING_KEY;
-
-typedef struct _CASC_INDEX_ENTRY
+// Normalized header of the index files.
+// Both version 1 and version 2 are converted to this structure
+typedef struct _CASC_INDEX_HEADER
{
- BYTE IndexKey[CASC_FILE_KEY_SIZE]; // The first 9 bytes of the encoding key
- 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
+ USHORT IndexVersion; // 5 for index v 1.0, 7 for index version 2.0
+ BYTE BucketIndex; // Should be the same as the first byte of the hex filename.
+ BYTE StorageOffsetLength; // Length, in bytes, of the StorageOffset field in the EKey entry
+ BYTE EncodedSizeLength; // Length, in bytes, of the EncodedSize in the EKey entry
+ BYTE EKeyLength; // Length, in bytes, of the (trimmed) EKey in the EKey entry
+ BYTE FileOffsetBits; // Number of bits of the archive file offset in StorageOffset field. Rest is data segment index
+ BYTE Alignment;
+ ULONGLONG SegmentSize; // Size of one data segment (aka data.### file)
+ size_t HeaderLength; // Length of the on-disk header structure, in bytes
+ size_t HeaderPadding; // Length of padding after the header
+ size_t EntryLength; // Length of the on-disk EKey entry structure, in bytes
+ size_t EKeyCount; // Number of EKey entries. Only supplied for index files version 1.
+
+} CASC_INDEX_HEADER, *PCASC_INDEX_HEADER;
+
+// Normalized footer of the archive index files (md5.index)
+typedef struct _CASC_ARCINDEX_FOOTER
{
- 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
+ BYTE TocHash[MD5_HASH_SIZE]; // Hash of the structure
+ BYTE FooterHash[MD5_HASH_SIZE]; // MD5 hash of the footer, possibly shortened
+ BYTE Version; // Version of the index footer
+ BYTE OffsetBytes; // Length, in bytes, of the file offset field
+ BYTE SizeBytes; // Length, in bytes, of the file size field
+ BYTE EKeyBytes; // Length, in bytes, of the EKey field
+ BYTE FooterHashBytes; // Length, in bytes, of the hash and checksum
+ BYTE Alignment[3];
+ size_t ElementCount; // total number of elements in the index file
+ size_t PageLength; // Length, in bytes, of the index page
+ size_t ItemLength; // Length, in bytes, of the single item
+ size_t FooterLength; // Length, in bytes, of the index footer structure
+
+} CASC_ARCINDEX_FOOTER, *PCASC_ARCINDEX_FOOTER;
+
+// Normalized structure for archive index entry
+typedef struct _CASC_ARCINDEX_ENTRY
{
- 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;
+ BYTE IndexHash[MD5_HASH_SIZE];
+ BYTE EKey[MD5_HASH_SIZE];
+ DWORD ArchiveOffset;
+ DWORD EncodedSize;
+} CASC_ARCINDEX_ENTRY, *PCASC_ARCINDEX_ENTRY;
-// 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
+// Normalized header of the ENCODING file
typedef struct _CASC_ENCODING_HEADER
{
- BYTE Magic[2]; // "EN"
- 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 Size_StringTable1[4]; // Size of the string block #1
-
+ USHORT Magic; // FILE_MAGIC_ENCODING ('EN')
+ USHORT Version; // Expected to be 1 by CascLib
+ BYTE CKeyLength; // The content key length in ENCODING file. Usually 0x10
+ BYTE EKeyLength; // The encoded key length in ENCODING file. Usually 0x10
+ DWORD CKeyPageSize; // Size of the CKey page in bytes
+ DWORD EKeyPageSize; // Size of the CKey page in bytes
+ DWORD CKeyPageCount; // Number of CKey pages in the page table
+ DWORD EKeyPageCount; // Number of EKey pages in the page table
+ DWORD ESpecBlockSize; // Size of the ESpec string block, in bytes
} CASC_ENCODING_HEADER, *PCASC_ENCODING_HEADER;
-typedef struct _CASC_ENCODING_ENTRY
+typedef struct _CASC_DOWNLOAD_HEADER
{
- 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
+ USHORT Magic; // FILE_MAGIC_DOWNLOAD ('DL')
+ USHORT Version; // Version
+ USHORT EKeyLength; // Length of the EKey
+ USHORT EntryHasChecksum; // If nonzero, then the entry has checksum
+ DWORD EntryCount;
+ DWORD TagCount;
+ USHORT FlagByteSize;
+ USHORT BasePriority;
- // Followed by the index keys
- // (number of items = KeyCount)
- // Followed by the index keys (number of items = KeyCount)
-} CASC_ENCODING_ENTRY, *PCASC_ENCODING_ENTRY;
+ size_t HeaderLength; // Length of the on-disk header, in bytes
+ size_t EntryLength; // Length of the on-disk entry, in bytes
+
+} CASC_DOWNLOAD_HEADER, *PCASC_DOWNLOAD_HEADER;
+
+typedef struct _CASC_DOWNLOAD_ENTRY
+{
+ BYTE EKey[MD5_HASH_SIZE];
+ ULONGLONG EncodedSize;
+ DWORD Checksum;
+ DWORD Flags;
+ BYTE Priority;
+} CASC_DOWNLOAD_ENTRY, *PCASC_DOWNLOAD_ENTRY;
+
+// Capturable tag structure for loading from DOWNLOAD manifest
+typedef struct _CASC_TAG_ENTRY1
+{
+ const char * szTagName; // Tag name
+ LPBYTE Bitmap; // Bitmap
+ size_t BitmapLength; // Length of the bitmap, in bytes
+ size_t NameLength; // Length of the tag name, in bytes, not including '\0'
+ size_t TagLength; // Length of the on-disk tag, in bytes
+ DWORD TagValue; // Tag value
+} CASC_TAG_ENTRY1, *PCASC_TAG_ENTRY1;
+
+// Tag structure for storing in arrays
+typedef struct _CASC_TAG_ENTRY2
+{
+ size_t NameLength; // Length of the on-disk tag, in bytes
+ DWORD TagValue; // Tag value
+ char szTagName[0x08]; // Tag string. This member can be longer than declared. Aligned to 8 bytes.
+} CASC_TAG_ENTRY2, *PCASC_TAG_ENTRY2;
-// A version of CASC_ENCODING_ENTRY with one index key
-typedef struct _CASC_ENCODING_ENTRY_1
+typedef struct _CASC_INSTALL_HEADER
{
- 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
+ USHORT Magic; // FILE_MAGIC_DOWNLOAD ('DL')
+ BYTE Version; // Version
+ BYTE EKeyLength; // Length of the EKey
+ DWORD EntryCount;
+ DWORD TagCount;
-} CASC_ENCODING_ENTRY_1, *PCASC_ENCODING_ENTRY_1;
+ size_t HeaderLength; // Length of the on-disk header, in bytes
+} CASC_INSTALL_HEADER, *PCASC_INSTALL_HEADER;
-#define GET_INDEX_KEY(pEncodingEntry) (pEncodingEntry->EncodingKey + MD5_HASH_SIZE)
-#define FAKE_ENCODING_ENTRY_SIZE (sizeof(CASC_ENCODING_ENTRY) + MD5_HASH_SIZE)
+typedef struct _CASC_FILE_FRAME
+{
+ CONTENT_KEY FrameHash; // MD5 hash of the file frame
+ DWORD DataFileOffset; // Offset in the data file (data.###)
+ DWORD FileOffset; // File offset of this frame
+ DWORD EncodedSize; // Encoded size of the frame
+ DWORD ContentSize; // Content size of the frame
+} CASC_FILE_FRAME, *PCASC_FILE_FRAME;
//-----------------------------------------------------------------------------
// Structures for CASC storage and CASC file
-typedef struct _TCascStorage
+struct TCascStorage
{
- const char * szClassName; // "TCascStorage"
+ TCascStorage();
+ ~TCascStorage();
+ TCascStorage * AddRef();
+ TCascStorage * Release();
+
+ static TCascStorage * IsValid(HANDLE hStorage);
+
+ PFNPROGRESSCALLBACK PfnCallback; // Callback to be called during CascOpen(Online)Storage
+ void * PtrCallbackParam;
+
const TCHAR * szIndexFormat; // Format of the index file name
- TCHAR * szRootPath; // This is the game directory
+ const char * szClassName; // "TCascStorage"
+ const char * szProductName; // String representation of the product name
+ TCHAR * szRootPath; // Path where the build file is
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
+ TCHAR * szBuildFile; // Build file name (.build.info or .build.db)
+ TCHAR * szCdnServers; // Multi-SZ list of CDN servers
+ TCHAR * szCdnPath; // Remote CDN sub path for the product
+ TCHAR * szCodeName; // Product code name. Only for online storages
+ char * szRegion; // Product region. Only when "versions" is used as storage root file
+ CASC_PRODUCT Product; // Product enum value (see CASC_PRODUCT)
+ DWORD dwBuildNumber; // Product build number
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
DWORD dwDefaultLocale; // Default locale, read from ".build.info"
+ DWORD dwFeatures; // List of CASC features. See CASC_FEATURE_XXX
+ bool bAllowOrphans; // If TRUE, then orphaned items are allowed
CBLD_TYPE BuildFileType; // Type of the build file
- QUERY_KEY CdnConfigKey;
- QUERY_KEY CdnBuildKey;
- QUERY_KEY ArchivesGroup; // Key array of the "archive-group"
+ QUERY_KEY CdnConfigKey; // Currently selected CDN config file. Points to "config\%02X\%02X\%s
+ QUERY_KEY CdnBuildKey; // Currently selected CDN build file. Points to "config\%02X\%02X\%s
+
+ QUERY_KEY ArchiveGroup; // 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 PatchArchivesGroup; // Key array of the "patch-archive-group"
- QUERY_KEY RootKey;
- QUERY_KEY PatchKey;
- QUERY_KEY DownloadKey;
- QUERY_KEY InstallKey;
- QUERY_KEY EncodingKey;
-
- TFileStream * DataFileArray[CASC_MAX_DATA_FILES]; // Data file handles
+ QUERY_KEY BuildFiles; // List of supported build files
- CASC_MAPPING_TABLE KeyMapping[CASC_INDEX_COUNT]; // Key mapping
- PCASC_MAP pIndexEntryMap; // Map of index entries
+ TFileStream * DataFiles[CASC_MAX_DATA_FILES]; // Array of open data files
- QUERY_KEY EncodingFile; // Content of the ENCODING file
- PCASC_MAP pEncodingMap; // Map of encoding entries
- DYNAMIC_ARRAY ExtraEntries; // Extra encoding entries
+ CASC_CKEY_ENTRY EncodingCKey; // Information about ENCODING file
+ CASC_CKEY_ENTRY DownloadCKey; // Information about DOWNLOAD file
+ CASC_CKEY_ENTRY InstallCKey; // Information about INSTALL file
+ CASC_CKEY_ENTRY PatchFile; // Information about PATCH file
+ CASC_CKEY_ENTRY RootFile; // Information about ROOT file
+ CASC_CKEY_ENTRY SizeFile; // Information about SIZE file
+ CASC_CKEY_ENTRY VfsRoot; // The main VFS root file
+ CASC_ARRAY VfsRootList; // List of CASC_EKEY_ENTRY for each TVFS sub-root
TRootHandler * pRootHandler; // Common handler for various ROOT file formats
-
-} TCascStorage;
-
-typedef struct _TCascFile
+ CASC_ARRAY ArcIndexArray; // Array of CASC_ARCINDEX_ENTRY, loaded from archive indexes
+ CASC_ARRAY IndexArray; // Array of CASC_CKEY_ENTRY loaded from local index files
+ CASC_ARRAY CKeyArray; // Array of CASC_CKEY_ENTRY, one entry for each physical file
+ CASC_ARRAY TagsArray; // Array of CASC_DOWNLOAD_TAG2
+ CASC_MAP ArcIndexMap; // Map of EKey -> CASC_ARCINDEX_ENTRY
+ CASC_MAP CKeyMap; // Map of CKey -> CASC_CKEY_ENTRY
+ CASC_MAP EKeyMap; // Map of EKey -> CASC_EKEY_ENTRY
+ size_t LocalFiles; // Number of files that are present locally
+ size_t TotalFiles; // Total number of files in the storage, some may not be present locally
+ size_t EKeyEntries; // Number of CKeyEntry-ies loaded from text build file
+ size_t OrphanItems; // Number of EKey entries in indexes that do not have their counterpart in ENCODING
+ size_t SkippedItems; // Number of EKey entries in indexes that were ignored due to insufficient capacity of CKeyArray
+ size_t EKeyLength; // EKey length from the index files
+ DWORD FileOffsetBits; // Nimber of bits in the storage offset which mean data segent offset
+
+ CASC_ARRAY ExtraKeysList; // List additional encryption keys
+ CASC_MAP EncryptionKeys; // Map of encryption keys
+
+};
+
+struct TCascFile
{
+ TCascFile(TCascStorage * ahs, PCASC_CKEY_ENTRY apCKeyEntry)
+ {
+ ULONGLONG StorageOffset;
+ ULONGLONG FileOffsMask;
+
+ // Reference the storage handle
+ hs = ahs->AddRef();
+ szClassName = "TCascFile";
+
+ // Init class variables
+ pCKeyEntry = apCKeyEntry;
+ pFrames = NULL;
+ pbFileCache = NULL;
+ cbFileCache = 0;
+
+ // Supply the sizes
+ StorageOffset = pCKeyEntry->StorageOffset;
+ FileOffsMask = ((ULONGLONG)1 << hs->FileOffsetBits) - 1;
+ ArchiveIndex = (DWORD)(StorageOffset >> hs->FileOffsetBits);
+ ArchiveOffset = (DWORD)(StorageOffset & FileOffsMask);
+ EncodedSize = pCKeyEntry->EncodedSize;
+ ContentSize = pCKeyEntry->ContentSize;
+ FilePointer = 0;
+ FrameCount = 0;
+ bVerifyIntegrity = false;
+ bDownloadFileIf = false;
+ bLocalFileStream = false;
+ }
+
+ ~TCascFile()
+ {
+ // Close (dereference) the archive handle
+ hs = hs->Release();
+ szClassName = NULL;
+
+ // Free the file cache and frame array
+ CASC_FREE(pbFileCache);
+ CASC_FREE(pFrames);
+
+ // If we are supposed to close the file stream, do it
+ if (pStream && bLocalFileStream)
+ FileStream_Close(pStream);
+ }
+
+ static TCascFile * IsValid(HANDLE hFile)
+ {
+ TCascFile * hf = (TCascFile *)hFile;
+
+ return (hf != INVALID_HANDLE_VALUE &&
+ hf != NULL &&
+ hf->hs != NULL &&
+ hf->szClassName != NULL &&
+ hf->pCKeyEntry != NULL) ? hf : NULL;
+ }
+
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 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_CKEY_ENTRY pCKeyEntry;
PCASC_FILE_FRAME pFrames; // Array of file frames
+ DWORD ArchiveIndex; // Index of the archive (data.###)
+ DWORD ArchiveOffset; // Offset in the archive (data.###)
+ DWORD FilePointer; // Current file pointer
+ DWORD EncodedSize; // Encoded size. This is the size of encoded header, all file frame headers and all file frames
+ DWORD ContentSize; // Content size. This is the size of the file content, aka the file size
DWORD FrameCount; // Number of the file frames
+ DWORD bVerifyIntegrity:1; // If true, then the data are validated more strictly when read
+ DWORD bDownloadFileIf:1; // If true, then the data will be downloaded from the online storage if missing
+ DWORD bLocalFileStream:1; // If true, then the file stream is a local file
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
-
-#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
-} TCascFile;
+};
-typedef struct _TCascSearch
+struct TCascSearch
{
+ TCascSearch(TCascStorage * ahs, LPCTSTR aszListFile, const char * aszMask)
+ {
+ // Init the class
+ szClassName = "TCascSearch";
+ hs = ahs->AddRef();
+
+ // Init provider-specific data
+ pCache = NULL;
+ nFileIndex = 0;
+ nSearchState = 0;
+ bListFileUsed = false;
+
+ // Allocate mask
+ szListFile = CascNewStr(aszListFile);
+ szMask = CascNewStr((aszMask != NULL) ? aszMask : "*");
+ }
+
+ ~TCascSearch()
+ {
+ // Dereference the CASC storage
+ hs = hs->Release();
+ szClassName = NULL;
+
+ // Free the rest of the members
+ CASC_FREE(szMask);
+ CASC_FREE(szListFile);
+ CASC_FREE(pCache);
+ }
+
+ static TCascSearch * IsValid(HANDLE hFind)
+ {
+ TCascSearch * pSearch = (TCascSearch *)hFind;
+
+ return (hFind != INVALID_HANDLE_VALUE &&
+ hFind != NULL &&
+ pSearch->szClassName != NULL &&
+ !strcmp(pSearch->szClassName, "TCascSearch") &&
+ pSearch->szMask != NULL) ? pSearch : NULL;
+ }
+
TCascStorage * hs; // Pointer to the storage handle
const char * szClassName; // Contains "TCascSearch"
TCHAR * szListFile; // Name of the listfile
void * pCache; // Listfile cache
char * szMask; // Search mask
- char szFileName[MAX_PATH]; // Buffer for the file name
// 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;
+ size_t nFileIndex; // Root-specific search context
+ DWORD nSearchState:8; // The current search state (0 = listfile, 1 = nameless, 2 = done)
+ DWORD bListFileUsed:1; // TRUE: The listfile has already been loaded
+};
//-----------------------------------------------------------------------------
-// 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)
-
-#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)
-
-#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)
+// Common functions (CascCommon.cpp)
-#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);
-
-void ConvertIntegerToBytes_4(DWORD Value, LPBYTE ValueAsBytes);
+bool OpenFileByCKeyEntry(TCascStorage * hs, PCASC_CKEY_ENTRY pCKeyEntry, DWORD dwOpenFlags, HANDLE * PtrFileHandle);
+LPBYTE LoadInternalFileToMemory(TCascStorage * hs, PCASC_CKEY_ENTRY pCKeyEntry, DWORD * pcbFileData);
+LPBYTE LoadFileToMemory(const TCHAR * szFileName, DWORD * pcbFileData);
void FreeCascBlob(PQUERY_KEY pQueryKey);
//-----------------------------------------------------------------------------
// Text file parsing (CascFiles.cpp)
-int LoadBuildInfo(TCascStorage * hs);
+int DownloadFileFromCDN(TCascStorage * hs, const TCHAR * szSubDir, LPBYTE pbEKey, const TCHAR * szExtension, TCHAR * szOutLocalPath, size_t cchOutLocalPath);
int CheckGameDirectory(TCascStorage * hs, TCHAR * szDirectory);
-
-int GetRootVariableIndex(const char * szLinePtr, const char * szLineEnd, const char * szVariableName, int * PtrIndex);
-int ParseRootFileLine(const char * szLinePtr, const char * szLineEnd, int nFileNameIndex, PQUERY_KEY pEncodingKey, char * szFileName, size_t nMaxChars);
+int LoadCdnsInfo(TCascStorage * hs);
+int LoadBuildInfo(TCascStorage * hs);
+int LoadCdnConfigFile(TCascStorage * hs);
+int LoadCdnBuildFile(TCascStorage * hs);
//-----------------------------------------------------------------------------
// Internal file functions
-TCascStorage * IsValidStorageHandle(HANDLE hStorage);
-TCascFile * IsValidFileHandle(HANDLE hFile);
+void * ProbeOutputBuffer(void * pvBuffer, size_t cbLength, size_t cbMinLength, size_t * pcbLengthNeeded);
+
+PCASC_CKEY_ENTRY FindCKeyEntry_CKey(TCascStorage * hs, LPBYTE pbCKey, PDWORD PtrIndex = NULL);
+PCASC_CKEY_ENTRY FindCKeyEntry_EKey(TCascStorage * hs, LPBYTE pbEKey, PDWORD PtrIndex = NULL);
-PCASC_ENCODING_ENTRY FindEncodingEntry(TCascStorage * hs, PQUERY_KEY pEncodingKey, PDWORD PtrIndex);
-PCASC_INDEX_ENTRY FindIndexEntry(TCascStorage * hs, PQUERY_KEY pIndexKey);
+size_t GetTagBitmapLength(LPBYTE pbFilePtr, LPBYTE pbFileEnd, DWORD EntryCount);
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);
+int CascLoadEncryptionKeys(TCascStorage * hs);
+int CascDecrypt(TCascStorage * hs, LPBYTE pbOutBuffer, PDWORD pcbOutBuffer, LPBYTE pbInBuffer, DWORD cbInBuffer, DWORD dwFrameIndex);
+
+//-----------------------------------------------------------------------------
+// Support for index files
+
+int LoadIndexFiles(TCascStorage * hs);
+
//-----------------------------------------------------------------------------
// Support for ROOT file
int RootHandler_CreateMNDX(TCascStorage * hs, LPBYTE pbRootFile, DWORD cbRootFile);
+int RootHandler_CreateTVFS(TCascStorage * hs, LPBYTE pbRootFile, DWORD cbRootFile);
int RootHandler_CreateDiablo3(TCascStorage * hs, LPBYTE pbRootFile, DWORD cbRootFile);
+int RootHandler_CreateWoW(TCascStorage * hs, LPBYTE pbRootFile, DWORD cbRootFile, DWORD dwLocaleMask);
int RootHandler_CreateOverwatch(TCascStorage * hs, LPBYTE pbRootFile, DWORD cbRootFile);
-int RootHandler_CreateWoW6(TCascStorage * hs, LPBYTE pbRootFile, DWORD cbRootFile, DWORD dwLocaleMask);
-int RootHandler_CreateSC1(TCascStorage * hs, LPBYTE pbRootFile, DWORD cbRootFile);
+int RootHandler_CreateStarcraft1(TCascStorage * hs, LPBYTE pbRootFile, DWORD cbRootFile);
+int RootHandler_CreateInstall(TCascStorage * hs, LPBYTE pbRootFile, DWORD cbRootFile);
//-----------------------------------------------------------------------------
-// Dumping CASC data structures
+// Dumpers (CascDumpData.cpp)
#ifdef _DEBUG
-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 CascDumpEncodingEntry(TCascStorage * hs, TDumpContext * dc, PCASC_ENCODING_ENTRY pEncodingEntry, int nDumpLevel);
-void CascDumpFile(const char * szFileName, HANDLE hFile);
-#endif // _DEBUG
+void CascDumpFile(HANDLE hFile, const char * szDumpFile = NULL);
+void CascDumpStorage(HANDLE hStorage, const char * szDumpFile = NULL);
+#endif
#endif // __CASCCOMMON_H__