mirror of
https://github.com/TrinityCore/TrinityCore.git
synced 2026-01-16 07:30:42 +01:00
Dep/CascLib: Update to ladislav-zezula/CascLib@07ab5f37ad
(cherry picked from commit 464d8e39e0)
This commit is contained in:
@@ -23,6 +23,7 @@
|
||||
|
||||
#if defined(_DEBUG) && !defined(CASCLIB_NODEBUG)
|
||||
#define CASCLIB_DEBUG
|
||||
//#define CASCLIB_WRITE_VERIFIED_FILENAMES // If defined, TRootHandler_WoW will save all files whose hashes are confirmed
|
||||
#endif
|
||||
|
||||
#include "CascPort.h"
|
||||
@@ -109,14 +110,13 @@ typedef struct _CASC_BUILD_FILE
|
||||
} CASC_BUILD_FILE, *PCASC_BUILD_FILE;
|
||||
|
||||
// Information about index file
|
||||
struct CASC_INDEX
|
||||
typedef struct _CASC_INDEX
|
||||
{
|
||||
CASC_BLOB FileData;
|
||||
LPTSTR szFileName; // Full name of the index file
|
||||
DWORD NewSubIndex; // New subindex
|
||||
DWORD OldSubIndex; // Old subindex
|
||||
};
|
||||
typedef CASC_INDEX * PCASC_INDEX;
|
||||
} CASC_INDEX, *PCASC_INDEX;
|
||||
|
||||
// Normalized header of the index files.
|
||||
// Both version 1 and version 2 are converted to this structure
|
||||
@@ -277,6 +277,22 @@ struct TCascStorage
|
||||
hs->ClassName == CASC_MAGIC_STORAGE) ? hs : NULL;
|
||||
}
|
||||
|
||||
DWORD SetProductCodeName(LPCSTR szNewCodeName, size_t nLength = 0)
|
||||
{
|
||||
if(szCodeName == NULL && szNewCodeName != NULL)
|
||||
{
|
||||
// Make sure we have the length
|
||||
if(nLength == 0)
|
||||
nLength = strlen(szNewCodeName);
|
||||
|
||||
// Allocate the code name buffer and copy from ANSI string
|
||||
if((szCodeName = CASC_ALLOC<TCHAR>(nLength + 1)) == NULL)
|
||||
return ERROR_NOT_ENOUGH_MEMORY;
|
||||
CascStrCopy(szCodeName, nLength + 1, szNewCodeName, nLength);
|
||||
}
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
// Class recognizer. Has constant value of 'CASCSTOR' (CASC_MAGIC_STORAGE)
|
||||
ULONGLONG ClassName;
|
||||
|
||||
@@ -456,7 +472,7 @@ inline void FreeCascBlob(PCASC_BLOB pBlob)
|
||||
//-----------------------------------------------------------------------------
|
||||
// Text file parsing (CascFiles.cpp)
|
||||
|
||||
bool InvokeProgressCallback(TCascStorage * hs, LPCSTR szMessage, LPCSTR szObject, DWORD CurrentValue, DWORD TotalValue);
|
||||
bool InvokeProgressCallback(TCascStorage * hs, CASC_PROGRESS_MSG Message, LPCSTR szObject, DWORD CurrentValue, DWORD TotalValue);
|
||||
DWORD GetFileSpanInfo(PCASC_CKEY_ENTRY pCKeyEntry, PULONGLONG PtrContentSize, PULONGLONG PtrEncodedSize = NULL);
|
||||
DWORD FetchCascFile(TCascStorage * hs, CPATH_TYPE PathType, LPBYTE pbEKey, LPCTSTR szExtension, CASC_PATH<TCHAR> & LocalPath, PCASC_ARCHIVE_INFO pArchiveInfo = NULL);
|
||||
DWORD CheckCascBuildFileExact(CASC_BUILD_FILE & BuildFile, LPCTSTR szLocalPath);
|
||||
|
||||
@@ -496,16 +496,7 @@ static DWORD LoadVfsRootEntry(TCascStorage * hs, const char * szVariableName, co
|
||||
|
||||
static DWORD LoadBuildProductId(TCascStorage * hs, const char * /* szVariableName */, const char * szDataBegin, const char * szDataEnd, void * /* pvParam */)
|
||||
{
|
||||
size_t nLength = (szDataEnd - szDataBegin);
|
||||
|
||||
if(hs->szCodeName == NULL)
|
||||
{
|
||||
if((hs->szCodeName = CASC_ALLOC<TCHAR>(nLength + 1)) != NULL)
|
||||
{
|
||||
CascStrCopy(hs->szCodeName, nLength + 1, szDataBegin, nLength);
|
||||
}
|
||||
}
|
||||
|
||||
hs->SetProductCodeName(szDataBegin, (szDataEnd - szDataBegin));
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -559,14 +550,6 @@ static int LoadQueryKey(const CASC_CSV_COLUMN & Column, CASC_BLOB & Key)
|
||||
return LoadHashArray(&Key, Column.szValue, Column.szValue + Column.nLength, 1);
|
||||
}
|
||||
|
||||
static void SetProductCodeName(TCascStorage * hs, LPCSTR szCodeName)
|
||||
{
|
||||
if(hs->szCodeName == NULL && szCodeName != NULL)
|
||||
{
|
||||
hs->szCodeName = CascNewStrA2T(szCodeName);
|
||||
}
|
||||
}
|
||||
|
||||
static DWORD GetDefaultCdnServers(TCascStorage * hs, const CASC_CSV_COLUMN & Column)
|
||||
{
|
||||
if(hs->szCdnServers == NULL && Column.nLength != 0)
|
||||
@@ -661,12 +644,12 @@ static DWORD ParseFile_BuildInfo(TCascStorage * hs, CASC_CSV & Csv)
|
||||
return ERROR_CANCELLED;
|
||||
|
||||
// We now have preferred product to open
|
||||
SetProductCodeName(hs, ProductsList[nChoiceIndex]);
|
||||
hs->SetProductCodeName(ProductsList[nChoiceIndex]);
|
||||
}
|
||||
else if(nProductCount == 1)
|
||||
{
|
||||
// We now have preferred product to open
|
||||
SetProductCodeName(hs, ProductsList[nDefault]);
|
||||
hs->SetProductCodeName(ProductsList[nDefault]);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -692,7 +675,7 @@ static DWORD ParseFile_BuildInfo(TCascStorage * hs, CASC_CSV & Csv)
|
||||
continue;
|
||||
|
||||
// Save the code name of the selected product
|
||||
SetProductCodeName(hs, Csv[i]["Product!STRING:0"].szValue);
|
||||
hs->SetProductCodeName(Csv[i]["Product!STRING:0"].szValue);
|
||||
nSelected = i;
|
||||
break;
|
||||
}
|
||||
@@ -949,7 +932,7 @@ static DWORD LoadCsvFile(TCascStorage * hs, PARSE_REGION_LINE PfnParseRegionLine
|
||||
{
|
||||
// Inform the user that we are downloading something
|
||||
CascStrCopy(szFileNameA, _countof(szFileNameA), szFileName);
|
||||
if(InvokeProgressCallback(hs, "Downloading the \"%s\" file", szFileNameA, 0, 0))
|
||||
if(InvokeProgressCallback(hs, CascProgressDownloadingFile, szFileNameA, 0, 0))
|
||||
return ERROR_CANCELLED;
|
||||
|
||||
// Download the file using Ribbit/HTTP protocol
|
||||
@@ -1275,6 +1258,23 @@ static DWORD HttpDownloadFile(
|
||||
return dwErrCode;
|
||||
}
|
||||
|
||||
DWORD SetProductCodeName(TCascStorage * hs, LPCSTR szCodeName, size_t nLength)
|
||||
{
|
||||
if(hs->szCodeName == NULL && szCodeName != NULL)
|
||||
{
|
||||
// Make sure we have the length
|
||||
if(nLength == 0)
|
||||
{
|
||||
nLength = strlen(szCodeName);
|
||||
}
|
||||
|
||||
if((hs->szCodeName = CASC_ALLOC<TCHAR>(nLength + 1)) == NULL)
|
||||
return ERROR_NOT_ENOUGH_MEMORY;
|
||||
CascStrCopy(hs->szCodeName, nLength + 1, szCodeName, nLength);
|
||||
}
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
DWORD FetchCascFile(
|
||||
TCascStorage * hs,
|
||||
LPCTSTR szRootPath,
|
||||
@@ -1450,13 +1450,13 @@ static LPTSTR CheckForDirectories(LPCTSTR szParentFolder, ...)
|
||||
//-----------------------------------------------------------------------------
|
||||
// Public functions
|
||||
|
||||
bool InvokeProgressCallback(TCascStorage * hs, LPCSTR szMessage, LPCSTR szObject, DWORD CurrentValue, DWORD TotalValue)
|
||||
bool InvokeProgressCallback(TCascStorage * hs, CASC_PROGRESS_MSG Message, LPCSTR szObject, DWORD CurrentValue, DWORD TotalValue)
|
||||
{
|
||||
PCASC_OPEN_STORAGE_ARGS pArgs = hs->pArgs;
|
||||
bool bResult = false;
|
||||
|
||||
if(pArgs && pArgs->PfnProgressCallback)
|
||||
bResult = pArgs->PfnProgressCallback(pArgs->PtrProgressParam, szMessage, szObject, CurrentValue, TotalValue);
|
||||
bResult = pArgs->PfnProgressCallback(pArgs->PtrProgressParam, Message, szObject, CurrentValue, TotalValue);
|
||||
return bResult;
|
||||
}
|
||||
|
||||
@@ -1522,14 +1522,14 @@ DWORD CheckCascBuildFileExact(CASC_BUILD_FILE & BuildFile, LPCTSTR szLocalPath)
|
||||
}
|
||||
|
||||
// Unrecognized file name
|
||||
return ERROR_BAD_FORMAT;
|
||||
return ERROR_FILE_NOT_FOUND;
|
||||
}
|
||||
|
||||
DWORD CheckCascBuildFileDirs(CASC_BUILD_FILE & BuildFile, LPCTSTR szLocalPath)
|
||||
{
|
||||
CASC_PATH<TCHAR> WorkPath(szLocalPath, NULL);
|
||||
DWORD dwErrCode = ERROR_FILE_NOT_FOUND;
|
||||
|
||||
DWORD dwLevelCount = 0;
|
||||
|
||||
// Clear the build file structure
|
||||
memset(&BuildFile, 0, sizeof(CASC_BUILD_FILE));
|
||||
|
||||
@@ -1547,16 +1547,15 @@ DWORD CheckCascBuildFileDirs(CASC_BUILD_FILE & BuildFile, LPCTSTR szLocalPath)
|
||||
}
|
||||
}
|
||||
|
||||
// Try to cut off one path path
|
||||
if(!WorkPath.CutLastPart())
|
||||
// Try to cut off one path path. Don't go indefinitely.
|
||||
if((dwLevelCount > 5) || !WorkPath.CutLastPart())
|
||||
{
|
||||
dwErrCode = ERROR_PATH_NOT_FOUND;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Unrecognized file name
|
||||
return dwErrCode;
|
||||
// None of the supported file names was found
|
||||
return ERROR_FILE_NOT_FOUND;
|
||||
}
|
||||
|
||||
DWORD CheckOnlineStorage(PCASC_OPEN_STORAGE_ARGS pArgs, CASC_BUILD_FILE & BuildFile, bool bOnlineStorage)
|
||||
@@ -1616,6 +1615,7 @@ DWORD CheckArchiveFilesDirectories(TCascStorage * hs)
|
||||
DWORD CheckDataFilesDirectory(TCascStorage * hs)
|
||||
{
|
||||
CASC_PATH<TCHAR> DataPath(hs->szRootPath, _T("data"), NULL);
|
||||
DWORD dwErrCode;
|
||||
bool bTwoDigitFolderFound = false;
|
||||
|
||||
// When CASC_FEATURE_ONLINE is not set, then the folder must exist
|
||||
@@ -1623,17 +1623,15 @@ DWORD CheckDataFilesDirectory(TCascStorage * hs)
|
||||
{
|
||||
// Check if there are subfolders at all. If not, do not bother
|
||||
// the file system with open requests into data files folder
|
||||
if(ScanDirectory(DataPath, CheckForTwoDigitFolder, NULL, &bTwoDigitFolderFound) != ERROR_SUCCESS)
|
||||
return ERROR_PATH_NOT_FOUND;
|
||||
if((dwErrCode = ScanDirectory(DataPath, CheckForTwoDigitFolder, NULL, &bTwoDigitFolderFound)) != ERROR_SUCCESS)
|
||||
return dwErrCode;
|
||||
|
||||
if(bTwoDigitFolderFound == false)
|
||||
return ERROR_PATH_NOT_FOUND;
|
||||
}
|
||||
|
||||
// Create the path for raw files
|
||||
if((hs->szFilesPath = DataPath.New()) == NULL)
|
||||
return ERROR_NOT_ENOUGH_MEMORY;
|
||||
return ERROR_SUCCESS;
|
||||
return ((hs->szFilesPath = DataPath.New()) == NULL) ? ERROR_NOT_ENOUGH_MEMORY : ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
DWORD LoadBuildFile_Versions_Cdns(TCascStorage * hs)
|
||||
@@ -1705,7 +1703,7 @@ DWORD LoadCdnConfigFile(TCascStorage * hs)
|
||||
assert(hs->CdnConfigKey.pbData != NULL && hs->CdnConfigKey.cbData == MD5_HASH_SIZE);
|
||||
|
||||
// Inform the user about what we are doing
|
||||
if(InvokeProgressCallback(hs, "Loading CDN config file", NULL, 0, 0))
|
||||
if(InvokeProgressCallback(hs, CascProgressLoadingFile, "CDN config", 0, 0))
|
||||
return ERROR_CANCELLED;
|
||||
|
||||
// Load the CDN config file
|
||||
@@ -1718,7 +1716,7 @@ DWORD LoadCdnBuildFile(TCascStorage * hs)
|
||||
assert(hs->CdnBuildKey.pbData != NULL && hs->CdnBuildKey.cbData == MD5_HASH_SIZE);
|
||||
|
||||
// Inform the user about what we are doing
|
||||
if(InvokeProgressCallback(hs, "Loading CDN build file", NULL, 0, 0))
|
||||
if(InvokeProgressCallback(hs, CascProgressLoadingFile, "CDN build", 0, 0))
|
||||
return ERROR_CANCELLED;
|
||||
|
||||
// Load the CDN config file. Note that we don't
|
||||
|
||||
@@ -276,7 +276,7 @@ static DWORD LoadIndexItems(TCascStorage * hs, CASC_INDEX_HEADER & InHeader, EKE
|
||||
while((pbEKeyEntry + EntryLength) <= pbEKeyEnd)
|
||||
{
|
||||
// ENCODING for Starcraft II Beta
|
||||
BREAK_ON_XKEY3(pbEKeyEntry, 0x8b, 0x0d, 0x9a);
|
||||
// BREAK_ON_XKEY3(pbEKeyEntry, 0x8b, 0x0d, 0x9a);
|
||||
|
||||
if(!PfnEKeyEntry(hs, InHeader, pbEKeyEntry))
|
||||
return ERROR_INDEX_PARSING_DONE;
|
||||
@@ -487,7 +487,7 @@ static DWORD ProcessLocalIndexFiles(TCascStorage * hs, EKEY_ENTRY_CALLBACK PfnEK
|
||||
CASC_INDEX & IndexFile = hs->IndexFiles[i];
|
||||
|
||||
// Inform the user about what we are doing
|
||||
if(InvokeProgressCallback(hs, "Loading index files", NULL, i, dwIndexCount))
|
||||
if(InvokeProgressCallback(hs, CascProgressLoadingIndexes, NULL, i, dwIndexCount))
|
||||
{
|
||||
dwErrCode = ERROR_CANCELLED;
|
||||
break;
|
||||
@@ -514,7 +514,7 @@ static DWORD LoadLocalIndexFiles(TCascStorage * hs)
|
||||
DWORD dwErrCode;
|
||||
|
||||
// Inform the user about what we are doing
|
||||
if(InvokeProgressCallback(hs, "Loading index files", NULL, 0, 0))
|
||||
if(InvokeProgressCallback(hs, CascProgressLoadingIndexes, NULL, 0, 0))
|
||||
return ERROR_CANCELLED;
|
||||
|
||||
// Perform the directory scan
|
||||
@@ -749,7 +749,7 @@ static DWORD LoadArchiveIndexFiles(TCascStorage * hs)
|
||||
LPBYTE pbIndexHash = hs->ArchivesKey.pbData + (i * MD5_HASH_SIZE);
|
||||
|
||||
// Inform the user about what we are doing
|
||||
if(InvokeProgressCallback(hs, "Downloading archive indexes", NULL, (DWORD)(i), (DWORD)(nArchiveCount)))
|
||||
if(InvokeProgressCallback(hs, CascProgressDownloadingArchiveIndexes, NULL, (DWORD)(i), (DWORD)(nArchiveCount)))
|
||||
{
|
||||
dwErrCode = ERROR_CANCELLED;
|
||||
break;
|
||||
|
||||
@@ -72,6 +72,12 @@ extern "C" {
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(CASCLIB_DETECT_UNICODE_MISMATCHES)
|
||||
#if defined(_UNICODE) != defined(CASCLIB_UNICODE)
|
||||
#error CascLib was not built with the same UNICODE setting as your project
|
||||
#endif
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Defines
|
||||
|
||||
@@ -318,12 +324,21 @@ typedef struct _CASC_FILE_SPAN_INFO
|
||||
//-----------------------------------------------------------------------------
|
||||
// Extended version of CascOpenStorage
|
||||
|
||||
typedef enum _CASC_PROGRESS_MSG
|
||||
{
|
||||
CascProgressLoadingFile, // "Loading file: %s"
|
||||
CascProgressLoadingManifest, // "Loading manifest: %s"
|
||||
CascProgressDownloadingFile, // "Downloading file: %s"
|
||||
CascProgressLoadingIndexes, // "Loading index files"
|
||||
CascProgressDownloadingArchiveIndexes, // "Downloading archive indexes"
|
||||
} CASC_PROGRESS_MSG, *PCASC_PROGRESS_MSG;
|
||||
|
||||
// Some operations (e.g. opening an online storage) may take long time.
|
||||
// This callback allows an application to be notified about loading progress
|
||||
// and even cancel the storage loading process
|
||||
typedef bool (WINAPI * PFNPROGRESSCALLBACK)( // Return 'true' to cancel the loading process
|
||||
void * PtrUserParam, // User-specific parameter passed to the callback
|
||||
LPCSTR szWork, // Text for the current activity (example: "Loading "ENCODING" file")
|
||||
CASC_PROGRESS_MSG ProgressMsg, // Text for the current activity. The target callback needs to translate it into language-specific message
|
||||
LPCSTR szObject, // (optional) name of the object tied to the activity (example: index file name)
|
||||
DWORD CurrentValue, // (optional) current object being processed
|
||||
DWORD TotalValue // (optional) If non-zero, this is the total number of objects to process
|
||||
|
||||
@@ -442,7 +442,7 @@ static DWORD LoadEncodingManifest(TCascStorage * hs)
|
||||
DWORD dwErrCode = ERROR_SUCCESS;
|
||||
|
||||
// Inform the user about what we are doing
|
||||
if(InvokeProgressCallback(hs, "Loading ENCODING manifest", NULL, 0, 0))
|
||||
if(InvokeProgressCallback(hs, CascProgressLoadingManifest, "ENCODING", 0, 0))
|
||||
return ERROR_CANCELLED;
|
||||
|
||||
// Fill-in the information from the index entry and insert it to the file tree
|
||||
@@ -753,7 +753,7 @@ static int LoadDownloadManifest(TCascStorage * hs)
|
||||
DWORD dwErrCode = ERROR_SUCCESS;
|
||||
|
||||
// Inform the user about what we are doing
|
||||
if(InvokeProgressCallback(hs, "Loading DOWNLOAD manifest", NULL, 0, 0))
|
||||
if(InvokeProgressCallback(hs, CascProgressLoadingManifest, "DOWNLOAD", 0, 0))
|
||||
return ERROR_CANCELLED;
|
||||
|
||||
// Load the entire DOWNLOAD file to memory
|
||||
@@ -786,7 +786,7 @@ static int LoadInstallManifest(TCascStorage * hs)
|
||||
DWORD dwErrCode = ERROR_SUCCESS;
|
||||
|
||||
// Inform the user about what we are doing
|
||||
if(InvokeProgressCallback(hs, "Loading INSTALL manifest", NULL, 0, 0))
|
||||
if(InvokeProgressCallback(hs, CascProgressLoadingManifest, "INSTALL", 0, 0))
|
||||
return ERROR_CANCELLED;
|
||||
|
||||
// Load the entire DOWNLOAD file to memory
|
||||
@@ -854,7 +854,7 @@ static int LoadBuildManifest(TCascStorage * hs, DWORD dwLocaleMask)
|
||||
assert(hs->pRootHandler == NULL);
|
||||
|
||||
// Inform the user about what we are doing
|
||||
if(InvokeProgressCallback(hs, "Loading ROOT manifest", NULL, 0, 0))
|
||||
if(InvokeProgressCallback(hs, CascProgressLoadingManifest, "ROOT", 0, 0))
|
||||
return ERROR_CANCELLED;
|
||||
|
||||
// Locale: The default parameter is 0 - in that case, we load all locales
|
||||
@@ -913,6 +913,10 @@ __LoadRootFile:
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
dwErrCode = ERROR_BAD_FORMAT;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -922,7 +926,7 @@ __LoadRootFile:
|
||||
// Handle reparsing of the root file
|
||||
if(dwErrCode == ERROR_REPARSE_ROOT && pCKeyEntry != &hs->RootFile)
|
||||
{
|
||||
if(InvokeProgressCallback(hs, "Loading ROOT manifest (reparsed)", NULL, 0, 0))
|
||||
if(InvokeProgressCallback(hs, CascProgressLoadingManifest, "ROOT (reparsed)", 0, 0))
|
||||
return ERROR_CANCELLED;
|
||||
|
||||
// Replace the root handler
|
||||
@@ -1182,6 +1186,12 @@ static DWORD LoadCascStorage(TCascStorage * hs, PCASC_OPEN_STORAGE_ARGS pArgs, L
|
||||
hs->dwBuildNumber = 21742 + hs->InstallCKey.ContentSize;
|
||||
}
|
||||
|
||||
// Make sure we have a code name. Not a case of WoW build 22267
|
||||
if(hs->szCodeName == NULL && hs->dwBuildNumber == 22267)
|
||||
{
|
||||
hs->SetProductCodeName("wow", 3);
|
||||
}
|
||||
|
||||
// Create the array of CKey entries. Each entry represents a file in the storage
|
||||
if(dwErrCode == ERROR_SUCCESS)
|
||||
{
|
||||
@@ -1337,6 +1347,13 @@ static DWORD ParseOpenParams(LPTSTR szParams, PCASC_OPEN_STORAGE_ARGS pArgs)
|
||||
pArgs->szRegion = szParamsPtr;
|
||||
}
|
||||
|
||||
// There could be region appended at the end
|
||||
if((szParamsPtr = GetNextParam(szParamsPtr)) != NULL)
|
||||
{
|
||||
if(pArgs->szBuildKey && pArgs->szBuildKey[0])
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
pArgs->szBuildKey = szParamsPtr;
|
||||
}
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
@@ -100,10 +100,6 @@
|
||||
|
||||
#define PKEXPORT
|
||||
|
||||
#ifndef __SYS_ZLIB
|
||||
#define __SYS_ZLIB
|
||||
#endif
|
||||
|
||||
#ifndef __BIG_ENDIAN__
|
||||
#define CASCLIB_PLATFORM_LITTLE_ENDIAN
|
||||
#endif
|
||||
@@ -210,6 +206,7 @@
|
||||
#define _tremove remove
|
||||
#define _taccess access
|
||||
#define _access access
|
||||
#define _tfopen fopen
|
||||
|
||||
#define _stricmp strcasecmp
|
||||
#define _strnicmp strncasecmp
|
||||
|
||||
@@ -1290,6 +1290,9 @@ bool WINAPI CascReadFile(HANDLE hFile, void * pvBuffer, DWORD dwBytesToRead, PDW
|
||||
case CascCacheLastFrame:
|
||||
dwBytesRead2 = ReadFile_FrameCached(hf, pbBuffer, StartOffset, EndOffset);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// If the second-stage-read failed, we invalidate the entire operation and return 0 bytes read
|
||||
|
||||
@@ -34,7 +34,7 @@ typedef struct _APM_HEADER_V3
|
||||
// Followed by the array of APM_ENTRY (count is in "EntryCount")
|
||||
// Followed by the array of APM_PACKAGE (count is in "PackageCount")
|
||||
|
||||
} APM_HEADER_V3, * PAPM_HEADER_V3;
|
||||
} APM_HEADER_V3, *PAPM_HEADER_V3;
|
||||
|
||||
typedef struct _APM_HEADER_V2
|
||||
{
|
||||
@@ -48,7 +48,7 @@ typedef struct _APM_HEADER_V2
|
||||
// Followed by the array of APM_ENTRY (count is in "EntryCount")
|
||||
// Followed by the array of APM_PACKAGE (count is in "PackageCount")
|
||||
|
||||
} APM_HEADER_V2, * PAPM_HEADER_V2;
|
||||
} APM_HEADER_V2, *PAPM_HEADER_V2;
|
||||
|
||||
typedef struct _APM_HEADER_V1
|
||||
{
|
||||
@@ -61,7 +61,7 @@ typedef struct _APM_HEADER_V1
|
||||
// Followed by the array of APM_ENTRY (count is in "EntryCount")
|
||||
// Followed by the array of APM_PACKAGE (count is in "PackageCount")
|
||||
|
||||
} APM_HEADER_V1, * PAPM_HEADER_V1;
|
||||
} APM_HEADER_V1, *PAPM_HEADER_V1;
|
||||
|
||||
// On-disk format, size = 0x0C
|
||||
typedef struct _APM_ENTRY_V1
|
||||
@@ -69,7 +69,7 @@ typedef struct _APM_ENTRY_V1
|
||||
DWORD Index;
|
||||
DWORD HashA_Lo; // Must split the hashes in order to make this structure properly aligned
|
||||
DWORD HashA_Hi;
|
||||
} APM_ENTRY_V1, * PAPM_ENTRY_V1;
|
||||
} APM_ENTRY_V1, *PAPM_ENTRY_V1;
|
||||
|
||||
// On-disk format, size = 0x14
|
||||
typedef struct _APM_ENTRY_V2
|
||||
@@ -91,7 +91,7 @@ typedef struct _APM_PACKAGE_ENTRY_V1
|
||||
ULONGLONG PackageGUID; // 077 file
|
||||
ULONGLONG Unknown1;
|
||||
DWORD Unknown2;
|
||||
} APM_PACKAGE_ENTRY_V1, * PAPM_PACKAGE_ENTRY_V1;
|
||||
} APM_PACKAGE_ENTRY_V1, *PAPM_PACKAGE_ENTRY_V1;
|
||||
|
||||
// On-disk format
|
||||
typedef struct _APM_PACKAGE_ENTRY_V2
|
||||
|
||||
@@ -712,7 +712,7 @@ struct TRootHandler_TVFS : public TFileTreeRoot
|
||||
FileTree.SetKeyLength(RootHeader.EKeySize);
|
||||
|
||||
// Initialize the array of span entries
|
||||
dwErrCode = SpanArray.Create(sizeof(CASC_CKEY_ENTRY), 0x100);
|
||||
dwErrCode = SpanArray.Create(sizeof(CASC_CKEY_ENTRY), 0x10000);
|
||||
if(dwErrCode != ERROR_SUCCESS)
|
||||
return dwErrCode;
|
||||
|
||||
|
||||
@@ -35,6 +35,19 @@ typedef enum _ROOT_FORMAT
|
||||
RootFormatWoW_v2, // Since build 30080 (WoW 8.2.0)
|
||||
} ROOT_FORMAT, *PROOT_FORMAT;
|
||||
|
||||
// The last byte of the structure causes wrong alignment with default compiler options
|
||||
#pragma pack(push, 1)
|
||||
typedef struct _FILE_ROOT_GROUP_HEADER_58221 // Since build 58221 (11.1.0.58221)
|
||||
{
|
||||
DWORD NumberOfFiles; // Number of entries
|
||||
DWORD LocaleFlags; // File locale mask (CASC_LOCALE_XXX)
|
||||
DWORD ContentFlags1;
|
||||
DWORD ContentFlags2;
|
||||
BYTE ContentFlags3;
|
||||
|
||||
} FILE_ROOT_GROUPHEADER_58221, *PFILE_ROOT_GROUPHEADER_58221;
|
||||
#pragma pack(pop)
|
||||
|
||||
// ROOT file header since build 50893 (10.1.7)
|
||||
typedef struct _FILE_ROOT_HEADER_50893
|
||||
{
|
||||
@@ -43,7 +56,7 @@ typedef struct _FILE_ROOT_HEADER_50893
|
||||
DWORD Version; // Must be 1
|
||||
DWORD TotalFiles;
|
||||
DWORD FilesWithNameHash;
|
||||
} FILE_ROOT_HEADER_50893, * PFILE_ROOT_HEADER_50893;
|
||||
} FILE_ROOT_HEADER_50893, *PFILE_ROOT_HEADER_50893;
|
||||
|
||||
// ROOT file header since build 30080 (8.2.0)
|
||||
typedef struct _FILE_ROOT_HEADER_30080
|
||||
@@ -97,14 +110,15 @@ struct TRootHandler_WoW : public TFileTreeRoot
|
||||
{
|
||||
public:
|
||||
|
||||
typedef LPBYTE (*CAPTURE_ROOT_HEADER)(LPBYTE pbRootPtr, LPBYTE pbRootEnd, PROOT_FORMAT RootFormat, PDWORD FileCounterHashless);
|
||||
typedef LPBYTE (*CAPTURE_ROOT_HEADER)(LPBYTE pbRootPtr, LPBYTE pbRootEnd, PROOT_FORMAT RootFormat, PDWORD FileCounterHashless, PDWORD Version);
|
||||
|
||||
TRootHandler_WoW(ROOT_FORMAT RFormat, DWORD HashlessFileCount) : TFileTreeRoot(FTREE_FLAGS_WOW)
|
||||
TRootHandler_WoW(ROOT_FORMAT aRootFormat, DWORD aFileCounterHashless, LPCTSTR szDumpFile = NULL) : TFileTreeRoot(FTREE_FLAGS_WOW)
|
||||
{
|
||||
// Turn off the "we know file names" bit
|
||||
FileCounterHashless = HashlessFileCount;
|
||||
FileCounterHashless = aFileCounterHashless;
|
||||
FileCounter = 0;
|
||||
RootFormat = RFormat;
|
||||
RootFormat = aRootFormat;
|
||||
fp = NULL;
|
||||
|
||||
// Update the flags based on format
|
||||
switch(RootFormat)
|
||||
@@ -117,10 +131,44 @@ struct TRootHandler_WoW : public TFileTreeRoot
|
||||
dwFeatures |= CASC_FEATURE_ROOT_CKEY | CASC_FEATURE_LOCALE_FLAGS | CASC_FEATURE_CONTENT_FLAGS | CASC_FEATURE_FNAME_HASHES;
|
||||
break;
|
||||
}
|
||||
|
||||
// Create the file for dumping listfile
|
||||
if(szDumpFile && szDumpFile[0])
|
||||
{
|
||||
fp = _tfopen(szDumpFile, _T("wt"));
|
||||
}
|
||||
}
|
||||
|
||||
~TRootHandler_WoW()
|
||||
{
|
||||
if(fp != NULL)
|
||||
fclose(fp);
|
||||
fp = NULL;
|
||||
}
|
||||
|
||||
#ifdef CASCLIB_WRITE_VERIFIED_FILENAMES
|
||||
void VerifyAndLogFileName(LPCSTR szFileName, ULONG FileDataId)
|
||||
{
|
||||
PCASC_FILE_NODE pFileNode;
|
||||
ULONGLONG FileNameHash = CalcFileNameHash(szFileName);
|
||||
|
||||
if((pFileNode = FileTree.Find(FileNameHash)) != NULL)
|
||||
{
|
||||
if(pFileNode->FileNameHash == FileNameHash)
|
||||
{
|
||||
if(FileDataId != 0)
|
||||
fprintf(fp, "%u;%s\n", FileDataId, szFileName);
|
||||
else
|
||||
fprintf(fp, "%s\n", szFileName);
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
#define VerifyAndLogFileName(szFileName, FileDataId) /* */
|
||||
#endif
|
||||
|
||||
// Check for the new format (World of Warcraft 10.1.7, build 50893)
|
||||
static LPBYTE CaptureRootHeader_50893(LPBYTE pbRootPtr, LPBYTE pbRootEnd, PROOT_FORMAT RootFormat, PDWORD FileCounterHashless)
|
||||
static LPBYTE CaptureRootHeader_50893(LPBYTE pbRootPtr, LPBYTE pbRootEnd, PROOT_FORMAT RootFormat, PDWORD FileCounterHashless, PDWORD Version)
|
||||
{
|
||||
FILE_ROOT_HEADER_50893 RootHeader;
|
||||
|
||||
@@ -132,7 +180,7 @@ struct TRootHandler_WoW : public TFileTreeRoot
|
||||
// Verify the root file header
|
||||
if(RootHeader.Signature != CASC_WOW_ROOT_SIGNATURE)
|
||||
return NULL;
|
||||
if(RootHeader.Version != 1)
|
||||
if(RootHeader.Version != 1 && RootHeader.Version != 2)
|
||||
return NULL;
|
||||
if(RootHeader.FilesWithNameHash > RootHeader.TotalFiles)
|
||||
return NULL;
|
||||
@@ -142,11 +190,12 @@ struct TRootHandler_WoW : public TFileTreeRoot
|
||||
|
||||
*RootFormat = RootFormatWoW_v2;
|
||||
*FileCounterHashless = RootHeader.TotalFiles - RootHeader.FilesWithNameHash;
|
||||
*Version = RootHeader.Version;
|
||||
return pbRootPtr + RootHeader.SizeOfHeader;
|
||||
}
|
||||
|
||||
// Check for the root format for build 30080+ (WoW 8.2.0)
|
||||
static LPBYTE CaptureRootHeader_30080(LPBYTE pbRootPtr, LPBYTE pbRootEnd, PROOT_FORMAT RootFormat, PDWORD FileCounterHashless)
|
||||
static LPBYTE CaptureRootHeader_30080(LPBYTE pbRootPtr, LPBYTE pbRootEnd, PROOT_FORMAT RootFormat, PDWORD FileCounterHashless, PDWORD Version)
|
||||
{
|
||||
FILE_ROOT_HEADER_30080 RootHeader;
|
||||
|
||||
@@ -163,11 +212,12 @@ struct TRootHandler_WoW : public TFileTreeRoot
|
||||
|
||||
*RootFormat = RootFormatWoW_v2;
|
||||
*FileCounterHashless = RootHeader.TotalFiles - RootHeader.FilesWithNameHash;
|
||||
*Version = 0;
|
||||
return pbRootPtr + sizeof(FILE_ROOT_HEADER_30080);
|
||||
}
|
||||
|
||||
// Check for the root format for build 18125+ (WoW 6.0.1)
|
||||
static LPBYTE CaptureRootHeader_18125(LPBYTE pbRootPtr, LPBYTE pbRootEnd, PROOT_FORMAT RootFormat, PDWORD FileCounterHashless)
|
||||
static LPBYTE CaptureRootHeader_18125(LPBYTE pbRootPtr, LPBYTE pbRootEnd, PROOT_FORMAT RootFormat, PDWORD FileCounterHashless, PDWORD Version)
|
||||
{
|
||||
size_t DataLength;
|
||||
|
||||
@@ -183,10 +233,11 @@ struct TRootHandler_WoW : public TFileTreeRoot
|
||||
|
||||
*RootFormat = RootFormatWoW_v1;
|
||||
*FileCounterHashless = 0;
|
||||
*Version = 0;
|
||||
return pbRootPtr;
|
||||
}
|
||||
|
||||
static LPBYTE CaptureRootHeader(LPBYTE pbRootPtr, LPBYTE pbRootEnd, PROOT_FORMAT RootFormat, PDWORD FileCounterHashless)
|
||||
static LPBYTE CaptureRootHeader(LPBYTE pbRootPtr, LPBYTE pbRootEnd, PROOT_FORMAT RootFormat, PDWORD FileCounterHashless, PDWORD Version)
|
||||
{
|
||||
CAPTURE_ROOT_HEADER PfnCaptureRootHeader[] =
|
||||
{
|
||||
@@ -199,7 +250,7 @@ struct TRootHandler_WoW : public TFileTreeRoot
|
||||
{
|
||||
LPBYTE pbCapturedPtr;
|
||||
|
||||
if((pbCapturedPtr = PfnCaptureRootHeader[i](pbRootPtr, pbRootEnd, RootFormat, FileCounterHashless)) != NULL)
|
||||
if((pbCapturedPtr = PfnCaptureRootHeader[i](pbRootPtr, pbRootEnd, RootFormat, FileCounterHashless, Version)) != NULL)
|
||||
{
|
||||
return pbCapturedPtr;
|
||||
}
|
||||
@@ -207,16 +258,34 @@ struct TRootHandler_WoW : public TFileTreeRoot
|
||||
return NULL;
|
||||
}
|
||||
|
||||
LPBYTE CaptureRootGroup(FILE_ROOT_GROUP & RootGroup, LPBYTE pbRootPtr, LPBYTE pbRootEnd)
|
||||
LPBYTE CaptureRootGroup(FILE_ROOT_GROUP & RootGroup, LPBYTE pbRootPtr, LPBYTE pbRootEnd, DWORD dwRootVersion)
|
||||
{
|
||||
// Reset the entire root group structure
|
||||
memset(&RootGroup, 0, sizeof(FILE_ROOT_GROUP));
|
||||
|
||||
// Validate the locale block header
|
||||
if((pbRootPtr + sizeof(FILE_ROOT_GROUP_HEADER)) >= pbRootEnd)
|
||||
return NULL;
|
||||
memcpy(&RootGroup.Header, pbRootPtr, sizeof(FILE_ROOT_GROUP_HEADER));
|
||||
pbRootPtr = pbRootPtr + sizeof(FILE_ROOT_GROUP_HEADER);
|
||||
if(dwRootVersion == 0 || dwRootVersion == 1)
|
||||
{
|
||||
// Validate the locale block header
|
||||
if((pbRootPtr + sizeof(FILE_ROOT_GROUP_HEADER)) >= pbRootEnd)
|
||||
return NULL;
|
||||
memcpy(&RootGroup.Header, pbRootPtr, sizeof(FILE_ROOT_GROUP_HEADER));
|
||||
pbRootPtr = pbRootPtr + sizeof(FILE_ROOT_GROUP_HEADER);
|
||||
}
|
||||
else if(dwRootVersion == 2)
|
||||
{
|
||||
PFILE_ROOT_GROUPHEADER_58221 pRootGroupHeader;
|
||||
|
||||
// Get pointer to the root group header
|
||||
if((pbRootPtr + sizeof(FILE_ROOT_GROUPHEADER_58221)) >= pbRootEnd)
|
||||
return NULL;
|
||||
pRootGroupHeader = (PFILE_ROOT_GROUPHEADER_58221)pbRootPtr;
|
||||
pbRootPtr = pbRootPtr + sizeof(FILE_ROOT_GROUPHEADER_58221);
|
||||
|
||||
// Convert to old ContentFlags for now...
|
||||
RootGroup.Header.NumberOfFiles = pRootGroupHeader->NumberOfFiles;
|
||||
RootGroup.Header.ContentFlags = pRootGroupHeader->ContentFlags1 | pRootGroupHeader->ContentFlags2 | (DWORD)(pRootGroupHeader->ContentFlags3 << 17);
|
||||
RootGroup.Header.LocaleFlags = pRootGroupHeader->LocaleFlags;
|
||||
}
|
||||
|
||||
// Validate the array of file data IDs
|
||||
if((pbRootPtr + (sizeof(DWORD) * RootGroup.Header.NumberOfFiles)) >= pbRootEnd)
|
||||
@@ -345,7 +414,8 @@ struct TRootHandler_WoW : public TFileTreeRoot
|
||||
LPBYTE pbRootEnd,
|
||||
DWORD dwLocaleMask,
|
||||
BYTE bOverrideLowViolence,
|
||||
BYTE bAudioLocale)
|
||||
BYTE bAudioLocale,
|
||||
DWORD dwRootVersion)
|
||||
{
|
||||
FILE_ROOT_GROUP RootBlock;
|
||||
|
||||
@@ -360,7 +430,7 @@ struct TRootHandler_WoW : public TFileTreeRoot
|
||||
//OutputDebugStringA(szMessage);
|
||||
|
||||
// Validate the file locale block
|
||||
pbRootPtr = CaptureRootGroup(RootBlock, pbRootPtr, pbRootEnd);
|
||||
pbRootPtr = CaptureRootGroup(RootBlock, pbRootPtr, pbRootEnd, dwRootVersion);
|
||||
if(pbRootPtr == NULL)
|
||||
return ERROR_BAD_FORMAT;
|
||||
|
||||
@@ -446,33 +516,34 @@ struct TRootHandler_WoW : public TFileTreeRoot
|
||||
LPBYTE pbRootPtr,
|
||||
LPBYTE pbRootEnd,
|
||||
DWORD dwLocaleMask,
|
||||
BYTE bAudioLocale)
|
||||
BYTE bAudioLocale,
|
||||
DWORD dwRootVersion)
|
||||
{
|
||||
DWORD dwErrCode;
|
||||
|
||||
// Load the locale as-is
|
||||
dwErrCode = ParseWowRootFile_Level2(hs, pbRootPtr, pbRootEnd, dwLocaleMask, false, bAudioLocale);
|
||||
dwErrCode = ParseWowRootFile_Level2(hs, pbRootPtr, pbRootEnd, dwLocaleMask, false, bAudioLocale, dwRootVersion);
|
||||
if(dwErrCode != ERROR_SUCCESS)
|
||||
return dwErrCode;
|
||||
|
||||
// If we wanted enGB, we also load enUS for the missing files
|
||||
if(dwLocaleMask == CASC_LOCALE_ENGB)
|
||||
ParseWowRootFile_Level2(hs, pbRootPtr, pbRootEnd, CASC_LOCALE_ENUS, false, bAudioLocale);
|
||||
ParseWowRootFile_Level2(hs, pbRootPtr, pbRootEnd, CASC_LOCALE_ENUS, false, bAudioLocale, dwRootVersion);
|
||||
|
||||
if(dwLocaleMask == CASC_LOCALE_PTPT)
|
||||
ParseWowRootFile_Level2(hs, pbRootPtr, pbRootEnd, CASC_LOCALE_PTBR, false, bAudioLocale);
|
||||
ParseWowRootFile_Level2(hs, pbRootPtr, pbRootEnd, CASC_LOCALE_PTBR, false, bAudioLocale, dwRootVersion);
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
// WoW.exe: 004146C7 (BuildManifest::Load)
|
||||
DWORD Load(TCascStorage * hs, LPBYTE pbRootPtr, LPBYTE pbRootEnd, DWORD dwLocaleMask)
|
||||
DWORD Load(TCascStorage * hs, LPBYTE pbRootPtr, LPBYTE pbRootEnd, DWORD dwLocaleMask, DWORD dwRootVersion)
|
||||
{
|
||||
DWORD dwErrCode;
|
||||
|
||||
dwErrCode = ParseWowRootFile_Level1(hs, pbRootPtr, pbRootEnd, dwLocaleMask, 0);
|
||||
dwErrCode = ParseWowRootFile_Level1(hs, pbRootPtr, pbRootEnd, dwLocaleMask, 0, dwRootVersion);
|
||||
if(dwErrCode == ERROR_SUCCESS)
|
||||
dwErrCode = ParseWowRootFile_Level1(hs, pbRootPtr, pbRootEnd, dwLocaleMask, 1);
|
||||
dwErrCode = ParseWowRootFile_Level1(hs, pbRootPtr, pbRootEnd, dwLocaleMask, 1, dwRootVersion);
|
||||
|
||||
#ifdef CASCLIB_DEBUG
|
||||
// Dump the array of the file data IDs
|
||||
@@ -507,6 +578,9 @@ struct TRootHandler_WoW : public TFileTreeRoot
|
||||
break;
|
||||
}
|
||||
|
||||
// Try to verify the file name by hash
|
||||
VerifyAndLogFileName(szFileName, FileDataId);
|
||||
|
||||
//
|
||||
// Several files were renamed around WoW build 50893 (10.1.7). Example:
|
||||
//
|
||||
@@ -543,10 +617,11 @@ struct TRootHandler_WoW : public TFileTreeRoot
|
||||
break;
|
||||
}
|
||||
|
||||
// Calculate the hash of the file name
|
||||
FileNameHash = CalcFileNameHash(szFileName);
|
||||
// Try to verify the file name by hash
|
||||
VerifyAndLogFileName(szFileName, 0);
|
||||
|
||||
// Try to find the file node by file name hash
|
||||
// Calculate the hash of the file name and lookup in tree
|
||||
FileNameHash = CalcFileNameHash(szFileName);
|
||||
pFileNode = FileTree.Find(FileNameHash);
|
||||
if(pFileNode != NULL && pFileNode->NameLength == 0)
|
||||
{
|
||||
@@ -562,6 +637,7 @@ struct TRootHandler_WoW : public TFileTreeRoot
|
||||
}
|
||||
|
||||
ROOT_FORMAT RootFormat; // Root file format
|
||||
FILE * fp; // Handle to the dump file
|
||||
DWORD FileCounterHashless; // Number of files for which we don't have hash. Meaningless for WoW before 8.2.0
|
||||
DWORD FileCounter; // Counter of loaded files. Only used during loading of ROOT file
|
||||
};
|
||||
@@ -573,24 +649,34 @@ DWORD RootHandler_CreateWoW(TCascStorage * hs, CASC_BLOB & RootFile, DWORD dwLoc
|
||||
{
|
||||
TRootHandler_WoW * pRootHandler = NULL;
|
||||
ROOT_FORMAT RootFormat = RootFormatWoW_v1;
|
||||
LPCTSTR szDumpFile = NULL;
|
||||
LPBYTE pbRootFile = RootFile.pbData;
|
||||
LPBYTE pbRootEnd = RootFile.End();
|
||||
LPBYTE pbRootPtr;
|
||||
DWORD FileCounterHashless = 0;
|
||||
DWORD RootVersion = 0;
|
||||
DWORD dwErrCode = ERROR_BAD_FORMAT;
|
||||
|
||||
// Verify the root header
|
||||
if((pbRootPtr = TRootHandler_WoW::CaptureRootHeader(pbRootFile, pbRootEnd, &RootFormat, &FileCounterHashless)) == NULL)
|
||||
if((pbRootPtr = TRootHandler_WoW::CaptureRootHeader(pbRootFile, pbRootEnd, &RootFormat, &FileCounterHashless, &RootVersion)) == NULL)
|
||||
return ERROR_BAD_FORMAT;
|
||||
|
||||
// Create the WOW handler
|
||||
pRootHandler = new TRootHandler_WoW(RootFormat, FileCounterHashless);
|
||||
#ifdef CASCLIB_WRITE_VERIFIED_FILENAMES
|
||||
LPCTSTR szExtension = (RootFormat == RootFormatWoW_v1) ? _T("txt") : _T("csv");
|
||||
TCHAR szBuffer[MAX_PATH];
|
||||
|
||||
CascStrPrintf(szBuffer, _countof(szBuffer), _T("\\listfile_wow_%u_%s.%s"), hs->dwBuildNumber, hs->szCodeName, szExtension);
|
||||
szDumpFile = szBuffer;
|
||||
#endif
|
||||
|
||||
// Create the root handler
|
||||
pRootHandler = new TRootHandler_WoW(RootFormat, FileCounterHashless, szDumpFile);
|
||||
if(pRootHandler != NULL)
|
||||
{
|
||||
//fp = fopen("E:\\file-data-ids2.txt", "wt");
|
||||
|
||||
// Load the root directory. If load failed, we free the object
|
||||
dwErrCode = pRootHandler->Load(hs, pbRootPtr, pbRootEnd, dwLocaleMask);
|
||||
dwErrCode = pRootHandler->Load(hs, pbRootPtr, pbRootEnd, dwLocaleMask, RootVersion);
|
||||
if(dwErrCode != ERROR_SUCCESS)
|
||||
{
|
||||
delete pRootHandler;
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
#define CASC_INDEX_COUNT 0x10 // Number of index files
|
||||
#define CASC_CKEY_SIZE 0x10 // Size of the content key
|
||||
#define CASC_EKEY_SIZE 0x09 // Size of the encoded key
|
||||
#define CASC_MAX_DATA_FILES 0x100 // Maximum number of data files
|
||||
#define CASC_MAX_DATA_FILES 0x1000 // Maximum number of data files
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// The index files structures
|
||||
|
||||
@@ -31,6 +31,8 @@ EXPORTS
|
||||
|
||||
CascAddEncryptionKey
|
||||
CascAddStringEncryptionKey
|
||||
CascImportKeysFromString
|
||||
CascImportKeysFromFile
|
||||
CascFindEncryptionKey
|
||||
CascGetNotFoundEncryptionKey
|
||||
|
||||
|
||||
@@ -77,7 +77,9 @@ unsigned char IntToHexChar[] = "0123456789abcdef";
|
||||
//-----------------------------------------------------------------------------
|
||||
// GetCascError/SetCascError support for non-Windows platform
|
||||
|
||||
static DWORD dwLastError = ERROR_SUCCESS;
|
||||
#ifndef CASCLIB_PLATFORM_WINDOWS
|
||||
static __thread DWORD dwLastError = ERROR_SUCCESS;
|
||||
#endif
|
||||
|
||||
DWORD GetCascError()
|
||||
{
|
||||
@@ -92,8 +94,9 @@ void SetCascError(DWORD dwErrCode)
|
||||
{
|
||||
#ifdef CASCLIB_PLATFORM_WINDOWS
|
||||
SetLastError(dwErrCode);
|
||||
#endif
|
||||
#else
|
||||
dwLastError = dwErrCode;
|
||||
#endif
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
@@ -63,7 +63,7 @@ catch2
|
||||
|
||||
CascLib (An open-source implementation of library for reading CASC storage from Blizzard games since 2014)
|
||||
https://github.com/ladislav-zezula/CascLib
|
||||
Version: 5c60050770767f2e606f6fec0c35beb8b9b00c60
|
||||
Version: 07ab5f37ad282cc101d5c17793c550a0a6d4637f
|
||||
|
||||
rapidjson (A fast JSON parser/generator for C++ with both SAX/DOM style API http://rapidjson.org/)
|
||||
https://github.com/Tencent/rapidjson
|
||||
|
||||
Reference in New Issue
Block a user