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; // Insert the item to the linear file list pFileEntry = (PCASC_FILE_ENTRY)Array_Insert(&pRootHandler->FileTable, NULL, 1); if(pFileEntry != NULL) { // 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 PLISTFILE_MAP ListMap_InsertName(PLISTFILE_MAP pListMap, const char * szFileName, size_t nLength) { PLISTFILE_ENTRY pListEntry; size_t cbToAllocate; size_t cbEntrySize; // Make sure there is enough space in the list map cbEntrySize = sizeof(LISTFILE_ENTRY) + nLength; cbEntrySize = ALIGN_TO_SIZE(cbEntrySize, 8); if((pListMap->cbBuffer + cbEntrySize) > pListMap->cbBufferMax) { cbToAllocate = sizeof(LISTFILE_MAP) + (pListMap->cbBufferMax * 3) / 2; pListMap = (PLISTFILE_MAP)CASC_REALLOC(BYTE, pListMap, cbToAllocate); if(pListMap == NULL) return NULL; pListMap->cbBufferMax = (pListMap->cbBufferMax * 3) / 2; } // Get the pointer to the first entry pListEntry = (PLISTFILE_ENTRY)((LPBYTE)(pListMap + 1) + pListMap->cbBuffer); pListEntry->FileNameHash = CalcFileNameHash(szFileName); pListEntry->cbEntrySize = (DWORD)cbEntrySize; // Copy the file name to the entry memcpy(pListEntry->szFileName, szFileName, nLength); pListEntry->szFileName[nLength] = 0; // Move the next entry pListMap->cbBuffer += cbEntrySize; pListMap->nEntries++; return pListMap; }
static void ResolveFullFileNames( TRootHandler_Diablo3 * pRootHandler, PDIABLO3_CORE_TOC_ENTRY pCoreTocEntries, PCASC_MAP pPackageMap, LPBYTE pbCoreTocFile, DWORD dwFileIndexes) { PCASC_FILE_ENTRY pFileEntry; char * szPlainName; char * szNamePtr; size_t nLength; DWORD dwRootIndex; DWORD dwFileIndex; DWORD dwSubIndex; char szShortName[MAX_PATH+1]; char szFullName[MAX_PATH+1]; // Keep compiler happy CASCLIB_UNUSED(dwFileIndexes); // Parse the entire file table for(size_t i = 0; i < pRootHandler->FileTable.ItemCount; i++) { // Retrieve the file entry at n-th position pFileEntry = (PCASC_FILE_ENTRY)Array_ItemAt(&pRootHandler->FileTable, i); // Skip the items that already have full name if(pFileEntry->dwFlags & CASC_ENTRY_SHORT_NAME) { // Retrieve the file index of that file dwRootIndex = INDEX64_ROOT_INDEX(pFileEntry->FileNameHash); dwFileIndex = INDEX64_FILE_INDEX(pFileEntry->FileNameHash); dwSubIndex = (pFileEntry->dwFlags & CASC_ENTRY_HAS_SUBINDEX) ? INDEX64_SUB_INDEX(pFileEntry->FileNameHash) : DIABLO3_INVALID_INDEX; assert(dwFileIndex < dwFileIndexes); // Get the plain name of the file szPlainName = (char *)(pbCoreTocFile + pCoreTocEntries[dwFileIndex].NameOffset); // Create the short file name nLength = CreateShortName(pPackageMap, dwRootIndex, pCoreTocEntries[dwFileIndex].AssetIndex, szPlainName, dwSubIndex, szShortName); // Insert the short name to the list of the names szNamePtr = (char *)Array_Insert(&pRootHandler->FileNames, szShortName, nLength + 1); pFileEntry->dwFileName = (DWORD)Array_IndexOf(&pRootHandler->FileNames, szNamePtr); // Create the full file name nLength = CreateFileName(pRootHandler, szShortName, szFullName); pFileEntry->FileNameHash = CalcFileNameHash(szFullName); // Insert the entry to the name map. Use the mapping of FullName -> FileHash Map_InsertObject(pRootHandler->pRootMap, pFileEntry, &pFileEntry->FileNameHash); } } }
// 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); }
static LPBYTE D3Handler_GetKey(TRootHandler_Diablo3 * pRootHandler, const char * szFileName) { PCASC_FILE_ENTRY pFileEntry; ULONGLONG FileNameHash = CalcFileNameHash(szFileName); // Find the file in the name table pFileEntry = (PCASC_FILE_ENTRY)Map_FindObject(pRootHandler->pRootMap, &FileNameHash, NULL); return (pFileEntry != NULL) ? pFileEntry->EncodingKey.Value : NULL; }
// Insert an entry with file name as-is static int InsertFileEntry( TRootHandler_Diablo3 * pRootHandler, ENCODING_KEY & EncodingKey, const char * szFileName, size_t cchFileName) { PCASC_FILE_ENTRY pFileEntry; // We must not allow the file name array to be reallocated. // Reallocating the array would cause pointers in TRootHandler_Diablo3::pRootMap // become invalid if(pRootHandler->FileTable.ItemCount >= pRootHandler->FileTable.ItemCountMax) { assert(false); return ERROR_NOT_ENOUGH_MEMORY; } // Insert the plain name to the root handler's global name list szFileName = (const char *)Array_Insert(&pRootHandler->FileNames, szFileName, cchFileName); if(szFileName == NULL) return ERROR_NOT_ENOUGH_MEMORY; // Make sure that we don't exceed the file limit at this phase pFileEntry = (PCASC_FILE_ENTRY)Array_Insert(&pRootHandler->FileTable, NULL, 1); assert(pFileEntry != NULL); // Store the info into the file entry pFileEntry->EncodingKey = EncodingKey; pFileEntry->FileNameHash = CalcFileNameHash(szFileName); pFileEntry->dwFileName = (DWORD)Array_IndexOf(&pRootHandler->FileNames, szFileName); pFileEntry->dwFlags = 0; // Verify collisions (debug version only) assert(Map_FindObject(pRootHandler->pRootMap, &pFileEntry->FileNameHash, NULL) == NULL); // Calculate the file name hash Map_InsertObject(pRootHandler->pRootMap, pFileEntry, &pFileEntry->FileNameHash); // Success return ERROR_SUCCESS; }