diff options
Diffstat (limited to 'src/SFileCompactArchive.cpp')
-rw-r--r-- | src/SFileCompactArchive.cpp | 91 |
1 files changed, 47 insertions, 44 deletions
diff --git a/src/SFileCompactArchive.cpp b/src/SFileCompactArchive.cpp index 3b2ba83..238873c 100644 --- a/src/SFileCompactArchive.cpp +++ b/src/SFileCompactArchive.cpp @@ -173,11 +173,11 @@ static int CopyNonMpqData( static int CopyMpqFileSectors( TMPQArchive * ha, TMPQFile * hf, - TFileStream * pNewStream) + TFileStream * pNewStream, + ULONGLONG MpqFilePos) // MPQ file position in the new archive { TFileEntry * pFileEntry = hf->pFileEntry; ULONGLONG RawFilePos; // Used for calculating sector offset in the old MPQ archive - ULONGLONG MpqFilePos; // MPQ file position in the new archive DWORD dwBytesToCopy = pFileEntry->dwCmpSize; DWORD dwPatchSize = 0; // Size of patch header DWORD dwFileKey1 = 0; // File key used for decryption @@ -185,10 +185,6 @@ static int CopyMpqFileSectors( DWORD dwCmpSize = 0; // Compressed file size, including patch header int nError = ERROR_SUCCESS; - // Remember the position in the destination file - FileStream_GetPos(pNewStream, &MpqFilePos); - MpqFilePos -= ha->MpqPos; - // Resolve decryption keys. Note that the file key given // in the TMPQFile structure also includes the key adjustment if(nError == ERROR_SUCCESS && (pFileEntry->dwFlags & MPQ_FILE_ENCRYPTED)) @@ -374,7 +370,7 @@ static int CopyMpqFileSectors( ha->pHeader->dwRawChunkSize); } - // Update file position in the block table + // Verify the number of bytes written if(nError == ERROR_SUCCESS) { // At this point, number of bytes written should be exactly @@ -391,12 +387,7 @@ static int CopyMpqFileSectors( // into compressed size // - if(dwCmpSize <= pFileEntry->dwCmpSize && pFileEntry->dwCmpSize <= dwCmpSize + dwPatchSize) - { - // Note: DO NOT update the compressed size in the file entry, no matter how bad it is. - pFileEntry->ByteOffset = MpqFilePos; - } - else + if(!(dwCmpSize <= pFileEntry->dwCmpSize && pFileEntry->dwCmpSize <= dwCmpSize + dwPatchSize)) { nError = ERROR_FILE_CORRUPT; assert(false); @@ -411,6 +402,7 @@ static int CopyMpqFiles(TMPQArchive * ha, LPDWORD pFileKeys, TFileStream * pNewS TFileEntry * pFileTableEnd = ha->pFileTable + ha->dwFileTableSize; TFileEntry * pFileEntry; TMPQFile * hf = NULL; + ULONGLONG MpqFilePos; int nError = ERROR_SUCCESS; // Walk through all files and write them to the destination MPQ archive @@ -418,49 +410,60 @@ static int CopyMpqFiles(TMPQArchive * ha, LPDWORD pFileKeys, TFileStream * pNewS { // Copy all the file sectors // Only do that when the file has nonzero size - if((pFileEntry->dwFlags & MPQ_FILE_EXISTS) && pFileEntry->dwFileSize != 0) + if((pFileEntry->dwFlags & MPQ_FILE_EXISTS)) { - // Allocate structure for the MPQ file - hf = CreateFileHandle(ha, pFileEntry); - if(hf == NULL) - return ERROR_NOT_ENOUGH_MEMORY; - - // Set the file decryption key - hf->dwFileKey = pFileKeys[pFileEntry - ha->pFileTable]; + // Query the position where the destination file will be + FileStream_GetPos(pNewStream, &MpqFilePos); + MpqFilePos = MpqFilePos - ha->MpqPos; - // If the file is a patch file, load the patch header - if(pFileEntry->dwFlags & MPQ_FILE_PATCH_FILE) + // Perform file copy ONLY if the file has nonzero size + if(pFileEntry->dwFileSize != 0) { - nError = AllocatePatchInfo(hf, true); + // Allocate structure for the MPQ file + hf = CreateFileHandle(ha, pFileEntry); + if(hf == NULL) + return ERROR_NOT_ENOUGH_MEMORY; + + // Set the file decryption key + hf->dwFileKey = pFileKeys[pFileEntry - ha->pFileTable]; + + // If the file is a patch file, load the patch header + if(pFileEntry->dwFlags & MPQ_FILE_PATCH_FILE) + { + nError = AllocatePatchInfo(hf, true); + if(nError != ERROR_SUCCESS) + break; + } + + // Allocate buffers for file sector and sector offset table + nError = AllocateSectorBuffer(hf); if(nError != ERROR_SUCCESS) break; - } - // Allocate buffers for file sector and sector offset table - nError = AllocateSectorBuffer(hf); - if(nError != ERROR_SUCCESS) - break; + // Also allocate sector offset table and sector checksum table + nError = AllocateSectorOffsets(hf, true); + if(nError != ERROR_SUCCESS) + break; - // Also allocate sector offset table and sector checksum table - nError = AllocateSectorOffsets(hf, true); - if(nError != ERROR_SUCCESS) - break; + // Also load sector checksums, if any + if(pFileEntry->dwFlags & MPQ_FILE_SECTOR_CRC) + { + nError = AllocateSectorChecksums(hf, false); + if(nError != ERROR_SUCCESS) + break; + } - // Also load sector checksums, if any - if(pFileEntry->dwFlags & MPQ_FILE_SECTOR_CRC) - { - nError = AllocateSectorChecksums(hf, false); + // Copy all file sectors + nError = CopyMpqFileSectors(ha, hf, pNewStream, MpqFilePos); if(nError != ERROR_SUCCESS) break; - } - // Copy all file sectors - nError = CopyMpqFileSectors(ha, hf, pNewStream); - if(nError != ERROR_SUCCESS) - break; + // Free buffers. This also sets "hf" to NULL. + FreeFileHandle(hf); + } - // Free buffers. This also sets "hf" to NULL. - FreeFileHandle(hf); + // Note: DO NOT update the compressed size in the file entry, no matter how bad it is. + pFileEntry->ByteOffset = MpqFilePos; } } |