| 506 | } |
| 507 | |
| 508 | TMPQHash * LoadMpkHashTable(TMPQArchive * ha) |
| 509 | { |
| 510 | TMPQHeader * pHeader = ha->pHeader; |
| 511 | TMPQHash * pHashTable = NULL; |
| 512 | TMPKHash * pMpkHash; |
| 513 | TMPQHash * pHash = NULL; |
| 514 | DWORD dwHashTableSize = pHeader->dwHashTableSize; |
| 515 | |
| 516 | // MPKs use different hash table searching. |
| 517 | // Instead of using MPQ_HASH_TABLE_INDEX hash as index, |
| 518 | // they store the value directly in the hash table. |
| 519 | // Also for faster searching, the hash table is sorted ascending by the value |
| 520 | |
| 521 | // Load and decrypt the MPK hash table. |
| 522 | pMpkHash = (TMPKHash *)LoadMpkTable(ha, pHeader->dwHashTablePos, pHeader->dwHashTableSize * sizeof(TMPKHash)); |
| 523 | if(pMpkHash != NULL) |
| 524 | { |
| 525 | // Calculate the hash table size as if it was real MPQ hash table |
| 526 | pHeader->dwHashTableSize = GetNearestPowerOfTwo(pHeader->dwHashTableSize); |
| 527 | pHeader->HashTableSize64 = pHeader->dwHashTableSize * sizeof(TMPQHash); |
| 528 | |
| 529 | // Now allocate table that will serve like a true MPQ hash table, |
| 530 | // so we translate the MPK hash table to MPQ hash table |
| 531 | pHashTable = STORM_ALLOC(TMPQHash, pHeader->dwHashTableSize); |
| 532 | if(pHashTable != NULL) |
| 533 | { |
| 534 | // Set the entire hash table to free |
| 535 | memset(pHashTable, 0xFF, (size_t)pHeader->HashTableSize64); |
| 536 | |
| 537 | // Copy the MPK hash table into MPQ hash table |
| 538 | for(DWORD i = 0; i < dwHashTableSize; i++) |
| 539 | { |
| 540 | // Finds the free hash entry in the hash table |
| 541 | // We don't expect any errors here, because we are putting files to empty hash table |
| 542 | pHash = FindFreeHashEntry(pHashTable, pHeader->dwHashTableSize, pMpkHash[i].dwName1); |
| 543 | assert(pHash->dwBlockIndex == HASH_ENTRY_FREE); |
| 544 | |
| 545 | // Copy the MPK hash entry to the hash table |
| 546 | pHash->dwBlockIndex = pMpkHash[i].dwBlockIndex; |
| 547 | pHash->Platform = 0; |
| 548 | pHash->lcLocale = 0; |
| 549 | pHash->dwName1 = pMpkHash[i].dwName2; |
| 550 | pHash->dwName2 = pMpkHash[i].dwName3; |
| 551 | } |
| 552 | } |
| 553 | |
| 554 | // Free the temporary hash table |
| 555 | STORM_FREE(pMpkHash); |
| 556 | } |
| 557 | |
| 558 | return pHashTable; |
| 559 | } |
| 560 | |
| 561 | static DWORD ConvertMpkFlagsToMpqFlags(DWORD dwMpkFlags) |
| 562 | { |
no test coverage detected