From 17d51a8256d1d1dbab5fd7000ee5f4f31b74d338 Mon Sep 17 00:00:00 2001 From: Ladislav Zezula Date: Thu, 8 Nov 2018 17:06:12 +0100 Subject: * New feature: Force add listfile --- src/FileStream.cpp | 4 ++-- src/SBaseFileTable.cpp | 28 ++++++++++++++++++---------- src/SFileOpenArchive.cpp | 6 +++++- src/StormLib.h | 16 +++++++++------- test/StormTest.cpp | 17 +++++++++++++---- 5 files changed, 47 insertions(+), 24 deletions(-) diff --git a/src/FileStream.cpp b/src/FileStream.cpp index 84f36c0..514a683 100644 --- a/src/FileStream.cpp +++ b/src/FileStream.cpp @@ -41,9 +41,9 @@ DWORD GetLastError() return nLastError; } -void SetLastError(DWORD nError) +void SetLastError(DWORD dwErrCode) { - nLastError = nError; + nLastError = dwErrCode; } #endif diff --git a/src/SBaseFileTable.cpp b/src/SBaseFileTable.cpp index 700df48..a54f152 100644 --- a/src/SBaseFileTable.cpp +++ b/src/SBaseFileTable.cpp @@ -2069,10 +2069,10 @@ int DeleteFileEntry(TMPQArchive * ha, TMPQFile * hf) return ERROR_SUCCESS; } -DWORD InvalidateInternalFile(TMPQArchive * ha, const char * szFileName, DWORD dwFlagNone, DWORD dwFlagNew) +DWORD InvalidateInternalFile(TMPQArchive * ha, const char * szFileName, DWORD dwFlagNone, DWORD dwFlagNew, DWORD dwForceAddTheFile = 0) { TMPQFile * hf = NULL; - DWORD dwFileFlags = 0; + DWORD dwFileFlags = MPQ_FILE_DEFAULT_INTERNAL; int nError = ERROR_FILE_NOT_FOUND; // Open the file from the MPQ @@ -2084,17 +2084,25 @@ DWORD InvalidateInternalFile(TMPQArchive * ha, const char * szFileName, DWORD dw // Delete the file entry nError = DeleteFileEntry(ha, hf); if(nError == ERROR_SUCCESS) - { - ha->dwFlags |= dwFlagNew; - ha->dwReservedFiles++; - } + dwForceAddTheFile = 1; - // Free the file entry + // Close the file FreeFileHandle(hf); } - // If the deletion failed, set the "none" flag - ha->dwFlags |= (nError != ERROR_SUCCESS) ? dwFlagNone : 0; + // Are we going to add the file? + if(dwForceAddTheFile) + { + ha->dwFlags |= dwFlagNew; + ha->dwReservedFiles++; + } + else + { + ha->dwFlags |= dwFlagNone; + dwFileFlags = 0; + } + + // Return the intended file flags return dwFileFlags; } @@ -2112,7 +2120,7 @@ void InvalidateInternalFiles(TMPQArchive * ha) // Invalidate the (listfile), if not done yet if((ha->dwFlags & (MPQ_FLAG_LISTFILE_NONE | MPQ_FLAG_LISTFILE_NEW)) == 0) { - ha->dwFileFlags1 = InvalidateInternalFile(ha, LISTFILE_NAME, MPQ_FLAG_LISTFILE_NONE, MPQ_FLAG_LISTFILE_NEW); + ha->dwFileFlags1 = InvalidateInternalFile(ha, LISTFILE_NAME, MPQ_FLAG_LISTFILE_NONE, MPQ_FLAG_LISTFILE_NEW, (ha->dwFlags & MPQ_FLAG_LISTFILE_FORCE)); } // Invalidate the (attributes), if not done yet diff --git a/src/SFileOpenArchive.cpp b/src/SFileOpenArchive.cpp index 15dffe4..9307cd8 100644 --- a/src/SFileOpenArchive.cpp +++ b/src/SFileOpenArchive.cpp @@ -375,6 +375,10 @@ bool WINAPI SFileOpenArchive( if(dwFlags & (MPQ_OPEN_NO_LISTFILE | MPQ_OPEN_NO_ATTRIBUTES)) ha->dwFlags |= MPQ_FLAG_READ_ONLY; + // Check if the caller wants to force adding listfile + if(dwFlags & MPQ_OPEN_FORCE_LISTFILE) + ha->dwFlags |= MPQ_FLAG_LISTFILE_FORCE; + // Remember whether whis is a map for Warcraft III if(bIsWarcraft3Map) ha->dwFlags |= MPQ_FLAG_WAR3_MAP; @@ -522,7 +526,7 @@ bool WINAPI SFileFlushArchive(HANDLE hMpq) nResultError = nError; } - if(ha->dwFlags & MPQ_FLAG_LISTFILE_NEW) + if(ha->dwFlags & (MPQ_FLAG_LISTFILE_NEW | MPQ_FLAG_LISTFILE_FORCE)) { nError = SListFileSaveToMpq(ha); if(nError != ERROR_SUCCESS) diff --git a/src/StormLib.h b/src/StormLib.h index b9f60a4..31f6eda 100644 --- a/src/StormLib.h +++ b/src/StormLib.h @@ -181,7 +181,7 @@ extern "C" { #define SFILE_OPEN_ANY_LOCALE 0xFFFFFFFE // Reserved for StormLib internal use #define SFILE_OPEN_LOCAL_FILE 0xFFFFFFFF // Open a local file -// Flags for TMPQArchive::dwFlags +// Flags for TMPQArchive::dwFlags. Used internally #define MPQ_FLAG_READ_ONLY 0x00000001 // If set, the MPQ has been open for read-only access #define MPQ_FLAG_CHANGED 0x00000002 // If set, the MPQ tables have been changed #define MPQ_FLAG_MALFORMED 0x00000004 // Malformed data structure detected (W3M map protectors) @@ -193,10 +193,11 @@ extern "C" { #define MPQ_FLAG_WAR3_MAP 0x00000100 // If set, this MPQ is a map for Warcraft III #define MPQ_FLAG_LISTFILE_NONE 0x00000200 // Set when no (listfile) was found in InvalidateInternalFiles #define MPQ_FLAG_LISTFILE_NEW 0x00000400 // Set when (listfile) invalidated by InvalidateInternalFiles -#define MPQ_FLAG_ATTRIBUTES_NONE 0x00000800 // Set when no (attributes) was found in InvalidateInternalFiles -#define MPQ_FLAG_ATTRIBUTES_NEW 0x00001000 // Set when (attributes) invalidated by InvalidateInternalFiles -#define MPQ_FLAG_SIGNATURE_NONE 0x00002000 // Set when no (signature) was found in InvalidateInternalFiles -#define MPQ_FLAG_SIGNATURE_NEW 0x00004000 // Set when (signature) invalidated by InvalidateInternalFiles +#define MPQ_FLAG_LISTFILE_FORCE 0x00000800 // Save updated listfile on exit +#define MPQ_FLAG_ATTRIBUTES_NONE 0x00001000 // Set when no (attributes) was found in InvalidateInternalFiles +#define MPQ_FLAG_ATTRIBUTES_NEW 0x00002000 // Set when (attributes) invalidated by InvalidateInternalFiles +#define MPQ_FLAG_SIGNATURE_NONE 0x00004000 // Set when no (signature) was found in InvalidateInternalFiles +#define MPQ_FLAG_SIGNATURE_NEW 0x00008000 // Set when (signature) invalidated by InvalidateInternalFiles // Values for TMPQArchive::dwSubType #define MPQ_SUBTYPE_MPQ 0x00000000 // The file is a MPQ file (Blizzard games) @@ -322,6 +323,7 @@ extern "C" { #define MPQ_OPEN_FORCE_MPQ_V1 0x00080000 // Always open the archive as MPQ v 1.00, ignore the "wFormatVersion" variable in the header #define MPQ_OPEN_CHECK_SECTOR_CRC 0x00100000 // On files with MPQ_FILE_SECTOR_CRC, the CRC will be checked when reading file #define MPQ_OPEN_PATCH 0x00200000 // This archive is a patch MPQ. Used internally. +#define MPQ_OPEN_FORCE_LISTFILE 0x00400000 // Force add listfile even if there is none at the moment of opening #define MPQ_OPEN_READ_ONLY STREAM_FLAG_READ_ONLY // Flags for SFileCreateArchive @@ -1101,8 +1103,8 @@ int WINAPI SCompDecompress2(void * pvOutBuffer, int * pcbOutBuffer, void * pv #ifndef PLATFORM_WINDOWS -void SetLastError(DWORD err); -DWORD GetLastError(); +void SetLastError(DWORD dwErrCode); +DWORD GetLastError(); #endif diff --git a/test/StormTest.cpp b/test/StormTest.cpp index d248bd6..fd85abf 100644 --- a/test/StormTest.cpp +++ b/test/StormTest.cpp @@ -4404,6 +4404,15 @@ int _tmain(int argc, TCHAR * argv[]) printf("==== Test Suite for StormLib version %s ====\n", STORMLIB_VERSION_STRING); nError = InitializeMpqDirectory(argv, argc); + HANDLE hMpq = NULL; + + if(SFileOpenArchive(_T("e:\\hm.w3x"), 0, MPQ_OPEN_FORCE_LISTFILE, &hMpq)) + { + SFileAddListFile(hMpq, _T("c:\\Tools32\\ListFiles\\Warcraft III Maps.txt")); + SFileAddFile(hMpq, _T("e:\\dummy.txt"), "dummy.txt", 0); + SFileCloseArchive(hMpq); + } + // Not a test, but rather a tool for creating links to duplicated files // if(nError == ERROR_SUCCESS) // nError = FindFilePairs(ForEachFile_CreateArchiveLink, "2004 - WoW\\06080", "2004 - WoW\\06299"); @@ -4463,11 +4472,11 @@ int _tmain(int argc, TCHAR * argv[]) // Open a stream, paired with local master if(nError == ERROR_SUCCESS) nError = TestReadFile_MasterMirror(_T("MPQ_2013_v4_alternate-complete.MPQ"), _T("MPQ_2013_v4_alternate-original.MPQ"), true); -*/ + // Open a stream, paired with remote master (takes hell lot of time!!!) if(nError == ERROR_SUCCESS) nError = TestReadFile_MasterMirror(_T("MPQ_2013_v4_alternate-downloaded.MPQ"), _T("http://www.zezula.net\\mpqs\\alternate.zip"), false); -/* + // Search in listfile if(nError == ERROR_SUCCESS) nError = TestSearchListFile(_T("ListFile_Blizzard.txt")); @@ -4700,7 +4709,7 @@ int _tmain(int argc, TCHAR * argv[]) // Check the SFileGetFileInfo function if(nError == ERROR_SUCCESS) nError = TestOpenArchive_GetFileInfo(_T("MPQ_2002_v1_StrongSignature.w3m"), _T("MPQ_2013_v4_SC2_EmptyMap.SC2Map")); -*/ + // Downloadable MPQ archive if(nError == ERROR_SUCCESS) nError = TestOpenArchive_MasterMirror(_T("part-file://MPQ_2009_v1_patch-partial.MPQ.part"), _T("MPQ_2009_v1_patch-original.MPQ"), "world\\Azeroth\\DEADMINES\\PASSIVEDOODADS\\GOBLINMELTINGPOT\\DUST2.BLP", false); @@ -4839,7 +4848,7 @@ int _tmain(int argc, TCHAR * argv[]) // Test replacing a file with zero size file if(nError == ERROR_SUCCESS) nError = TestModifyArchive_ReplaceFile(_T("MPQ_2014_v4_Base.StormReplay"), _T("AddFile-replay.message.events")); - +*/ #ifdef _MSC_VER _CrtDumpMemoryLeaks(); #endif // _MSC_VER -- cgit v1.2.3