diff options
Diffstat (limited to 'dep/CascLib/src/CascCommon.h')
-rw-r--r-- | dep/CascLib/src/CascCommon.h | 245 |
1 files changed, 135 insertions, 110 deletions
diff --git a/dep/CascLib/src/CascCommon.h b/dep/CascLib/src/CascCommon.h index b1248544b9f..a0caa5d85eb 100644 --- a/dep/CascLib/src/CascCommon.h +++ b/dep/CascLib/src/CascCommon.h @@ -30,6 +30,7 @@ #include "common/Directory.h" #include "common/ListFile.h" #include "common/Csv.h" +#include "common/Path.h" #include "common/RootHandler.h" // Headers from Alexander Peslyak's MD5 implementation @@ -52,6 +53,14 @@ #define BREAKIF(condition) { /* NOTHING */ } #endif +#define CASC_MAGIC_STORAGE 0x524F545343534143 // 'CASCSTOR' +#define CASC_MAGIC_FILE 0x454C494643534143 // 'CASCFILE' +#define CASC_MAGIC_FIND 0x444E494643534143 // 'CASCFIND' + +// For CASC_CDN_DOWNLOAD::Flags +#define CASC_CDN_FLAG_PORT1119 0x0001 // Use port 1119 +#define CASC_CDN_FORCE_DOWNLOAD 0x0002 // Force downloading the file even if in the cache + //----------------------------------------------------------------------------- // In-memory structures @@ -63,6 +72,13 @@ typedef enum _CBLD_TYPE CascVersionsDb // versions (downloaded online) } CBLD_TYPE, *PCBLD_TYPE; +typedef enum _CSTRTG +{ + CascCacheInvalid, // Do not cache anything. Used as invalid value + CascCacheNothing, // Do not cache anything. Used on internal files, where the content is loaded directly to the user buffer + CascCacheLastFrame, // Only cache one file frame +} CSTRTG, *PCSTRTG; + // Tag file entry, loaded from the DOWNLOAD file typedef struct _CASC_TAG_ENTRY { @@ -97,7 +113,7 @@ typedef struct _CASC_ARCINDEX_FOOTER 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 EKeyLength; // 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 @@ -107,15 +123,6 @@ typedef struct _CASC_ARCINDEX_FOOTER } CASC_ARCINDEX_FOOTER, *PCASC_ARCINDEX_FOOTER; -// Normalized structure for archive index entry -typedef struct _CASC_ARCINDEX_ENTRY -{ - BYTE IndexHash[MD5_HASH_SIZE]; - BYTE EKey[MD5_HASH_SIZE]; - DWORD ArchiveOffset; - DWORD EncodedSize; -} CASC_ARCINDEX_ENTRY, *PCASC_ARCINDEX_ENTRY; - // Normalized header of the ENCODING file typedef struct _CASC_ENCODING_HEADER { @@ -188,12 +195,51 @@ typedef struct _CASC_INSTALL_HEADER typedef struct _CASC_FILE_FRAME { CONTENT_KEY FrameHash; // MD5 hash of the file frame + ULONGLONG StartOffset; // Starting offset of the file span + ULONGLONG EndOffset; // Ending offset of the file span 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; +typedef struct _CASC_FILE_SPAN +{ + ULONGLONG StartOffset; // Starting offset of the file span + ULONGLONG EndOffset; // Ending offset of the file span + PCASC_FILE_FRAME pFrames; + TFileStream * pStream; // [Opened] stream for the file span + DWORD ArchiveIndex; // Index of the archive + DWORD ArchiveOffs; // Offset in the archive + DWORD HeaderSize; // Size of encoded frame headers + DWORD FrameCount; // Number of frames in this span + +} CASC_FILE_SPAN, *PCASC_FILE_SPAN; + +// Structure for downloading a file from the CDN (https://wowdev.wiki/TACT#File_types) +// Remote path is combined as the following: +// [szCdnsHost] /[szCdnsPath]/[szPathType]/EKey[0-1]/EKey[2-3]/[EKey].[Extension] +// level3.blizzard.com/tpr/bnt001 /data /fe /3d /fe3d7cf9d04e07066de32bd95a5c2627.index +typedef struct _CASC_CDN_DOWNLOAD +{ + ULONGLONG ArchiveOffs; // Archive offset (if pbArchiveKey != NULL) + LPCTSTR szCdnsHost; // Address of the remote CDN server. ("level3.blizzard.com") + // If NULL, the downloader will try all CDN servers from the storage + LPCTSTR szCdnsPath; // Remote CDN path ("tpr/bnt001") + LPCTSTR szPathType; // Path type ("config", "data", "patch") + LPCTSTR szLoPaType; // Local path type ("config", "data", "patch"). If NULL, it's gonna be the same like szPathType, If "", then it's not used + LPCTSTR szFileName; // Plain file name, without path and extension + LPBYTE pbArchiveKey; // If non-NULL, then the file is present in the archive. + LPBYTE pbEKey; // 16-byte EKey of the file of of the archive + LPCTSTR szExtension; // Extension for the file. Can be NULL. + + LPTSTR szLocalPath; // Pointer to the variable that, upon success, reveives the local path where the file was downloaded + size_t ccLocalPath; // Maximum length of szLocalPath, in TCHARs + DWORD ArchiveIndex; // Index of the archive (if pbArchiveKey != NULL) + DWORD EncodedSize; // Encoded length (if pbArchiveKey != NULL) + DWORD Flags; // See CASC_CDN_FLAG_XXX + +} CASC_CDN_DOWNLOAD, *PCASC_CDN_DOWNLOAD; + //----------------------------------------------------------------------------- // Structures for CASC storage and CASC file @@ -201,16 +247,26 @@ struct TCascStorage { TCascStorage(); ~TCascStorage(); + TCascStorage * AddRef(); TCascStorage * Release(); - static TCascStorage * IsValid(HANDLE hStorage); + static TCascStorage * IsValid(HANDLE hStorage) + { + TCascStorage * hs = (TCascStorage *)hStorage; + + return (hs != INVALID_HANDLE_VALUE && + hs != NULL && + hs->ClassName == CASC_MAGIC_STORAGE) ? hs : NULL; + } + + // Class recognizer. Has constant value of 'CASCSTOR' (CASC_MAGIC_STORAGE) + ULONGLONG ClassName; + // Class members PCASC_OPEN_STORAGE_ARGS pArgs; // Open storage arguments. Only valid during opening the storage LPCTSTR szIndexFormat; // Format of the index file name - LPCSTR szClassName; // "TCascStorage" - LPCSTR szProductName; // String representation of the product name LPTSTR szCodeName; // On local storage, this select a product in a multi-product storage. For online storage, this selects a product LPTSTR szRootPath; // Path where the build file is LPTSTR szDataPath; // This is the directory where data files are @@ -219,12 +275,10 @@ struct TCascStorage LPTSTR szCdnServers; // Multi-SZ list of CDN servers LPTSTR szCdnPath; // Remote CDN sub path for the product LPSTR szRegion; // Product region. Only when "versions" is used as storage root file - CASC_PRODUCT Product; // Product enum value (see CASC_PRODUCT) + DWORD dwDefaultLocale; // Default locale, read from ".build.info" DWORD dwBuildNumber; // Product build number DWORD dwRefCount; // Number of references - 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 @@ -249,20 +303,17 @@ struct TCascStorage CASC_ARRAY VfsRootList; // List of CASC_EKEY_ENTRY for each TVFS sub-root TRootHandler * pRootHandler; // Common handler for various ROOT file formats - 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 IndexArray; // Array of CASC_EKEY_ENTRY, loaded from online indexes + CASC_ARRAY CKeyArray; // Array of CASC_CKEY_ENTRY, loaded from ENCODING 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 + CASC_MAP IndexMap; // Map of EKey -> IndexArray (for online archives) + CASC_MAP CKeyMap; // Map of CKey -> CKeyArray + CASC_MAP EKeyMap; // Map of EKey -> CKeyArray 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 + DWORD FileOffsetBits; // Number 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 @@ -271,49 +322,12 @@ struct TCascStorage 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; + TCascFile(TCascStorage * hs, PCASC_CKEY_ENTRY pCKeyEntry); + ~TCascFile(); - // 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); - } + DWORD OpenFileSpans(LPCTSTR szSpanList); + void InitFileSpans(PCASC_FILE_SPAN pSpans, DWORD dwSpanCount); + void InitCacheStrategy(); static TCascFile * IsValid(HANDLE hFile) { @@ -321,31 +335,32 @@ struct TCascFile return (hf != INVALID_HANDLE_VALUE && hf != NULL && - hf->hs != NULL && - hf->szClassName != NULL && + hf->ClassName == CASC_MAGIC_FILE && hf->pCKeyEntry != NULL) ? hf : NULL; } + // Class recognizer. Has constant value of 'CASCFILE' (CASC_MAGIC_FILE) + ULONGLONG ClassName; + + // Class members TCascStorage * hs; // Pointer to storage structure - TFileStream * pStream; // An open data stream - const char * szClassName; // "TCascFile" - - 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 + + PCASC_CKEY_ENTRY pCKeyEntry; // Pointer to the first CKey entry. Each entry describes one file span + PCASC_FILE_SPAN pFileSpan; // Pointer to the first file span entry + ULONGLONG ContentSize; // Content size. This is the summed content size of all file spans + ULONGLONG EncodedSize; // Encoded size. This is the summed encoded size of all file spans + ULONGLONG FilePointer; // Current file pointer + DWORD SpanCount; // Number of file spans. There is one CKey entry for each file span 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 + DWORD bCloseFileStream:1; // If true, file stream needs to be closed during CascCloseFile DWORD bOvercomeEncrypted:1; // If true, then CascReadFile will fill the part that is encrypted (and key was not found) with zeros + DWORD bFreeCKeyEntries:1; // If true, dectructor will free the array of CKey entries - LPBYTE pbFileCache; // Pointer to file cache - DWORD cbFileCache; // Size of the file cache - + ULONGLONG FileCacheStart; // Starting offset of the file cached area + ULONGLONG FileCacheEnd; // Ending offset of the file cached area + LPBYTE pbFileCache; // Pointer to file cached area + CSTRTG CacheStrategy; // Caching strategy. See CSTRTG enum for more info }; struct TCascSearch @@ -353,7 +368,7 @@ struct TCascSearch TCascSearch(TCascStorage * ahs, LPCTSTR aszListFile, const char * aszMask) { // Init the class - szClassName = "TCascSearch"; + ClassName = CASC_MAGIC_FIND; hs = ahs->AddRef(); // Init provider-specific data @@ -371,7 +386,7 @@ struct TCascSearch { // Dereference the CASC storage hs = hs->Release(); - szClassName = NULL; + ClassName = 0; // Free the rest of the members CASC_FREE(szMask); @@ -385,14 +400,14 @@ struct TCascSearch return (hFind != INVALID_HANDLE_VALUE && hFind != NULL && - pSearch->szClassName != NULL && - !strcmp(pSearch->szClassName, "TCascSearch") && + pSearch->ClassName == CASC_MAGIC_FIND && pSearch->szMask != NULL) ? pSearch : NULL; } + ULONGLONG ClassName; // Contains 'CASCFIND' + TCascStorage * hs; // Pointer to the storage handle - const char * szClassName; // Contains "TCascSearch" - TCHAR * szListFile; // Name of the listfile + LPTSTR szListFile; // Name of the listfile void * pCache; // Listfile cache char * szMask; // Search mask @@ -405,22 +420,32 @@ struct TCascSearch //----------------------------------------------------------------------------- // Common functions (CascCommon.cpp) -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); +inline void FreeCascBlob(PQUERY_KEY pBlob) +{ + if(pBlob != NULL) + { + CASC_FREE(pBlob->pbData); + pBlob->cbData = 0; + } +} //----------------------------------------------------------------------------- // Text file parsing (CascFiles.cpp) bool InvokeProgressCallback(TCascStorage * hs, LPCSTR szMessage, LPCSTR szObject, DWORD CurrentValue, DWORD TotalValue); -DWORD DownloadFileFromCDN(TCascStorage * hs, const TCHAR * szSubDir, LPBYTE pbEKey, const TCHAR * szExtension, TCHAR * szOutLocalPath, size_t cchOutLocalPath); -DWORD CheckGameDirectory(TCascStorage * hs, TCHAR * szDirectory); -DWORD LoadCdnsInfo(TCascStorage * hs); +DWORD GetFileSpanInfo(PCASC_CKEY_ENTRY pCKeyEntry, PULONGLONG PtrContentSize, PULONGLONG PtrEncodedSize = NULL); +DWORD DownloadFileFromCDN(TCascStorage * hs, CASC_CDN_DOWNLOAD & CdnsInfo); +DWORD CheckGameDirectory(TCascStorage * hs, LPTSTR szDirectory); +DWORD LoadCdnsFile(TCascStorage * hs); DWORD LoadBuildInfo(TCascStorage * hs); DWORD LoadCdnConfigFile(TCascStorage * hs); DWORD LoadCdnBuildFile(TCascStorage * hs); +LPBYTE LoadInternalFileToMemory(TCascStorage * hs, PCASC_CKEY_ENTRY pCKeyEntry, DWORD * pcbFileData); +LPBYTE LoadFileToMemory(LPCTSTR szFileName, DWORD * pcbFileData); +bool OpenFileByCKeyEntry(TCascStorage * hs, PCASC_CKEY_ENTRY pCKeyEntry, DWORD dwOpenFlags, HANDLE * PtrFileHandle); +bool SetCacheStrategy(HANDLE hFile, CSTRTG CacheStrategy); + //----------------------------------------------------------------------------- // Internal file functions @@ -431,27 +456,27 @@ PCASC_CKEY_ENTRY FindCKeyEntry_EKey(TCascStorage * hs, LPBYTE pbEKey, PDWORD Ptr size_t GetTagBitmapLength(LPBYTE pbFilePtr, LPBYTE pbFileEnd, DWORD EntryCount); -int CascDecompress(LPBYTE pvOutBuffer, PDWORD pcbOutBuffer, LPBYTE pvInBuffer, DWORD cbInBuffer); -int CascDirectCopy(LPBYTE pbOutBuffer, PDWORD pcbOutBuffer, LPBYTE pbInBuffer, DWORD cbInBuffer); +DWORD CascDecompress(LPBYTE pvOutBuffer, PDWORD pcbOutBuffer, LPBYTE pvInBuffer, DWORD cbInBuffer); +DWORD 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); +DWORD CascLoadEncryptionKeys(TCascStorage * hs); +DWORD CascDecrypt(TCascStorage * hs, LPBYTE pbOutBuffer, PDWORD pcbOutBuffer, LPBYTE pbInBuffer, DWORD cbInBuffer, DWORD dwFrameIndex); //----------------------------------------------------------------------------- // Support for index files -int LoadIndexFiles(TCascStorage * hs); +DWORD 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_CreateStarcraft1(TCascStorage * hs, LPBYTE pbRootFile, DWORD cbRootFile); -int RootHandler_CreateInstall(TCascStorage * hs, LPBYTE pbRootFile, DWORD cbRootFile); +DWORD RootHandler_CreateMNDX(TCascStorage * hs, LPBYTE pbRootFile, DWORD cbRootFile); +DWORD RootHandler_CreateTVFS(TCascStorage * hs, LPBYTE pbRootFile, DWORD cbRootFile); +DWORD RootHandler_CreateDiablo3(TCascStorage * hs, LPBYTE pbRootFile, DWORD cbRootFile); +DWORD RootHandler_CreateWoW(TCascStorage * hs, LPBYTE pbRootFile, DWORD cbRootFile, DWORD dwLocaleMask); +DWORD RootHandler_CreateOverwatch(TCascStorage * hs, LPBYTE pbRootFile, DWORD cbRootFile); +DWORD RootHandler_CreateStarcraft1(TCascStorage * hs, LPBYTE pbRootFile, DWORD cbRootFile); +DWORD RootHandler_CreateInstall(TCascStorage * hs, LPBYTE pbRootFile, DWORD cbRootFile); //----------------------------------------------------------------------------- // Dumpers (CascDumpData.cpp) |