diff options
author | Ladislav Zezula <zezula@volny.cz> | 2025-08-06 09:34:58 +0200 |
---|---|---|
committer | Ladislav Zezula <zezula@volny.cz> | 2025-08-06 09:34:58 +0200 |
commit | db410fd564af358cb7c1e2e72cdbaeaeef510e09 (patch) | |
tree | cbe34ab3d2d2c7ab784ba890b7d2a3436bb6795b | |
parent | 65582d5649ce19afcac9fde06804c7f9ab3e2716 (diff) |
Fixed renaming files vs file locale
-rw-r--r-- | make-msvc.bat | 14 | ||||
-rw-r--r-- | make.bat | 8 | ||||
-rw-r--r-- | src/SFileAddFile.cpp | 33 | ||||
-rw-r--r-- | src/StormCommon.h | 2 | ||||
-rw-r--r-- | src/lzma/C/Threads.c | 2 | ||||
-rwxr-xr-x | test/StormTest.cpp | 80 | ||||
-rw-r--r-- | test/stormlib-test-001.txt | 1 |
7 files changed, 124 insertions, 16 deletions
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 @@ -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. |