Beispiel #1
0
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;
}
Beispiel #2
0
static PLISTFILE_MAP ListMap_Finish(PLISTFILE_MAP pListMap)
{
    PLISTFILE_ENTRY pListEntry;
    PCASC_MAP pMap;
    LPBYTE pbEntry;

    // Sanity check
    assert(pListMap->pNameMap == NULL);
    
    // Create the map
    pListMap->pNameMap = pMap = Map_Create((DWORD)pListMap->nEntries, sizeof(ULONGLONG), 0);
    if(pListMap->pNameMap == NULL)
    {
        ListFile_FreeMap(pListMap);
        return NULL;
    }

    // Fill the map
    pbEntry = (LPBYTE)(pListMap + 1);
    for(size_t i = 0; i < pListMap->nEntries; i++)
    {
        // Get the listfile entry
        pListEntry = (PLISTFILE_ENTRY)pbEntry;
        pbEntry += pListEntry->cbEntrySize;

        // Insert the entry to the map
        Map_InsertObject(pMap, pListEntry);
    }

    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);
        }
    }
}
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;
}
// 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;
}