diff options
author | Ladislav <Zezula> | 2014-03-27 17:21:38 +0100 |
---|---|---|
committer | Ladislav <Zezula> | 2014-03-27 17:21:38 +0100 |
commit | 27631209d90b8863db06b4c81c7b21efb32f2f2d (patch) | |
tree | a8680e8c5c4262c514b25d129eb1cd0f1ddf6178 /src/SFileAttributes.cpp | |
parent | c8db90a9c4dcf30b626861bfe6efeec818a78719 (diff) |
+ Fixed crash when adding file after an empty archive has been flushed
Diffstat (limited to 'src/SFileAttributes.cpp')
-rw-r--r-- | src/SFileAttributes.cpp | 93 |
1 files changed, 51 insertions, 42 deletions
diff --git a/src/SFileAttributes.cpp b/src/SFileAttributes.cpp index aafd4c3..ca865a0 100644 --- a/src/SFileAttributes.cpp +++ b/src/SFileAttributes.cpp @@ -246,7 +246,7 @@ static LPBYTE CreateAttributesFile(TMPQArchive * ha, DWORD * pcbAttrFile) LPBYTE pbAttrFile; LPBYTE pbAttrPtr; size_t cbAttrFile; - DWORD dwFinalEntries = ha->dwFileTableSize + ha->dwReservedFiles + 1; + DWORD dwFinalEntries = ha->dwFileTableSize + ha->dwReservedFiles; // Check if we need patch bits in the (attributes) file for(pFileEntry = ha->pFileTable; pFileEntry < pFileTableEnd; pFileEntry++) @@ -283,7 +283,7 @@ static LPBYTE CreateAttributesFile(TMPQArchive * ha, DWORD * pcbAttrFile) *pArrayCRC32++ = BSWAP_INT32_UNSIGNED(pFileEntry->dwCrc32); // Skip the reserved entries - pbAttrPtr = (LPBYTE)(pArrayCRC32 + ha->dwReservedFiles + 1); + pbAttrPtr = (LPBYTE)(pArrayCRC32 + ha->dwReservedFiles); } // Write the array of file time @@ -296,7 +296,7 @@ static LPBYTE CreateAttributesFile(TMPQArchive * ha, DWORD * pcbAttrFile) *pArrayFileTime++ = BSWAP_INT64_UNSIGNED(pFileEntry->FileTime); // Skip the reserved entries - pbAttrPtr = (LPBYTE)(pArrayFileTime + ha->dwReservedFiles + 1); + pbAttrPtr = (LPBYTE)(pArrayFileTime + ha->dwReservedFiles); } // Write the array of MD5s @@ -312,7 +312,7 @@ static LPBYTE CreateAttributesFile(TMPQArchive * ha, DWORD * pcbAttrFile) } // Skip the reserved items - pbAttrPtr = pbArrayMD5 + ((ha->dwReservedFiles + 1) * MD5_DIGEST_SIZE); + pbAttrPtr = pbArrayMD5 + (ha->dwReservedFiles * MD5_DIGEST_SIZE); } // Write the array of patch bits @@ -334,8 +334,8 @@ static LPBYTE CreateAttributesFile(TMPQArchive * ha, DWORD * pcbAttrFile) dwBitMask = (dwBitMask << 0x07) | (dwBitMask >> 0x01); } - // Note: Do not increment the array by the last bit that belongs to (attributes). - // This might create the array one byte less (if the number of files a multiplier of 8). + // Having incremented the bit array just by the number of items in the file table + // will create the bit array one byte less of the number of files is a multiplier of 8). // Blizzard MPQs have the same feature. // Move past the bit array @@ -410,48 +410,57 @@ int SAttrFileSaveToMpq(TMPQArchive * ha) DWORD cbAttrFile = 0; int nError = ERROR_SUCCESS; - // If there are no file flags for (attributes) file, do nothing - if(ha->dwFileFlags2 == 0 || ha->dwMaxFileCount == 0) - return ERROR_SUCCESS; + // Only save the attributes if we should do so + if(ha->dwFileFlags2 != 0) + { + // At this point, we expect to have at least one reserved entry in the file table + assert(ha->dwFlags & MPQ_FLAG_ATTRIBUTES_INVALID); + assert(ha->dwReservedFiles >= 1); + + // Create the raw data that is to be written to (attributes) + // Note: Blizzard MPQs have entries for (listfile) and (attributes), + // but they are filled empty + pbAttrFile = CreateAttributesFile(ha, &cbAttrFile); + if(pbAttrFile != NULL) + { + // We expect it to be nonzero size + assert(cbAttrFile != 0); + + // Determine the real flags for (attributes) + if(ha->dwFileFlags2 == MPQ_FILE_EXISTS) + ha->dwFileFlags2 = GetDefaultSpecialFileFlags(cbAttrFile, ha->pHeader->wFormatVersion); + + // Create the attributes file in the MPQ + nError = SFileAddFile_Init(ha, ATTRIBUTES_NAME, + 0, + cbAttrFile, + LANG_NEUTRAL, + ha->dwFileFlags2 | MPQ_FILE_REPLACEEXISTING, + &hf); + + // Write the attributes file raw data to it + if(nError == ERROR_SUCCESS) + { + // Write the content of the attributes file to the MPQ + nError = SFileAddFile_Write(hf, pbAttrFile, cbAttrFile, MPQ_COMPRESSION_ZLIB); + SFileAddFile_Finish(hf); + } - // We expect at least one reserved entry to be there - assert(ha->dwReservedFiles >= 1); - ha->dwReservedFiles--; + // Free the attributes buffer + STORM_FREE(pbAttrFile); + } + else + { + // If the list file is empty, we assume ERROR_SUCCESS + nError = (cbAttrFile == 0) ? ERROR_SUCCESS : ERROR_NOT_ENOUGH_MEMORY; + } - // Create the raw data that is to be written to (attributes) - // Note: Blizzard MPQs have entries for (listfile) and (attributes), - // but they are filled empty - pbAttrFile = CreateAttributesFile(ha, &cbAttrFile); - if(pbAttrFile != NULL) - { - // We expect it to be nonzero size - assert(cbAttrFile != 0); - - // Determine the real flags for (attributes) - if(ha->dwFileFlags2 == MPQ_FILE_EXISTS) - ha->dwFileFlags2 = GetDefaultSpecialFileFlags(cbAttrFile, ha->pHeader->wFormatVersion); - - // Create the attributes file in the MPQ - nError = SFileAddFile_Init(ha, ATTRIBUTES_NAME, - 0, - cbAttrFile, - LANG_NEUTRAL, - ha->dwFileFlags2 | MPQ_FILE_REPLACEEXISTING, - &hf); - - // Write the attributes file raw data to it + // If the save process succeeded, we clear the MPQ_FLAG_ATTRIBUTE_INVALID flag if(nError == ERROR_SUCCESS) { - // Write the content of the attributes file to the MPQ - nError = SFileAddFile_Write(hf, pbAttrFile, cbAttrFile, MPQ_COMPRESSION_ZLIB); - SFileAddFile_Finish(hf); - - // Clear the invalidate flag ha->dwFlags &= ~MPQ_FLAG_ATTRIBUTES_INVALID; + ha->dwReservedFiles--; } - - // Free the attributes buffer - STORM_FREE(pbAttrFile); } return nError; |