示例#1
0
static void DumpIndexKey(
    FILE * fp,
    TCascStorage * hs,
    LPBYTE pbIndexKey,
    int nDumpLevel)
{
    PCASC_INDEX_ENTRY pIndexEntry;
    TCascFile * hf;
    QUERY_KEY QueryKey;
    HANDLE hFile;
    BYTE HeaderArea[MAX_HEADER_AREA_SIZE];
    char szBuffer[0x20];

    QueryKey.pbData = pbIndexKey;
    QueryKey.cbData = MD5_HASH_SIZE;
    pIndexEntry = FindIndexEntry(hs, &QueryKey);
    if(pIndexEntry != NULL)
    {
        ULONGLONG FileOffset = ConvertBytesToInteger_5(pIndexEntry->FileOffsetBE);
        DWORD ArchIndex = (DWORD)(FileOffset >> 0x1E);
        DWORD FileSize = ConvertBytesToInteger_4_LE(pIndexEntry->FileSizeLE);

        // Mask the file offset
        FileOffset &= 0x3FFFFFFF;
        fprintf(fp, "    data.%03u at 0x%08x (0x%lx bytes)\n",
                    ArchIndex,
             (DWORD)FileOffset,
                    FileSize);

        if(nDumpLevel > 2)
        {
            QueryKey.pbData = pIndexEntry->IndexKey;
            QueryKey.cbData = MD5_HASH_SIZE;
            if(CascOpenFileByIndexKey((HANDLE)hs, &QueryKey, 0, &hFile))
            {
                // Make sure that the data file is open and frame header loaded
                CascGetFileSize(hFile, NULL);
                hf = IsValidFileHandle(hFile);
                assert(hf->pStream != NULL);

                // Read the header area
                FileOffset = hf->HeaderOffset - BLTE_HEADER_DELTA;
                FileStream_Read(hf->pStream, &FileOffset, HeaderArea, sizeof(HeaderArea));
                CascCloseFile(hFile);

                // Dump the header area
                fprintf(fp, "    FileSize: %X  Rest: %s\n",
                            ConvertBytesToInteger_4_LE(&HeaderArea[0x10]),
                            StringFromBinary(&HeaderArea[0x14], 10, szBuffer));
            }
        }
    }
示例#2
0
static TCascFile * CreateFileHandle(TCascStorage * hs, PCASC_INDEX_ENTRY pIndexEntry)
{
    ULONGLONG FileOffsMask = ((ULONGLONG)1 << hs->KeyMapping[0].SegmentBits) - 1;
    ULONGLONG FileOffset = ConvertBytesToInteger_5(pIndexEntry->FileOffsetBE);
    TCascFile * hf;

    // Allocate the CASC file structure
    hf = (TCascFile *)CASC_ALLOC(TCascFile, 1);
    if(hf != NULL)
    {
        // Initialize the structure
        memset(hf, 0, sizeof(TCascFile));
        hf->ArchiveIndex = (DWORD)(FileOffset >> hs->KeyMapping[0].SegmentBits);
        hf->HeaderOffset = (DWORD)(FileOffset & FileOffsMask);
        hf->szClassName = "TCascFile";

        // Copy the file size. Note that for all files except ENCODING,
        // this is the compressed file size
        hf->CompressedSize = ConvertBytesToInteger_4_LE(pIndexEntry->FileSizeLE);

        // For now, we set the file size to be equal to compressed size
        // This is used when loading the ENCODING file, which does not
        // have entry in the encoding table
        hf->FileSize = hf->CompressedSize;

        // Increment the number of references to the archive
        hs->dwRefCount++;
        hf->hs = hs;
    }
示例#3
0
static TCascFile * CreateFileHandle(TCascStorage * hs, PQUERY_KEY pCKey, PQUERY_KEY pEKey, PCASC_EKEY_ENTRY pEKeyEntry, DWORD dwOpenFlags, DWORD dwContentSize)
{
    ULONGLONG StorageOffset = ConvertBytesToInteger_5(pEKeyEntry->StorageOffset);
    ULONGLONG FileOffsMask = ((ULONGLONG)1 << hs->IndexFile[0].FileOffsetBits) - 1;
    TCascFile * hf;

    // Allocate the CASC file structure
    hf = (TCascFile *)CASC_ALLOC(TCascFile, 1);
    if(hf != NULL)
    {
        // Initialize the structure
        memset(hf, 0, sizeof(TCascFile));
        hf->ArchiveIndex = (DWORD)(StorageOffset >> hs->IndexFile[0].FileOffsetBits);
        hf->ArchiveOffset = (DWORD)(StorageOffset & FileOffsMask);
        hf->szClassName = "TCascFile";
        hf->OpenFlags = dwOpenFlags;

        // Supply the content key, if available
        if(pCKey != NULL)
        {
            assert(pCKey->pbData != NULL && pCKey->cbData == MD5_HASH_SIZE);
            memcpy(hf->CKey.Value, pCKey->pbData, pCKey->cbData);
        }

        // Supply the encoded key, if available
        if(pEKey != NULL)
        {
            assert(pEKey->pbData != NULL && CASC_EKEY_SIZE <= pEKey->cbData && pEKey->cbData <= MD5_HASH_SIZE);
            memcpy(hf->EKey.Value, pEKey->pbData, pEKey->cbData);
        }

        // Copy the encoded file size
        if(pEKeyEntry != NULL)
        {
            hf->EncodedSize = ConvertBytesToInteger_4_LE(pEKeyEntry->EncodedSize);
        }

        // Set the content size
        hf->ContentSize = dwContentSize;

        // Increment the number of references to the archive
        hs->dwRefCount++;
        hf->hs = hs;
    }
示例#4
0
void CascDumpIndexEntry(
    TCascStorage * /* hs */,
    TDumpContext * dc,
    PCASC_INDEX_ENTRY pIndexEntry,
    int /* nDumpLevel */)
{
    if(pIndexEntry != NULL)
    {
        ULONGLONG FileOffset = ConvertBytesToInteger_5(pIndexEntry->FileOffsetBE);
        DWORD ArchIndex = (DWORD)(FileOffset >> 0x1E);
        DWORD FileSize = ConvertBytesToInteger_4_LE(pIndexEntry->FileSizeLE);

        // Mask the file offset
        FileOffset &= 0x3FFFFFFF;
        dump_print(dc, "    data.%03u at 0x%08x (0x%lx bytes)\n",
                       ArchIndex,
                (DWORD)FileOffset,
                       FileSize);

        //if(nDumpLevel > 2)
        //{
        //    QueryKey.pbData = pIndexEntry->IndexKey;
        //    QueryKey.cbData = MD5_HASH_SIZE;
        //    if(CascOpenFileByIndexKey((HANDLE)hs, &QueryKey, 0, &hFile))
        //    {
        //        // Make sure that the data file is open and frame header loaded
        //        CascGetFileSize(hFile, NULL);
        //        hf = IsValidFileHandle(hFile);
        //        assert(hf->pStream != NULL);

        //        // Read the header area
        //        FileOffset = hf->HeaderOffset - BLTE_HEADER_DELTA;
        //        FileStream_Read(hf->pStream, &FileOffset, HeaderArea, sizeof(HeaderArea));
        //        CascCloseFile(hFile);

        //        // Dump the header area
        //        dump_print(dc, "    FileSize: %X  Rest: %s\n",
        //                       ConvertBytesToInteger_4_LE(&HeaderArea[0x10]),
        //                       StringFromBinary(&HeaderArea[0x14], 10, szBuffer));
        //    }
        //}
    }
示例#5
0
static int EnsureHeaderAreaIsLoaded(TCascFile * hf)
{
    TCascStorage * hs = hf->hs;
    ULONGLONG FileOffset = hf->HeaderOffset;
    LPBYTE pbHeaderArea;
    DWORD FileSignature;
    DWORD FileSize;
    BYTE HeaderArea[MAX_HEADER_AREA_SIZE];
    int nError;

    // We need the data file to be open
    nError = EnsureDataStreamIsOpen(hf);
    if(nError != ERROR_SUCCESS)
        return nError;

    // Make sure that we already know the shift
    // to the begin of file data.
    // Note that older builds of Heroes of the Storm have entries pointing
    // to the beginning of the header area.
    // Newer versions of HOTS have encoding entries pointing directly to
    // the BLTE header
    if(hs->dwFileBeginDelta == 0xFFFFFFFF)
    {
        FileSignature = 0;
        FileOffset = hf->HeaderOffset;
        if(!FileStream_Read(hf->pStream, &FileOffset, &FileSignature, sizeof(DWORD)))
            return ERROR_FILE_CORRUPT;

        hs->dwFileBeginDelta = (FileSignature == BLTE_HEADER_SIGNATURE) ? BLTE_HEADER_DELTA : 0;
    }
           
    // If the file size is not loaded yet, do it
    if(hf->FrameCount == 0)
    {
        // Load the part before BLTE header + header itself
        FileOffset = hf->HeaderOffset - hs->dwFileBeginDelta;
        if(!FileStream_Read(hf->pStream, &FileOffset, HeaderArea, sizeof(HeaderArea)))
            return ERROR_FILE_CORRUPT;

        // Copy the MD5 hash of the frame array
        memcpy(hf->FrameArrayHash, HeaderArea, MD5_HASH_SIZE);
        pbHeaderArea = HeaderArea + MD5_HASH_SIZE;

        // Copy the file size
        FileSize = ConvertBytesToInteger_4_LE(pbHeaderArea);
        pbHeaderArea += 0x0E;

        // Verify the BLTE signature
        if(ConvertBytesToInteger_4_LE(pbHeaderArea) != BLTE_HEADER_SIGNATURE)
            return ERROR_BAD_FORMAT;
        pbHeaderArea += sizeof(DWORD);

        // Load the size of the frame headers
        hf->HeaderSize = ConvertBytesToInteger_4(pbHeaderArea);
        if(hf->HeaderSize & 0x80000000)
            return ERROR_BAD_FORMAT;
        pbHeaderArea += sizeof(DWORD);

        // Read the header size
        assert(hs->dwFileBeginDelta <= BLTE_HEADER_DELTA);
        hf->HeaderOffset += (BLTE_HEADER_DELTA - hs->dwFileBeginDelta);
        hf->FrameCount = 1;

        // Retrieve the frame count, if different from 1
        if(hf->HeaderSize != 0)
        {
            // The next byte must be 0x0F
            if(pbHeaderArea[0] != 0x0F)
                return ERROR_BAD_FORMAT;
            pbHeaderArea++;

            // Next three bytes form number of frames
            hf->FrameCount = ConvertBytesToInteger_3(pbHeaderArea);
        }

#ifdef CASCLIB_TEST
        hf->FileSize_HdrArea = FileSize;
#endif
    }

    return ERROR_SUCCESS;
}