### Basic CMake Project Setup Source: https://github.com/ladislav-zezula/casclib/blob/master/CMakeLists.txt Sets the minimum required CMake version and the project name. Includes standard directories for installation. ```cmake cmake_minimum_required(VERSION 3.2) project(CascLib) include(GNUInstallDirs) ``` -------------------------------- ### Install CascLib on Debian/Ubuntu Source: https://github.com/ladislav-zezula/casclib/blob/master/_autodocs/README.md Install the CascLib library packages on Debian or Ubuntu systems. Use dpkg-buildpackage to build and then dpkg to install. ```bash dpkg-buildpackage -us -uc sudo dpkg -i libcasc1_3.0_*.deb libcasc-dev_3.0_*.deb ``` -------------------------------- ### Linking Libraries and Installation (Shared) Source: https://github.com/ladislav-zezula/casclib/blob/master/CMakeLists.txt Links necessary libraries and defines installation paths for the shared library artifacts. ```cmake target_link_libraries(casc ${LINK_LIBS}) install(TARGETS casc EXPORT CascLibTargets RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} FRAMEWORK DESTINATION /Library/Frameworks) target_include_directories(casc PUBLIC $ $ ) # On Win32, build CascLib.dll if(WIN32) set_target_properties(casc PROPERTIES OUTPUT_NAME CascLib) endif() target_compile_definitions(casc PUBLIC ${PUBLIC_COMPILE_DEFINITIONS}) ``` -------------------------------- ### CascLib Structure Versioning Example Source: https://github.com/ladislav-zezula/casclib/blob/master/_autodocs/architecture.md Demonstrates how to set the Size field in CASC_OPEN_STORAGE_ARGS for forward compatibility with newer library versions. ```c Args.Size = sizeof(CASC_OPEN_STORAGE_ARGS); ``` -------------------------------- ### Not Enough Memory Error Example Source: https://github.com/ladislav-zezula/casclib/blob/master/_autodocs/errors.md This error occurs when there is insufficient memory to complete an operation, such as allocating space for storage or files. It maps to ERROR_NOT_ENOUGH_MEMORY. ```text Insufficient memory for operation ↓ ERROR_NOT_ENOUGH_MEMORY ``` -------------------------------- ### Path Not Found Error Example Source: https://github.com/ladislav-zezula/casclib/blob/master/_autodocs/errors.md This error occurs when the specified storage path is invalid or inaccessible. It corresponds to the standard Windows ERROR_PATH_NOT_FOUND or POSIX ENOENT. ```text Storage path not found ↓ ERROR_PATH_NOT_FOUND ``` -------------------------------- ### File Too Large Error Example Source: https://github.com/ladislav-zezula/casclib/blob/master/_autodocs/errors.md This error is triggered if a file exceeds the maximum size supported by the system. It corresponds to ERROR_FILE_TOO_LARGE. ```text File is larger than system supports ↓ ERROR_FILE_TOO_LARGE ``` -------------------------------- ### Access Denied Error Example Source: https://github.com/ladislav-zezula/casclib/blob/master/_autodocs/errors.md This error occurs when there are insufficient permissions to access a file or directory. It maps to Windows ERROR_ACCESS_DENIED or POSIX EPERM. ```text File exists but access denied ↓ ERROR_ACCESS_DENIED ``` -------------------------------- ### Import Encryption Keys from File Source: https://github.com/ladislav-zezula/casclib/blob/master/_autodocs/api-reference/encryption-keys.md Imports encryption keys from a specified file. The file should contain one key per line in the format 'KeyName HexKey'. Blank lines and comments starting with '#' are ignored. The function returns true if at least one key was imported successfully. ```c bool WINAPI CascImportKeysFromFile( HANDLE hStorage, LPCTSTR szFileName ); ``` ```c // Keys file format: // # WoW Encryption Keys // 0403020100000000 0102030405060708090a0b0c0d0e0f10 // 1807060504030201 101f0e0d0c0b0a09080706050403020 // // # Diablo 3 Keys // 2a2c2e30323436 0a0c0e101214161820222426282a2c2e if (!CascImportKeysFromFile(hStorage, _T("keys.txt"))) { printf("Failed to import keys: %u\n", GetCascError()); } ``` -------------------------------- ### Bad Format Error Example Source: https://github.com/ladislav-zezula/casclib/blob/master/_autodocs/errors.md Indicates that the storage structure is corrupted or invalid, or that unexpected data format is encountered within a file. This maps to ERROR_BAD_FORMAT. ```text Unexpected format in file or storage ↓ ERROR_BAD_FORMAT ``` -------------------------------- ### File Not Found Error Example Source: https://github.com/ladislav-zezula/casclib/blob/master/_autodocs/errors.md This error is triggered when CascOpenFile is called for a file that does not exist in the storage. It corresponds to the standard Windows ERROR_FILE_NOT_FOUND or POSIX ENOENT. ```text File does not exist ↓ ERROR_FILE_NOT_FOUND ``` -------------------------------- ### Network Not Available Error Example Source: https://github.com/ladislav-zezula/casclib/blob/master/_autodocs/errors.md This error is triggered when an operation requiring online storage fails due to a lack of network connectivity. It maps to ERROR_NETWORK_NOT_AVAILABLE. ```text Online storage without network ↓ ERROR_NETWORK_NOT_AVAILABLE ``` -------------------------------- ### Robust CascLib Application Template Source: https://github.com/ladislav-zezula/casclib/blob/master/_autodocs/usage-patterns.md A complete template for a robust CascLib application, demonstrating initialization, storage and file operations, and resource cleanup. This serves as a starting point for developing CASC-based applications. ```c #include "CascLib.h" #include int main() { HANDLE hStorage = NULL; HANDLE hFile = NULL; int ExitCode = 1; // Initialize printf("Opening CASC storage...\n"); // Open storage with configuration CASC_OPEN_STORAGE_ARGS Args; memset(&Args, 0, sizeof(Args)); Args.Size = sizeof(Args); Args.szLocalPath = _T("D:\\WoW\\Data"); Args.dwLocaleMask = CASC_LOCALE_ENUS; if (!CascOpenStorageEx(_T("D:\\WoW\\Data"), &Args, false, &hStorage)) { printf("ERROR: Failed to open storage (%u)\n", GetCascError()); goto Cleanup; } printf("Storage opened successfully\n"); // Get storage info DWORD FileCount; if (CascGetStorageInfo(hStorage, CascStorageLocalFileCount, &FileCount, sizeof(FileCount), NULL)) { printf("Files in storage: %u\n", FileCount); } // Open file printf("\nOpening file...\n"); if (!CascOpenFile(hStorage, "World\\Maps\\World\\world.lit", CASC_INVALID_ID, CASC_OPEN_BY_NAME, &hFile)) { printf("ERROR: Failed to open file (%u)\n", GetCascError()); goto Cleanup; } // Get file size ULONGLONG FileSize; if (!CascGetFileSize64(hFile, &FileSize)) { printf("ERROR: Failed to get file size (%u)\n", GetCascError()); goto Cleanup; } printf("File size: %llu bytes\n", FileSize); // Read file printf("Reading file...\n"); BYTE Buffer[4096]; DWORD BytesRead; if (!CascReadFile(hFile, Buffer, sizeof(Buffer), &BytesRead)) { printf("ERROR: Failed to read file (%u)\n", GetCascError()); goto Cleanup; } printf("Read %u bytes\n", BytesRead); ExitCode = 0; // Success Cleanup: if (hFile != NULL) { CascCloseFile(hFile); } if (hStorage != NULL) { CascStorageClose(hStorage); } printf("\nDone.\n"); return ExitCode; } ``` -------------------------------- ### Start CASC File Enumeration Source: https://github.com/ladislav-zezula/casclib/blob/master/_autodocs/api-reference/find-operations.md Initiates a search for files matching a specified pattern in a CASC storage. Use this to begin iterating through files. The szListFile parameter can help resolve file names when only hashes are available. ```c HANDLE WINAPI CascFindFirstFile( HANDLE hStorage, LPCSTR szMask, PCASC_FIND_DATA pFindData, LPCTSTR szListFile ); ``` ```c CASC_FIND_DATA FindData; HANDLE hFind; hFind = CascFindFirstFile(hStorage, "*.blp", &FindData, NULL); if (hFind != INVALID_HANDLE_VALUE) { do { printf("Found: %s (Size: %llu)\n", FindData.szFileName, FindData.FileSize); } while (CascFindNextFile(hFind, &FindData)); CascFindClose(hFind); } ``` -------------------------------- ### Use Specific Locale Masks Source: https://github.com/ladislav-zezula/casclib/blob/master/_autodocs/usage-patterns.md When specifying locale masks, be precise and avoid using CASC_LOCALE_ALL unless necessary. This example shows how to correctly set masks for specific locales like English (US) and French (France). ```c // Be specific rather than using CASC_LOCALE_ALL Args.dwLocaleMask = CASC_LOCALE_ENUS; // Good Args.dwLocaleMask = CASC_LOCALE_ENUS | CASC_LOCALE_FRFR; // Good // Avoid: CASC_LOCALE_ALL when only need English ``` -------------------------------- ### Open by Name Flow Source: https://github.com/ladislav-zezula/casclib/blob/master/_autodocs/architecture.md Illustrates the sequence of operations when opening a file by its name within the CASC storage system. This flow involves locating the file in the ROOT file, retrieving its keys, potentially loading encoding information, and finally returning a file handle with decompression and decryption setup. ```text CascOpenFile(hStorage, "World\Maps\world.lit") ↓ RootHandler->GetFileByName("World\Maps\world.lit") ↓ Locate in ROOT file → Get CKey/EKey ↓ Load from ENCODING if needed ↓ Return file handle with span information ↓ TCascFile object created with decompression/decryption setup ``` -------------------------------- ### Configure and Open Storage with Progress Callback Source: https://github.com/ladislav-zezula/casclib/blob/master/_autodocs/configuration.md Sets up CASC storage arguments, including local path, code name, locales, features, and a progress callback, then attempts to open the storage. Handles potential errors during opening. ```c CASC_OPEN_STORAGE_ARGS Args; memset(&Args, 0, sizeof(Args)); Args.Size = sizeof(Args); // Storage location Args.szLocalPath = _T("D:\\WoW"); Args.szCodeName = _T("wowt"); // PTR // Locales Args.dwLocaleMask = CASC_LOCALE_ENUS | CASC_LOCALE_FRFR; // Features Args.dwFlags = CASC_FEATURE_FILE_NAMES | CASC_FEATURE_ONLINE; // Callbacks Args.PfnProgressCallback = ProgressCallback; Args.PtrProgressParam = NULL; // or pointer to user data // Build version Args.szBuildKey = NULL; // Use latest; or specify specific build HANDLE hStorage; if (!CascOpenStorageEx(Args.szLocalPath, &Args, false, &hStorage)) { printf("Failed: %u\n", GetCascError()); } else { // Use storage... CascCloseStorage(hStorage); } ``` -------------------------------- ### Initialize CASC_OPEN_STORAGE_ARGS Structure Source: https://github.com/ladislav-zezula/casclib/blob/master/_autodocs/configuration.md Demonstrates the essential first steps for configuring storage: clearing the structure with memset and setting its size. These actions ensure the structure is in a known state before other parameters are populated. ```c CASC_OPEN_STORAGE_ARGS Args; memset(&Args, 0, sizeof(Args)); // Clear all fields Args.Size = sizeof(Args); // Set required size ``` -------------------------------- ### Get Next CASC File Match Source: https://github.com/ladislav-zezula/casclib/blob/master/_autodocs/api-reference/find-operations.md Retrieves the next file that matches the search pattern initiated by CascFindFirstFile. Call this function repeatedly until it returns false to get all matching files. ```c bool WINAPI CascFindNextFile(HANDLE hFind, PCASC_FIND_DATA pFindData); ``` ```c CASC_FIND_DATA FindData; HANDLE hFind; DWORD FileCount = 0; hFind = CascFindFirstFile(hStorage, "*", &FindData, NULL); if (hFind != INVALID_HANDLE_VALUE) { do { FileCount++; } while (CascFindNextFile(hFind, &FindData)); printf("Total files: %u\n", FileCount); CascFindClose(hFind); } ``` -------------------------------- ### Cancelled Operation Error Example Source: https://github.com/ladislav-zezula/casclib/blob/master/_autodocs/errors.md Indicates that an operation was cancelled, typically by the user through a progress callback. This corresponds to ERROR_CANCELLED. ```text User cancelled opening through callback ↓ ERROR_CANCELLED ``` -------------------------------- ### Initialize CASC_OPEN_STORAGE_ARGS Source: https://github.com/ladislav-zezula/casclib/blob/master/_autodocs/configuration.md Initializes the CASC_OPEN_STORAGE_ARGS structure with zeros and sets its size. The size must be set first to enable versioning. ```c CASC_OPEN_STORAGE_ARGS Args; mset(&Args, 0, sizeof(Args)); Args.Size = sizeof(Args); // Must set size first ``` -------------------------------- ### File Offline Error Example Source: https://github.com/ladislav-zezula/casclib/blob/master/_autodocs/errors.md Occurs when a file is required from online storage but is not available locally. This maps to ERROR_FILE_OFFLINE. ```text File requires data from online storage ↓ ERROR_FILE_OFFLINE ``` -------------------------------- ### Open Storage with Product Selection Callback Source: https://github.com/ladislav-zezula/casclib/blob/master/_autodocs/usage-patterns.md Opens a CASCLib storage by providing a callback function that allows the user to select from available products if multiple are present. ```c bool OpenWithProductSelection(LPCTSTR szPath, HANDLE *phStorage) { CASC_OPEN_STORAGE_ARGS Args; // Define callback auto ProductCallback = [](void *Param, LPCSTR *Products, size_t Count, size_t *Selected) -> bool { printf("Available products:\n"); for (size_t i = 0; i < Count; i++) printf(" %zu: %s\n", i, Products[i]); printf("Select (0-%zu): ", Count - 1); scanf("%zu", Selected); return *Selected >= Count; // Cancel if invalid }; memset(&Args, 0, sizeof(Args)); Args.Size = sizeof(Args); Args.szLocalPath = szPath; Args.dwLocaleMask = CASC_LOCALE_ENUS; Args.PfnProductCallback = ProductCallback; return CascOpenStorageEx(szPath, &Args, false, phStorage); } ``` -------------------------------- ### Content Flags Source: https://github.com/ladislav-zezula/casclib/blob/master/_autodocs/types.md Defines bitmask flags indicating file installation requirements and platform compatibility for World of Warcraft content. ```c #define CASC_CFLAG_INSTALL 0x04 // Required for installation #define CASC_CFLAG_LOAD_ON_WINDOWS 0x08 // Load on Windows #define CASC_CFLAG_LOAD_ON_MAC 0x10 // Load on Mac #define CASC_CFLAG_X86_32 0x20 // 32-bit x86 #define CASC_CFLAG_X86_64 0x40 // 64-bit x86 #define CASC_CFLAG_LOW_VIOLENCE 0x80 // Low violence variant #define CASC_CFLAG_DONT_LOAD 0x100 // Do not load #define CASC_CFLAG_UPDATE_PLUGIN 0x800 // Update plugin #define CASC_CFLAG_ARM64 0x8000 // ARM 64-bit #define CASC_CFLAG_ENCRYPTED 0x8000000 // File is encrypted #define CASC_CFLAG_NO_NAME_HASH 0x10000000 // No file name hash #define CASC_CFLAG_UNCMN_RESOLUTION 0x20000000 // Uncommon resolution #define CASC_CFLAG_BUNDLE 0x40000000 // Bundle file #define CASC_CFLAG_NO_COMPRESSION 0x80000000 // Not compressed ``` -------------------------------- ### Open WoW Storage (PTR/Live) Source: https://github.com/ladislav-zezula/casclib/blob/master/_autodocs/usage-patterns.md Opens a World of Warcraft storage, differentiating between the live and Public Test Realm (PTR) versions using specific product codes. ```c bool OpenWoWStorage(LPCTSTR szPath, bool bPTR, HANDLE *phStorage) { CASC_OPEN_STORAGE_ARGS Args; memset(&Args, 0, sizeof(Args)); Args.Size = sizeof(Args); Args.szLocalPath = szPath; Args.szCodeName = bPTR ? _T("wowt") : _T("wow"); Args.dwLocaleMask = CASC_LOCALE_ENUS; return CascOpenStorageEx(szPath, &Args, false, phStorage); } ``` -------------------------------- ### Add Encryption Keys Source: https://github.com/ladislav-zezula/casclib/blob/master/_autodocs/README.md Demonstrates adding encryption keys to a storage using different methods: binary key, hex string, and from a file. ```c // From binary key BYTE Key[CASC_KEY_LENGTH] = { 0x01, 0x02, ... }; CascAddEncryptionKey(hStorage, 0x0403020100000000, Key); // From hex string CascAddStringEncryptionKey(hStorage, 0x0403020100000000, "0102030405060708090a0b0c0d0e0f10"); // From file CascImportKeysFromFile(hStorage, _T("encryption_keys.txt")); ``` -------------------------------- ### Get Default CDN URL Source: https://github.com/ladislav-zezula/casclib/blob/master/_autodocs/api-reference/cdn-support.md Retrieves the default CDN URL for a Blizzard product. The returned URL is read-only and should not be modified. ```c LPCTSTR WINAPI CascCdnGetDefault(); ``` ```c LPCTSTR pszDefaultUrl = CascCdnGetDefault(); if (pszDefaultUrl != NULL) { printf("Default CDN URL: %s\n", pszDefaultUrl); } else { printf("No default CDN available\n"); } ``` -------------------------------- ### Open Storage with Product Selection Callback Source: https://github.com/ladislav-zezula/casclib/blob/master/_autodocs/configuration.md Configures CASC_OPEN_STORAGE_ARGS to use a custom product selection callback for multi-product storages. This allows dynamic product choice at runtime. ```c // Setup CASC_OPEN_STORAGE_ARGS Args; memset(&Args, 0, sizeof(Args)); Args.Size = sizeof(Args); Args.szLocalPath = _T("D:\\WoW"); Args.PfnProductCallback = ProductSelectionCallback; Args.dwLocaleMask = CASC_LOCALE_ENUS; HANDLE hStorage; CascOpenStorageEx(_T("D:\\WoW"), &Args, false, &hStorage); ``` -------------------------------- ### File Encrypted Error Example Source: https://github.com/ladislav-zezula/casclib/blob/master/_autodocs/errors.md This error is raised when a file is encrypted and the necessary decryption key is not available. It is represented by ERROR_FILE_ENCRYPTED. ```text File is encrypted but key missing ↓ ERROR_FILE_ENCRYPTED ``` -------------------------------- ### Basic File Access with CascLib Source: https://github.com/ladislav-zezula/casclib/blob/master/_autodocs/usage-patterns.md Demonstrates the fundamental steps to open a storage, open a specific file by name, read a portion of its content into a buffer, and then close both the file and the storage. This is useful for accessing individual files within a CAS storage. ```cpp #include "CascLib.h" #include void BasicFileAccess() { HANDLE hStorage, hFile; BYTE Buffer[4096]; DWORD BytesRead; // Open storage if (!CascOpenStorage(_T("D:\\WoW\\Data"), CASC_LOCALE_ENUS, &hStorage)) { printf("Open storage failed: %u\n", GetCascError()); return; } // Open file if (!CascOpenFile(hStorage, "World\\Maps\\World\\world.lit", CASC_INVALID_ID, CASC_OPEN_BY_NAME, &hFile)) { printf("Open file failed: %u\n", GetCascError()); CascCloseStorage(hStorage); return; } // Read file if (!CascReadFile(hFile, Buffer, sizeof(Buffer), &BytesRead)) { printf("Read file failed: %u\n", GetCascError()); } else { printf("Read %u bytes\n", BytesRead); } // Cleanup CascCloseFile(hFile); CascCloseStorage(hStorage); } ``` -------------------------------- ### File Corrupt Error Example Source: https://github.com/ladislav-zezula/casclib/blob/master/_autodocs/errors.md Indicates that the data integrity check (CRC/hash) for a file has failed. This corresponds to the custom ERROR_FILE_CORRUPT. ```text File data is corrupted ↓ ERROR_FILE_CORRUPT ``` -------------------------------- ### Initialize CASC Structures Source: https://github.com/ladislav-zezula/casclib/blob/master/_autodocs/usage-patterns.md Demonstrates the correct way to initialize CASC structures before use. Always initialize structures to zero and set their Size field. ```c CASC_OPEN_STORAGE_ARGS Args; memset(&Args, 0, sizeof(Args)); // Initialize all fields to zero Args.Size = sizeof(Args); // Set required size ``` -------------------------------- ### Arithmetic Overflow Error Example Source: https://github.com/ladislav-zezula/casclib/blob/master/_autodocs/errors.md This error is triggered when a string value is too large to fit into its intended type during an operation. It corresponds to ERROR_ARITHMETIC_OVERFLOW. ```text String value doesn't fit in type ↓ ERROR_ARITHMETIC_OVERFLOW ``` -------------------------------- ### SetCascError Usage Example Source: https://github.com/ladislav-zezula/casclib/blob/master/_autodocs/api-reference/error-handling.md Demonstrates internal use of SetCascError by CascLib, followed by retrieval with GetCascError. Each thread maintains its own error code. ```c // Internal use by CascLib SetCascError(ERROR_FILE_NOT_FOUND); // Retrieve with GetCascError() DWORD dwErr = GetCascError(); ``` -------------------------------- ### Windows Platform Configuration Source: https://github.com/ladislav-zezula/casclib/blob/master/CMakeLists.txt Applies Windows-specific settings, including linking 'wininet' and handling UNICODE definitions. ```cmake set(PUBLIC_COMPILE_DEFINITIONS CASCLIB_NO_AUTO_LINK_LIBRARY CASCLIB_NODEBUG) if(WIN32) list(APPEND LINK_LIBS wininet) if(CASC_UNICODE) message(STATUS "Build UNICODE version") add_definitions(-DUNICODE -D_UNICODE) list(APPEND PUBLIC_COMPILE_DEFINITIONS CASCLIB_UNICODE) else() message(STATUS "Build ANSI version") endif() list(APPEND PUBLIC_COMPILE_DEFINITIONS CASCLIB_DETECT_UNICODE_MISMATCHES) endif() ``` -------------------------------- ### Open Online Storage for World of Warcraft Source: https://github.com/ladislav-zezula/casclib/blob/master/_autodocs/usage-patterns.md Opens a CASC storage handle configured for online access, using the default World of Warcraft product and a local cache directory. Requires CASC_FEATURE_ONLINE flag. ```c bool OpenOnlineWoW(HANDLE *phStorage) { CASC_OPEN_STORAGE_ARGS Args; memset(&Args, 0, sizeof(Args)); Args.Size = sizeof(Args); Args.szLocalPath = _T("./wow_cache"); // Local cache directory Args.dwLocaleMask = CASC_LOCALE_ENUS; Args.dwFlags = CASC_FEATURE_ONLINE; // Enable online support return CascOpenStorageEx(_T("wow"), &Args, true, phStorage); } ``` -------------------------------- ### CascFindFirstFile Source: https://github.com/ladislav-zezula/casclib/blob/master/_autodocs/api-reference/find-operations.md Starts enumeration of files matching a search pattern. It returns a handle to the find operation or INVALID_HANDLE_VALUE if no matches or an error occurred. ```APIDOC ## CascFindFirstFile ### Description Starts enumeration of files matching a search pattern. ### Method `HANDLE WINAPI CascFindFirstFile( HANDLE hStorage, LPCSTR szMask, PCASC_FIND_DATA pFindData, LPCTSTR szListFile );` ### Parameters #### Path Parameters - **hStorage** (HANDLE) - Required - Handle to open CASC storage - **szMask** (LPCSTR) - Required - Search pattern with wildcards (e.g., "*.blp", "World\*") or "*" for all files - **pFindData** (PCASC_FIND_DATA) - Required - Pointer to CASC_FIND_DATA structure to receive first match - **szListFile** (LPCTSTR) - Optional - Path to listfile containing known file names; if NULL, only hashes are available ### Return Value Handle to find operation if successful; INVALID_HANDLE_VALUE if no matches or error occurred. ### Remarks - Returns INVALID_HANDLE_VALUE if no files match pattern or error occurs - Call CascFindNextFile() to get subsequent matches - Call CascFindClose() to release find handle - szMask supports wildcards: '*' (any characters), '?' (single character) - szListFile format: one file name per line; helps populate szFileName when only hash available - pFindData->NameType indicates if name is full path, DataId, CKey, or EKey ### Example ```c CASC_FIND_DATA FindData; HANDLE hFind; hFind = CascFindFirstFile(hStorage, "*.blp", &FindData, NULL); if (hFind != INVALID_HANDLE_VALUE) { do { printf("Found: %s (Size: %llu)\n", FindData.szFileName, FindData.FileSize); } while (CascFindNextFile(hFind, &FindData)); CascFindClose(hFind); } ``` ``` -------------------------------- ### Get File Size (64-bit) Source: https://github.com/ladislav-zezula/casclib/blob/master/_autodocs/api-reference/file-operations.md Retrieves the uncompressed size of an open file as a 64-bit value. Preferred for files larger than 4 GB. ```c bool WINAPI CascGetFileSize64(HANDLE hFile, PULONGLONG PtrFileSize); ``` ```c ULONGLONG FileSize; if (!CascGetFileSize64(hFile, &FileSize)) { printf("Failed to get file size: %u\n", GetCascError()); } else { printf("File size: %llu bytes\n", FileSize); } ``` -------------------------------- ### Open Online Storage with Default CDN Source: https://github.com/ladislav-zezula/casclib/blob/master/_autodocs/configuration.md Opens an online storage instance using the default CDN. The bOnlineStorage parameter must be set to true. ```c CASC_OPEN_STORAGE_ARGS Args; memset(&Args, 0, sizeof(Args)); Args.Size = sizeof(Args); Args.szLocalPath = _T("C:\\CascCache"); // Cache directory Args.dwLocaleMask = CASC_LOCALE_ENUS; HANDLE hStorage; if (!CascOpenStorageEx(_T("wow"), &Args, true, &hStorage)) // bOnlineStorage=true { printf("Failed to open online storage\n"); } ``` -------------------------------- ### Handle CascLib Storage Errors Source: https://github.com/ladislav-zezula/casclib/blob/master/_autodocs/README.md Check for errors after a CascLib storage operation fails. Get the thread-local error code using GetCascError. ```c if (!CascOpenStorage(path, locale, &hStorage)) { DWORD dwErr = GetCascError(); // Handle error... } ``` -------------------------------- ### Open CASC Storage with Default Options Source: https://github.com/ladislav-zezula/casclib/blob/master/_autodocs/api-reference/storage.md Opens a CASC storage container from a local path with default settings. This is a simpler alternative to CascOpenStorageEx when default configurations are sufficient. ```c bool WINAPI CascOpenStorage( LPCTSTR szParams, DWORD dwLocaleMask, HANDLE * phStorage ); ``` ```c HANDLE hStorage; if (!CascOpenStorage(_T("D:\\WoW\\Data"), CASC_LOCALE_ENUS, &hStorage)) { printf("Failed to open storage: %u\n", GetCascError()); return; } // Use storage... CascCloseStorage(hStorage); ``` -------------------------------- ### CascFindNextFile Source: https://github.com/ladislav-zezula/casclib/blob/master/_autodocs/api-reference/find-operations.md Gets the next file matching the search pattern from an ongoing enumeration. It returns true if a next file is found, and false otherwise. ```APIDOC ## CascFindNextFile ### Description Gets next file matching the search pattern. ### Method `bool WINAPI CascFindNextFile( HANDLE hFind, PCASC_FIND_DATA pFindData ); ` ### Parameters #### Path Parameters - **hFind** (HANDLE) - Required - Handle returned by CascFindFirstFile() - **pFindData** (PCASC_FIND_DATA) - Required - Pointer to CASC_FIND_DATA structure to receive next match ### Return Value true if next file found; false if no more files or error occurred. ### Remarks - Call repeatedly until function returns false - Each call fills pFindData with next matching file - Returns false on error or when enumeration reaches end ### Example ```c CASC_FIND_DATA FindData; HANDLE hFind; DWORD FileCount = 0; hFind = CascFindFirstFile(hStorage, "*", &FindData, NULL); if (hFind != INVALID_HANDLE_VALUE) { do { FileCount++; } while (CascFindNextFile(hFind, &FindData)); printf("Total files: %u\n", FileCount); CascFindClose(hFind); } ``` ``` -------------------------------- ### File Enumeration Process Source: https://github.com/ladislav-zezula/casclib/blob/master/_autodocs/architecture.md Outlines the steps involved in enumerating files that match a given pattern. This process utilizes the root handler to iterate through files and apply pattern matching. ```text CascFindFirstFile(hStorage, "*.blp") ↓ RootHandler->EnumFiles() ↓ For each file in ROOT: ├── Check pattern match ├── Load file metadata ├── Populate CASC_FIND_DATA └── Return first match ``` -------------------------------- ### Open Storage with Progress Monitoring Source: https://github.com/ladislav-zezula/casclib/blob/master/_autodocs/usage-patterns.md Opens a CASCLib storage while registering a progress callback function to monitor the operation's status. This is useful for long-running operations like downloading or indexing. ```c bool OpenStorageWithProgress(LPCTSTR szPath, HANDLE *phStorage) { CASC_OPEN_STORAGE_ARGS Args; memset(&Args, 0, sizeof(Args)); Args.Size = sizeof(Args); Args.szLocalPath = szPath; Args.dwLocaleMask = CASC_LOCALE_ENUS; Args.PfnProgressCallback = ProgressCallback; return CascOpenStorageEx(szPath, &Args, false, phStorage); } ``` -------------------------------- ### Enumerate Files Matching Pattern with CascLib Source: https://github.com/ladislav-zezula/casclib/blob/master/_autodocs/usage-patterns.md Shows how to find and list all files within a storage that match a given wildcard pattern. It iterates through the found files, printing their names, sizes, and types. This is useful for discovering files or processing multiple files that adhere to a naming convention. ```cpp void EnumerateFiles(HANDLE hStorage, const char *szPattern) { CASC_FIND_DATA FindData; HANDLE hFind; DWORD FileCount = 0; hFind = CascFindFirstFile(hStorage, szPattern, &FindData, NULL); if (hFind == INVALID_HANDLE_VALUE) { printf("No files found for pattern: %s\n", szPattern); return; } do { printf("[%u] %s (Size: %llu, Type: %u)\n", FileCount++, FindData.szFileName, FindData.FileSize, FindData.NameType); // Process file data as needed if (FindData.dwFileDataId != CASC_INVALID_ID) printf(" FileDataId: %u\n", FindData.dwFileDataId); if (FindData.dwLocaleFlags != CASC_INVALID_ID) printf(" Locales: 0x%08x\n", FindData.dwLocaleFlags); } while (CascFindNextFile(hFind, &FindData)); printf("Total files found: %u\n", FileCount); CascFindClose(hFind); } ``` -------------------------------- ### CascLib Error Propagation Example Source: https://github.com/ladislav-zezula/casclib/blob/master/_autodocs/architecture.md Illustrates the error handling flow where a failed function sets a thread-local error code, which the caller then retrieves. ```c CascOpenFile fails ↓ SetCascError(ERROR_FILE_NOT_FOUND) ↓ Return false ↓ Caller checks GetCascError() ``` -------------------------------- ### PFNPRODUCTCALLBACK Source: https://github.com/ladislav-zezula/casclib/blob/master/_autodocs/types.md Callback function for selecting a product in multi-product storage. This function is invoked when the CASC storage contains multiple products and a selection needs to be made. ```APIDOC ## Callback Function Type: PFNPRODUCTCALLBACK ### Description Callback function for selecting product in multi-product storage. ### Signature ```c typedef bool (WINAPI * PFNPRODUCTCALLBACK)( void * PtrUserParam, // User parameter passed to CascOpenStorageEx LPCSTR * ProductList, // Array of product code names size_t ProductCount, // Number of products size_t * PtrSelectedProduct // Output: selected product index (0-based) ); ``` ### Parameters - **PtrUserParam** (`void *`): User-defined value from `CascOpenStorageEx`. - **ProductList** (`LPCSTR *`): Null-terminated array of product code names. - **ProductCount** (`size_t`): Number of products in `ProductList`. - **PtrSelectedProduct** (`size_t *`): On input, default selection (usually 0); on output, selected product index. ### Return Value - `true`: To cancel operation. - `false`: To continue with selected product. ### Usage Assign to `CASC_OPEN_STORAGE_ARGS.PfnProductCallback`. ``` -------------------------------- ### Open PTR Storage using Code Name Source: https://github.com/ladislav-zezula/casclib/blob/master/_autodocs/configuration.md Opens a storage instance for a specific product code (e.g., 'wowt' for PTR) by setting the szCodeName field. This is useful for accessing different versions of a game. ```c CASC_OPEN_STORAGE_ARGS Args; memset(&Args, 0, sizeof(Args)); Args.Size = sizeof(Args); Args.szLocalPath = _T("D:\\WoW"); Args.szCodeName = _T("wowt"); // PTR instead of live Args.dwLocaleMask = CASC_LOCALE_ENUS; HANDLE hStorage; if (!CascOpenStorageEx(_T("D:\\WoW"), &Args, false, &hStorage)) { printf("Failed to open PTR storage\n"); } ``` -------------------------------- ### Handling Storage Open Errors in CASCLib Source: https://github.com/ladislav-zezula/casclib/blob/master/_autodocs/errors.md Shows how to handle errors when opening a CASCLib storage. Covers path not found, invalid format, access denied, and out of memory errors. ```c HANDLE hStorage; if (!CascOpenStorage(_T("D:\\WoW\\Data"), CASC_LOCALE_ENUS, &hStorage)) { DWORD dwErr = GetCascError(); switch (dwErr) { case ERROR_PATH_NOT_FOUND: printf("Storage path not found\n"); break; case ERROR_BAD_FORMAT: printf("Storage format invalid (corrupted?)\n"); break; case ERROR_ACCESS_DENIED: printf("Permission denied accessing storage\n"); break; case ERROR_NOT_ENOUGH_MEMORY: printf("Out of memory opening storage\n"); break; default: printf("Failed to open storage: error %u\n", dwErr); break; } } ``` -------------------------------- ### Build CascLib on Linux with CMake Source: https://github.com/ladislav-zezula/casclib/blob/master/_autodocs/README.md Compile the CascLib library on Linux using CMake. Navigate to the casclib directory, run cmake, and then make. ```bash cd casclib cmake . make ``` -------------------------------- ### GetCascError Usage Example Source: https://github.com/ladislav-zezula/casclib/blob/master/_autodocs/api-reference/error-handling.md Shows how to use GetCascError after a failed CascLib operation (CascOpenFile) to determine the specific error. Call immediately after a failed function. ```c HANDLE hFile; if (!CascOpenFile(hStorage, szFileName, CASC_INVALID_ID, CASC_OPEN_BY_NAME, &hFile)) { DWORD dwErr = GetCascError(); switch (dwErr) { case ERROR_FILE_NOT_FOUND: printf("File not found: %s\n", szFileName); break; case ERROR_FILE_ENCRYPTED: printf("File is encrypted and key is missing\n"); break; case ERROR_FILE_CORRUPT: printf("File is corrupted\n"); break; default: printf("Failed to open file: %u\n", dwErr); break; } return; } // File opened successfully CascCloseFile(hFile); ``` -------------------------------- ### Get Storage Information Source: https://github.com/ladislav-zezula/casclib/blob/master/_autodocs/usage-patterns.md Retrieves and prints general information about the CASC storage, such as file count and supported features. This function is useful for understanding the capabilities of the storage. ```c bool GetStorageInfo(HANDLE hStorage) { DWORD FileCount; DWORD Features; CASC_STORAGE_PRODUCT Product; printf("Storage information:\n"); if (CascGetStorageInfo(hStorage, CascStorageLocalFileCount, &FileCount, sizeof(FileCount), NULL)) printf(" Local files: %u\n", FileCount); if (CascGetStorageInfo(hStorage, CascStorageFeatures, &Features, sizeof(Features), NULL)) { printf(" Features: 0x%08x\n", Features); if (Features & CASC_FEATURE_FILE_NAMES) printf(" - File names supported\n"); if (Features & CASC_FEATURE_ONLINE) printf(" - Online CDN supported\n"); if (Features & CASC_FEATURE_FILE_DATA_IDS) printf(" - File data IDs supported\n"); } if (CascGetStorageInfo(hStorage, CascStorageProduct, &Product, sizeof(Product), NULL)) { printf(" Product: %s\n", Product.szCodeName); if (Product.BuildNumber > 0) printf(" Build: %u\n", Product.BuildNumber); } return true; } ``` -------------------------------- ### Test Application Build Option Source: https://github.com/ladislav-zezula/casclib/blob/master/CMakeLists.txt Enables the build of a test application. Forces static library building for linking the test executable. ```cmake option(CASC_BUILD_TESTS "Build Test application" OFF) if(CASC_BUILD_TESTS) set(CASC_BUILD_STATIC_LIB ON CACHE BOOL "Force Static library building to link test app" FORCE) message(STATUS "Build Test application") add_executable(CascLib_test ${TEST_SRC_FILES}) set_target_properties(CascLib_test PROPERTIES LINK_FLAGS "-pthread") target_link_libraries(CascLib_test casc_static) install(TARGETS CascLib_test RUNTIME DESTINATION bin) endif() ``` -------------------------------- ### Get File Metadata Source: https://github.com/ladislav-zezula/casclib/blob/master/_autodocs/usage-patterns.md Retrieves and prints detailed metadata for a specified file within the CASC storage. Ensure the file is opened successfully before calling this function. ```c bool GetFileMetadata(HANDLE hStorage, const char *szFileName) { HANDLE hFile; CASC_FILE_FULL_INFO FileInfo; if (!CascOpenFile(hStorage, szFileName, CASC_INVALID_ID, CASC_OPEN_BY_NAME, &hFile)) { printf("Failed to open file\n"); return false; } if (!CascGetFileInfo(hFile, CascFileFullInfo, &FileInfo, sizeof(FileInfo), NULL)) { printf("Failed to get file info\n"); CascCloseFile(hFile); return false; } // Print metadata printf("File: %s\n", szFileName); printf(" Content size: %llu bytes\n", FileInfo.ContentSize); printf(" Encoded size: %llu bytes\n", FileInfo.EncodedSize); printf(" Span count: %u\n", FileInfo.SpanCount); printf(" Data file: %s\n", FileInfo.DataFileName); printf(" Segment index: %u\n", FileInfo.SegmentIndex); if (FileInfo.FileDataId != CASC_INVALID_ID) printf(" File data ID: %u\n", FileInfo.FileDataId); if (FileInfo.LocaleFlags != CASC_INVALID_ID) printf(" Locale flags: 0x%08x\n", FileInfo.LocaleFlags); if (FileInfo.ContentFlags != CASC_INVALID_ID) printf(" Content flags: 0x%08x\n", FileInfo.ContentFlags); CascCloseFile(hFile); return true; } ``` -------------------------------- ### Get File Size (32-bit) Source: https://github.com/ladislav-zezula/casclib/blob/master/_autodocs/api-reference/file-operations.md Retrieves the low 32 bits of an open file's size. The high 32 bits can be optionally retrieved. This is a legacy function; CascGetFileSize64 is preferred. ```c DWORD WINAPI CascGetFileSize(HANDLE hFile, PDWORD pdwFileSizeHigh); ``` ```c DWORD SizeLow, SizeHigh; SizeLow = CascGetFileSize(hFile, &SizeHigh); if (SizeLow == INVALID_HANDLE_VALUE) { printf("Failed to get file size: %u\n", GetCascError()); } else { ULONGLONG FileSize = ((ULONGLONG)SizeHigh << 32) | SizeLow; printf("File size: %llu bytes\n", FileSize); } ``` -------------------------------- ### Enumerate Files Source: https://github.com/ladislav-zezula/casclib/blob/master/_autodocs/README.md Finds and lists files within a storage that match a given wildcard pattern. Prints the filename and size for each found file. ```c CASC_FIND_DATA FindData; HANDLE hFind; hFind = CascFindFirstFile(hStorage, "*.blp", &FindData, NULL); if (hFind != INVALID_HANDLE_VALUE) { do { printf("File: %s (Size: %llu bytes)\n", FindData.szFileName, FindData.FileSize); } while (CascFindNextFile(hFind, &FindData)); CascFindClose(hFind); } ``` -------------------------------- ### Handling CDN Download Errors in CASCLib Source: https://github.com/ladislav-zezula/casclib/blob/master/_autodocs/errors.md Provides an example of handling errors during a CDN download using CascCdnDownload. It checks for network issues, file not found on CDN, and memory allocation failures. ```c DWORD FileSize; LPBYTE pData; pData = CascCdnDownload( _T("http://us.patch.battle.net:1119"), _T("wow"), _T("config/versions"), &FileSize ); if (pData == NULL) { DWORD dwErr = GetCascError(); switch (dwErr) { case ERROR_NETWORK_NOT_AVAILABLE: printf("No network connectivity\n"); break; case ERROR_FILE_NOT_FOUND: printf("File not found on CDN\n"); break; case ERROR_NOT_ENOUGH_MEMORY: printf("Not enough memory to download file\n"); break; default: printf("Download failed: error %u\n", dwErr); break; } } else { printf("Downloaded %u bytes\n", FileSize); CascCdnFree(pData); } ``` -------------------------------- ### Static Library Build Option Source: https://github.com/ladislav-zezula/casclib/blob/master/CMakeLists.txt Enables building a statically linked library. Defines the library name and includes directories. ```cmake option(CASC_BUILD_STATIC_LIB "Build static linked library" OFF) if(CASC_BUILD_STATIC_LIB) message(STATUS "Build static linked library") add_library(casc_static STATIC ${SRC_FILES} ${HEADER_FILES}) target_link_libraries(casc_static ${LINK_LIBS}) set_target_properties(casc_static PROPERTIES OUTPUT_NAME casc) target_include_directories(casc_static PUBLIC $ $ ) install(TARGETS casc_static EXPORT CascLibTargets ``` -------------------------------- ### CASC_OPEN_STORAGE_ARGS Structure Source: https://github.com/ladislav-zezula/casclib/blob/master/_autodocs/types.md Extended arguments for configuring storage opening with CascOpenStorageEx(). Requires setting the Size field. ```c typedef struct _CASC_OPEN_STORAGE_ARGS { size_t Size; // Size of this structure (must be sizeof(CASC_OPEN_STORAGE_ARGS)) LPCTSTR szLocalPath; // Path to storage directory or local cache LPCTSTR szCodeName; // Product code name (overrides szParams) LPCTSTR szRegion; // Product region PFNPROGRESSCALLBACK PfnProgressCallback; // Progress callback void * PtrProgressParam; // Parameter for progress callback PFNPRODUCTCALLBACK PfnProductCallback; // Product selection callback void * PtrProductParam; // Parameter for product callback DWORD dwLocaleMask; // Locale mask (e.g., CASC_LOCALE_ENUS) DWORD dwFlags; // Feature flags (CASC_FEATURE_*) LPCTSTR szBuildKey; // Build key (specific build version) LPCTSTR szCdnHostUrl; // Custom CDN URL } CASC_OPEN_STORAGE_ARGS; ``` -------------------------------- ### Product Selection Callback Function Source: https://github.com/ladislav-zezula/casclib/blob/master/_autodocs/configuration.md A callback function that allows the user to select a product from a list when opening a multi-product storage. It prints available products and reads user input. ```c bool WINAPI ProductSelectionCallback( void * PtrUserParam, LPCSTR * ProductList, size_t ProductCount, size_t * PtrSelectedProduct) { printf("Available products:\n"); for (size_t i = 0; i < ProductCount; i++) { printf(" %zu: %s\n", i, ProductList[i]); } printf("Select product (0-%zu): ", ProductCount - 1); size_t selection; scanf("%zu", &selection); if (selection < ProductCount) { *PtrSelectedProduct = selection; return false; // Continue with selection } return true; // Cancel } ``` -------------------------------- ### Defining Source Files Source: https://github.com/ladislav-zezula/casclib/blob/master/CMakeLists.txt Lists all source files for the project, categorized by their respective subdirectories. ```cmake set(SRC_FILES src/common/Common.cpp src/common/Directory.cpp src/common/Csv.cpp src/common/FileStream.cpp src/common/FileTree.cpp src/common/ListFile.cpp src/common/Mime.cpp src/common/RootHandler.cpp src/common/Sockets.cpp src/hashes/md5.cpp src/hashes/sha1.cpp src/jenkins/lookup3.c src/overwatch/apm.cpp src/overwatch/cmf.cpp src/overwatch/aes.cpp src/CascDecompress.cpp src/CascDecrypt.cpp src/CascDumpData.cpp src/CascFiles.cpp src/CascFindFile.cpp src/CascIndexFiles.cpp src/CascOpenFile.cpp src/CascOpenStorage.cpp src/CascReadFile.cpp src/CascRootFile_Diablo3.cpp src/CascRootFile_Install.cpp src/CascRootFile_MNDX.cpp src/CascRootFile_Text.cpp src/CascRootFile_TVFS.cpp src/CascRootFile_OW.cpp src/CascRootFile_WoW.cpp ) ``` -------------------------------- ### Read Entire File into Buffer with CascLib Source: https://github.com/ladislav-zezula/casclib/blob/master/_autodocs/usage-patterns.md Provides a function to read the entire content of a file into a dynamically allocated buffer. It first gets the file size, allocates memory, and then reads the file in chunks. This pattern is suitable when the entire file content is needed in memory at once. ```cpp LPBYTE ReadCompleteFile(HANDLE hStorage, const char *szFileName, ULONGLONG *pFileSize) { HANDLE hFile; LPBYTE pBuffer = NULL; ULONGLONG FileSize; ULONGLONG Offset = 0; DWORD BytesToRead, BytesRead; // Open file if (!CascOpenFile(hStorage, szFileName, CASC_INVALID_ID, CASC_OPEN_BY_NAME, &hFile)) { printf("Failed to open: %s\n", szFileName); return NULL; } // Get file size if (!CascGetFileSize64(hFile, &FileSize)) { printf("Failed to get file size\n"); CascCloseFile(hFile); return NULL; } // Allocate buffer pBuffer = (LPBYTE)malloc((size_t)FileSize); if (pBuffer == NULL) { printf("Out of memory\n"); CascCloseFile(hFile); return NULL; } // Read entire file while (Offset < FileSize) { BytesToRead = (DWORD)((FileSize - Offset) < 0x10000 ? (FileSize - Offset) : 0x10000); if (!CascReadFile(hFile, pBuffer + Offset, BytesToRead, &BytesRead)) { printf("Read failed at offset %llu\n", Offset); free(pBuffer); CascCloseFile(hFile); return NULL; } if (BytesRead == 0) break; // EOF Offset += BytesRead; } // Return results *pFileSize = Offset; CascCloseFile(hFile); return pBuffer; } ```