From 486a7dd29f3bdf884d4be5588d9171daa5da1bae Mon Sep 17 00:00:00 2001 From: Ladislav Zezula Date: Thu, 3 Jul 2025 09:27:16 +0200 Subject: Replaced GetLastError with SErrGetLastError --- src/StormCommon.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/StormCommon.h') diff --git a/src/StormCommon.h b/src/StormCommon.h index 52f5cd0..ed67fe1 100644 --- a/src/StormCommon.h +++ b/src/StormCommon.h @@ -333,7 +333,7 @@ DWORD ConvertMpqHeaderToFormat4(TMPQArchive * ha, ULONGLONG MpqOffset, ULONGLONG bool IsValidHashEntry(TMPQArchive * ha, TMPQHash * pHash); -TMPQHash * FindFreeHashEntry(TMPQArchive * ha, DWORD dwStartIndex, DWORD dwName1, DWORD dwName2, LCID lcFileLocale); +TMPQHash * FindFreeHashEntry(TMPQArchive * ha, DWORD dwStartIndex, DWORD dwHashCheck1, DWORD dwHashCheck2, LCID lcFileLocale); TMPQHash * GetFirstHashEntry(TMPQArchive * ha, const char * szFileName); TMPQHash * GetNextHashEntry(TMPQArchive * ha, TMPQHash * pFirstHash, TMPQHash * pPrevHash); TMPQHash * AllocateHashEntry(TMPQArchive * ha, TFileEntry * pFileEntry, LCID lcFileLocale); -- cgit v1.2.3 From db410fd564af358cb7c1e2e72cdbaeaeef510e09 Mon Sep 17 00:00:00 2001 From: Ladislav Zezula Date: Wed, 6 Aug 2025 09:34:58 +0200 Subject: Fixed renaming files vs file locale --- make-msvc.bat | 14 +++++--- make.bat | 8 ++--- src/SFileAddFile.cpp | 33 ++++++++++++++++--- src/StormCommon.h | 2 +- src/lzma/C/Threads.c | 2 +- test/StormTest.cpp | 80 ++++++++++++++++++++++++++++++++++++++++++++++ test/stormlib-test-001.txt | 1 + 7 files changed, 124 insertions(+), 16 deletions(-) (limited to 'src/StormCommon.h') diff --git a/make-msvc.bat b/make-msvc.bat index 946274e..5bbdbf3 100644 --- a/make-msvc.bat +++ b/make-msvc.bat @@ -25,9 +25,13 @@ if exist "%PROGRAM_FILES_X64%\Microsoft Visual Studio\2022\Enterprise\VC\Auxilia if exist "%PROGRAM_FILES_X64%\Microsoft Visual Studio\2022\Professional\VC\Auxiliary\Build\vcvarsall.bat" set VCVARS_20xx=%PROGRAM_FILES_X64%\Microsoft Visual Studio\2022\Professional\VC\Auxiliary\Build\vcvarsall.bat if exist "%PROGRAM_FILES_X64%\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvarsall.bat" set VCVARS_20xx=%PROGRAM_FILES_X64%\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvarsall.bat -:: Build all libraries using Visual Studio 2008 and 202x +:: Build all libraries using Visual Studio 2008 +rmdir /S /Q .\bin\%LIB_NAME% if not "x%VCVARS_2008%" == "x" call :BuildLibs "%VCVARS_2008%" x86 %LIB_NAME%_vs08.sln vs2008 if not "x%VCVARS_2008%" == "x" call :BuildLibs "%VCVARS_2008%" x64 %LIB_NAME%_vs08.sln vs2008 + +:: Build all libraries using Visual Studio 2017+ +rmdir /S /Q .\bin\%LIB_NAME% if not "x%VCVARS_20xx%" == "x" call :BuildLibs "%VCVARS_20xx%" x86 %LIB_NAME%.sln if not "x%VCVARS_20xx%" == "x" call :BuildLibs "%VCVARS_20xx%" x64 %LIB_NAME%.sln goto:eof @@ -92,7 +96,7 @@ devenv.com %1 /project "%LIB_NAME%" /rebuild "%5|%2" if not exist ..\aaa goto:eof if not exist ..\aaa\inc md ..\aaa\inc if not exist ..\aaa\%3 md ..\aaa\%3 -copy /Y /D .\src\StormLib.h ..\aaa\inc >nul -copy /Y /D .\src\StormPort.h ..\aaa\inc >nul -copy /Y /D .\bin\StormLib\%2\%5\%4.lib ..\aaa\%3\%4.lib >nul -copy /Y /D .\bin\StormLib\%2\%5\%4.pdb ..\aaa\%3\%4.pdb >nul +copy /Y .\src\StormLib.h ..\aaa\inc >nul +copy /Y .\src\StormPort.h ..\aaa\inc >nul +copy /Y .\bin\%LIB_NAME%\%2\%5\%4.lib ..\aaa\%3\%4.lib >nul +copy /Y .\bin\%LIB_NAME%\%2\%5\%4.pdb ..\aaa\%3\%4.pdb >nul diff --git a/make.bat b/make.bat index 4eb8cec..3c46626 100644 --- a/make.bat +++ b/make.bat @@ -20,10 +20,10 @@ echo. :BUILD_BINARY_64 echo Building %BINARY_NAME%.lib (64-bit) ... set DDKBUILDENV= -call %WDKDIR%\bin\setenv.bat %WDKDIR%\ fre x64 WLH +call %WDKDIR%\bin\setenv.bat %WDKDIR%\ fre x64 wnet cd /d %PROJECT_DIR% build.exe -czgw -del buildfre_wlh_amd64.log +del buildfre_wnet_amd64.log echo. :BUILD_BINARY_32 @@ -42,8 +42,8 @@ if not exist ..\aaa\lib32 md ..\aaa\lib32 if not exist ..\aaa\lib64 md ..\aaa\lib64 copy /Y .\src\StormLib.h ..\aaa\inc >nul copy /Y .\src\StormPort.h ..\aaa\inc >nul -copy /Y .\objfre_wlh_amd64\amd64\%BINARY_NAME%.lib ..\aaa\lib64\%BINARY_NAME%.lib >nul -copy /Y .\objfre_w2k_x86\i386\%BINARY_NAME%.lib ..\aaa\lib32\%BINARY_NAME%.lib >nul +copy /Y .\objfre_wnet_amd64\amd64\%BINARY_NAME%.lib ..\aaa\lib64\%BINARY_NAME%.lib >nul +copy /Y .\objfre_w2k_x86\i386\%BINARY_NAME%.lib ..\aaa\lib32\%BINARY_NAME%.lib >nul :CLEANUP if exist sources-cpp.cpp del sources-cpp.cpp diff --git a/src/SFileAddFile.cpp b/src/SFileAddFile.cpp index e04e876..f281d94 100644 --- a/src/SFileAddFile.cpp +++ b/src/SFileAddFile.cpp @@ -1163,8 +1163,11 @@ bool WINAPI SFileRemoveFile(HANDLE hMpq, const char * szFileName, DWORD dwSearch bool WINAPI SFileRenameFile(HANDLE hMpq, const char * szFileName, const char * szNewFileName) { TMPQArchive * ha = IsValidMpqHandle(hMpq); + TFileEntry * pFileEntry; TMPQFile * hf; + DWORD dwHashIndex = 0; DWORD dwErrCode = ERROR_SUCCESS; + LCID lcFileLocale = 0; // Test the valid parameters if(ha == NULL) @@ -1181,11 +1184,25 @@ bool WINAPI SFileRenameFile(HANDLE hMpq, const char * szFileName, const char * s dwErrCode = ERROR_ACCESS_DENIED; } - // Open the new file. If exists, we don't allow rename operation + // Retrieve the locale of the existing file + // Could be the preferred one or neutral one + if(dwErrCode == ERROR_SUCCESS && ha->pHashTable != NULL) + { + if((pFileEntry = GetFileEntryLocale(ha, szFileName, g_lcFileLocale, &dwHashIndex)) != NULL) + { + lcFileLocale = ha->pHashTable[dwHashIndex].Locale; + } + else + dwErrCode = ERROR_FILE_NOT_FOUND; + } + + // The target file entry must not be there if(dwErrCode == ERROR_SUCCESS) { - if(GetFileEntryLocale(ha, szNewFileName, g_lcFileLocale) != NULL) + if(GetFileEntryExact(ha, szNewFileName, lcFileLocale) != NULL) + { dwErrCode = ERROR_ALREADY_EXISTS; + } } // Open the file from the MPQ @@ -1195,9 +1212,9 @@ bool WINAPI SFileRenameFile(HANDLE hMpq, const char * szFileName, const char * s if(SFileOpenFileEx(hMpq, szFileName, SFILE_OPEN_BASE_FILE, (HANDLE *)&hf)) { ULONGLONG RawDataOffs; - TFileEntry * pFileEntry = hf->pFileEntry; // Invalidate the entries for internal files + pFileEntry = hf->pFileEntry; InvalidateInternalFiles(ha); // Rename the file entry in the table @@ -1266,15 +1283,21 @@ bool WINAPI SFileSetFileLocale(HANDLE hFile, LCID lcNewLocale) TFileEntry * pFileEntry; TMPQFile * hf = IsValidFileHandle(hFile); - // Invalid handle => do nothing + // Invalid file handle => return error if(hf == NULL) { SErrSetLastError(ERROR_INVALID_HANDLE); return false; } + // Invalid archive handle => return error + if((ha = IsValidMpqHandle(hf->ha)) == NULL) + { + SErrSetLastError(ERROR_INVALID_HANDLE); + return false; + } + // Do not allow to rename files in MPQ open for read only - ha = hf->ha; if(ha->dwFlags & MPQ_FLAG_READ_ONLY) { SErrSetLastError(ERROR_ACCESS_DENIED); diff --git a/src/StormCommon.h b/src/StormCommon.h index ed67fe1..7f71452 100644 --- a/src/StormCommon.h +++ b/src/StormCommon.h @@ -366,7 +366,7 @@ void FreeBetTable(TMPQBetTable * pBetTable); // Functions for finding files in the file table TFileEntry * GetFileEntryLocale(TMPQArchive * ha, const char * szFileName, LCID lcFileLocale, LPDWORD PtrHashIndex = NULL); -TFileEntry * GetFileEntryExact(TMPQArchive * ha, const char * szFileName, LCID lcFileLocale, LPDWORD PtrHashIndex); +TFileEntry * GetFileEntryExact(TMPQArchive * ha, const char * szFileName, LCID lcFileLocale, LPDWORD PtrHashIndex = NULL); // Allocates file name in the file entry void AllocateFileName(TMPQArchive * ha, TFileEntry * pFileEntry, const char * szFileName); diff --git a/src/lzma/C/Threads.c b/src/lzma/C/Threads.c index 17f70be..7af1da2 100644 --- a/src/lzma/C/Threads.c +++ b/src/lzma/C/Threads.c @@ -9,7 +9,7 @@ static WRes GetError() { - DWORD res = SErrGetLastError(); + DWORD res = GetLastError(); return (res) ? (WRes)(res) : 1; } diff --git a/test/StormTest.cpp b/test/StormTest.cpp index 285f381..3cbd854 100755 --- a/test/StormTest.cpp +++ b/test/StormTest.cpp @@ -1049,6 +1049,25 @@ static DWORD GetFilePatchCount(TLogHelper * pLogger, HANDLE hMpq, LPCSTR szFileN return nPatchCount; } +static DWORD SetLocaleForFileOperations(HANDLE hMpq, LPCSTR szFileName, LCID lcLocale) +{ + HANDLE hFile = NULL; + DWORD dwErrCode = ERROR_SUCCESS; + + if(SFileOpenFileEx(hMpq, szFileName, 0, &hFile)) + { + if(!SFileSetFileLocale(hFile, lcLocale)) + dwErrCode = SErrGetLastError(); + SFileSetLocale(lcLocale); + SFileCloseFile(hFile); + } + else + { + dwErrCode = SErrGetLastError(); + } + return dwErrCode; +} + static DWORD VerifyFilePatchCount(TLogHelper * pLogger, HANDLE hMpq, LPCSTR szFileName, DWORD dwExpectedPatchCount) { DWORD dwPatchCount = 0; @@ -3057,6 +3076,61 @@ static DWORD TestCreateArchive(const TEST_INFO2 & TestInfo) return TestCreateArchive(szPlainNameT, TestInfo.szName2, TestInfo.dwFlags); } +static DWORD TestRenameFile(LPCTSTR szPlainName) +{ + TLogHelper Logger("TestRenameFile", szPlainName); + LPCSTR szSourceFile = "war3map.mmp"; + LPCSTR szTargetFile = "war3map.wts"; + HANDLE hMpq = NULL; + DWORD dwErrCode; + DWORD dwFailed = 0; + LCID LCID_RURU = 0x0419; + LCID LCID_ESES = 0x040A; + + // Create copy of the archive and open it + dwErrCode = OpenExistingArchiveWithCopy(&Logger, szPlainName, szPlainName, &hMpq); + if(dwErrCode == ERROR_SUCCESS) + { + // Try to rename an existing file to "war3map.wts". + // This must fail because the file already exists. + if(SFileRenameFile(hMpq, szSourceFile, szTargetFile)) + dwFailed++; + + // Now change locale of an existing file to Russian + if(SetLocaleForFileOperations(hMpq, szSourceFile, LCID_RURU) != ERROR_SUCCESS) + dwFailed++; + + // The rename should work now + if(!SFileRenameFile(hMpq, szSourceFile, szTargetFile)) + dwFailed++; + + // Changing the file locale to Neutral should fail now, + // because such file already exists + if(SetLocaleForFileOperations(hMpq, szTargetFile, 0) != ERROR_ALREADY_EXISTS) + dwFailed++; + + // Pick another source file + szSourceFile = "war3map.shd"; + + // Change the file locale to Spain + if(SetLocaleForFileOperations(hMpq, szSourceFile, LCID_ESES) != ERROR_SUCCESS) + dwFailed++; + + // This rename should also work, because there is no target file with Spanish locale + if(!SFileRenameFile(hMpq, szSourceFile, szTargetFile)) + dwFailed++; + + // Evaluate the result + if(dwFailed != 0) + dwErrCode = ERROR_CAN_NOT_COMPLETE; + SFileCloseArchive(hMpq); + } + + // Restore the original file locale + SFileSetLocale(LANG_NEUTRAL); + return dwErrCode; +} + static DWORD TestCreateArchive_TestGaps(LPCTSTR szPlainName) { TLogHelper Logger("TestCreateGaps", szPlainName); @@ -3322,6 +3396,7 @@ static DWORD TestCreateArchive_FileFlagTest(LPCTSTR szPlainName) // Create paths for local file to be added CreateFullPathName(szFileName1, _countof(szFileName1), szDataFileDir, _T("new-file.exe")); CreateFullPathName(szFileName2, _countof(szFileName2), szDataFileDir, _T("new-file.bin")); + SFileSetLocale(LANG_NEUTRAL); // Create an empty file that will serve as holder for the MPQ dwErrCode = CreateEmptyFile(&Logger, szPlainName, 0x100000, szFullPath); @@ -4503,6 +4578,11 @@ int _tmain(int argc, TCHAR * argv[]) #endif #ifdef TEST_MISC_MPQS + + // Test creating of an archive the same way like MPQ Editor does + if(dwErrCode == ERROR_SUCCESS) + dwErrCode = TestRenameFile(_T("MPQ_2002_v1_StrongSignature.w3m")); + // Test creating of an archive the same way like MPQ Editor does if(dwErrCode == ERROR_SUCCESS) dwErrCode = TestCreateArchive_TestGaps(_T("StormLibTest_GapsTest.mpq")); diff --git a/test/stormlib-test-001.txt b/test/stormlib-test-001.txt index 062652f..cf96931 100644 --- a/test/stormlib-test-001.txt +++ b/test/stormlib-test-001.txt @@ -163,6 +163,7 @@ CreateNewMpq (StormLibTest_简体中文.mpq) succeeded. CreateNewMpq (StormLibTest_الععربية.mpq) succeeded. CreateNewMpq (StormLibTest_NonStdNames.mpq) succeeded. CreateNewMpq (StormLibTest_MpqEditorTest.mpq) succeeded. +TestRenameFile (MPQ_2002_v1_StrongSignature.w3m) succeeded. TestCreateGaps (StormLibTest_GapsTest.mpq) succeeded. TestCreateFull (StormLibTest_FileTableFull.mpq) succeeded. TestCreateFull (StormLibTest_FileTableFull.mpq) succeeded. -- cgit v1.2.3