mirror of
https://github.com/ladislav-zezula/StormLib.git
synced 2026-01-15 21:00:32 +01:00
Fixed renaming files vs file locale
This commit is contained in:
@@ -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
|
||||
|
||||
8
make.bat
8
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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
static WRes GetError()
|
||||
{
|
||||
DWORD res = SErrGetLastError();
|
||||
DWORD res = GetLastError();
|
||||
return (res) ? (WRes)(res) : 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -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"));
|
||||
|
||||
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user