static int CopyMpqFiles(TMPQArchive * ha, LPDWORD pFileKeys, TFileStream * pNewStream) { 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 for(pFileEntry = ha->pFileTable; pFileEntry < pFileTableEnd; pFileEntry++) { // Copy all the file sectors // Only do that when the file has nonzero size if((pFileEntry->dwFlags & MPQ_FILE_EXISTS)) { // Query the position where the destination file will be FileStream_GetPos(pNewStream, &MpqFilePos); MpqFilePos = MpqFilePos - ha->MpqPos; // Perform file copy ONLY if the file has nonzero size if(pFileEntry->dwFileSize != 0) { // 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; // 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; } // Copy all file sectors nError = CopyMpqFileSectors(ha, hf, pNewStream, MpqFilePos); if(nError != ERROR_SUCCESS) break; // 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; } } // Cleanup and exit if(hf != NULL) FreeFileHandle(hf); return nError; }
static int CopyMpqFiles(TMPQArchive * ha, LPDWORD pFileKeys, TFileStream * pNewStream) { TFileEntry * pFileTableEnd = ha->pFileTable + ha->dwFileTableSize; TFileEntry * pFileEntry; TMPQFile * hf = NULL; int nError = ERROR_SUCCESS; // Walk through all files and write them to the destination MPQ archive for(pFileEntry = ha->pFileTable; pFileEntry < pFileTableEnd; pFileEntry++) { // Copy all the file sectors // Only do that when the file has nonzero size if ((pFileEntry->dwFlags & MPQ_FILE_EXISTS) && pFileEntry->dwFileSize != 0) { // Allocate structure for the MPQ file hf = CreateMpqFile(ha); if (hf == NULL) return ERROR_NOT_ENOUGH_MEMORY; // Store file entry hf->pFileEntry = pFileEntry; // Set the raw file position hf->MpqFilePos = pFileEntry->ByteOffset; hf->RawFilePos = ha->MpqPos + hf->MpqFilePos; // Set the file decryption key hf->dwFileKey = pFileKeys[pFileEntry - ha->pFileTable]; hf->dwDataSize = pFileEntry->dwFileSize; // 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; // 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; } // Copy all file sectors nError = CopyMpqFileSectors(ha, hf, pNewStream); if (nError != ERROR_SUCCESS) break; // Free buffers. This also sets "hf" to NULL. FreeMPQFile(hf); } } // Cleanup and exit if (hf != NULL) FreeMPQFile(hf); return nError; }
static int CopyMpqFiles(TMPQArchive * ha, DWORD * pFileKeys, TFileStream * pNewStream) { TMPQBlockEx * pBlockEx = ha->pExtBlockTable; TMPQBlock * pBlockEnd = ha->pBlockTable + ha->pHeader->dwBlockTableSize; TMPQBlock * pBlock; TMPQFile * hf = NULL; int nError = ERROR_SUCCESS; // Walk through all files and write them to the destination MPQ archive for(pBlock = ha->pBlockTable; pBlock < pBlockEnd; pBlock++, pBlockEx++) { // Copy all the file sectors // Only do that when the file has nonzero size if((pBlock->dwFlags & MPQ_FILE_EXISTS) && pBlock->dwFSize != 0) { // Allocate structure for the MPQ file hf = CreateMpqFile(ha, "<compacting>"); if(hf == NULL) return ERROR_NOT_ENOUGH_MEMORY; // Store block positions hf->pBlockEx = pBlockEx; hf->pBlock = pBlock; // Set the raw file position hf->MpqFilePos.HighPart = hf->pBlockEx->wFilePosHigh; hf->MpqFilePos.LowPart = hf->pBlock->dwFilePos; hf->RawFilePos.QuadPart = ha->MpqPos.QuadPart + hf->MpqFilePos.LowPart; // Set the file decryption key hf->dwFileKey = pFileKeys[pBlock - ha->pBlockTable]; // 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; if(pBlock->dwFlags & MPQ_FILE_SECTOR_CRC) { nError = AllocateSectorChecksums(hf, false); 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. FreeMPQFile(hf); } } // Cleanup and exit if(hf != NULL) FreeMPQFile(hf); return nError; }