diff options
author | Shauren <shauren.trinity@gmail.com> | 2019-06-06 16:48:21 +0200 |
---|---|---|
committer | Shauren <shauren.trinity@gmail.com> | 2019-06-08 17:09:24 +0200 |
commit | fc330fd8ff0115804d9c4b53a1f810c00dd63de9 (patch) | |
tree | cfa10998fed66779834bf0b7a9b8b799d33d91d4 /dep/CascLib/src/CascRootFile_WoW6.cpp | |
parent | 82c7b6c5688495d90c4ee5995a4ff74039348296 (diff) |
Dep/CascLib: Update to ladislav-zezula/CascLib@a1197edf0b3bd4d52c3f39be7fa7b44bb0b98012
Diffstat (limited to 'dep/CascLib/src/CascRootFile_WoW6.cpp')
-rw-r--r-- | dep/CascLib/src/CascRootFile_WoW6.cpp | 595 |
1 files changed, 0 insertions, 595 deletions
diff --git a/dep/CascLib/src/CascRootFile_WoW6.cpp b/dep/CascLib/src/CascRootFile_WoW6.cpp deleted file mode 100644 index 74805d07620..00000000000 --- a/dep/CascLib/src/CascRootFile_WoW6.cpp +++ /dev/null @@ -1,595 +0,0 @@ -/*****************************************************************************/ -/* CascOpenStorage.cpp Copyright (c) Ladislav Zezula 2014 */ -/*---------------------------------------------------------------------------*/ -/* Storage functions for CASC */ -/* Note: WoW6 offsets refer to WoW.exe 6.0.3.19116 (32-bit) */ -/* SHA1: c10e9ffb7d040a37a356b96042657e1a0c95c0dd */ -/*---------------------------------------------------------------------------*/ -/* Date Ver Who Comment */ -/* -------- ---- --- ------- */ -/* 29.04.14 1.00 Lad The first version of CascOpenStorage.cpp */ -/*****************************************************************************/ - -#define __CASCLIB_SELF__ -#include "CascLib.h" -#include "CascCommon.h" - -//----------------------------------------------------------------------------- -// Local structures - -#define ROOT_SEARCH_PHASE_INITIALIZING 0 -#define ROOT_SEARCH_PHASE_LISTFILE 1 -#define ROOT_SEARCH_PHASE_NAMELESS 2 -#define ROOT_SEARCH_PHASE_FINISHED 2 - -// On-disk version of locale block -typedef struct _FILE_LOCALE_BLOCK -{ - DWORD NumberOfFiles; // Number of entries - DWORD Flags; - DWORD Locales; // File locale mask (CASC_LOCALE_XXX) - - // Followed by a block of 32-bit integers (count: NumberOfFiles) - // Followed by the MD5 and file name hash (count: NumberOfFiles) - -} FILE_LOCALE_BLOCK, *PFILE_LOCALE_BLOCK; - -// On-disk version of root entry -typedef struct _FILE_ROOT_ENTRY -{ - ENCODING_KEY EncodingKey; // MD5 of the file - ULONGLONG FileNameHash; // Jenkins hash of the file name - -} FILE_ROOT_ENTRY, *PFILE_ROOT_ENTRY; - - -typedef struct _CASC_ROOT_BLOCK -{ - PFILE_LOCALE_BLOCK pLocaleBlockHdr; // Pointer to the locale block - PDWORD FileDataIds; // Pointer to the array of File Data IDs - PFILE_ROOT_ENTRY pRootEntries; - -} CASC_ROOT_BLOCK, *PCASC_ROOT_BLOCK; - -// Root file entry for CASC storages without MNDX root file (World of Warcraft 6.0+) -// Does not match to the in-file structure of the root entry -typedef struct _CASC_FILE_ENTRY -{ - ENCODING_KEY EncodingKey; // File encoding key (MD5) - ULONGLONG FileNameHash; // Jenkins hash of the file name - DWORD FileDataId; // File Data Index - DWORD Locales; // Locale flags of the file - -} CASC_FILE_ENTRY, *PCASC_FILE_ENTRY; - -struct TRootHandler_WoW6 : public TRootHandler -{ - // Linear global list of file entries - DYNAMIC_ARRAY FileTable; - DYNAMIC_ARRAY FileDataIdLookupTable; - - // Global map of FileName -> FileEntry - PCASC_MAP pRootMap; - - // For counting files - DWORD dwTotalFileCount; -}; - -// Prototype for root file parsing routine -typedef int (*PARSE_ROOT)(TRootHandler_WoW6 * pRootHandler, PCASC_ROOT_BLOCK pBlockInfo); - -//----------------------------------------------------------------------------- -// Local functions - -static bool IsFileDataIdName(const char * szFileName) -{ - BYTE BinaryValue[4]; - - // File name must begin with "File", case insensitive - if(AsciiToUpperTable_BkSlash[szFileName[0]] == 'F' && - AsciiToUpperTable_BkSlash[szFileName[1]] == 'I' && - AsciiToUpperTable_BkSlash[szFileName[2]] == 'L' && - AsciiToUpperTable_BkSlash[szFileName[3]] == 'E') - { - // Then, 8 hexadecimal digits must follow - if(ConvertStringToBinary(szFileName + 4, 8, BinaryValue) == ERROR_SUCCESS) - { - // Must be followed by an extension or end-of-string - return (szFileName[0x0C] == 0 || szFileName[0x0C] == '.'); - } - } - - return false; -} - -static int FileDataIdCompare(const void *, const void * pvFile1, const void * pvFile2) -{ - return ((PCASC_FILE_ENTRY)pvFile1)->FileDataId - ((PCASC_FILE_ENTRY)pvFile2)->FileDataId; -} - -// Search by FileDataId -PCASC_FILE_ENTRY FindRootEntry(DYNAMIC_ARRAY & FileTable, DWORD FileDataId) -{ - PCASC_FILE_ENTRY* pStartEntry = (PCASC_FILE_ENTRY*)FileTable.ItemArray; - PCASC_FILE_ENTRY* pMidlEntry; - PCASC_FILE_ENTRY* pEndEntry = pStartEntry + FileTable.ItemCount - 1; - int nResult; - - // Perform binary search on the table - while(pStartEntry < pEndEntry) - { - // Calculate the middle of the interval - pMidlEntry = pStartEntry + ((pEndEntry - pStartEntry) / 2); - - // Did we find it? - nResult = (int)FileDataId - (int)(*pMidlEntry)->FileDataId; - if(nResult == 0) - return *pMidlEntry; - - // Move the interval to the left or right - (nResult < 0) ? pEndEntry = pMidlEntry : pStartEntry = pMidlEntry + 1; - } - - return NULL; -} - -// Search by file name hash -// Also used in CascSearchFile -PCASC_FILE_ENTRY FindRootEntry(PCASC_MAP pRootMap, const char * szFileName, DWORD * PtrTableIndex) -{ - // Calculate the HASH value of the normalized file name - ULONGLONG FileNameHash = CalcFileNameHash(szFileName); - - // Perform the hash search - return (PCASC_FILE_ENTRY)Map_FindObject(pRootMap, &FileNameHash, PtrTableIndex); -} - -LPBYTE VerifyLocaleBlock(PCASC_ROOT_BLOCK pBlockInfo, LPBYTE pbFilePointer, LPBYTE pbFileEnd) -{ - // Validate the file locale block - pBlockInfo->pLocaleBlockHdr = (PFILE_LOCALE_BLOCK)pbFilePointer; - pbFilePointer = (LPBYTE)(pBlockInfo->pLocaleBlockHdr + 1); - if(pbFilePointer > pbFileEnd) - return NULL; - - // Validate the array of 32-bit integers - pBlockInfo->FileDataIds = (PDWORD)pbFilePointer; - pbFilePointer = (LPBYTE)(pBlockInfo->FileDataIds + pBlockInfo->pLocaleBlockHdr->NumberOfFiles); - if(pbFilePointer > pbFileEnd) - return NULL; - - // Validate the array of root entries - pBlockInfo->pRootEntries = (PFILE_ROOT_ENTRY)pbFilePointer; - pbFilePointer = (LPBYTE)(pBlockInfo->pRootEntries + pBlockInfo->pLocaleBlockHdr->NumberOfFiles); - if(pbFilePointer > pbFileEnd) - return NULL; - - // Return the position of the next block - return pbFilePointer; -} - -static int ParseRoot_CountFiles( - TRootHandler_WoW6 * pRootHandler, - PCASC_ROOT_BLOCK pRootBlock) -{ - // Add the file count to the total file count - pRootHandler->dwTotalFileCount += pRootBlock->pLocaleBlockHdr->NumberOfFiles; - return ERROR_SUCCESS; -} - -static int ParseRoot_AddRootEntries( - TRootHandler_WoW6 * pRootHandler, - PCASC_ROOT_BLOCK pRootBlock) -{ - PCASC_FILE_ENTRY pFileEntry; - DWORD dwFileDataId = 0; - - // Sanity checks - assert(pRootHandler->FileTable.ItemArray != NULL); - assert(pRootHandler->FileTable.ItemCountMax != 0); - assert(pRootHandler->FileDataIdLookupTable.ItemArray != NULL); - assert(pRootHandler->FileDataIdLookupTable.ItemCountMax != 0); - - // WoW.exe (build 19116): Blocks with zero files are skipped - for(DWORD i = 0; i < pRootBlock->pLocaleBlockHdr->NumberOfFiles; i++) - { - // Create new entry, with overflow check - if(pRootHandler->FileTable.ItemCount >= pRootHandler->FileTable.ItemCountMax) - return ERROR_INSUFFICIENT_BUFFER; - pFileEntry = (PCASC_FILE_ENTRY)Array_Insert(&pRootHandler->FileTable, NULL, 1); - - if (pRootHandler->FileDataIdLookupTable.ItemCount >= pRootHandler->FileDataIdLookupTable.ItemCountMax) - return ERROR_INSUFFICIENT_BUFFER; - Array_Insert(&pRootHandler->FileDataIdLookupTable, &pFileEntry, 1); - - // (004147A3) Prepare the CASC_FILE_ENTRY structure - pFileEntry->FileNameHash = pRootBlock->pRootEntries[i].FileNameHash; - pFileEntry->FileDataId = dwFileDataId + pRootBlock->FileDataIds[i]; - pFileEntry->Locales = pRootBlock->pLocaleBlockHdr->Locales; - pFileEntry->EncodingKey = pRootBlock->pRootEntries[i].EncodingKey; - - // Also, insert the entry to the map - Map_InsertObject(pRootHandler->pRootMap, pFileEntry, &pFileEntry->FileNameHash); - - // Update the local File Data Id - assert((pFileEntry->FileDataId + 1) > pFileEntry->FileDataId); - dwFileDataId = pFileEntry->FileDataId + 1; - - // Move to the next root entry - pFileEntry++; - } - - return ERROR_SUCCESS; -} - -static int ParseWowRootFileInternal( - TRootHandler_WoW6 * pRootHandler, - PARSE_ROOT pfnParseRoot, - LPBYTE pbRootFile, - LPBYTE pbRootFileEnd, - DWORD dwLocaleMask, - BYTE bOverrideArchive, - BYTE bAudioLocale) -{ - CASC_ROOT_BLOCK RootBlock; - - // Now parse the root file - while(pbRootFile < pbRootFileEnd) - { - // Validate the file locale block - pbRootFile = VerifyLocaleBlock(&RootBlock, pbRootFile, pbRootFileEnd); - if(pbRootFile == NULL) - break; - - // WoW.exe (build 19116): Entries with flag 0x100 set are skipped - if(RootBlock.pLocaleBlockHdr->Flags & 0x100) - continue; - - // WoW.exe (build 19116): Entries with flag 0x80 set are skipped if overrideArchive CVAR is set to FALSE (which is by default in non-chinese clients) - if((RootBlock.pLocaleBlockHdr->Flags & 0x80) && bOverrideArchive == 0) - continue; - - // WoW.exe (build 19116): Entries with (flags >> 0x1F) not equal to bAudioLocale are skipped - if((RootBlock.pLocaleBlockHdr->Flags >> 0x1F) != bAudioLocale) - continue; - - // WoW.exe (build 19116): Locales other than defined mask are skipped too - if((RootBlock.pLocaleBlockHdr->Locales & dwLocaleMask) == 0) - continue; - - // Now call the custom function - pfnParseRoot(pRootHandler, &RootBlock); - } - - return ERROR_SUCCESS; -} - -/* -// known dwRegion values returned from sub_661316 (7.0.3.22210 x86 win), also referred by lua GetCurrentRegion -#define WOW_REGION_US 0x01 -#define WOW_REGION_KR 0x02 -#define WOW_REGION_EU 0x03 -#define WOW_REGION_TW 0x04 -#define WOW_REGION_CN 0x05 - -#define WOW_LOCALE_ENUS 0x00 -#define WOW_LOCALE_KOKR 0x01 -#define WOW_LOCALE_FRFR 0x02 -#define WOW_LOCALE_DEDE 0x03 -#define WOW_LOCALE_ZHCN 0x04 -#define WOW_LOCALE_ZHTW 0x05 -#define WOW_LOCALE_ESES 0x06 -#define WOW_LOCALE_ESMX 0x07 -#define WOW_LOCALE_RURU 0x08 -#define WOW_LOCALE_PTBR 0x0A -#define WOW_LOCALE_ITIT 0x0B - - // dwLocale is obtained from a WOW_LOCALE_* to CASC_LOCALE_BIT_* mapping (sub_6615D0 in 7.0.3.22210 x86 win) - // because (ENUS, ENGB) and (PTBR, PTPT) pairs share the same value on WOW_LOCALE_* enum - // dwRegion is used to distinguish them - if(dwRegion == WOW_REGION_EU) - { - // Is this english version of WoW? - if(dwLocale == CASC_LOCALE_BIT_ENUS) - { - LoadWowRootFileLocales(hs, pbRootFile, cbRootFile, CASC_LOCALE_ENGB, bOverrideArchive, bAudioLocale); - LoadWowRootFileLocales(hs, pbRootFile, cbRootFile, CASC_LOCALE_ENUS, bOverrideArchive, bAudioLocale); - return ERROR_SUCCESS; - } - - // Is this portuguese version of WoW? - if(dwLocale == CASC_LOCALE_BIT_PTBR) - { - LoadWowRootFileLocales(hs, pbRootFile, cbRootFile, CASC_LOCALE_PTPT, bOverrideArchive, bAudioLocale); - LoadWowRootFileLocales(hs, pbRootFile, cbRootFile, CASC_LOCALE_PTBR, bOverrideArchive, bAudioLocale); - } - } - else - LoadWowRootFileLocales(hs, pbRootFile, cbRootFile, (1 << dwLocale), bOverrideArchive, bAudioLocale); -*/ - -static int ParseWowRootFile2( - TRootHandler_WoW6 * pRootHandler, - PARSE_ROOT pfnParseRoot, - LPBYTE pbRootFile, - LPBYTE pbRootFileEnd, - DWORD dwLocaleMask, - BYTE bAudioLocale) -{ - // Load the locale as-is - ParseWowRootFileInternal(pRootHandler, pfnParseRoot, pbRootFile, pbRootFileEnd, dwLocaleMask, false, bAudioLocale); - - // If we wanted enGB, we also load enUS for the missing files - if(dwLocaleMask == CASC_LOCALE_ENGB) - ParseWowRootFileInternal(pRootHandler, pfnParseRoot, pbRootFile, pbRootFileEnd, CASC_LOCALE_ENUS, false, bAudioLocale); - - if(dwLocaleMask == CASC_LOCALE_PTPT) - ParseWowRootFileInternal(pRootHandler, pfnParseRoot, pbRootFile, pbRootFileEnd, CASC_LOCALE_PTBR, false, bAudioLocale); - - return ERROR_SUCCESS; -} - -// WoW.exe: 004146C7 (BuildManifest::Load) -static int ParseWowRootFile( - TRootHandler_WoW6 * pRootHandler, - PARSE_ROOT pfnParseRoot, - LPBYTE pbRootFile, - LPBYTE pbRootFileEnd, - DWORD dwLocaleMask) -{ - ParseWowRootFile2(pRootHandler, pfnParseRoot, pbRootFile, pbRootFileEnd, dwLocaleMask, 0); - ParseWowRootFile2(pRootHandler, pfnParseRoot, pbRootFile, pbRootFileEnd, dwLocaleMask, 1); - return ERROR_SUCCESS; -} - -//----------------------------------------------------------------------------- -// Implementation of WoW6 root file - -static int WowHandler_Insert( - TRootHandler_WoW6 * pRootHandler, - const char * szFileName, - LPBYTE pbEncodingKey) -{ - PCASC_FILE_ENTRY pFileEntry; - DWORD FileDataId = 0; - - // Don't let the number of items to overflow - if(pRootHandler->FileTable.ItemCount >= pRootHandler->FileTable.ItemCountMax) - return ERROR_NOT_ENOUGH_MEMORY; - - if (pRootHandler->FileDataIdLookupTable.ItemCount >= pRootHandler->FileDataIdLookupTable.ItemCountMax) - return ERROR_NOT_ENOUGH_MEMORY; - - // Insert the item to the linear file list - pFileEntry = (PCASC_FILE_ENTRY)Array_Insert(&pRootHandler->FileTable, NULL, 1); - if(pFileEntry != NULL) - { - Array_Insert(&pRootHandler->FileDataIdLookupTable, &pFileEntry, 1); - - // Get the file data ID of the previous item (0 if this is the first one) - if(pRootHandler->FileTable.ItemCount > 1) - FileDataId = pFileEntry[-1].FileDataId; - - // Fill-in the new entry - pFileEntry->EncodingKey = *(PENCODING_KEY)pbEncodingKey; - pFileEntry->FileNameHash = CalcFileNameHash(szFileName); - pFileEntry->FileDataId = FileDataId + 1; - pFileEntry->Locales = CASC_LOCALE_ALL; - - // Verify collisions (debug version only) - assert(Map_FindObject(pRootHandler->pRootMap, &pFileEntry->FileNameHash, NULL) == NULL); - - // Insert the entry to the map - Map_InsertObject(pRootHandler->pRootMap, pFileEntry, &pFileEntry->FileNameHash); - } - - return ERROR_SUCCESS; -} - -static LPBYTE WowHandler_Search( - TRootHandler_WoW6 * pRootHandler, - TCascSearch * pSearch, - PDWORD /* PtrFileSize */, - PDWORD PtrLocaleFlags, - PDWORD PtrFileDataId) -{ - PCASC_FILE_ENTRY pFileEntry; - - // Only if we have a listfile - if(pSearch->pCache != NULL) - { - // Keep going through the listfile - while(ListFile_GetNext(pSearch->pCache, pSearch->szMask, pSearch->szFileName, MAX_PATH)) - { - // Find the root entry - pFileEntry = FindRootEntry(pRootHandler->pRootMap, pSearch->szFileName, NULL); - if(pFileEntry != NULL) - { - // Give the caller the locale mask - if(PtrLocaleFlags != NULL) - PtrLocaleFlags[0] = pFileEntry->Locales; - if(PtrFileDataId != NULL) - PtrFileDataId[0] = pFileEntry->FileDataId; - return pFileEntry->EncodingKey.Value; - } - } - } - - // No more files - return NULL; -} - -static LPBYTE WowHandler_GetKey(TRootHandler_WoW6 * pRootHandler, const char * szFileName) -{ - PCASC_FILE_ENTRY pFileEntry; - DWORD FileDataId; - BYTE FileDataIdLE[4]; - - // Open by FileDataId. The file name must be as following: - // File########.unk, where '#' are hexa-decimal numbers (case insensitive). - // Extension is ignored in that case - if(IsFileDataIdName(szFileName)) - { - ConvertStringToBinary(szFileName + 4, 8, FileDataIdLE); - FileDataId = ConvertBytesToInteger_4(FileDataIdLE); - - pFileEntry = FindRootEntry(pRootHandler->FileDataIdLookupTable, FileDataId); - } - else - { - // Find by the file name hash - pFileEntry = FindRootEntry(pRootHandler->pRootMap, szFileName, NULL); - } - - return (pFileEntry != NULL) ? pFileEntry->EncodingKey.Value : NULL; -} - -static void WowHandler_EndSearch(TRootHandler_WoW6 * /* pRootHandler */, TCascSearch * pSearch) -{ - if(pSearch->pRootContext != NULL) - CASC_FREE(pSearch->pRootContext); - pSearch->pRootContext = NULL; -} - -static DWORD WowHandler_GetFileId(TRootHandler_WoW6 * pRootHandler, const char * szFileName) -{ - PCASC_FILE_ENTRY pFileEntry; - - // Find by the file name hash - pFileEntry = FindRootEntry(pRootHandler->pRootMap, szFileName, NULL); - return (pFileEntry != NULL) ? pFileEntry->FileDataId : 0; -} - -static void WowHandler_Close(TRootHandler_WoW6 * pRootHandler) -{ - if(pRootHandler != NULL) - { - Array_Free(&pRootHandler->FileTable); - Array_Free(&pRootHandler->FileDataIdLookupTable); - Map_Free(pRootHandler->pRootMap); - CASC_FREE(pRootHandler); - } -} - -#ifdef _DEBUG -static void TRootHandlerWoW6_Dump( - TCascStorage * hs, - TDumpContext * dc, // Pointer to an opened file - LPBYTE pbRootFile, - DWORD cbRootFile, - const TCHAR * szListFile, - int nDumpLevel) -{ - PCASC_ENCODING_ENTRY pEncodingEntry; - CASC_ROOT_BLOCK BlockInfo; - PLISTFILE_MAP pListMap; - QUERY_KEY EncodingKey; - LPBYTE pbRootFileEnd = pbRootFile + cbRootFile; - LPBYTE pbFilePointer; - char szOneLine[0x100]; - DWORD i; - - // Create the listfile map - pListMap = ListFile_CreateMap(szListFile); - - // Dump the root entries - for(pbFilePointer = pbRootFile; pbFilePointer <= pbRootFileEnd; ) - { - // Validate the root block - pbFilePointer = VerifyLocaleBlock(&BlockInfo, pbFilePointer, pbRootFileEnd); - if(pbFilePointer == NULL) - break; - - // Dump the locale block - dump_print(dc, "Flags: %08X Locales: %08X NumberOfFiles: %u\n" - "=========================================================\n", - BlockInfo.pLocaleBlockHdr->Flags, - BlockInfo.pLocaleBlockHdr->Locales, - BlockInfo.pLocaleBlockHdr->NumberOfFiles); - - // Dump the hashes and encoding keys - for(i = 0; i < BlockInfo.pLocaleBlockHdr->NumberOfFiles; i++) - { - // Dump the entry - dump_print(dc, "%08X %08X-%08X %s %s\n", - (DWORD)(BlockInfo.FileDataIds[i]), - (DWORD)(BlockInfo.pRootEntries[i].FileNameHash >> 0x20), - (DWORD)(BlockInfo.pRootEntries[i].FileNameHash), - StringFromMD5(BlockInfo.pRootEntries[i].EncodingKey.Value, szOneLine), - ListFile_FindName(pListMap, BlockInfo.pRootEntries[i].FileNameHash)); - - // Find the encoding entry in the encoding table - if(nDumpLevel >= DUMP_LEVEL_ENCODING_FILE) - { - EncodingKey.pbData = BlockInfo.pRootEntries[i].EncodingKey.Value; - EncodingKey.cbData = MD5_HASH_SIZE; - pEncodingEntry = FindEncodingEntry(hs, &EncodingKey, NULL); - CascDumpEncodingEntry(hs, dc, pEncodingEntry, nDumpLevel); - } - } - - // Put extra newline - dump_print(dc, "\n"); - } - - ListFile_FreeMap(pListMap); -} -#endif - -//----------------------------------------------------------------------------- -// Public functions - -int RootHandler_CreateWoW6(TCascStorage * hs, LPBYTE pbRootFile, DWORD cbRootFile, DWORD dwLocaleMask) -{ - TRootHandler_WoW6 * pRootHandler; - LPBYTE pbRootFileEnd = pbRootFile + cbRootFile; - int nError; - - // Verify the size - if(pbRootFile == NULL || cbRootFile <= sizeof(PFILE_LOCALE_BLOCK)) - nError = ERROR_FILE_CORRUPT; - - // Allocate the root handler object - hs->pRootHandler = pRootHandler = CASC_ALLOC(TRootHandler_WoW6, 1); - if(pRootHandler == NULL) - return ERROR_NOT_ENOUGH_MEMORY; - - // Fill-in the handler functions - memset(pRootHandler, 0, sizeof(TRootHandler_WoW6)); - pRootHandler->Insert = (ROOT_INSERT)WowHandler_Insert; - pRootHandler->Search = (ROOT_SEARCH)WowHandler_Search; - pRootHandler->EndSearch = (ROOT_ENDSEARCH)WowHandler_EndSearch; - pRootHandler->GetKey = (ROOT_GETKEY)WowHandler_GetKey; - pRootHandler->Close = (ROOT_CLOSE)WowHandler_Close; - pRootHandler->GetFileId = (ROOT_GETFILEID)WowHandler_GetFileId; - -#ifdef _DEBUG - pRootHandler->Dump = TRootHandlerWoW6_Dump; // Support for ROOT file dump -#endif // _DEBUG - - // Count the files that are going to be loaded - ParseWowRootFile(pRootHandler, ParseRoot_CountFiles, pbRootFile, pbRootFileEnd, dwLocaleMask); - pRootHandler->dwTotalFileCount += CASC_EXTRA_FILES; - - // Create linear table that will contain all root items - nError = Array_Create(&pRootHandler->FileTable, CASC_FILE_ENTRY, pRootHandler->dwTotalFileCount); - if(nError != ERROR_SUCCESS) - return nError; - - // Create sorted table that will contain all root items to lookup by FileDataId - nError = Array_Create(&pRootHandler->FileDataIdLookupTable, PCASC_FILE_ENTRY, pRootHandler->dwTotalFileCount); - if (nError != ERROR_SUCCESS) - return nError; - - // Create the map of FileHash ->FileEntry - pRootHandler->pRootMap = Map_Create(pRootHandler->dwTotalFileCount, sizeof(ULONGLONG), FIELD_OFFSET(CASC_FILE_ENTRY, FileNameHash)); - if(pRootHandler->pRootMap == NULL) - return ERROR_NOT_ENOUGH_MEMORY; - - // Parse the root file again and insert all files to the map - ParseWowRootFile(pRootHandler, ParseRoot_AddRootEntries, pbRootFile, pbRootFileEnd, dwLocaleMask); - - // Sort entries by FileDataId for searches - qsort_pointer_array((void**)pRootHandler->FileDataIdLookupTable.ItemArray, pRootHandler->FileDataIdLookupTable.ItemCount, &FileDataIdCompare, NULL); - return ERROR_SUCCESS; -} |