diff options
author | Shauren <shauren.trinity@gmail.com> | 2019-06-06 16:48:21 +0200 |
---|---|---|
committer | Shauren <shauren.trinity@gmail.com> | 2019-06-08 17:09:24 +0200 |
commit | fc330fd8ff0115804d9c4b53a1f810c00dd63de9 (patch) | |
tree | cfa10998fed66779834bf0b7a9b8b799d33d91d4 /dep/CascLib/src/CascCommon.h | |
parent | 82c7b6c5688495d90c4ee5995a4ff74039348296 (diff) |
Dep/CascLib: Update to ladislav-zezula/CascLib@a1197edf0b3bd4d52c3f39be7fa7b44bb0b98012
Diffstat (limited to 'dep/CascLib/src/CascCommon.h')
-rw-r--r-- | dep/CascLib/src/CascCommon.h | 554 |
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__ |