| 1255 | } |
| 1256 | |
| 1257 | int AllocateSectorChecksums(TMPQFile * hf, bool bLoadFromFile) |
| 1258 | { |
| 1259 | TMPQArchive * ha = hf->ha; |
| 1260 | TFileEntry * pFileEntry = hf->pFileEntry; |
| 1261 | ULONGLONG RawFilePos; |
| 1262 | DWORD dwCompressedSize = 0; |
| 1263 | DWORD dwExpectedSize; |
| 1264 | DWORD dwCrcOffset; // Offset of the CRC table, relative to file offset in the MPQ |
| 1265 | DWORD dwCrcSize; |
| 1266 | |
| 1267 | // Caller of AllocateSectorChecksums must ensure these |
| 1268 | assert(hf->SectorChksums == NULL); |
| 1269 | assert(hf->SectorOffsets != NULL); |
| 1270 | assert(hf->pFileEntry != NULL); |
| 1271 | assert(hf->ha != NULL); |
| 1272 | |
| 1273 | // Single unit files don't have sector checksums |
| 1274 | if(pFileEntry->dwFlags & MPQ_FILE_SINGLE_UNIT) |
| 1275 | return ERROR_SUCCESS; |
| 1276 | |
| 1277 | // Caller must ensure that we are only called when we have sector checksums |
| 1278 | assert(pFileEntry->dwFlags & MPQ_FILE_SECTOR_CRC); |
| 1279 | |
| 1280 | // |
| 1281 | // Older MPQs store an array of CRC32's after |
| 1282 | // the raw file data in the MPQ. |
| 1283 | // |
| 1284 | // In newer MPQs, the (since Cataclysm BETA) the (attributes) file |
| 1285 | // contains additional 32-bit values beyond the sector table. |
| 1286 | // Their number depends on size of the (attributes), but their |
| 1287 | // meaning is unknown. They are usually zeroed in retail game files, |
| 1288 | // but contain some sort of checksum in BETA MPQs |
| 1289 | // |
| 1290 | |
| 1291 | // Does the size of the file table match with the CRC32-based checksums? |
| 1292 | dwExpectedSize = (hf->dwSectorCount + 2) * sizeof(DWORD); |
| 1293 | if(hf->SectorOffsets[0] != 0 && hf->SectorOffsets[0] == dwExpectedSize) |
| 1294 | { |
| 1295 | // If we are not loading from the MPQ file, we just allocate the sector table |
| 1296 | // In that case, do not check any sizes |
| 1297 | if(bLoadFromFile == false) |
| 1298 | { |
| 1299 | hf->SectorChksums = STORM_ALLOC(DWORD, hf->dwSectorCount); |
| 1300 | if(hf->SectorChksums == NULL) |
| 1301 | return ERROR_NOT_ENOUGH_MEMORY; |
| 1302 | |
| 1303 | // Fill the checksum table with zeros |
| 1304 | memset(hf->SectorChksums, 0, hf->dwSectorCount * sizeof(DWORD)); |
| 1305 | return ERROR_SUCCESS; |
| 1306 | } |
| 1307 | else |
| 1308 | { |
| 1309 | // Is there valid size of the sector checksums? |
| 1310 | if(hf->SectorOffsets[hf->dwSectorCount + 1] >= hf->SectorOffsets[hf->dwSectorCount]) |
| 1311 | dwCompressedSize = hf->SectorOffsets[hf->dwSectorCount + 1] - hf->SectorOffsets[hf->dwSectorCount]; |
| 1312 | |
| 1313 | // Ignore cases when the length is too small or too big. |
| 1314 | if(dwCompressedSize < sizeof(DWORD) || dwCompressedSize > hf->dwSectorSize) |
no test coverage detected