aboutsummaryrefslogtreecommitdiff
path: root/dep/CascLib/src/CascRootFile_WoW6.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'dep/CascLib/src/CascRootFile_WoW6.cpp')
-rw-r--r--dep/CascLib/src/CascRootFile_WoW6.cpp595
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;
-}