aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/SFileAddFile.cpp9
-rw-r--r--src/SFileCompactArchive.cpp91
-rw-r--r--src/SFileReadFile.cpp173
3 files changed, 141 insertions, 132 deletions
diff --git a/src/SFileAddFile.cpp b/src/SFileAddFile.cpp
index f941141..5997c1b 100644
--- a/src/SFileAddFile.cpp
+++ b/src/SFileAddFile.cpp
@@ -479,11 +479,14 @@ int SFileAddFile_Init(
// Call the callback, if needed
if(ha->pfnAddFileCB != NULL)
ha->pfnAddFileCB(ha->pvAddFileUserData, 0, hf->dwDataSize, false);
+ hf->nAddFileError = ERROR_SUCCESS;
}
- // Store the error code from Add File operation
- if(hf != NULL)
- hf->nAddFileError = nError;
+ // Fre the file handle if failed
+ if(nError != ERROR_SUCCESS && hf != NULL)
+ FreeFileHandle(hf);
+
+ // Give the handle to the caller
*phf = hf;
return nError;
}
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;
}
}
diff --git a/src/SFileReadFile.cpp b/src/SFileReadFile.cpp
index 124f0b3..6884f55 100644
--- a/src/SFileReadFile.cpp
+++ b/src/SFileReadFile.cpp
@@ -95,111 +95,114 @@ static int ReadMpqSectors(TMPQFile * hf, LPBYTE pbBuffer, DWORD dwByteOffset, DW
CalculateRawSectorOffset(RawFilePos, hf, dwRawSectorOffset);
// Set file pointer and read all required sectors
- if(!FileStream_Read(ha->pStream, &RawFilePos, pbInSector, dwRawBytesToRead))
- return GetLastError();
- dwBytesRead = 0;
-
- // Now we have to decrypt and decompress all file sectors that have been loaded
- for(DWORD i = 0; i < dwSectorsToRead; i++)
+ if(FileStream_Read(ha->pStream, &RawFilePos, pbInSector, dwRawBytesToRead))
{
- DWORD dwRawBytesInThisSector = ha->dwSectorSize;
- DWORD dwBytesInThisSector = ha->dwSectorSize;
- DWORD dwIndex = dwSectorIndex + i;
-
- // If there is not enough bytes in the last sector,
- // cut the number of bytes in this sector
- if(dwRawBytesInThisSector > dwBytesToRead)
- dwRawBytesInThisSector = dwBytesToRead;
- if(dwBytesInThisSector > dwBytesToRead)
- dwBytesInThisSector = dwBytesToRead;
-
- // If the file is compressed, we have to adjust the raw sector size
- if(pFileEntry->dwFlags & MPQ_FILE_COMPRESS_MASK)
- dwRawBytesInThisSector = hf->SectorOffsets[dwIndex + 1] - hf->SectorOffsets[dwIndex];
-
- // If the file is encrypted, we have to decrypt the sector
- if(pFileEntry->dwFlags & MPQ_FILE_ENCRYPTED)
+ // Now we have to decrypt and decompress all file sectors that have been loaded
+ for(DWORD i = 0; i < dwSectorsToRead; i++)
{
- BSWAP_ARRAY32_UNSIGNED(pbInSector, dwRawBytesInThisSector);
-
- // If we don't know the key, try to detect it by file content
- if(hf->dwFileKey == 0)
+ DWORD dwRawBytesInThisSector = ha->dwSectorSize;
+ DWORD dwBytesInThisSector = ha->dwSectorSize;
+ DWORD dwIndex = dwSectorIndex + i;
+
+ // If there is not enough bytes in the last sector,
+ // cut the number of bytes in this sector
+ if(dwRawBytesInThisSector > dwBytesToRead)
+ dwRawBytesInThisSector = dwBytesToRead;
+ if(dwBytesInThisSector > dwBytesToRead)
+ dwBytesInThisSector = dwBytesToRead;
+
+ // If the file is compressed, we have to adjust the raw sector size
+ if(pFileEntry->dwFlags & MPQ_FILE_COMPRESS_MASK)
+ dwRawBytesInThisSector = hf->SectorOffsets[dwIndex + 1] - hf->SectorOffsets[dwIndex];
+
+ // If the file is encrypted, we have to decrypt the sector
+ if(pFileEntry->dwFlags & MPQ_FILE_ENCRYPTED)
{
- hf->dwFileKey = DetectFileKeyByContent(pbInSector, dwBytesInThisSector, hf->dwDataSize);
+ BSWAP_ARRAY32_UNSIGNED(pbInSector, dwRawBytesInThisSector);
+
+ // If we don't know the key, try to detect it by file content
if(hf->dwFileKey == 0)
{
- nError = ERROR_UNKNOWN_FILE_KEY;
- break;
+ hf->dwFileKey = DetectFileKeyByContent(pbInSector, dwBytesInThisSector, hf->dwDataSize);
+ if(hf->dwFileKey == 0)
+ {
+ nError = ERROR_UNKNOWN_FILE_KEY;
+ break;
+ }
}
+
+ DecryptMpqBlock(pbInSector, dwRawBytesInThisSector, hf->dwFileKey + dwIndex);
+ BSWAP_ARRAY32_UNSIGNED(pbInSector, dwRawBytesInThisSector);
}
- DecryptMpqBlock(pbInSector, dwRawBytesInThisSector, hf->dwFileKey + dwIndex);
- BSWAP_ARRAY32_UNSIGNED(pbInSector, dwRawBytesInThisSector);
- }
+ // If the file has sector CRC check turned on, perform it
+ if(hf->bCheckSectorCRCs && hf->SectorChksums != NULL)
+ {
+ DWORD dwAdlerExpected = hf->SectorChksums[dwIndex];
+ DWORD dwAdlerValue = 0;
- // If the file has sector CRC check turned on, perform it
- if(hf->bCheckSectorCRCs && hf->SectorChksums != NULL)
- {
- DWORD dwAdlerExpected = hf->SectorChksums[dwIndex];
- DWORD dwAdlerValue = 0;
+ // We can only check sector CRC when it's not zero
+ // Neither can we check it if it's 0xFFFFFFFF.
+ if(dwAdlerExpected != 0 && dwAdlerExpected != 0xFFFFFFFF)
+ {
+ dwAdlerValue = adler32(0, pbInSector, dwRawBytesInThisSector);
+ if(dwAdlerValue != dwAdlerExpected)
+ {
+ nError = ERROR_CHECKSUM_ERROR;
+ break;
+ }
+ }
+ }
- // We can only check sector CRC when it's not zero
- // Neither can we check it if it's 0xFFFFFFFF.
- if(dwAdlerExpected != 0 && dwAdlerExpected != 0xFFFFFFFF)
+ // If the sector is really compressed, decompress it.
+ // WARNING : Some sectors may not be compressed, it can be determined only
+ // by comparing uncompressed and compressed size !!!
+ if(dwRawBytesInThisSector < dwBytesInThisSector)
{
- dwAdlerValue = adler32(0, pbInSector, dwRawBytesInThisSector);
- if(dwAdlerValue != dwAdlerExpected)
+ int cbOutSector = dwBytesInThisSector;
+ int cbInSector = dwRawBytesInThisSector;
+ int nResult = 0;
+
+ // Is the file compressed by Blizzard's multiple compression ?
+ if(pFileEntry->dwFlags & MPQ_FILE_COMPRESS)
{
- nError = ERROR_CHECKSUM_ERROR;
- break;
+ if(ha->pHeader->wFormatVersion >= MPQ_FORMAT_VERSION_2)
+ nResult = SCompDecompress2(pbOutSector, &cbOutSector, pbInSector, cbInSector);
+ else
+ nResult = SCompDecompress(pbOutSector, &cbOutSector, pbInSector, cbInSector);
}
- }
- }
- // If the sector is really compressed, decompress it.
- // WARNING : Some sectors may not be compressed, it can be determined only
- // by comparing uncompressed and compressed size !!!
- if(dwRawBytesInThisSector < dwBytesInThisSector)
- {
- int cbOutSector = dwBytesInThisSector;
- int cbInSector = dwRawBytesInThisSector;
- int nResult = 0;
+ // Is the file compressed by PKWARE Data Compression Library ?
+ else if(pFileEntry->dwFlags & MPQ_FILE_IMPLODE)
+ {
+ nResult = SCompExplode(pbOutSector, &cbOutSector, pbInSector, cbInSector);
+ }
- // Is the file compressed by Blizzard's multiple compression ?
- if(pFileEntry->dwFlags & MPQ_FILE_COMPRESS)
- {
- if(ha->pHeader->wFormatVersion >= MPQ_FORMAT_VERSION_2)
- nResult = SCompDecompress2(pbOutSector, &cbOutSector, pbInSector, cbInSector);
- else
- nResult = SCompDecompress(pbOutSector, &cbOutSector, pbInSector, cbInSector);
+ // Did the decompression fail ?
+ if(nResult == 0)
+ {
+ nError = ERROR_FILE_CORRUPT;
+ break;
+ }
}
-
- // Is the file compressed by PKWARE Data Compression Library ?
- else if(pFileEntry->dwFlags & MPQ_FILE_IMPLODE)
+ else
{
- nResult = SCompExplode(pbOutSector, &cbOutSector, pbInSector, cbInSector);
+ if(pbOutSector != pbInSector)
+ memcpy(pbOutSector, pbInSector, dwBytesInThisSector);
}
- // Did the decompression fail ?
- if(nResult == 0)
- {
- nError = ERROR_FILE_CORRUPT;
- break;
- }
+ // Move pointers
+ dwBytesToRead -= dwBytesInThisSector;
+ dwByteOffset += dwBytesInThisSector;
+ dwBytesRead += dwBytesInThisSector;
+ pbOutSector += dwBytesInThisSector;
+ pbInSector += dwRawBytesInThisSector;
+ dwSectorsDone++;
}
- else
- {
- if(pbOutSector != pbInSector)
- memcpy(pbOutSector, pbInSector, dwBytesInThisSector);
- }
-
- // Move pointers
- dwBytesToRead -= dwBytesInThisSector;
- dwByteOffset += dwBytesInThisSector;
- dwBytesRead += dwBytesInThisSector;
- pbOutSector += dwBytesInThisSector;
- pbInSector += dwRawBytesInThisSector;
- dwSectorsDone++;
+ }
+ else
+ {
+ nError = GetLastError();
}
// Free all used buffers