| 2325 | } |
| 2326 | |
| 2327 | static TMPQHash * LoadHashTable(TMPQArchive * ha) |
| 2328 | { |
| 2329 | TMPQHeader * pHeader = ha->pHeader; |
| 2330 | ULONGLONG ByteOffset; |
| 2331 | TMPQHash * pHashTable = NULL; |
| 2332 | DWORD dwTableSize; |
| 2333 | DWORD dwCmpSize; |
| 2334 | DWORD dwRealTableSize = 0; |
| 2335 | |
| 2336 | // Note: It is allowed to load hash table if it is at offset 0. |
| 2337 | // Example: MPQ_2016_v1_ProtectedMap_HashOffsIsZero.w3x |
| 2338 | // if(pHeader->dwHashTablePos == 0 && pHeader->wHashTablePosHi == 0) |
| 2339 | // return NULL; |
| 2340 | |
| 2341 | // If the hash table size is zero, do nothing |
| 2342 | if(pHeader->dwHashTableSize == 0) |
| 2343 | return NULL; |
| 2344 | |
| 2345 | // Load the hash table for MPQ variations |
| 2346 | switch(ha->dwSubType) |
| 2347 | { |
| 2348 | case MPQ_SUBTYPE_MPQ: |
| 2349 | |
| 2350 | // Calculate the position and size of the hash table |
| 2351 | ByteOffset = FileOffsetFromMpqOffset(ha, MAKE_OFFSET64(pHeader->wHashTablePosHi, pHeader->dwHashTablePos)); |
| 2352 | dwTableSize = pHeader->dwHashTableSize * sizeof(TMPQHash); |
| 2353 | dwCmpSize = (DWORD)pHeader->HashTableSize64; |
| 2354 | |
| 2355 | // Read, decrypt and uncompress the hash table |
| 2356 | pHashTable = (TMPQHash *)LoadMpqTable(ha, ByteOffset, pHeader->MD5_HashTable, dwCmpSize, dwTableSize, g_dwHashTableKey, &dwRealTableSize); |
| 2357 | // DumpHashTable(pHashTable, pHeader->dwHashTableSize); |
| 2358 | |
| 2359 | // If the hash table was cut, we can/have to defragment it |
| 2360 | if(pHashTable != NULL && dwRealTableSize != 0 && dwRealTableSize < dwTableSize) |
| 2361 | { |
| 2362 | ha->dwRealHashTableSize = dwRealTableSize; |
| 2363 | ha->dwFlags |= (MPQ_FLAG_MALFORMED | MPQ_FLAG_HASH_TABLE_CUT); |
| 2364 | } |
| 2365 | break; |
| 2366 | |
| 2367 | case MPQ_SUBTYPE_SQP: |
| 2368 | pHashTable = LoadSqpHashTable(ha); |
| 2369 | break; |
| 2370 | |
| 2371 | case MPQ_SUBTYPE_MPK: |
| 2372 | pHashTable = LoadMpkHashTable(ha); |
| 2373 | break; |
| 2374 | } |
| 2375 | |
| 2376 | // Return the loaded hash table |
| 2377 | return pHashTable; |
| 2378 | } |
| 2379 | |
| 2380 | DWORD CreateFileTable(TMPQArchive * ha, DWORD dwFileTableSize) |
| 2381 | { |
no test coverage detected