diff options
35 files changed, 1099 insertions, 460 deletions
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..8bfe95f --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,115 @@ +name: CMake + +on: [push, pull_request] + +env: + BUILD_TYPE: Release + +jobs: + debian-bookworm: + runs-on: ubuntu-latest + container: + image: debian:bookworm + + strategy: + matrix: + storm_use_bundled_libraries: [ ON, OFF ] + with_libtomcrypt: [ ON, OFF ] + build_shared_libs: [ ON, OFF ] + unicode: [ ON, OFF ] + + steps: + - uses: actions/checkout@v4 + + - name: Install dependencies + run: apt-get -y update && apt-get install -y build-essential cmake + + - name: Conditionally install libtomcrypt-dev + if: matrix.with_libtomcrypt == 'ON' + run: apt-get install -y libtomcrypt-dev pkg-config + + - name: CMake Configuration + run: | + cmake -B build \ + -D CMAKE_BUILD_TYPE=Release \ + -D STORM_USE_BUNDLED_LIBRARIES=${{ matrix.storm_use_bundled_libraries }} \ + -D WITH_LIBTOMCRYPT=${{ matrix.with_libtomcrypt }} \ + -D BUILD_SHARED_LIBS=${{ matrix.build_shared_libs }} \ + -D STORM_UNICODE=${{ matrix.unicode }} + + - name: Build + run: cmake --build build --config Release + + fedora-latest: + if: true + runs-on: ubuntu-latest + container: + image: fedora:latest + + steps: + - uses: actions/checkout@v4 + + - name: Install dependencies + run: dnf -y install cmake gcc gcc-c++ + + - name: Cmake + run: cmake -B build -D CMAKE_BUILD_TYPE=$BUILD_TYPE -D BUILD_SHARED_LIBS=ON + + - name: Build + run: cmake --build build --config Release + + windows-latest-x64: + if: true + runs-on: windows-latest + + steps: + - uses: actions/checkout@v4 + + - uses: TheMrMilchmann/setup-msvc-dev@v3 + with: + arch: x64 + + - name: Cmake + run: cmake -B build -D CMAKE_BUILD_TYPE=$BUILD_TYPE -D BUILD_SHARED_LIBS=ON + + - name: Build + run: cmake --build build --config Release + + - name: Debug + shell: bash + run: ls -la build + + - name: Check PE + shell: bash + working-directory: ./build/Release + run: | + file "stormlib.dll" + file "stormlib.dll" |grep "x86-64" + + windows-latest-x86: + if: true + runs-on: windows-latest + + steps: + - uses: actions/checkout@v4 + + - uses: TheMrMilchmann/setup-msvc-dev@v3 + with: + arch: x86 + + - name: Cmake + run: cmake -B build -D CMAKE_BUILD_TYPE=$BUILD_TYPE -D BUILD_SHARED_LIBS=ON + + - name: Build + run: cmake --build build --config Release + + - name: Debug + shell: bash + run: ls -la build + + - name: Check PE + shell: bash + working-directory: ./build/Release + run: | + file "stormlib.dll" + file "stormlib.dll" |grep "x86-64" diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..18702ed --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,187 @@ +name: Release + +on: + push: + tags: + - '*' + +jobs: + deb: + if: true + runs-on: ubuntu-latest + container: + image: debian:bookworm + env: + BUILD_TYPE: Release + + steps: + - uses: actions/checkout@v4 + + - name: Install dependencies + run: apt-get -y update && apt-get install -y build-essential cmake + + - name: Cmake + run: cmake -B build -D BUILD_SHARED_LIBS=ON -DCMAKE_BUILD_TYPE=$BUILD_TYPE + + - name: Build + run: cmake --build build --config $BUILD_TYPE + + - name: Package + id: package + working-directory: build + run: | + cpack -G "DEB" -D CPACK_PACKAGE_FILE_NAME=libstorm-dev_${{ github.ref_name }}_amd64 + + - uses: actions/upload-artifact@v4 + with: + retention-days: 1 + overwrite: true + name: libstorm-dev_${{ github.ref_name }}_amd64.deb + path: build/libstorm-dev_${{ github.ref_name }}_amd64.deb + + rpm: + if: true + runs-on: ubuntu-latest + container: + image: fedora:latest + env: + BUILD_TYPE: Release + + steps: + - uses: actions/checkout@v4 + + - name: Install dependencies + run: dnf -y install cmake gcc gcc-c++ rpm-build + + - name: Cmake + run: cmake -B build -D BUILD_SHARED_LIBS=ON -DCMAKE_BUILD_TYPE=$BUILD_TYPE + + - name: Build + run: cmake --build build --config $BUILD_TYPE + + - name: Package + working-directory: build + run: cpack -G "RPM" -D CPACK_PACKAGE_FILE_NAME=libstorm-devel-${{ github.ref_name }}.x86_64 + + - uses: actions/upload-artifact@v4 + with: + retention-days: 1 + overwrite: true + name: libstorm-devel-${{ github.ref_name }}.x86_64.rpm + path: build/libstorm-devel-${{ github.ref_name }}.x86_64.rpm + + build_win: + if: true + runs-on: windows-latest + strategy: + matrix: + arch: [ amd64, x86 ] + build_type: [ Release, Debug ] + unicode: [ ON, OFF ] + shared: [ ON, OFF ] + + steps: + - uses: actions/checkout@v4 + + - uses: TheMrMilchmann/setup-msvc-dev@v3 + with: + arch: ${{ matrix.arch }} + + - name: Configure CMake for amd64 + if: ${{ matrix.arch == 'amd64' }} + shell: cmd + run: cmake -B build -DBUILD_SHARED_LIBS=${{ matrix.shared }} -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} -DSTORM_UNICODE=${{ matrix.unicode }} + + - name: Configure CMake for x86 + if: ${{ matrix.arch == 'x86' }} + shell: cmd + run: cmake -B build -DBUILD_SHARED_LIBS=${{ matrix.shared }} -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} -DSTORM_UNICODE=${{ matrix.unicode }} -A Win32 + + - name: Build + shell: cmd + run: cmake --build build --config ${{ matrix.build_type }} + + - name: Check PE + if: ${{ matrix.shared == 'ON' }} + shell: bash + working-directory: ./build/${{ matrix.build_type }} + run: | + file "stormlib.dll" + if [[ "${{ matrix.arch }}" == "x86" ]]; then + file "stormlib.dll" | grep -E "Intel 80386|Intel i386" + else + file "stormlib.dll" | grep "x86-64" + fi + + - name: Install to staging area + shell: cmd + run: cmake --install build --prefix build/staging --config ${{ matrix.build_type }} + + - name: Create Archive + shell: pwsh + id: create_archive + working-directory: ./build/staging + run: | + $r = if ("${{ matrix.build_type }}" -eq "Release") { "R" } else { "D" } + $a = if ("${{ matrix.unicode }}" -eq "ON") { "U" } else { "A" } + $s = if ("${{ matrix.shared }}" -eq "ON") { "D" } else { "S" } + + $zipSuffix = "${r}${a}${s}" + $zipName = "stormlib_${{ github.ref_name }}_${{ matrix.arch }}_${zipSuffix}.zip" + "zip_name=$zipName" | Out-File -FilePath $env:GITHUB_OUTPUT -Encoding utf8 -Append + + Compress-Archive -Path include -DestinationPath $zipName + + $binItems = Get-ChildItem -Path bin\* -ErrorAction SilentlyContinue + if ($binItems) { + Compress-Archive -Path bin/* -DestinationPath $zipName -Update + } + $libItems = Get-ChildItem -Path lib\* -ErrorAction SilentlyContinue + if ($libItems) { + Compress-Archive -Path "lib/*" -DestinationPath $zipName -Update + } + - uses: actions/upload-artifact@v4 + with: + retention-days: 1 + overwrite: true + name: ${{ steps.create_archive.outputs.zip_name }} + path: build/staging/${{ steps.create_archive.outputs.zip_name }} + + release: + needs: [deb, rpm, build_win] + runs-on: ubuntu-latest + + steps: + - name: Download deb + uses: actions/download-artifact@v4 + with: + name: libstorm-dev_${{ github.ref_name }}_amd64.deb + + - name: Download rpm + uses: actions/download-artifact@v4 + with: + name: libstorm-devel-${{ github.ref_name }}.x86_64.rpm + + - name: Download win + uses: actions/download-artifact@v4 + with: + pattern: "*.zip" + merge-multiple: true + + - name: Generate SHA256 checksums + run: | + for file in *.zip *.deb *.rpm; do + sha256sum "$file" >> "release.sha256" + done + + - name: Create GitHub Release + uses: softprops/action-gh-release@v1 + with: + files: | + *.deb + *.sha256 + *.rpm + *.zip + tag_name: ${{ github.ref_name }} + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
\ No newline at end of file @@ -109,6 +109,9 @@ stylecop.* ~$* *.dbmdl Generated_Code #added for RIA/Silverlight projects +.idea/ +cmake-build-*/ +build/ # Backup & report files from converting an old project file to a newer # Visual Studio version. Backup files are not needed, because we have git ;-) diff --git a/.vscode/launch.json b/.vscode/launch.json index e9457ca..e9418f6 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -9,7 +9,7 @@ "name": "(gdb) Launch", "type": "cppdbg", "request": "launch", - "program": "${workspaceFolder}/build/StormLib_test", + "program": "${workspaceFolder}/build/test/StormLib_test", "args": [], "stopAtEntry": false, "cwd": "${workspaceFolder}", diff --git a/CMakeLists.txt b/CMakeLists.txt index 8d17ebe..c78e88a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ -project(StormLib) cmake_minimum_required(VERSION 3.10) +project(StormLib) set(LIBRARY_NAME storm) set(CMAKE_CXX_STANDARD 11) @@ -9,17 +9,6 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON) include(CMakeDependentOption) include(GNUInstallDirs) -option(STORM_UNICODE "Compile UNICODE version instead of ANSI one (Visual Studio only)" OFF) - -if(WIN32) - if(STORM_UNICODE) - message(STATUS "Build UNICODE version") - add_definitions(-DUNICODE -D_UNICODE) - else() - message(STATUS "Build ANSI version") - endif() -endif() - option(BUILD_SHARED_LIBS "Compile shared libraries" OFF) option(STORM_SKIP_INSTALL "Skip installing files" OFF) option(STORM_USE_BUNDLED_LIBRARIES @@ -296,17 +285,15 @@ set(ZLIB_FILES src/zlib/zutil.c ) -set(TEST_SRC_FILES - test/StormTest.cpp -) +add_library(${LIBRARY_NAME} ${LIB_TYPE}) -add_definitions(-D_7ZIP_ST -DBZ_STRICT_ANSI) +target_compile_definitions(${LIBRARY_NAME} PRIVATE -D_7ZIP_ST -DBZ_STRICT_ANSI) set(LINK_LIBS) find_package(ZLIB) if (ZLIB_FOUND AND NOT STORM_USE_BUNDLED_LIBRARIES) set(LINK_LIBS ${LINK_LIBS} ZLIB::ZLIB) - add_definitions(-D__SYS_ZLIB) + target_compile_definitions(${LIBRARY_NAME} PRIVATE -D__SYS_ZLIB) else() set(SRC_FILES ${SRC_FILES} ${ZLIB_FILES}) endif() @@ -314,7 +301,7 @@ endif() find_package(BZip2) if (BZIP2_FOUND AND NOT STORM_USE_BUNDLED_LIBRARIES) set(LINK_LIBS ${LINK_LIBS} BZip2::BZip2) - add_definitions(-D__SYS_BZLIB) + target_compile_definitions(${LIBRARY_NAME} PRIVATE -D__SYS_BZLIB) else() set(SRC_FILES ${SRC_FILES} ${BZIP2_FILES}) endif() @@ -330,7 +317,7 @@ else() find_path(LIBTOMCRYPT_INCLUDE_DIR NAMES tomcrypt.h HINTS ${PC_LIBTOMCRYPT_INCLUDE_DIRS} REQUIRED) find_library(LIBTOMCRYPT_LIBRARY NAMES tomcrypt HINTS ${PC_LIBTOMCRYPT_LIBRARY_DIRS} REQUIRED) set(LINK_LIBS ${LINK_LIBS} ${LIBTOMCRYPT_LIBRARY}) - include_directories(${LIBTOMCRYPT_INCLUDE_DIR}) + target_include_directories(${LIBRARY_NAME} PRIVATE ${LIBTOMCRYPT_INCLUDE_DIR}) else() set(SRC_ADDITIONAL_FILES ${TOMCRYPT_FILES} ${TOMMATH_FILES}) endif() @@ -341,11 +328,22 @@ if(${CMAKE_SYSTEM_NAME} MATCHES "(Free|Net|Open)BSD") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DO_LARGEFILE=0 -Dstat64=stat -Dlstat64=lstat -Dlseek64=lseek -Doff64_t=off_t -Dfstat64=fstat -Dftruncate64=ftruncate") endif() -add_library(${LIBRARY_NAME} ${LIB_TYPE} ${SRC_FILES} ${SRC_ADDITIONAL_FILES} ${STORM_DEF_FILES}) +target_sources(${LIBRARY_NAME} PRIVATE ${SRC_FILES} ${SRC_ADDITIONAL_FILES} ${STORM_DEF_FILES}) if(WIN32) set_target_properties(${LIBRARY_NAME} PROPERTIES OUTPUT_NAME "StormLib") endif() +option(STORM_UNICODE "Compile UNICODE version instead of ANSI one (Visual Studio only)" OFF) + +if(WIN32) + if(STORM_UNICODE) + message(STATUS "Build UNICODE version") + target_compile_definitions(${LIBRARY_NAME} PRIVATE UNICODE _UNICODE) + else() + message(STATUS "Build ANSI version") + endif() +endif() + target_link_libraries(${LIBRARY_NAME} ${LINK_LIBS}) add_library(${PROJECT_NAME}::${LIBRARY_NAME} ALIAS ${LIBRARY_NAME}) # Allow users to link StormLib::storm when using add_subdirectory target_compile_definitions(${LIBRARY_NAME} INTERFACE STORMLIB_NO_AUTO_LINK) #CMake will take care of the linking @@ -360,7 +358,7 @@ if(BUILD_SHARED_LIBS) endif() if(UNIX) SET(VERSION_MAJOR "9") - SET(VERSION_MINOR "22") + SET(VERSION_MINOR "30") SET(VERSION_PATCH "0") SET(VERSION_STRING "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}") set_target_properties(${LIBRARY_NAME} PROPERTIES VERSION "${VERSION_STRING}") @@ -392,8 +390,10 @@ if (NOT STORM_SKIP_INSTALL) SET(CPACK_PACKAGE_VERSION_MAJOR "${VERSION_MAJOR}") SET(CPACK_PACKAGE_VERSION_MINOR "${VERSION_MINOR}") SET(CPACK_PACKAGE_VERSION "${VERSION_MAJOR}.${VERSION_MINOR}") + SET(CPACK_PACKAGING_INSTALL_PREFIX "/usr/local") #DEB configuration + set(CPACK_DEBIAN_PACKAGE_EPOCH 1) SET(CPACK_DEBIAN_PACKAGE_SECTION "libs") SET(CPACK_DEBIAN_PACKAGE_HOMEPAGE "http://www.zezula.net/en/mpq/stormlib.html") SET(CPACK_DEBIAN_PACKAGE_MAINTAINER "imbacen@gmail.com") @@ -401,6 +401,7 @@ if (NOT STORM_SKIP_INSTALL) SET(CPACK_DEBIAN_PACKAGE_DEPENDS "zlib1g,bzip2") #RPM configuration + set(CPACK_RPM_PACKAGE_EPOCH 1) SET(CPACK_RPM_PACKAGE_RELEASE 1) SET(CPACK_RPM_PACKAGE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE") SET(CPACK_RPM_PACKAGE_GROUP "${PROJECT_NAME}") @@ -411,9 +412,7 @@ if (NOT STORM_SKIP_INSTALL) endif() if(STORM_BUILD_TESTS) - find_package(ALSA REQUIRED) - add_executable(StormLib_test ${TEST_SRC_FILES}) - target_link_libraries(StormLib_test ${LIBRARY_NAME} ${ALSA_LIBRARIES}) - install(TARGETS StormLib_test RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) + enable_testing() + add_subdirectory(test) endif() @@ -21,6 +21,23 @@ Note that you can also build the library using newer toolset, such as v143. To d 4. Choose "Rebuild" 5. The result libraries are in `.\bin\Win32` and `.\bin\x64` +### Windows (any Visual Studio version with CMake) +You can open the appropriate Visual Studio cmd prompt or launch regular cmd and load the necessary environment as specified below. +Change your VS version as needed. + +amd64 +``` +"C:/Program Files/Microsoft Visual Studio/2022/Community/VC/Auxiliary/Build/vcvarsall.bat" x64 +cmake -G "Visual Studio 17 2022" -B build_amd64 -D BUILD_SHARED_LIBS=ON +cmake --build build --config Release +``` + +x86 +``` +"C:/Program Files/Microsoft Visual Studio/2022/Community/VC/Auxiliary/Build/vcvarsall.bat" x86 +cmake -G "Visual Studio 17 2022" -B build_x86 -D BUILD_SHARED_LIBS=ON +``` + ### Windows (Test Project) 1. Include the main StormLib header: `#include <StormLib.h>` 2. Set the correct library directory for StormLibXYZ.lib: @@ -30,13 +47,32 @@ Note that you can also build the library using newer toolset, such as v143. To d 3. Rebuild ### Linux -1. Download latest release -2. Install StormLib: ``` -$ cd <path-to-StormLib> -$ cmake CMakeLists.txt -$ make -$ make install +git clone https://github.com/ladislav-zezula/StormLib.git +cd StormLib && git checkout <latest-release-tag> +cmake -B build -D BUILD_SHARED_LIBS=ON +cmake --build build --config Release +sudo cmake --install build ``` -3. Include StormLib in your project: `#include <StormLib.h>` -4. Make sure you compile your project with `-lstorm -lz -lbz2` + +Include StormLib in your project: `#include <StormLib.h>` +Make sure you compile your project with `-lstorm -lz -lbz2` + +To produce deb/rpm packages: +``` +cd build +cpack -G "DEB" -D CPACK_PACKAGE_FILE_NAME=libstorm-dev_v9.30_amd64 +cpack -G "RPM" -D CPACK_PACKAGE_FILE_NAME=libstorm-devel-v9.30.x86_64 +``` + +### List of all CMake options + +| Option Name | Description | Default | +|-------------------------------|-------------------------------------------------------------------|---------| +| `BUILD_SHARED_LIBS` | Compile shared libraries | OFF | +| `STORM_UNICODE` | Unicode or ANSI support | OFF | +| `STORM_SKIP_INSTALL` | Skip installing files | OFF | +| `STORM_USE_BUNDLED_LIBRARIES` | Force use of bundled dependencies instead of system libraries | OFF | +| `WITH_LIBTOMCRYPT` | Use system LibTomCrypt library (non-Windows only) | OFF | +| `STORM_BUILD_TESTS` | Compile StormLib test application | OFF | +| `STORMTEST_USE_OLD_PATHS` | Uses hardcoded paths for test files, OFF uses `build_folder/work` | ON | 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 @@ -1,15 +1,15 @@ @echo off -if not "x%WDKDIR%" == "x" goto SELECT_LIB +if not "x%WDKDIR%" == "x" goto SELECT_BINARY echo The WDKDIR environment variable is not set echo Set this variable to your WDK directory (without ending backslash) echo Example: set WDKDIR C:\WinDDK\6001 pause goto:eof -:SELECT_LIB +:SELECT_BINARY set PROJECT_DIR=%~dp0 -set LIBRARY_NAME=StormLibWDK set SAVE_PATH=%PATH% +set BINARY_NAME=StormLibWDK :PREPARE_SOURCES echo Preparing sources ... @@ -17,22 +17,22 @@ copy .\src\wdk\sources-cpp.cpp . >nul copy .\src\wdk\sources-wdk-* . >nul echo. -:BUILD_LIB_32 -echo Building %LIBRARY_NAME%.lib (32-bit) ... +:BUILD_BINARY_64 +echo Building %BINARY_NAME%.lib (64-bit) ... set DDKBUILDENV= -call %WDKDIR%\bin\setenv.bat %WDKDIR%\ fre w2k -cd %PROJECT_DIR% +call %WDKDIR%\bin\setenv.bat %WDKDIR%\ fre x64 wnet +cd /d %PROJECT_DIR% build.exe -czgw -del buildfre_w2k_x86.log +del buildfre_wnet_amd64.log echo. -:BUILD_LIB_64 -echo Building %LIBRARY_NAME%.lib (64-bit) ... +:BUILD_BINARY_32 +echo Building %BINARY_NAME%.lib (32-bit) ... set DDKBUILDENV= -call %WDKDIR%\bin\setenv.bat %WDKDIR%\ fre x64 WLH -cd %PROJECT_DIR% +call %WDKDIR%\bin\setenv.bat %WDKDIR%\ fre w2k +cd /d %PROJECT_DIR% build.exe -czgw -del buildfre_wlh_amd64.log +del buildfre_w2k_x86.log echo. :COPY_OUTPUT @@ -42,12 +42,11 @@ 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\%LIBRARY_NAME%.lib ..\aaa\lib64\%LIBRARY_NAME%.lib >nul -copy /Y .\objfre_w2k_x86\i386\%LIBRARY_NAME%.lib ..\aaa\lib32\%LIBRARY_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 if exist sources-wdk-* del sources-wdk-* if exist build.bat del build.bat set PATH=%SAVE_PATH% -set SAVE_PATH= diff --git a/src/FileStream.cpp b/src/FileStream.cpp index 39db0a0..95f48a7 100644 --- a/src/FileStream.cpp +++ b/src/FileStream.cpp @@ -33,25 +33,6 @@ //-----------------------------------------------------------------------------
// Local functions - platform-specific functions
-#ifndef STORMLIB_WINDOWS
-
-#ifndef STORMLIB_WIIU
-static thread_local DWORD dwLastError = ERROR_SUCCESS;
-#else
-static DWORD dwLastError = ERROR_SUCCESS;
-#endif
-
-DWORD GetLastError()
-{
- return dwLastError;
-}
-
-void SetLastError(DWORD dwErrCode)
-{
- dwLastError = dwErrCode;
-}
-#endif
-
static DWORD StringToInt(const char * szString)
{
DWORD dwValue = 0;
@@ -118,7 +99,7 @@ static bool BaseFile_Create(TFileStream * pStream) if(handle == -1)
{
pStream->Base.File.hFile = INVALID_HANDLE_VALUE;
- dwLastError = errno;
+ SErrSetLastError(errno);
return false;
}
@@ -171,7 +152,7 @@ static bool BaseFile_Open(TFileStream * pStream, const TCHAR * szFileName, DWORD if(handle == -1)
{
pStream->Base.File.hFile = INVALID_HANDLE_VALUE;
- dwLastError = errno;
+ SErrSetLastError(errno);
return false;
}
@@ -179,7 +160,7 @@ static bool BaseFile_Open(TFileStream * pStream, const TCHAR * szFileName, DWORD if(fstat64(handle, &fileinfo) == -1)
{
pStream->Base.File.hFile = INVALID_HANDLE_VALUE;
- dwLastError = errno;
+ SErrSetLastError(errno);
close(handle);
return false;
}
@@ -249,7 +230,7 @@ static bool BaseFile_Read( bytes_read = read((intptr_t)pStream->Base.File.hFile, pvBuffer, (size_t)dwBytesToRead);
if(bytes_read == -1)
{
- dwLastError = errno;
+ SErrSetLastError(errno);
return false;
}
@@ -262,7 +243,7 @@ static bool BaseFile_Read( // If the number of bytes read doesn't match to required amount, return false
pStream->Base.File.FilePos = ByteOffset + dwBytesRead;
if(dwBytesRead != dwBytesToRead)
- SetLastError(ERROR_HANDLE_EOF);
+ SErrSetLastError(ERROR_HANDLE_EOF);
return (dwBytesRead == dwBytesToRead);
}
@@ -318,7 +299,7 @@ static bool BaseFile_Write(TFileStream * pStream, ULONGLONG * pByteOffset, const bytes_written = write((intptr_t)pStream->Base.File.hFile, pvBuffer, (size_t)dwBytesToWrite);
if(bytes_written == -1)
{
- dwLastError = errno;
+ SErrSetLastError(errno);
return false;
}
@@ -334,7 +315,7 @@ static bool BaseFile_Write(TFileStream * pStream, ULONGLONG * pByteOffset, const pStream->Base.File.FileSize = pStream->Base.File.FilePos;
if(dwBytesWritten != dwBytesToWrite)
- SetLastError(ERROR_DISK_FULL);
+ SErrSetLastError(ERROR_DISK_FULL);
return (dwBytesWritten == dwBytesToWrite);
}
@@ -353,7 +334,7 @@ static bool BaseFile_Resize(TFileStream * pStream, ULONGLONG NewFileSize) // Set the position at the new file size
dwNewPos = SetFilePointer(pStream->Base.File.hFile, (LONG)NewFileSize, &FileSizeHi, FILE_BEGIN);
- if(dwNewPos == INVALID_SET_FILE_POINTER && GetLastError() != ERROR_SUCCESS)
+ if(dwNewPos == INVALID_SET_FILE_POINTER && SErrGetLastError() != ERROR_SUCCESS)
return false;
// Set the current file pointer as the end of the file
@@ -373,7 +354,7 @@ static bool BaseFile_Resize(TFileStream * pStream, ULONGLONG NewFileSize) {
if(ftruncate64((intptr_t)pStream->Base.File.hFile, (off64_t)NewFileSize) == -1)
{
- dwLastError = errno;
+ SErrSetLastError(errno);
return false;
}
@@ -417,7 +398,7 @@ static bool BaseFile_Replace(TFileStream * pStream, TFileStream * pNewStream) // "rename" on Linux also works if the target file exists
if(rename(pNewStream->szFileName, pStream->szFileName) == -1)
{
- dwLastError = errno;
+ SErrSetLastError(errno);
return false;
}
@@ -599,7 +580,7 @@ static bool BaseMap_Open(TFileStream * pStream, LPCTSTR szFileName, DWORD dwStre // Did the mapping fail?
if(bResult == false)
- dwLastError = errno;
+ SErrSetLastError(errno);
return bResult;
#else
@@ -748,7 +729,7 @@ static bool BaseHttp_Open(TFileStream * pStream, const TCHAR * szFileName, DWORD if(_tcscmp(StatusCode, _T("200")))
{
InternetCloseHandle(hRequest);
- SetLastError(ERROR_FILE_NOT_FOUND);
+ SErrSetLastError(ERROR_FILE_NOT_FOUND);
return false;
}
}
@@ -793,7 +774,7 @@ static bool BaseHttp_Open(TFileStream * pStream, const TCHAR * szFileName, DWORD #else
// Not supported
- SetLastError(ERROR_NOT_SUPPORTED);
+ SErrSetLastError(ERROR_NOT_SUPPORTED);
pStream = pStream;
return false;
@@ -861,7 +842,7 @@ static bool BaseHttp_Read( // If the number of bytes read doesn't match the required amount, return false
if(dwTotalBytesRead != dwBytesToRead)
- SetLastError(ERROR_HANDLE_EOF);
+ SErrSetLastError(ERROR_HANDLE_EOF);
return (dwTotalBytesRead == dwBytesToRead);
#else
@@ -871,7 +852,7 @@ static bool BaseHttp_Read( pByteOffset = pByteOffset;
pvBuffer = pvBuffer;
dwBytesToRead = dwBytesToRead;
- SetLastError(ERROR_NOT_SUPPORTED);
+ SErrSetLastError(ERROR_NOT_SUPPORTED);
return false;
#endif
@@ -945,7 +926,7 @@ static bool BlockStream_Read( EndOffset = ByteOffset + dwBytesToRead;
if(EndOffset > pStream->StreamSize)
{
- SetLastError(ERROR_HANDLE_EOF);
+ SErrSetLastError(ERROR_HANDLE_EOF);
return false;
}
@@ -962,7 +943,7 @@ static bool BlockStream_Read( TransferBuffer = BlockBuffer = STORM_ALLOC(BYTE, (BlockCount * BlockSize));
if(TransferBuffer == NULL)
{
- SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ SErrSetLastError(ERROR_NOT_ENOUGH_MEMORY);
return false;
}
@@ -1040,7 +1021,7 @@ static bool BlockStream_Read( else
{
// If the block read failed, set the last error
- SetLastError(ERROR_FILE_INCOMPLETE);
+ SErrSetLastError(ERROR_FILE_INCOMPLETE);
}
// Call the callback to indicate we are done
@@ -1117,7 +1098,7 @@ static TFileStream * AllocateFileStream( // Don't allow another master file in the string
if(_tcschr(szNextFile + 1, _T('*')) != NULL)
{
- SetLastError(ERROR_INVALID_PARAMETER);
+ SErrSetLastError(ERROR_INVALID_PARAMETER);
return NULL;
}
@@ -1456,7 +1437,7 @@ static TFileStream * FlatStream_Open(const TCHAR * szFileName, DWORD dwStreamFla if(!FlatStream_CreateMirror(pStream))
{
FileStream_Close(pStream);
- SetLastError(ERROR_FILE_NOT_FOUND);
+ SErrSetLastError(ERROR_FILE_NOT_FOUND);
return NULL;
}
}
@@ -1875,7 +1856,7 @@ static TFileStream * PartStream_Open(const TCHAR * szFileName, DWORD dwStreamFla if(!PartStream_CreateMirror(pStream))
{
FileStream_Close(pStream);
- SetLastError(ERROR_FILE_NOT_FOUND);
+ SErrSetLastError(ERROR_FILE_NOT_FOUND);
return NULL;
}
}
@@ -1892,7 +1873,7 @@ static TFileStream * PartStream_Open(const TCHAR * szFileName, DWORD dwStreamFla if(!PartStream_LoadBitmap(pStream))
{
FileStream_Close(pStream);
- SetLastError(ERROR_BAD_FORMAT);
+ SErrSetLastError(ERROR_BAD_FORMAT);
return NULL;
}
}
@@ -2212,7 +2193,7 @@ static TFileStream * MpqeStream_Open(const TCHAR * szFileName, DWORD dwStreamFla // Cleanup the stream and return
FileStream_Close(pStream);
- SetLastError(ERROR_UNKNOWN_FILE_KEY);
+ SErrSetLastError(ERROR_UNKNOWN_FILE_KEY);
return NULL;
}
@@ -2358,7 +2339,7 @@ static TFileStream * Block4Stream_Open(const TCHAR * szFileName, DWORD dwStreamF NewBaseArray = STORM_ALLOC(TBaseProviderData, dwBaseFiles + 1);
if(NewBaseArray == NULL)
{
- SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ SErrSetLastError(ERROR_NOT_ENOUGH_MEMORY);
return NULL;
}
@@ -2413,7 +2394,7 @@ static TFileStream * Block4Stream_Open(const TCHAR * szFileName, DWORD dwStreamF if(dwBaseFiles == 0)
{
FileStream_Close(pStream);
- SetLastError(ERROR_FILE_NOT_FOUND);
+ SErrSetLastError(ERROR_FILE_NOT_FOUND);
pStream = NULL;
}
@@ -2449,7 +2430,7 @@ TFileStream * FileStream_CreateFile( // We only support creation of flat, local file
if((dwStreamFlags & (STREAM_PROVIDERS_MASK)) != (STREAM_PROVIDER_FLAT | BASE_PROVIDER_FILE))
{
- SetLastError(ERROR_NOT_SUPPORTED);
+ SErrSetLastError(ERROR_NOT_SUPPORTED);
return NULL;
}
@@ -2523,7 +2504,7 @@ TFileStream * FileStream_OpenFile( return Block4Stream_Open(szFileName, dwStreamFlags);
default:
- SetLastError(ERROR_INVALID_PARAMETER);
+ SErrSetLastError(ERROR_INVALID_PARAMETER);
return NULL;
}
}
@@ -2635,7 +2616,7 @@ bool FileStream_SetCallback(TFileStream * pStream, SFILE_DOWNLOAD_CALLBACK pfnCa if(pStream->BlockRead == NULL)
{
- SetLastError(ERROR_NOT_SUPPORTED);
+ SErrSetLastError(ERROR_NOT_SUPPORTED);
return false;
}
@@ -2733,7 +2714,7 @@ bool FileStream_GetBitmap(TFileStream * pStream, void * pvBitmap, DWORD cbBitmap // Set last error value and return
if(bResult == false)
- SetLastError(ERROR_INSUFFICIENT_BUFFER);
+ SErrSetLastError(ERROR_INSUFFICIENT_BUFFER);
return bResult;
}
@@ -2753,8 +2734,8 @@ bool FileStream_GetBitmap(TFileStream * pStream, void * pvBitmap, DWORD cbBitmap *
* \returns
* - If the function reads the required amount of bytes, it returns true.
- * - If the function reads less than required bytes, it returns false and GetLastError() returns ERROR_HANDLE_EOF
- * - If the function fails, it reads false and GetLastError() returns an error code different from ERROR_HANDLE_EOF
+ * - If the function reads less than required bytes, it returns false and SErrGetLastError() returns ERROR_HANDLE_EOF
+ * - If the function fails, it reads false and SErrGetLastError() returns an error code different from ERROR_HANDLE_EOF
*/
bool FileStream_Read(TFileStream * pStream, ULONGLONG * pByteOffset, void * pvBuffer, DWORD dwBytesToRead)
{
@@ -2778,7 +2759,7 @@ bool FileStream_Write(TFileStream * pStream, ULONGLONG * pByteOffset, const void {
if(pStream->dwFlags & STREAM_FLAG_READ_ONLY)
{
- SetLastError(ERROR_ACCESS_DENIED);
+ SErrSetLastError(ERROR_ACCESS_DENIED);
return false;
}
@@ -2808,7 +2789,7 @@ bool FileStream_SetSize(TFileStream * pStream, ULONGLONG NewFileSize) {
if(pStream->dwFlags & STREAM_FLAG_READ_ONLY)
{
- SetLastError(ERROR_ACCESS_DENIED);
+ SErrSetLastError(ERROR_ACCESS_DENIED);
return false;
}
@@ -2868,14 +2849,14 @@ bool FileStream_Replace(TFileStream * pStream, TFileStream * pNewStream) // Only supported on flat files
if((pStream->dwFlags & STREAM_PROVIDERS_MASK) != (STREAM_PROVIDER_FLAT | BASE_PROVIDER_FILE))
{
- SetLastError(ERROR_NOT_SUPPORTED);
+ SErrSetLastError(ERROR_NOT_SUPPORTED);
return false;
}
// Not supported on read-only streams
if(pStream->dwFlags & STREAM_FLAG_READ_ONLY)
{
- SetLastError(ERROR_ACCESS_DENIED);
+ SErrSetLastError(ERROR_ACCESS_DENIED);
return false;
}
diff --git a/src/SBaseCommon.cpp b/src/SBaseCommon.cpp index ecbfc05..4d56502 100644 --- a/src/SBaseCommon.cpp +++ b/src/SBaseCommon.cpp @@ -736,7 +736,7 @@ TMPQFile * IsValidFileHandle(HANDLE hFile) // Hash table and block table manipulation
// Attempts to search a free hash entry, or an entry whose names and locale matches
-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 * pDeletedEntry = NULL; // If a deleted entry was found in the continuous hash range
TMPQHash * pFreeEntry = NULL; // If a free entry was found in the continuous hash range
@@ -757,7 +757,7 @@ TMPQHash * FindFreeHashEntry(TMPQArchive * ha, DWORD dwStartIndex, DWORD dwName1 TMPQHash * pHash = ha->pHashTable + dwIndex;
// If we found a matching entry, return that one
- if(pHash->dwName1 == dwName1 && pHash->dwName2 == dwName2 && pHash->Locale == Locale)
+ if(pHash->dwHashCheck1 == dwHashCheck1 && pHash->dwHashCheck2 == dwHashCheck2 && pHash->Locale == Locale)
return pHash;
// If we found a deleted entry, remember it but keep searching
@@ -788,8 +788,8 @@ TMPQHash * GetFirstHashEntry(TMPQArchive * ha, const char * szFileName) {
DWORD dwHashIndexMask = HASH_INDEX_MASK(ha);
DWORD dwStartIndex = ha->pfnHashString(szFileName, MPQ_HASH_TABLE_INDEX);
- DWORD dwName1 = ha->pfnHashString(szFileName, MPQ_HASH_NAME_A);
- DWORD dwName2 = ha->pfnHashString(szFileName, MPQ_HASH_NAME_B);
+ DWORD dwHashCheck1 = ha->pfnHashString(szFileName, MPQ_HASH_NAME_A);
+ DWORD dwHashCheck2 = ha->pfnHashString(szFileName, MPQ_HASH_NAME_B);
DWORD dwIndex;
// Set the initial index
@@ -801,7 +801,7 @@ TMPQHash * GetFirstHashEntry(TMPQArchive * ha, const char * szFileName) TMPQHash * pHash = ha->pHashTable + dwIndex;
// If the entry matches, we found it.
- if(pHash->dwName1 == dwName1 && pHash->dwName2 == dwName2 && MPQ_BLOCK_INDEX(pHash) < ha->dwFileTableSize)
+ if(pHash->dwHashCheck1 == dwHashCheck1 && pHash->dwHashCheck2 == dwHashCheck2 && MPQ_BLOCK_INDEX(pHash) < ha->dwFileTableSize)
return pHash;
// If that hash entry is a free entry, it means we haven't found the file
@@ -820,8 +820,8 @@ TMPQHash * GetNextHashEntry(TMPQArchive * ha, TMPQHash * pFirstHash, TMPQHash * {
DWORD dwHashIndexMask = HASH_INDEX_MASK(ha);
DWORD dwStartIndex = (DWORD)(pFirstHash - ha->pHashTable);
- DWORD dwName1 = pHash->dwName1;
- DWORD dwName2 = pHash->dwName2;
+ DWORD dwHashCheck1 = pHash->dwHashCheck1;
+ DWORD dwHashCheck2 = pHash->dwHashCheck2;
DWORD dwIndex = (DWORD)(pHash - ha->pHashTable);
// Now go for any next entry that follows the pHash,
@@ -836,7 +836,7 @@ TMPQHash * GetNextHashEntry(TMPQArchive * ha, TMPQHash * pFirstHash, TMPQHash * pHash = ha->pHashTable + dwIndex;
// If the entry matches, we found it.
- if(pHash->dwName1 == dwName1 && pHash->dwName2 == dwName2 && MPQ_BLOCK_INDEX(pHash) < ha->dwFileTableSize)
+ if(pHash->dwHashCheck1 == dwHashCheck1 && pHash->dwHashCheck2 == dwHashCheck2 && MPQ_BLOCK_INDEX(pHash) < ha->dwFileTableSize)
return pHash;
// If that hash entry is a free entry, it means we haven't found the file
@@ -853,19 +853,19 @@ TMPQHash * AllocateHashEntry( {
TMPQHash * pHash;
DWORD dwStartIndex = ha->pfnHashString(pFileEntry->szFileName, MPQ_HASH_TABLE_INDEX);
- DWORD dwName1 = ha->pfnHashString(pFileEntry->szFileName, MPQ_HASH_NAME_A);
- DWORD dwName2 = ha->pfnHashString(pFileEntry->szFileName, MPQ_HASH_NAME_B);
+ DWORD dwHashCheck1 = ha->pfnHashString(pFileEntry->szFileName, MPQ_HASH_NAME_A);
+ DWORD dwHashCheck2 = ha->pfnHashString(pFileEntry->szFileName, MPQ_HASH_NAME_B);
// Attempt to find a free hash entry
- pHash = FindFreeHashEntry(ha, dwStartIndex, dwName1, dwName2, lcFileLocale);
+ pHash = FindFreeHashEntry(ha, dwStartIndex, dwHashCheck1, dwHashCheck2, lcFileLocale);
if(pHash != NULL)
{
// Fill the free hash entry
- pHash->dwName1 = dwName1;
- pHash->dwName2 = dwName2;
+ pHash->dwHashCheck1 = dwHashCheck1;
+ pHash->dwHashCheck2 = dwHashCheck2;
pHash->Locale = SFILE_LOCALE(lcFileLocale);
pHash->Platform = SFILE_PLATFORM(lcFileLocale);
- pHash->Reserved = 0;
+ pHash->Flags = 0;
pHash->dwBlockIndex = (DWORD)(pFileEntry - ha->pFileTable);
}
@@ -965,7 +965,7 @@ TMPQFile * CreateWritableHandle(TMPQArchive * ha, DWORD dwFileSize) (ha->dwFileTableSize * sizeof(TMPQBlock));
if((TempPos >> 32) != 0)
{
- SetLastError(ERROR_DISK_FULL);
+ SErrSetLastError(ERROR_DISK_FULL);
return NULL;
}
}
@@ -974,7 +974,7 @@ TMPQFile * CreateWritableHandle(TMPQArchive * ha, DWORD dwFileSize) hf = CreateFileHandle(ha, NULL);
if(hf == NULL)
{
- SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ SErrSetLastError(ERROR_NOT_ENOUGH_MEMORY);
return NULL;
}
@@ -1019,6 +1019,11 @@ void * LoadMpqTable( return NULL;
}
}
+ else
+ {
+ // pocs/MPQ_2025_06_BadHashTableSize.mpq
+ dwCompressedSize = dwTableSize;
+ }
// Get the file offset from which we will read the table
// Note: According to Storm.dll from Warcraft III (version 2002),
@@ -1026,12 +1031,19 @@ void * LoadMpqTable( // and the table is loaded from the current file offset
if(ByteOffset == SFILE_INVALID_POS)
FileStream_GetPos(ha->pStream, &ByteOffset);
+ FileStream_GetSize(ha->pStream, &FileSize);
+
+ // Is the sector table within the file?
+ if(ByteOffset >= FileSize)
+ {
+ STORM_FREE(pbMpqTable);
+ return NULL;
+ }
// The hash table and block table can go beyond EOF.
// Storm.dll reads as much as possible, then fills the missing part with zeros.
// Abused by Spazzler map protector which sets hash table size to 0x00100000
// Abused by NP_Protect in MPQs v4 as well
- FileStream_GetSize(ha->pStream, &FileSize);
if((ByteOffset + dwBytesToRead) > FileSize)
{
// Fill the extra data with zeros
@@ -1056,7 +1068,7 @@ void * LoadMpqTable( }
else
{
- dwErrCode = GetLastError();
+ dwErrCode = SErrGetLastError();
}
if(dwErrCode == ERROR_SUCCESS)
@@ -1076,7 +1088,7 @@ void * LoadMpqTable( int cbInBuffer = (int)dwCompressedSize;
if(!SCompDecompress2(pbMpqTable, &cbOutBuffer, pbCompressed, cbInBuffer))
- dwErrCode = GetLastError();
+ dwErrCode = SErrGetLastError();
}
// Make sure that the table is properly byte-swapped
@@ -1172,7 +1184,7 @@ __AllocateAndLoadPatchInfo: if(!FileStream_Read(ha->pStream, &hf->RawFilePos, pPatchInfo, dwLength))
{
STORM_FREE(pPatchInfo);
- return GetLastError();
+ return SErrGetLastError();
}
// Perform necessary swapping
@@ -1282,7 +1294,7 @@ DWORD AllocateSectorOffsets(TMPQFile * hf, bool bLoadFromFile) // Free the sector offsets
STORM_FREE(hf->SectorOffsets);
hf->SectorOffsets = NULL;
- return GetLastError();
+ return SErrGetLastError();
}
// Swap the sector positions
@@ -1358,14 +1370,17 @@ DWORD AllocateSectorOffsets(TMPQFile * hf, bool bLoadFromFile) if((hf->SectorOffsets[0] & 0xFFFFFFFC) > dwSectorOffsLen)
{
// MPQ protectors put some ridiculous values there. We must limit the extra bytes
- if(hf->SectorOffsets[0] > (dwSectorOffsLen + 0x400)) {
+ if(hf->SectorOffsets[0] > (dwSectorOffsLen + 0x400))
+ {
STORM_FREE(hf->SectorOffsets);
hf->SectorOffsets = NULL;
return ERROR_FILE_CORRUPT;
}
+ // The new length of the sector offset must be aligned to DWORD
+ dwSectorOffsLen = (hf->SectorOffsets[0] & 0xFFFFFFFC);
+
// Free the old sector offset table
- dwSectorOffsLen = hf->SectorOffsets[0];
STORM_FREE(hf->SectorOffsets);
goto __LoadSectorOffsets;
}
@@ -1469,7 +1484,7 @@ DWORD WritePatchInfo(TMPQFile * hf) BSWAP_ARRAY32_UNSIGNED(pPatchInfo, 3 * sizeof(DWORD));
if(!FileStream_Write(ha->pStream, &hf->RawFilePos, pPatchInfo, sizeof(TPatchInfo)))
- return GetLastError();
+ return SErrGetLastError();
return ERROR_SUCCESS;
}
@@ -1498,7 +1513,7 @@ DWORD WriteSectorOffsets(TMPQFile * hf) // Write sector offsets to the archive
if(!FileStream_Write(ha->pStream, &RawFilePos, hf->SectorOffsets, dwSectorOffsLen))
- return GetLastError();
+ return SErrGetLastError();
// Not necessary, as the sector checksums
// are going to be freed when this is done.
@@ -1551,7 +1566,7 @@ DWORD WriteSectorChecksums(TMPQFile * hf) if(hf->pPatchInfo != NULL)
RawFilePos += hf->pPatchInfo->dwLength;
if(!FileStream_Write(ha->pStream, &RawFilePos, pbCompressed, dwCompressedSize))
- dwErrCode = GetLastError();
+ dwErrCode = SErrGetLastError();
// Not necessary, as the sector checksums
// are going to be freed when this is done.
@@ -1602,7 +1617,7 @@ DWORD WriteMemDataMD5( // Write the array od MD5's to the file
RawDataOffs += dwRawDataSize;
if(!FileStream_Write(pStream, &RawDataOffs, md5_array, dwMd5ArraySize))
- dwErrCode = GetLastError();
+ dwErrCode = SErrGetLastError();
// Give the caller the size of the MD5 array
if(pcbTotalSize != NULL)
@@ -1650,7 +1665,7 @@ DWORD WriteMpqDataMD5( // Read the chunk
if(!FileStream_Read(pStream, &RawDataOffs, pbFileChunk, dwToRead))
{
- dwErrCode = GetLastError();
+ dwErrCode = SErrGetLastError();
break;
}
@@ -1667,7 +1682,7 @@ DWORD WriteMpqDataMD5( if(dwErrCode == ERROR_SUCCESS)
{
if(!FileStream_Write(pStream, NULL, md5_array, dwMd5ArraySize))
- dwErrCode = GetLastError();
+ dwErrCode = SErrGetLastError();
}
// Free buffers and exit
diff --git a/src/SBaseDumpData.cpp b/src/SBaseDumpData.cpp index 16313dd..f52b927 100644 --- a/src/SBaseDumpData.cpp +++ b/src/SBaseDumpData.cpp @@ -52,8 +52,8 @@ void DumpHashTable(TMPQHash * pHashTable, DWORD dwHashTableSize) for(i = 0; i < dwHashTableSize; i++) { printf("[%08x] %08X %08X %04X %02X %08X\n", i, - pHashTable[i].dwName1, - pHashTable[i].dwName2, + pHashTable[i].dwHashCheck1, + pHashTable[i].dwHashCheck2, pHashTable[i].Locale, pHashTable[i].Platform, pHashTable[i].dwBlockIndex); diff --git a/src/SBaseFileTable.cpp b/src/SBaseFileTable.cpp index 843f81e..46daab5 100644 --- a/src/SBaseFileTable.cpp +++ b/src/SBaseFileTable.cpp @@ -586,6 +586,9 @@ DWORD ConvertMpqHeaderToFormat4( pHeader->BlockTableSize64 = (pHeader->dwBlockTableSize * sizeof(TMPQBlock));
BlockTablePos64 = MAKE_OFFSET64(pHeader->wBlockTablePosHi, pHeader->dwBlockTablePos);
+ // Supply the 64-bit archive size for signature verification
+ pHeader->ArchiveSize64 = pHeader->dwArchiveSize;
+
// We require the block table to follow hash table
if(BlockTablePos64 >= HashTablePos64)
{
@@ -600,7 +603,6 @@ DWORD ConvertMpqHeaderToFormat4( }
else
{
- pHeader->ArchiveSize64 = pHeader->dwArchiveSize;
ha->dwFlags |= MPQ_FLAG_MALFORMED;
}
@@ -651,7 +653,7 @@ DWORD ConvertMpqHeaderToFormat4( // Size of the block table
if(BlockTablePos64)
{
- if(BlockTablePos64 > FileSize)
+ if(BlockTablePos64 > FileSize || BlockTablePos64 >= MaxOffset)
return ERROR_FILE_CORRUPT;
pHeader->BlockTableSize64 = MaxOffset - BlockTablePos64;
MaxOffset = BlockTablePos64;
@@ -660,7 +662,7 @@ DWORD ConvertMpqHeaderToFormat4( // Size of the hash table
if(HashTablePos64)
{
- if(HashTablePos64 > FileSize)
+ if(HashTablePos64 > FileSize || HashTablePos64 >= MaxOffset)
return ERROR_FILE_CORRUPT;
pHeader->HashTableSize64 = MaxOffset - HashTablePos64;
MaxOffset = HashTablePos64;
@@ -1029,7 +1031,7 @@ static DWORD BuildFileTableFromBlockTable( pHash->dwBlockIndex = dwNewIndex;
// Dump the relocation entry
-// printf("Relocating hash entry %08X-%08X: %08X -> %08X\n", pHash->dwName1, pHash->dwName2, dwBlockIndex, dwNewIndex);
+// printf("Relocating hash entry %08X-%08X: %08X -> %08X\n", pHash->dwHashCheck1, pHash->dwHashCheck2, dwBlockIndex, dwNewIndex);
}
// Get the pointer to the file entry and the block entry
@@ -1291,7 +1293,7 @@ static DWORD SaveMpqTable( BSWAP_ARRAY32_UNSIGNED(pMpqTable, Size);
FileOffset = ha->MpqPos + ByteOffset;
if(!FileStream_Write(ha->pStream, &FileOffset, pMpqTable, (DWORD)Size))
- dwErrCode = GetLastError();
+ dwErrCode = SErrGetLastError();
// Free the compressed table, if any
if(pCompressed != NULL)
@@ -1362,7 +1364,7 @@ static DWORD SaveExtTable( if(FileStream_Write(ha->pStream, &FileOffset, pExtTable, dwTableSize))
cbTotalSize += dwTableSize;
else
- dwErrCode = GetLastError();
+ dwErrCode = SErrGetLastError();
// We have to write raw data MD5
if(dwErrCode == ERROR_SUCCESS && ha->pHeader->dwRawChunkSize != 0)
@@ -2222,11 +2224,11 @@ DWORD RenameFileEntry( lcFileLocale = SFILE_MAKE_LCID(pHashEntry->Locale, pHashEntry->Platform);
// Mark the hash table entry as deleted
- pHashEntry->dwName1 = 0xFFFFFFFF;
- pHashEntry->dwName2 = 0xFFFFFFFF;
+ pHashEntry->dwHashCheck1 = 0xFFFFFFFF;
+ pHashEntry->dwHashCheck2 = 0xFFFFFFFF;
pHashEntry->Locale = 0xFFFF;
pHashEntry->Platform = 0xFF;
- pHashEntry->Reserved = 0xFF;
+ pHashEntry->Flags = 0xFF;
pHashEntry->dwBlockIndex = HASH_ENTRY_DELETED;
}
@@ -2263,11 +2265,11 @@ DWORD DeleteFileEntry(TMPQArchive * ha, TMPQFile * hf) return ERROR_NOT_SUPPORTED;
// Mark the hash table entry as deleted
- pHashEntry->dwName1 = 0xFFFFFFFF;
- pHashEntry->dwName2 = 0xFFFFFFFF;
+ pHashEntry->dwHashCheck1 = 0xFFFFFFFF;
+ pHashEntry->dwHashCheck2 = 0xFFFFFFFF;
pHashEntry->Locale = 0xFFFF;
pHashEntry->Platform = 0xFF;
- pHashEntry->Reserved = 0xFF;
+ pHashEntry->Flags = 0xFF;
pHashEntry->dwBlockIndex = HASH_ENTRY_DELETED;
}
@@ -2506,7 +2508,8 @@ TMPQHetTable * LoadHetTable(TMPQArchive * ha) TMPQHeader * pHeader = ha->pHeader;
// If the HET table position is not 0, we expect the table to be present
- if(pHeader->HetTablePos64 && pHeader->HetTableSize64)
+ // Alsom the HET table must have a reasonable size
+ if(pHeader->HetTablePos64 && pHeader->HetTableSize64 && pHeader->HetTableSize64 < BET_TABLE_MAX_SIZE)
{
// Attempt to load the HET table (Hash Extended Table)
pExtTable = LoadExtTable(ha, pHeader->HetTablePos64, (size_t)pHeader->HetTableSize64, HET_TABLE_SIGNATURE, MPQ_KEY_HASH_TABLE);
@@ -2528,7 +2531,7 @@ TMPQBetTable * LoadBetTable(TMPQArchive * ha) TMPQHeader * pHeader = ha->pHeader;
// If the BET table position is not 0, we expect the table to be present
- if(pHeader->BetTablePos64 && pHeader->BetTableSize64)
+ if(pHeader->BetTablePos64 && pHeader->BetTableSize64 && pHeader->BetTableSize64 < BET_TABLE_MAX_SIZE)
{
// Attempt to load the HET table (Hash Extended Table)
pExtTable = LoadExtTable(ha, pHeader->BetTablePos64, (size_t)pHeader->BetTableSize64, BET_TABLE_SIGNATURE, MPQ_KEY_BLOCK_TABLE);
@@ -2560,12 +2563,7 @@ DWORD LoadAnyHashTable(TMPQArchive * ha) // Note that we load the classic hash table even when HET table exists,
// because if the MPQ gets modified and saved, hash table must be there
if(pHeader->dwHashTableSize)
- {
- // hash-table size must be a power or 2
- if ((pHeader->dwHashTableSize & (pHeader->dwHashTableSize - 1)) != 0)
- return ERROR_FILE_CORRUPT;
ha->pHashTable = LoadHashTable(ha);
- }
// At least one of the tables must be present
if(ha->pHetTable == NULL && ha->pHashTable == NULL)
@@ -2621,7 +2619,7 @@ static DWORD BuildFileTable_Classic(TMPQArchive * ha) // Load the hi-block table. It is not encrypted, nor compressed
ByteOffset = ha->MpqPos + pHeader->HiBlockTablePos64;
if(!FileStream_Read(ha->pStream, &ByteOffset, pHiBlockTable, dwTableSize))
- dwErrCode = GetLastError();
+ dwErrCode = SErrGetLastError();
// Now merge the hi-block table to the file table
if(dwErrCode == ERROR_SUCCESS)
@@ -3144,7 +3142,7 @@ DWORD SaveMPQTables(TMPQArchive * ha) BSWAP_ARRAY16_UNSIGNED(pHiBlockTable, HiBlockTableSize64);
if(!FileStream_Write(ha->pStream, &ByteOffset, pHiBlockTable, (DWORD)HiBlockTableSize64))
- dwErrCode = GetLastError();
+ dwErrCode = SErrGetLastError();
TablePos += HiBlockTableSize64;
}
@@ -3154,7 +3152,7 @@ DWORD SaveMPQTables(TMPQArchive * ha) ULONGLONG FileSize = ha->MpqPos + TablePos;
if(!FileStream_SetSize(ha->pStream, FileSize))
- dwErrCode = GetLastError();
+ dwErrCode = SErrGetLastError();
}
// Write the MPQ header
@@ -3177,7 +3175,7 @@ DWORD SaveMPQTables(TMPQArchive * ha) BSWAP_TMPQHEADER(&SaveMpqHeader, MPQ_FORMAT_VERSION_3);
BSWAP_TMPQHEADER(&SaveMpqHeader, MPQ_FORMAT_VERSION_4);
if(!FileStream_Write(ha->pStream, &ha->MpqPos, &SaveMpqHeader, pHeader->dwHeaderSize))
- dwErrCode = GetLastError();
+ dwErrCode = SErrGetLastError();
}
// Clear the changed flag
diff --git a/src/SBaseSubTypes.cpp b/src/SBaseSubTypes.cpp index 1ae9aae..10410dc 100644 --- a/src/SBaseSubTypes.cpp +++ b/src/SBaseSubTypes.cpp @@ -65,10 +65,10 @@ typedef struct _TSQPHash DWORD dwBlockIndex; // The hash of the file path, using method A. - DWORD dwName1; + DWORD dwHashCheck1; // The hash of the file path, using method B. - DWORD dwName2; + DWORD dwHashCheck2; } TSQPHash; @@ -213,12 +213,12 @@ TMPQHash * LoadSqpHashTable(TMPQArchive * ha) dwErrCode = ERROR_FILE_CORRUPT; // Copy the entry to the MPQ hash entry - pMpqHash->dwName1 = TempEntry.dwName1; - pMpqHash->dwName2 = TempEntry.dwName2; + pMpqHash->dwHashCheck1 = TempEntry.dwHashCheck1; + pMpqHash->dwHashCheck2 = TempEntry.dwHashCheck2; pMpqHash->dwBlockIndex = MPQ_BLOCK_INDEX(&TempEntry); pMpqHash->Locale = 0; pMpqHash->Platform = 0; - pMpqHash->Reserved = 0; + pMpqHash->Flags = 0; } } @@ -320,13 +320,13 @@ typedef struct _TMPKHeader typedef struct _TMPKHash { // The hash of the file path, using method A. - DWORD dwName1; + DWORD dwHashCheck1; // The hash of the file path, using method B. - DWORD dwName2; + DWORD dwHashCheck2; // The hash of the file path, using method C. - DWORD dwName3; + DWORD dwHashCheck3; // If the hash table entry is valid, this is the index into the block table of the file. // Otherwise, one of the following two values: @@ -590,16 +590,16 @@ TMPQHash * LoadMpkHashTable(TMPQArchive * ha) { // Finds the free hash entry in the hash table // We don't expect any errors here, because we are putting files to empty hash table - pHash = FindFreeHashEntry(pHashTable, pHeader->dwHashTableSize, pMpkHash[i].dwName1); + pHash = FindFreeHashEntry(pHashTable, pHeader->dwHashTableSize, pMpkHash[i].dwHashCheck1); assert(pHash->dwBlockIndex == HASH_ENTRY_FREE); // Copy the MPK hash entry to the hash table pHash->dwBlockIndex = pMpkHash[i].dwBlockIndex; pHash->Locale = 0; pHash->Platform = 0; - pHash->Reserved = 0; - pHash->dwName1 = pMpkHash[i].dwName2; - pHash->dwName2 = pMpkHash[i].dwName3; + pHash->Flags = 0; + pHash->dwHashCheck1 = pMpkHash[i].dwHashCheck2; + pHash->dwHashCheck2 = pMpkHash[i].dwHashCheck3; } } diff --git a/src/SCompression.cpp b/src/SCompression.cpp index 316a7fb..d585e82 100644 --- a/src/SCompression.cpp +++ b/src/SCompression.cpp @@ -678,7 +678,7 @@ int WINAPI SCompImplode(void * pvOutBuffer, int * pcbOutBuffer, void * pvInBuffe // Check for valid parameters if(!pcbOutBuffer || *pcbOutBuffer < cbInBuffer || !pvOutBuffer || !pvInBuffer) { - SetLastError(ERROR_INVALID_PARAMETER); + SErrSetLastError(ERROR_INVALID_PARAMETER); return 0; } @@ -710,7 +710,7 @@ int WINAPI SCompExplode(void * pvOutBuffer, int * pcbOutBuffer, void * pvInBuffe // Check for valid parameters if(!pcbOutBuffer || *pcbOutBuffer < cbInBuffer || !pvOutBuffer || !pvInBuffer) { - SetLastError(ERROR_INVALID_PARAMETER); + SErrSetLastError(ERROR_INVALID_PARAMETER); return 0; } @@ -729,7 +729,7 @@ int WINAPI SCompExplode(void * pvOutBuffer, int * pcbOutBuffer, void * pvInBuffe // Perform decompression if(!Decompress_PKLIB(pvOutBuffer, &cbOutBuffer, pvInBuffer, cbInBuffer)) { - SetLastError(ERROR_FILE_CORRUPT); + SErrSetLastError(ERROR_FILE_CORRUPT); return 0; } @@ -781,7 +781,7 @@ int WINAPI SCompCompress(void * pvOutBuffer, int * pcbOutBuffer, void * pvInBuff // Check for valid parameters if(!pcbOutBuffer || *pcbOutBuffer < cbInBuffer || !pvOutBuffer || !pvInBuffer) { - SetLastError(ERROR_INVALID_PARAMETER); + SErrSetLastError(ERROR_INVALID_PARAMETER); return 0; } @@ -817,7 +817,7 @@ int WINAPI SCompCompress(void * pvOutBuffer, int * pcbOutBuffer, void * pvInBuff // If at least one of the compressions remaing unknown, return an error if(uCompressionMask != 0) { - SetLastError(ERROR_NOT_SUPPORTED); + SErrSetLastError(ERROR_NOT_SUPPORTED); return 0; } } @@ -831,7 +831,7 @@ int WINAPI SCompCompress(void * pvOutBuffer, int * pcbOutBuffer, void * pvInBuff pbWorkBuffer = STORM_ALLOC(unsigned char, *pcbOutBuffer); if(pbWorkBuffer == NULL) { - SetLastError(ERROR_NOT_ENOUGH_MEMORY); + SErrSetLastError(ERROR_NOT_ENOUGH_MEMORY); return 0; } } @@ -980,7 +980,7 @@ static int SCompDecompressInternal( // If at least one of the compressions remaing unknown, return an error if(nCompressCount == 0 || uCompressionMask2 != 0) { - SetLastError(ERROR_NOT_SUPPORTED); + SErrSetLastError(ERROR_NOT_SUPPORTED); return 0; } @@ -990,7 +990,7 @@ static int SCompDecompressInternal( pbWorkBuffer = STORM_ALLOC(unsigned char, cbOutBuffer); if(pbWorkBuffer == NULL) { - SetLastError(ERROR_NOT_ENOUGH_MEMORY); + SErrSetLastError(ERROR_NOT_ENOUGH_MEMORY); return 0; } } @@ -1013,7 +1013,7 @@ static int SCompDecompressInternal( nResult = table[i].Decompress(pbOutput, &cbOutBuffer, pbInput, cbInLength); if(nResult == 0 || cbOutBuffer == 0) { - SetLastError(ERROR_FILE_CORRUPT); + SErrSetLastError(ERROR_FILE_CORRUPT); nResult = 0; break; } @@ -1051,7 +1051,7 @@ int WINAPI SCompDecompress2(void * pvOutBuffer, int * pcbOutBuffer, void * pvInB // Verify buffer sizes if(*pcbOutBuffer < cbInBuffer || cbInBuffer < 1) { - SetLastError(ERROR_INVALID_PARAMETER); + SErrSetLastError(ERROR_INVALID_PARAMETER); return 0; } @@ -1117,7 +1117,7 @@ int WINAPI SCompDecompress2(void * pvOutBuffer, int * pcbOutBuffer, void * pvInB break; default: - SetLastError(ERROR_FILE_CORRUPT); + SErrSetLastError(ERROR_FILE_CORRUPT); return 0; } @@ -1127,7 +1127,7 @@ int WINAPI SCompDecompress2(void * pvOutBuffer, int * pcbOutBuffer, void * pvInB pbWorkBuffer = STORM_ALLOC(unsigned char, *pcbOutBuffer); if(pbWorkBuffer == NULL) { - SetLastError(ERROR_NOT_ENOUGH_MEMORY); + SErrSetLastError(ERROR_NOT_ENOUGH_MEMORY); return 0; } } @@ -1151,7 +1151,7 @@ int WINAPI SCompDecompress2(void * pvOutBuffer, int * pcbOutBuffer, void * pvInB STORM_FREE(pbWorkBuffer); if(nResult == 0) - SetLastError(ERROR_FILE_CORRUPT); + SErrSetLastError(ERROR_FILE_CORRUPT); return nResult; } diff --git a/src/SFileAddFile.cpp b/src/SFileAddFile.cpp index 54dcbc5..f281d94 100644 --- a/src/SFileAddFile.cpp +++ b/src/SFileAddFile.cpp @@ -257,7 +257,7 @@ static DWORD WriteDataToMpqFile( // Write the file sector
if(!FileStream_Write(ha->pStream, &ByteOffset, pbToWrite, dwBytesInSector))
{
- dwErrCode = GetLastError();
+ dwErrCode = SErrGetLastError();
break;
}
@@ -343,7 +343,7 @@ static DWORD RecryptFileData( // Write the recrypted array back
if(!FileStream_Write(ha->pStream, &hf->RawFilePos, SectorOffsetsCopy, dwSectorOffsLen))
- dwErrCode = GetLastError();
+ dwErrCode = SErrGetLastError();
STORM_FREE(SectorOffsetsCopy);
}
@@ -373,7 +373,7 @@ static DWORD RecryptFileData( // Read the file sector
if(!FileStream_Read(ha->pStream, &RawFilePos, hf->pbFileSector, dwRawDataInSector))
{
- dwErrCode = GetLastError();
+ dwErrCode = SErrGetLastError();
break;
}
@@ -388,7 +388,7 @@ static DWORD RecryptFileData( // Write the sector back
if(!FileStream_Write(ha->pStream, &RawFilePos, hf->pbFileSector, dwRawDataInSector))
{
- dwErrCode = GetLastError();
+ dwErrCode = SErrGetLastError();
break;
}
@@ -443,7 +443,7 @@ DWORD SFileAddFile_Init( // Allocate the TMPQFile entry for newly added file
hf = CreateWritableHandle(ha, dwFileSize);
if(hf == NULL)
- return false;
+ return SErrGetLastError();
// Allocate file entry in the MPQ
if(dwErrCode == ERROR_SUCCESS)
@@ -477,7 +477,7 @@ DWORD SFileAddFile_Init( hf->pHashEntry = ha->pHashTable + dwHashIndex;
hf->pHashEntry->Locale = SFILE_LOCALE(lcFileLocale);
hf->pHashEntry->Platform = SFILE_PLATFORM(lcFileLocale);
- hf->pHashEntry->Reserved = 0;
+ hf->pHashEntry->Flags = 0;
}
// Prepare the file key
@@ -630,7 +630,7 @@ DWORD SFileAddFile_Write(TMPQFile * hf, const void * pvData, DWORD dwSize, DWORD if(hf->pPatchInfo != NULL)
{
if(!FileStream_Write(ha->pStream, &RawFilePos, hf->pPatchInfo, hf->pPatchInfo->dwLength))
- dwErrCode = GetLastError();
+ dwErrCode = SErrGetLastError();
pFileEntry->dwCmpSize += hf->pPatchInfo->dwLength;
RawFilePos += hf->pPatchInfo->dwLength;
@@ -642,7 +642,7 @@ DWORD SFileAddFile_Write(TMPQFile * hf, const void * pvData, DWORD dwSize, DWORD if(hf->SectorOffsets != NULL)
{
if(!FileStream_Write(ha->pStream, &RawFilePos, hf->SectorOffsets, hf->SectorOffsets[0]))
- dwErrCode = GetLastError();
+ dwErrCode = SErrGetLastError();
pFileEntry->dwCmpSize += hf->SectorOffsets[0];
RawFilePos += hf->SectorOffsets[0];
@@ -819,7 +819,7 @@ bool WINAPI SFileCreateFile( // Deal with the errors
if(dwErrCode != ERROR_SUCCESS)
- SetLastError(dwErrCode);
+ SErrSetLastError(dwErrCode);
return (dwErrCode == ERROR_SUCCESS);
}
@@ -865,7 +865,7 @@ bool WINAPI SFileWriteFile( // Deal with errors
if(dwErrCode != ERROR_SUCCESS)
- SetLastError(dwErrCode);
+ SErrSetLastError(dwErrCode);
return (dwErrCode == ERROR_SUCCESS);
}
@@ -886,7 +886,7 @@ bool WINAPI SFileFinishFile(HANDLE hFile) // Deal with errors
if(dwErrCode != ERROR_SUCCESS)
- SetLastError(dwErrCode);
+ SErrSetLastError(dwErrCode);
return (dwErrCode == ERROR_SUCCESS);
}
@@ -918,7 +918,7 @@ bool WINAPI SFileAddFileEx( // Check parameters
if(hMpq == NULL || szFileName == NULL || *szFileName == 0 || (ha = IsValidMpqHandle(hMpq)) == NULL)
{
- SetLastError(ERROR_INVALID_PARAMETER);
+ SErrSetLastError(ERROR_INVALID_PARAMETER);
return false;
}
@@ -974,7 +974,7 @@ bool WINAPI SFileAddFileEx( // Initiate adding file to the MPQ
if(!SFileCreateFile(hMpq, szArchivedName, FileTime, (DWORD)FileSize, g_lcFileLocale, dwFlags, &hMpqFile))
- dwErrCode = GetLastError();
+ dwErrCode = SErrGetLastError();
}
// Write the file data to the MPQ
@@ -988,7 +988,7 @@ bool WINAPI SFileAddFileEx( // Read data from the local file
if(!FileStream_Read(pStream, NULL, pbFileData, dwBytesToRead))
{
- dwErrCode = GetLastError();
+ dwErrCode = SErrGetLastError();
break;
}
@@ -1014,7 +1014,7 @@ bool WINAPI SFileAddFileEx( // Add the file sectors to the MPQ
if(!SFileWriteFile(hMpqFile, pbFileData, dwBytesToRead, dwCompression))
{
- dwErrCode = GetLastError();
+ dwErrCode = SErrGetLastError();
break;
}
@@ -1027,7 +1027,7 @@ bool WINAPI SFileAddFileEx( if(hMpqFile != NULL)
{
if(!SFileFinishFile(hMpqFile))
- dwErrCode = GetLastError();
+ dwErrCode = SErrGetLastError();
}
// Cleanup and exit
@@ -1036,7 +1036,7 @@ bool WINAPI SFileAddFileEx( if(pStream != NULL)
FileStream_Close(pStream);
if(dwErrCode != ERROR_SUCCESS)
- SetLastError(dwErrCode);
+ SErrSetLastError(dwErrCode);
return (dwErrCode == ERROR_SUCCESS);
}
@@ -1136,7 +1136,7 @@ bool WINAPI SFileRemoveFile(HANDLE hMpq, const char * szFileName, DWORD dwSearch FreeFileHandle(hf);
}
else
- dwErrCode = GetLastError();
+ dwErrCode = SErrGetLastError();
}
// If the file has been deleted, we need to invalidate
@@ -1155,7 +1155,7 @@ bool WINAPI SFileRemoveFile(HANDLE hMpq, const char * szFileName, DWORD dwSearch // Resolve error and exit
if(dwErrCode != ERROR_SUCCESS)
- SetLastError(dwErrCode);
+ SErrSetLastError(dwErrCode);
return (dwErrCode == ERROR_SUCCESS);
}
@@ -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
@@ -1226,7 +1243,7 @@ bool WINAPI SFileRenameFile(HANDLE hMpq, const char * szFileName, const char * s }
else
{
- dwErrCode = GetLastError();
+ dwErrCode = SErrGetLastError();
}
}
@@ -1236,7 +1253,7 @@ bool WINAPI SFileRenameFile(HANDLE hMpq, const char * szFileName, const char * s // Resolve error and exit
if(dwErrCode != ERROR_SUCCESS)
- SetLastError(dwErrCode);
+ SErrSetLastError(dwErrCode);
return (dwErrCode == ERROR_SUCCESS);
}
@@ -1249,7 +1266,7 @@ bool WINAPI SFileSetDataCompression(DWORD DataCompression) if((DataCompression & uValidMask) != DataCompression)
{
- SetLastError(ERROR_INVALID_PARAMETER);
+ SErrSetLastError(ERROR_INVALID_PARAMETER);
return false;
}
@@ -1266,39 +1283,45 @@ 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)
{
- SetLastError(ERROR_INVALID_HANDLE);
+ 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)
{
- SetLastError(ERROR_ACCESS_DENIED);
+ SErrSetLastError(ERROR_ACCESS_DENIED);
return false;
}
// Do not allow unnamed access
if(hf->pFileEntry->szFileName == NULL)
{
- SetLastError(ERROR_CAN_NOT_COMPLETE);
+ SErrSetLastError(ERROR_CAN_NOT_COMPLETE);
return false;
}
// Do not allow to change locale of any internal file
if(IsInternalMpqFileName(hf->pFileEntry->szFileName))
{
- SetLastError(ERROR_INTERNAL_FILE);
+ SErrSetLastError(ERROR_INTERNAL_FILE);
return false;
}
// Do not allow changing file locales if there is no hash table
if(hf->pHashEntry == NULL)
{
- SetLastError(ERROR_NOT_SUPPORTED);
+ SErrSetLastError(ERROR_NOT_SUPPORTED);
return false;
}
@@ -1306,14 +1329,14 @@ bool WINAPI SFileSetFileLocale(HANDLE hFile, LCID lcNewLocale) pFileEntry = GetFileEntryExact(ha, hf->pFileEntry->szFileName, lcNewLocale, NULL);
if(pFileEntry != NULL)
{
- SetLastError(ERROR_ALREADY_EXISTS);
+ SErrSetLastError(ERROR_ALREADY_EXISTS);
return false;
}
// Update the locale in the hash table entry
hf->pHashEntry->Locale = SFILE_LOCALE(lcNewLocale);
hf->pHashEntry->Platform = SFILE_PLATFORM(lcNewLocale);
- hf->pHashEntry->Reserved = 0;
+ hf->pHashEntry->Flags = 0;
ha->dwFlags |= MPQ_FLAG_CHANGED;
return true;
}
@@ -1327,7 +1350,7 @@ bool WINAPI SFileSetAddFileCallback(HANDLE hMpq, SFILE_ADDFILE_CALLBACK AddFileC if(!IsValidMpqHandle(hMpq))
{
- SetLastError(ERROR_INVALID_HANDLE);
+ SErrSetLastError(ERROR_INVALID_HANDLE);
return false;
}
diff --git a/src/SFileAttributes.cpp b/src/SFileAttributes.cpp index dbcc456..7a26562 100644 --- a/src/SFileAttributes.cpp +++ b/src/SFileAttributes.cpp @@ -392,7 +392,7 @@ DWORD SAttrLoadAttributes(TMPQArchive * ha) // Load the entire file to memory
if(!SFileReadFile(hFile, pbAttrFile, cbAttrFile, &dwBytesRead, NULL))
- ha->dwFlags |= (GetLastError() == ERROR_FILE_CORRUPT) ? MPQ_FLAG_MALFORMED : 0;
+ ha->dwFlags |= (SErrGetLastError() == ERROR_FILE_CORRUPT) ? MPQ_FLAG_MALFORMED : 0;
// Parse the (attributes)
if(dwBytesRead == cbAttrFile)
@@ -478,7 +478,7 @@ DWORD WINAPI SFileGetAttributes(HANDLE hMpq) // Verify the parameters
if(!IsValidMpqHandle(hMpq))
{
- SetLastError(ERROR_INVALID_PARAMETER);
+ SErrSetLastError(ERROR_INVALID_PARAMETER);
return SFILE_INVALID_ATTRIBUTES;
}
@@ -492,14 +492,14 @@ bool WINAPI SFileSetAttributes(HANDLE hMpq, DWORD dwFlags) // Verify the parameters
if(!IsValidMpqHandle(hMpq))
{
- SetLastError(ERROR_INVALID_PARAMETER);
+ SErrSetLastError(ERROR_INVALID_PARAMETER);
return false;
}
// Not allowed when the archive is read-only
if(ha->dwFlags & MPQ_FLAG_READ_ONLY)
{
- SetLastError(ERROR_ACCESS_DENIED);
+ SErrSetLastError(ERROR_ACCESS_DENIED);
return false;
}
@@ -523,14 +523,14 @@ bool WINAPI SFileUpdateFileAttributes(HANDLE hMpq, const char * szFileName) // Verify the parameters
if(!IsValidMpqHandle(ha))
{
- SetLastError(ERROR_INVALID_PARAMETER);
+ SErrSetLastError(ERROR_INVALID_PARAMETER);
return false;
}
// Not allowed when the archive is read-only
if(ha->dwFlags & MPQ_FLAG_READ_ONLY)
{
- SetLastError(ERROR_ACCESS_DENIED);
+ SErrSetLastError(ERROR_ACCESS_DENIED);
return false;
}
diff --git a/src/SFileCompactArchive.cpp b/src/SFileCompactArchive.cpp index 1077daa..63a6de2 100644 --- a/src/SFileCompactArchive.cpp +++ b/src/SFileCompactArchive.cpp @@ -116,14 +116,14 @@ static DWORD CopyNonMpqData( // Read from the source stream
if(!FileStream_Read(pSrcStream, &ByteOffset, DataBuffer, dwToRead))
{
- dwErrCode = GetLastError();
+ dwErrCode = SErrGetLastError();
break;
}
// Write to the target stream
if(!FileStream_Write(pTrgStream, NULL, DataBuffer, dwToRead))
{
- dwErrCode = GetLastError();
+ dwErrCode = SErrGetLastError();
break;
}
@@ -175,7 +175,7 @@ static DWORD CopyMpqFileSectors( {
BSWAP_ARRAY32_UNSIGNED(hf->pPatchInfo, sizeof(DWORD) * 3);
if(!FileStream_Write(pNewStream, NULL, hf->pPatchInfo, hf->pPatchInfo->dwLength))
- dwErrCode = GetLastError();
+ dwErrCode = SErrGetLastError();
// Save the size of the patch info
dwPatchSize = hf->pPatchInfo->dwLength;
@@ -202,7 +202,7 @@ static DWORD CopyMpqFileSectors( BSWAP_ARRAY32_UNSIGNED(SectorOffsetsCopy, dwSectorOffsLen);
if(!FileStream_Write(pNewStream, NULL, SectorOffsetsCopy, dwSectorOffsLen))
- dwErrCode = GetLastError();
+ dwErrCode = SErrGetLastError();
dwBytesToCopy -= dwSectorOffsLen;
dwCmpSize += dwSectorOffsLen;
@@ -244,7 +244,7 @@ static DWORD CopyMpqFileSectors( // Read the file sector
if(!FileStream_Read(ha->pStream, &RawFilePos, hf->pbFileSector, dwRawDataInSector))
{
- dwErrCode = GetLastError();
+ dwErrCode = SErrGetLastError();
break;
}
@@ -262,7 +262,7 @@ static DWORD CopyMpqFileSectors( // Now write the sector back to the file
if(!FileStream_Write(pNewStream, NULL, hf->pbFileSector, dwRawDataInSector))
{
- dwErrCode = GetLastError();
+ dwErrCode = SErrGetLastError();
break;
}
@@ -289,10 +289,10 @@ static DWORD CopyMpqFileSectors( if(dwCrcLength != 0)
{
if(!FileStream_Read(ha->pStream, NULL, hf->SectorChksums, dwCrcLength))
- dwErrCode = GetLastError();
+ dwErrCode = SErrGetLastError();
if(!FileStream_Write(pNewStream, NULL, hf->SectorChksums, dwCrcLength))
- dwErrCode = GetLastError();
+ dwErrCode = SErrGetLastError();
// Update compact progress
if(ha->pfnCompactCB != NULL)
@@ -321,10 +321,10 @@ static DWORD CopyMpqFileSectors( if(pbExtraData != NULL)
{
if(!FileStream_Read(ha->pStream, NULL, pbExtraData, dwBytesToCopy))
- dwErrCode = GetLastError();
+ dwErrCode = SErrGetLastError();
if(!FileStream_Write(pNewStream, NULL, pbExtraData, dwBytesToCopy))
- dwErrCode = GetLastError();
+ dwErrCode = SErrGetLastError();
// Include these extra data in the compressed size
dwCmpSize += dwBytesToCopy;
@@ -463,15 +463,17 @@ DWORD WINAPI SFileGetMaxFileCount(HANDLE hMpq) bool WINAPI SFileSetMaxFileCount(HANDLE hMpq, DWORD dwMaxFileCount)
{
TMPQArchive * ha = (TMPQArchive *)hMpq;
- DWORD dwNewHashTableSize = 0;
DWORD dwErrCode = ERROR_SUCCESS;
+ // Calculate the hash table size for the new file limit
+ DWORD dwNewHashTableSize = GetNearestPowerOfTwo(dwMaxFileCount);
+
// Test the valid parameters
if(!IsValidMpqHandle(hMpq))
dwErrCode = ERROR_INVALID_HANDLE;
if(ha->dwFlags & MPQ_FLAG_READ_ONLY)
dwErrCode = ERROR_ACCESS_DENIED;
- if(dwMaxFileCount < ha->dwFileTableSize)
+ if(dwNewHashTableSize < ha->dwFileTableSize)
dwErrCode = ERROR_DISK_FULL;
// ALL file names must be known in order to be able to rebuild hash table
@@ -480,9 +482,6 @@ bool WINAPI SFileSetMaxFileCount(HANDLE hMpq, DWORD dwMaxFileCount) dwErrCode = CheckIfAllFilesKnown(ha);
if(dwErrCode == ERROR_SUCCESS)
{
- // Calculate the hash table size for the new file limit
- dwNewHashTableSize = GetNearestPowerOfTwo(dwMaxFileCount);
-
// Rebuild both file tables
dwErrCode = RebuildFileTable(ha, dwNewHashTableSize);
}
@@ -501,7 +500,7 @@ bool WINAPI SFileSetMaxFileCount(HANDLE hMpq, DWORD dwMaxFileCount) // Return the error
if(dwErrCode != ERROR_SUCCESS)
- SetLastError(dwErrCode);
+ SErrSetLastError(dwErrCode);
return (dwErrCode == ERROR_SUCCESS);
}
@@ -514,7 +513,7 @@ bool WINAPI SFileSetCompactCallback(HANDLE hMpq, SFILE_COMPACT_CALLBACK pfnCompa if (!IsValidMpqHandle(hMpq))
{
- SetLastError(ERROR_INVALID_HANDLE);
+ SErrSetLastError(ERROR_INVALID_HANDLE);
return false;
}
@@ -574,7 +573,7 @@ bool WINAPI SFileCompactArchive(HANDLE hMpq, const TCHAR * szListFile, bool /* b // Create temporary file
pTempStream = FileStream_CreateFile(szTempFile, STREAM_PROVIDER_FLAT | BASE_PROVIDER_FILE);
if(pTempStream == NULL)
- dwErrCode = GetLastError();
+ dwErrCode = SErrGetLastError();
}
// Write the data before MPQ user data (if any)
@@ -615,7 +614,7 @@ bool WINAPI SFileCompactArchive(HANDLE hMpq, const TCHAR * szListFile, bool /* b BSWAP_TMPQHEADER(&SaveMpqHeader, MPQ_FORMAT_VERSION_3);
BSWAP_TMPQHEADER(&SaveMpqHeader, MPQ_FORMAT_VERSION_4);
if(!FileStream_Write(pTempStream, NULL, &SaveMpqHeader, ha->pHeader->dwHeaderSize))
- dwErrCode = GetLastError();
+ dwErrCode = SErrGetLastError();
// Update the progress
ha->CompactBytesProcessed += ha->pHeader->dwHeaderSize;
@@ -649,6 +648,6 @@ bool WINAPI SFileCompactArchive(HANDLE hMpq, const TCHAR * szListFile, bool /* b if(pFileKeys != NULL)
STORM_FREE(pFileKeys);
if(dwErrCode != ERROR_SUCCESS)
- SetLastError(dwErrCode);
+ SErrSetLastError(dwErrCode);
return (dwErrCode == ERROR_SUCCESS);
}
diff --git a/src/SFileCreateArchive.cpp b/src/SFileCreateArchive.cpp index bae3dcc..9a311e0 100644 --- a/src/SFileCreateArchive.cpp +++ b/src/SFileCreateArchive.cpp @@ -68,7 +68,7 @@ static DWORD WriteNakedMPQHeader(TMPQArchive * ha) BSWAP_TMPQHEADER(&Header, MPQ_FORMAT_VERSION_3); BSWAP_TMPQHEADER(&Header, MPQ_FORMAT_VERSION_4); if(!FileStream_Write(ha->pStream, &ha->MpqPos, &Header, dwBytesToWrite)) - dwErrCode = GetLastError(); + dwErrCode = SErrGetLastError(); return dwErrCode; } @@ -121,7 +121,7 @@ bool WINAPI SFileCreateArchive2(const TCHAR * szMpqName, PSFILE_CREATE_MPQ pCrea // Check the parameters, if they are valid if(szMpqName == NULL || *szMpqName == 0 || pCreateInfo == NULL || phMpq == NULL) { - SetLastError(ERROR_INVALID_PARAMETER); + SErrSetLastError(ERROR_INVALID_PARAMETER); return false; } @@ -133,7 +133,7 @@ bool WINAPI SFileCreateArchive2(const TCHAR * szMpqName, PSFILE_CREATE_MPQ pCrea (pCreateInfo->dwSectorSize & (pCreateInfo->dwSectorSize - 1)) || (pCreateInfo->dwRawChunkSize & (pCreateInfo->dwRawChunkSize - 1))) { - SetLastError(ERROR_INVALID_PARAMETER); + SErrSetLastError(ERROR_INVALID_PARAMETER); return false; } @@ -145,7 +145,7 @@ bool WINAPI SFileCreateArchive2(const TCHAR * szMpqName, PSFILE_CREATE_MPQ pCrea if(SFileOpenArchive(szMpqName, 0, STREAM_PROVIDER_FLAT | BASE_PROVIDER_FILE | MPQ_OPEN_NO_ATTRIBUTES | MPQ_OPEN_NO_LISTFILE, &hMpq)) { SFileCloseArchive(hMpq); - SetLastError(ERROR_ALREADY_EXISTS); + SErrSetLastError(ERROR_ALREADY_EXISTS); return false; } @@ -191,7 +191,7 @@ bool WINAPI SFileCreateArchive2(const TCHAR * szMpqName, PSFILE_CREATE_MPQ pCrea FileStream_GetSize(pStream, &MpqPos); MpqPos = (MpqPos + 0x1FF) & (ULONGLONG)0xFFFFFFFFFFFFFE00ULL; if(!FileStream_SetSize(pStream, MpqPos)) - dwErrCode = GetLastError(); + dwErrCode = SErrGetLastError(); #ifdef _DEBUG // Debug code, used for testing StormLib @@ -275,7 +275,7 @@ bool WINAPI SFileCreateArchive2(const TCHAR * szMpqName, PSFILE_CREATE_MPQ pCrea { FileStream_Close(pStream); FreeArchiveHandle(ha); - SetLastError(dwErrCode); + SErrSetLastError(dwErrCode); ha = NULL; } diff --git a/src/SFileExtractFile.cpp b/src/SFileExtractFile.cpp index 6b3b767..b65410c 100644 --- a/src/SFileExtractFile.cpp +++ b/src/SFileExtractFile.cpp @@ -22,7 +22,7 @@ bool WINAPI SFileExtractFile(HANDLE hMpq, const char * szToExtract, const TCHAR if(dwErrCode == ERROR_SUCCESS) { if(!SFileOpenFileEx(hMpq, szToExtract, dwSearchScope, &hMpqFile)) - dwErrCode = GetLastError(); + dwErrCode = SErrGetLastError(); } // Create the local file @@ -30,7 +30,7 @@ bool WINAPI SFileExtractFile(HANDLE hMpq, const char * szToExtract, const TCHAR { pLocalFile = FileStream_CreateFile(szExtracted, 0); if(pLocalFile == NULL) - dwErrCode = GetLastError(); + dwErrCode = SErrGetLastError(); } // Copy the file's content @@ -42,7 +42,7 @@ bool WINAPI SFileExtractFile(HANDLE hMpq, const char * szToExtract, const TCHAR // dwTransferred is only set to nonzero if something has been read. // dwErrCode can be ERROR_SUCCESS or ERROR_HANDLE_EOF if(!SFileReadFile(hMpqFile, szBuffer, sizeof(szBuffer), &dwTransferred, NULL)) - dwErrCode = GetLastError(); + dwErrCode = SErrGetLastError(); if(dwErrCode == ERROR_HANDLE_EOF) dwErrCode = ERROR_SUCCESS; if(dwTransferred == 0) @@ -50,7 +50,7 @@ bool WINAPI SFileExtractFile(HANDLE hMpq, const char * szToExtract, const TCHAR // If something has been actually read, write it if(!FileStream_Write(pLocalFile, NULL, szBuffer, dwTransferred)) - dwErrCode = GetLastError(); + dwErrCode = SErrGetLastError(); } // Close the files @@ -59,6 +59,6 @@ bool WINAPI SFileExtractFile(HANDLE hMpq, const char * szToExtract, const TCHAR if(pLocalFile != NULL) FileStream_Close(pLocalFile); if(dwErrCode != ERROR_SUCCESS) - SetLastError(dwErrCode); + SErrSetLastError(dwErrCode); return (dwErrCode == ERROR_SUCCESS); } diff --git a/src/SFileFindFile.cpp b/src/SFileFindFile.cpp index 8f4849f..5e09026 100644 --- a/src/SFileFindFile.cpp +++ b/src/SFileFindFile.cpp @@ -444,7 +444,7 @@ HANDLE WINAPI SFileFindFirstFile(HANDLE hMpq, const char * szMask, SFILE_FIND_DA if(dwErrCode != ERROR_SUCCESS)
{
FreeMPQSearch(hs);
- SetLastError(dwErrCode);
+ SErrSetLastError(dwErrCode);
}
// Return the result value
@@ -466,7 +466,7 @@ bool WINAPI SFileFindNextFile(HANDLE hFind, SFILE_FIND_DATA * lpFindFileData) dwErrCode = DoMPQSearch(hs, lpFindFileData);
if(dwErrCode != ERROR_SUCCESS)
- SetLastError(dwErrCode);
+ SErrSetLastError(dwErrCode);
return (dwErrCode == ERROR_SUCCESS);
}
@@ -477,7 +477,7 @@ bool WINAPI SFileFindClose(HANDLE hFind) // Check the parameters
if(hs == NULL)
{
- SetLastError(ERROR_INVALID_HANDLE);
+ SErrSetLastError(ERROR_INVALID_HANDLE);
return false;
}
diff --git a/src/SFileGetFileInfo.cpp b/src/SFileGetFileInfo.cpp index 1746fa0..3c05e13 100644 --- a/src/SFileGetFileInfo.cpp +++ b/src/SFileGetFileInfo.cpp @@ -44,7 +44,7 @@ static DWORD GetMpqFileCount(TMPQArchive * ha) static bool GetInfo_ReturnError(DWORD dwErrCode)
{
- SetLastError(dwErrCode);
+ SErrSetLastError(dwErrCode);
return false;
}
@@ -411,12 +411,12 @@ bool WINAPI SFileGetFileInfo( case SFileInfoNameHash1:
if(hf->pHashEntry == NULL)
return GetInfo_ReturnError(ERROR_INVALID_PARAMETER);
- return GetInfo(pvFileInfo, cbFileInfo, &hf->pHashEntry->dwName1, sizeof(DWORD), pcbLengthNeeded);
+ return GetInfo(pvFileInfo, cbFileInfo, &hf->pHashEntry->dwHashCheck1, sizeof(DWORD), pcbLengthNeeded);
case SFileInfoNameHash2:
if(hf->pHashEntry == NULL)
return GetInfo_ReturnError(ERROR_INVALID_PARAMETER);
- return GetInfo(pvFileInfo, cbFileInfo, &hf->pHashEntry->dwName2, sizeof(DWORD), pcbLengthNeeded);
+ return GetInfo(pvFileInfo, cbFileInfo, &hf->pHashEntry->dwHashCheck2, sizeof(DWORD), pcbLengthNeeded);
case SFileInfoNameHash3:
return GetInfo(pvFileInfo, cbFileInfo, &pFileEntry->FileNameHash, sizeof(ULONGLONG), pcbLengthNeeded);
@@ -483,7 +483,7 @@ bool WINAPI SFileFreeFileInfo(void * pvFileInfo, SFileInfoClass InfoClass) break;
}
- SetLastError(ERROR_INVALID_PARAMETER);
+ SErrSetLastError(ERROR_INVALID_PARAMETER);
return false;
}
@@ -621,7 +621,7 @@ bool WINAPI SFileGetFileName(HANDLE hFile, char * szFileName) }
if(dwErrCode != ERROR_SUCCESS)
- SetLastError(dwErrCode);
+ SErrSetLastError(dwErrCode);
return (dwErrCode == ERROR_SUCCESS);
}
diff --git a/src/SFileListFile.cpp b/src/SFileListFile.cpp index b2a3a3c..3e7a175 100644 --- a/src/SFileListFile.cpp +++ b/src/SFileListFile.cpp @@ -203,7 +203,7 @@ static TListFileCache * CreateListFileCache( }
// This combination should never happen
- SetLastError(ERROR_INVALID_PARAMETER);
+ SErrSetLastError(ERROR_INVALID_PARAMETER);
assert(false);
return NULL;
}
@@ -411,8 +411,8 @@ static DWORD SListFileCreateNodeForAllLocales(TMPQArchive * ha, const char * szF TFileEntry * pFileEntry;
TMPQHash * pHashEnd;
TMPQHash * pHash;
- DWORD dwName1;
- DWORD dwName2;
+ DWORD dwHashCheck1;
+ DWORD dwHashCheck2;
// If we have HET table, use that one
if(ha->pHetTable != NULL)
@@ -432,8 +432,8 @@ static DWORD SListFileCreateNodeForAllLocales(TMPQArchive * ha, const char * szF {
// Get the end of the hash table and both names
pHashEnd = ha->pHashTable + ha->pHeader->dwHashTableSize;
- dwName1 = ha->pfnHashString(szFileName, MPQ_HASH_NAME_A);
- dwName2 = ha->pfnHashString(szFileName, MPQ_HASH_NAME_B);
+ dwHashCheck1 = ha->pfnHashString(szFileName, MPQ_HASH_NAME_A);
+ dwHashCheck2 = ha->pfnHashString(szFileName, MPQ_HASH_NAME_B);
// Some protectors set very high hash table size (0x00400000 items or more)
// in order to make this process very slow. We will ignore items
@@ -445,7 +445,7 @@ static DWORD SListFileCreateNodeForAllLocales(TMPQArchive * ha, const char * szF // Go through the hash table and put the name in each item that has the same name pair
for(pHash = ha->pHashTable; pHash < pHashEnd; pHash++)
{
- if(pHash->dwName1 == dwName1 && pHash->dwName2 == dwName2 && MPQ_BLOCK_INDEX(pHash) < ha->dwFileTableSize)
+ if(pHash->dwHashCheck1 == dwHashCheck1 && pHash->dwHashCheck2 == dwHashCheck2 && MPQ_BLOCK_INDEX(pHash) < ha->dwFileTableSize)
{
// Allocate file name for the file entry
AllocateFileName(ha, ha->pFileTable + MPQ_BLOCK_INDEX(pHash), szFileName);
@@ -649,7 +649,7 @@ static bool DoListFileSearch(TListFileCache * pCache, SFILE_FIND_DATA * lpFindFi // No more files
memset(lpFindFileData, 0, sizeof(SFILE_FIND_DATA));
- SetLastError(ERROR_NO_MORE_FILES);
+ SErrSetLastError(ERROR_NO_MORE_FILES);
return false;
}
@@ -726,7 +726,7 @@ HANDLE WINAPI SListFileFindFirstFile(HANDLE hMpq, const TCHAR * szListFile, cons if(!DoListFileSearch(pCache, lpFindFileData))
{
memset(lpFindFileData, 0, sizeof(SFILE_FIND_DATA));
- SetLastError(ERROR_NO_MORE_FILES);
+ SErrSetLastError(ERROR_NO_MORE_FILES);
FreeListFileCache(pCache);
pCache = NULL;
}
diff --git a/src/SFileOpenArchive.cpp b/src/SFileOpenArchive.cpp index 217feca..d07d325 100644 --- a/src/SFileOpenArchive.cpp +++ b/src/SFileOpenArchive.cpp @@ -22,10 +22,36 @@ //----------------------------------------------------------------------------- // Local functions +#ifndef IMAGE_DOS_SIGNATURE + +#define IMAGE_DOS_SIGNATURE 0x5A4D // MZ +#define IMAGE_FILE_DLL 0x2000 // File is a DLL. + +typedef struct _IMAGE_DOS_HEADER +{ + USHORT e_magic; + USHORT dummy[0x1D]; + DWORD e_lfanew; +} IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER; + +typedef struct _IMAGE_FILE_HEADER +{ + USHORT Machine; + USHORT NumberOfSections; + DWORD TimeDateStamp; + DWORD PointerToSymbolTable; + DWORD NumberOfSymbols; + USHORT SizeOfOptionalHeader; + USHORT Characteristics; +} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER; +#endif + + static MTYPE CheckMapType(LPCTSTR szFileName, LPBYTE pbHeaderBuffer, size_t cbHeaderBuffer) { LPDWORD HeaderInt32 = (LPDWORD)pbHeaderBuffer; LPCTSTR szExtension; + MTYPE TypeByExtension = MapTypeNotRecognized; // Don't do any checks if there is not at least 16 bytes if(cbHeaderBuffer > 0x10) @@ -40,16 +66,22 @@ static MTYPE CheckMapType(LPCTSTR szFileName, LPBYTE pbHeaderBuffer, size_t cbHe // fake Warcraft III header into the Starcraft II maps if((szExtension = _tcsrchr(szFileName, _T('.'))) != NULL) { + // Check for Starcraft I maps by extension + if(!_tcsicmp(szExtension, _T(".scm")) || !_tcsicmp(szExtension, _T(".scx"))) + { + return MapTypeStarcraft; + } + // Check for Starcraft II maps by extension if(!_tcsicmp(szExtension, _T(".s2ma")) || !_tcsicmp(szExtension, _T(".SC2Map")) || !_tcsicmp(szExtension, _T(".SC2Mod"))) { return MapTypeStarcraft2; } - // Check for Starcraft I maps by extension - if(!_tcsicmp(szExtension, _T(".scm")) || !_tcsicmp(szExtension, _T(".scx"))) + // Check for Warcraft III maps by extension + if(!_tcsicmp(szExtension, _T(".w3m")) || !_tcsicmp(szExtension, _T(".w3x"))) { - return MapTypeStarcraft; + TypeByExtension = MapTypeWarcraft3; } } @@ -64,15 +96,30 @@ static MTYPE CheckMapType(LPCTSTR szFileName, LPBYTE pbHeaderBuffer, size_t cbHe // MIX files are DLL files that contain MPQ in overlay. // Only Warcraft III is able to load them, so we consider them Warcraft III maps - if(cbHeaderBuffer > 0x200 && pbHeaderBuffer[0] == 'M' && pbHeaderBuffer[1] == 'Z') + // Do not include EXE files, because they may be World of Warcraft patches + if(cbHeaderBuffer > sizeof(IMAGE_DOS_HEADER)) { - // Check the value of IMAGE_DOS_HEADER::e_lfanew at offset 0x3C - if(0 < HeaderInt32[0x0F] && HeaderInt32[0x0F] < 0x10000) - return MapTypeWarcraft3; + PIMAGE_FILE_HEADER pFileHeader; + PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)(pbHeaderBuffer); + size_t dwMaxAllowedSize = cbHeaderBuffer - sizeof(DWORD) - sizeof(IMAGE_FILE_HEADER); + + // Verify the header of EXE/DLL files + if((pDosHeader->e_magic == IMAGE_DOS_SIGNATURE) && (0 < pDosHeader->e_lfanew && pDosHeader->e_lfanew < 0x10000)) + { + // Is the file an EXE? + if((size_t)pDosHeader->e_lfanew <= dwMaxAllowedSize) + { + pFileHeader = (PIMAGE_FILE_HEADER)(pbHeaderBuffer + pDosHeader->e_lfanew + sizeof(DWORD)); + if(pFileHeader->Characteristics & IMAGE_FILE_DLL) + { + return MapTypeWarcraft3; + } + } + } } // No special map type recognized - return MapTypeNotRecognized; + return TypeByExtension; } static bool IsStarcraftBetaArchive(TMPQHeader * pHeader) @@ -177,7 +224,7 @@ bool WINAPI SFileSetArchiveMarkers(PSFILE_MARKERS pMarkers) // Check structure minimum size if(pMarkers == NULL || pMarkers->dwSize < SFILE_MARKERS_MIN_SIZE) { - SetLastError(ERROR_INVALID_PARAMETER); + SErrSetLastError(ERROR_INVALID_PARAMETER); return false; } @@ -241,7 +288,7 @@ bool WINAPI SFileOpenArchive( // Verify the parameters if(szMpqName == NULL || *szMpqName == 0 || phMpq == NULL) { - SetLastError(ERROR_INVALID_PARAMETER); + SErrSetLastError(ERROR_INVALID_PARAMETER); return false; } @@ -327,7 +374,7 @@ bool WINAPI SFileOpenArchive( // Read the eventual MPQ header if(!FileStream_Read(ha->pStream, &ByteOffset, pbHeaderBuffer, dwBytesAvailable)) { - dwErrCode = GetLastError(); + dwErrCode = SErrGetLastError(); break; } @@ -368,7 +415,7 @@ bool WINAPI SFileOpenArchive( // Read the eventual MPQ header from the position where the user data points if(!FileStream_Read(ha->pStream, &TempByteOffset, ha->HeaderData, sizeof(ha->HeaderData))) { - dwErrCode = GetLastError(); + dwErrCode = SErrGetLastError(); break; } @@ -500,6 +547,12 @@ bool WINAPI SFileOpenArchive( ha->dwValidFileFlags = MPQ_FILE_VALID_FLAGS_W3X; ha->dwFlags |= MPQ_FLAG_WAR3_MAP; break; + case MapTypeNotChecked: + case MapTypeNotRecognized: + case MapTypeAviFile: + case MapTypeStarcraft2: + // silence -Wswitch-enum + break; } // Set the size of file sector. Be sure to check for integer overflow @@ -574,7 +627,7 @@ bool WINAPI SFileOpenArchive( { FileStream_Close(pStream); FreeArchiveHandle(ha); - SetLastError(dwErrCode); + SErrSetLastError(dwErrCode); ha = NULL; } @@ -599,7 +652,7 @@ bool WINAPI SFileSetDownloadCallback(HANDLE hMpq, SFILE_DOWNLOAD_CALLBACK Downlo // Do nothing if 'hMpq' is bad parameter if(!IsValidMpqHandle(hMpq)) { - SetLastError(ERROR_INVALID_HANDLE); + SErrSetLastError(ERROR_INVALID_HANDLE); return false; } @@ -624,7 +677,7 @@ bool WINAPI SFileFlushArchive(HANDLE hMpq) // Do nothing if 'hMpq' is bad parameter if((ha = IsValidMpqHandle(hMpq)) == NULL) { - SetLastError(ERROR_INVALID_HANDLE); + SErrSetLastError(ERROR_INVALID_HANDLE); return false; } @@ -690,7 +743,7 @@ bool WINAPI SFileFlushArchive(HANDLE hMpq) // Return the error if(dwResultError != ERROR_SUCCESS) - SetLastError(dwResultError); + SErrSetLastError(dwResultError); return (dwResultError == ERROR_SUCCESS); } @@ -706,7 +759,7 @@ bool WINAPI SFileCloseArchive(HANDLE hMpq) // Only if the handle is valid if(ha == NULL) { - SetLastError(ERROR_INVALID_HANDLE); + SErrSetLastError(ERROR_INVALID_HANDLE); return false; } diff --git a/src/SFileOpenFileEx.cpp b/src/SFileOpenFileEx.cpp index 2954669..e555303 100644 --- a/src/SFileOpenFileEx.cpp +++ b/src/SFileOpenFileEx.cpp @@ -97,7 +97,7 @@ static bool OpenLocalFile(const char * szFileName, HANDLE * PtrFile) else { FileStream_Close(pStream); - SetLastError(ERROR_NOT_ENOUGH_MEMORY); + SErrSetLastError(ERROR_NOT_ENOUGH_MEMORY); } } *PtrFile = NULL; @@ -160,14 +160,14 @@ bool OpenPatchedFile(HANDLE hMpq, const char * szFileName, HANDLE * PtrFile) if(hfBase && hf && hf->pFileEntry->dwFlags & MPQ_FILE_DELETE_MARKER) { SFileCloseFile((HANDLE)(hfBase)); - SetLastError(ERROR_FILE_DELETED); + SErrSetLastError(ERROR_FILE_DELETED); hfBase = NULL; } } } else { - SetLastError(ERROR_FILE_NOT_FOUND); + SErrSetLastError(ERROR_FILE_NOT_FOUND); } // Give the updated base MPQ @@ -397,7 +397,7 @@ bool WINAPI SFileOpenFileEx(HANDLE hMpq, const char * szFileName, DWORD dwSearch // Return error code if(dwErrCode != ERROR_SUCCESS) - SetLastError(dwErrCode); + SErrSetLastError(dwErrCode); return (dwErrCode == ERROR_SUCCESS); } @@ -421,7 +421,7 @@ bool WINAPI SFileCloseFile(HANDLE hFile) if(!IsValidFileHandle(hFile)) { - SetLastError(ERROR_INVALID_HANDLE); + SErrSetLastError(ERROR_INVALID_HANDLE); return false; } diff --git a/src/SFilePatchArchives.cpp b/src/SFilePatchArchives.cpp index 5d9450d..790b96b 100644 --- a/src/SFilePatchArchives.cpp +++ b/src/SFilePatchArchives.cpp @@ -1155,11 +1155,11 @@ bool WINAPI SFileOpenPatchArchive( }
else
{
- dwErrCode = GetLastError();
+ dwErrCode = SErrGetLastError();
}
}
- SetLastError(dwErrCode);
+ SErrSetLastError(dwErrCode);
return false;
}
diff --git a/src/SFileReadFile.cpp b/src/SFileReadFile.cpp index 180d428..ee91cac 100644 --- a/src/SFileReadFile.cpp +++ b/src/SFileReadFile.cpp @@ -73,8 +73,8 @@ static DWORD ReadMpqSectors(TMPQFile * hf, LPBYTE pbBuffer, DWORD dwByteOffset, // or not, we won't try that again for the given file. // - AllocateSectorChecksums(hf, true); - hf->bLoadedSectorCRCs = true; + if(AllocateSectorChecksums(hf, true) == ERROR_SUCCESS) + hf->bLoadedSectorCRCs = true; } // TODO: If the raw data MD5s are not loaded yet, load them now @@ -224,7 +224,7 @@ static DWORD ReadMpqSectors(TMPQFile * hf, LPBYTE pbBuffer, DWORD dwByteOffset, } else { - dwErrCode = GetLastError(); + dwErrCode = SErrGetLastError(); } // Free all used buffers @@ -280,7 +280,7 @@ static DWORD ReadMpqFileSingleUnit(TMPQFile * hf, void * pvBuffer, DWORD dwFileP if(!FileStream_Read(ha->pStream, &RawFilePos, pbRawData, cbRawData)) { STORM_FREE(pbCompressed); - return GetLastError(); + return SErrGetLastError(); } // If the file is encrypted, we have to decrypt the data first @@ -310,7 +310,7 @@ static DWORD ReadMpqFileSingleUnit(TMPQFile * hf, void * pvBuffer, DWORD dwFileP // deDE\DBFilesClient\MountCapability.dbc 0x93->0x77 0x77 0x77 No // - if(pFileEntry->dwFlags & MPQ_FILE_PATCH_FILE) + if(pFileEntry->dwFlags & MPQ_FILE_PATCH_FILE && cbInBuffer > sizeof(TPatchInfo)) cbInBuffer = cbInBuffer - sizeof(TPatchInfo); // Is the file compressed by Blizzard's multiple compression ? @@ -411,7 +411,7 @@ static DWORD ReadMpkFileSingleUnit(TMPQFile * hf, void * pvBuffer, DWORD dwFileP if(!FileStream_Read(ha->pStream, &RawFilePos, pbRawData, pFileEntry->dwCmpSize)) { STORM_FREE(pbCompressed); - return GetLastError(); + return SErrGetLastError(); } // If the file is encrypted, we have to decrypt the data first @@ -666,7 +666,7 @@ static DWORD ReadMpqFileLocalFile(TMPQFile * hf, void * pvBuffer, DWORD dwFilePo if(!FileStream_Read(hf->pStream, &FilePosition1, pvBuffer, dwToRead)) { // If not all bytes have been read, then return the number of bytes read - if((dwErrCode = GetLastError()) == ERROR_HANDLE_EOF) + if((dwErrCode = SErrGetLastError()) == ERROR_HANDLE_EOF) { FileStream_GetPos(hf->pStream, &FilePosition2); dwBytesRead = (DWORD)(FilePosition2 - FilePosition1); @@ -699,13 +699,13 @@ bool WINAPI SFileReadFile(HANDLE hFile, void * pvBuffer, DWORD dwToRead, LPDWORD // Check valid parameters if((hf = IsValidFileHandle(hFile)) == NULL) { - SetLastError(ERROR_INVALID_HANDLE); + SErrSetLastError(ERROR_INVALID_HANDLE); return false; } if(pvBuffer == NULL) { - SetLastError(ERROR_INVALID_PARAMETER); + SErrSetLastError(ERROR_INVALID_PARAMETER); return false; } @@ -715,7 +715,7 @@ bool WINAPI SFileReadFile(HANDLE hFile, void * pvBuffer, DWORD dwToRead, LPDWORD dwErrCode = AllocatePatchInfo(hf, true); if(dwErrCode != ERROR_SUCCESS || hf->pPatchInfo == NULL) { - SetLastError(dwErrCode); + SErrSetLastError(dwErrCode); return false; } } @@ -768,7 +768,7 @@ bool WINAPI SFileReadFile(HANDLE hFile, void * pvBuffer, DWORD dwToRead, LPDWORD // If something failed, set the last error value if(dwErrCode != ERROR_SUCCESS) - SetLastError(dwErrCode); + SErrSetLastError(dwErrCode); return (dwErrCode == ERROR_SUCCESS); } @@ -818,7 +818,7 @@ DWORD WINAPI SFileGetFileSize(HANDLE hFile, LPDWORD pdwFileSizeHigh) return (DWORD)FileSize; } - SetLastError(ERROR_INVALID_HANDLE); + SErrSetLastError(ERROR_INVALID_HANDLE); return SFILE_INVALID_SIZE; } @@ -833,7 +833,7 @@ DWORD WINAPI SFileSetFilePointer(HANDLE hFile, LONG lFilePos, LONG * plFilePosHi // If the hFile is not a valid file handle, return an error. if(!IsValidFileHandle(hFile)) { - SetLastError(ERROR_INVALID_HANDLE); + SErrSetLastError(ERROR_INVALID_HANDLE); return SFILE_INVALID_POS; } @@ -881,7 +881,7 @@ DWORD WINAPI SFileSetFilePointer(HANDLE hFile, LONG lFilePos, LONG * plFilePosHi break; default: - SetLastError(ERROR_INVALID_PARAMETER); + SErrSetLastError(ERROR_INVALID_PARAMETER); return SFILE_INVALID_POS; } @@ -893,7 +893,7 @@ DWORD WINAPI SFileSetFilePointer(HANDLE hFile, LONG lFilePos, LONG * plFilePosHi { if(NewPosition > FileSize) // Position is negative { - SetLastError(ERROR_NEGATIVE_SEEK); + SErrSetLastError(ERROR_NEGATIVE_SEEK); return SFILE_INVALID_POS; } } diff --git a/src/SFileVerify.cpp b/src/SFileVerify.cpp index 9bbbb6b..96b5725 100644 --- a/src/SFileVerify.cpp +++ b/src/SFileVerify.cpp @@ -411,7 +411,7 @@ static DWORD VerifyRawMpqData( {
// Read the array of MD5
if(!FileStream_Read(ha->pStream, &DataOffset, pbMD5Array2, dwMD5Size))
- dwErrCode = GetLastError();
+ dwErrCode = SErrGetLastError();
}
// Compare the array of MD5
@@ -631,7 +631,7 @@ static DWORD VerifyFile( SFileReadFile(hFile, Buffer, sizeof(Buffer), &dwBytesRead, NULL);
if(dwBytesRead == 0)
{
- if(GetLastError() == ERROR_CHECKSUM_ERROR)
+ if(SErrGetLastError() == ERROR_CHECKSUM_ERROR)
dwVerifyResult |= VERIFY_FILE_SECTOR_CRC_ERROR;
break;
}
@@ -868,7 +868,7 @@ DWORD SSignFileFinish(TMPQArchive * ha) // Write the signature to the MPQ. Don't use SFile* functions, but write the hash directly
if(!FileStream_Write(ha->pStream, &si.BeginExclude, WeakSignature, MPQ_SIGNATURE_FILE_SIZE))
- return GetLastError();
+ return SErrGetLastError();
return ERROR_SUCCESS;
}
@@ -895,7 +895,7 @@ bool WINAPI SFileGetFileChecksums(HANDLE hMpq, const char * szFileName, LPDWORD // If verification failed, return zero
if(dwVerifyResult & VERIFY_FILE_ERROR_MASK)
{
- SetLastError(ERROR_FILE_CORRUPT);
+ SErrSetLastError(ERROR_FILE_CORRUPT);
return false;
}
@@ -1026,21 +1026,21 @@ bool WINAPI SFileSignArchive(HANDLE hMpq, DWORD dwSignatureType) ha = IsValidMpqHandle(hMpq);
if(ha == NULL)
{
- SetLastError(ERROR_INVALID_PARAMETER);
+ SErrSetLastError(ERROR_INVALID_PARAMETER);
return false;
}
// We only support weak signature, and only for MPQs version 1.0
if(dwSignatureType != SIGNATURE_TYPE_WEAK)
{
- SetLastError(ERROR_INVALID_PARAMETER);
+ SErrSetLastError(ERROR_INVALID_PARAMETER);
return false;
}
// The archive must not be malformed and must not be read-only
if(ha->dwFlags & (MPQ_FLAG_READ_ONLY | MPQ_FLAG_MALFORMED))
{
- SetLastError(ERROR_ACCESS_DENIED);
+ SErrSetLastError(ERROR_ACCESS_DENIED);
return false;
}
diff --git a/src/SMemUtf8.cpp b/src/SMemUtf8.cpp index 5832422..b9d5e9d 100644 --- a/src/SMemUtf8.cpp +++ b/src/SMemUtf8.cpp @@ -40,6 +40,8 @@ const unsigned char SMemCharToByte[0x80] = 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF // 0x70 }; +static TCHAR szInvalidCharPrefix[] = _T("%u["); + //----------------------------------------------------------------------------- // Local functions @@ -92,7 +94,7 @@ static DWORD UTF8_DecodeSequence(const BYTE * pbString, BYTE BitsMask, size_t cc } // https://en.wikipedia.org/wiki/UTF-8 -static DWORD UTF8_DecodeCodePoint(const BYTE * pbString, const BYTE * pbStringEnd, DWORD & dwCodePoint, size_t & ccBytesEaten) +DWORD UTF8_DecodeCodePoint(const BYTE * pbString, const BYTE * pbStringEnd, DWORD & dwCodePoint, size_t & ccBytesEaten) { // Reset the number of bytes eaten dwCodePoint = SFILE_UTF8_INVALID_CHARACTER; @@ -165,7 +167,7 @@ static size_t UTF8_EncodeSequence(DWORD dwCodePoint, BYTE LeadingByte, DWORD dwF return dwFollowByteCount + 1; } -static size_t UTF8_EncodeCodePoint(DWORD dwCodePoint, LPBYTE Utf8Buffer) +size_t UTF8_EncodeCodePoint(DWORD dwCodePoint, LPBYTE Utf8Buffer) { // 0x00 - 0x7F, 1 byte if(dwCodePoint < 0x80) @@ -217,7 +219,7 @@ static size_t UTF8_FlushInvalidChars(LPTSTR szBuffer, size_t ccBuffer, size_t nO // Space for 4 characters needed if(szBuffer != NULL && (nOutLength + nLengthNeeded) <= ccBuffer) { - memcpy(szBuffer + nOutLength, _T("%u["), 6); + memcpy(szBuffer + nOutLength, szInvalidCharPrefix, sizeof(szInvalidCharPrefix) - sizeof(TCHAR)); SMemBinToStr(szBuffer + nOutLength + 3, ccBuffer - 3, InvalidChars, nInvalidChars); @@ -549,3 +551,32 @@ DWORD WINAPI SMemFileNameToUTF8( pOutLength[0] = nOutLength; return dwErrCode; } + +//----------------------------------------------------------------------------- +// (Set/Get)LastError wrapper + +#ifndef STORMLIB_WINDOWS +#ifndef STORMLIB_WIIU +static thread_local DWORD dwLastError = ERROR_SUCCESS; +#else +static DWORD dwLastError = ERROR_SUCCESS; +#endif +#endif + +void SErrSetLastError(DWORD dwErrCode) +{ +#ifdef STORMLIB_WINDOWS + SetLastError(dwErrCode); +#else + dwLastError = dwErrCode; +#endif +} + +DWORD SErrGetLastError() +{ +#ifdef STORMLIB_WINDOWS + return GetLastError(); +#else + return dwLastError; +#endif +} diff --git a/src/StormCommon.h b/src/StormCommon.h index bf82039..cefb92c 100644 --- a/src/StormCommon.h +++ b/src/StormCommon.h @@ -239,8 +239,8 @@ DWORD SMemStrToBin(const XCHAR * szString, void * pvBinary, size_t cbBinary, siz BYTE StringByte0 = (BYTE)szString[0];
BYTE StringByte1 = (BYTE)szString[1];
- // Each character must be within the range of 0x80
- if(StringByte0 > 0x80 || StringByte1 > 0x80)
+ // Each character must be within the range of 0x00-0x7F
+ if(StringByte0 >= 0x80 || StringByte1 >= 0x80)
return ERROR_INVALID_PARAMETER;
if(SMemCharToByte[StringByte0] == 0xFF || SMemCharToByte[StringByte1] == 0xFF)
return ERROR_INVALID_PARAMETER;
@@ -277,6 +277,12 @@ void StringCat(TCHAR * szTarget, size_t cchTargetMax, const char * szSource); #endif
//-----------------------------------------------------------------------------
+// UTF-8 support
+
+DWORD UTF8_DecodeCodePoint(const BYTE * pbString, const BYTE * pbStringEnd, DWORD & dwCodePoint, size_t & ccBytesEaten);
+size_t UTF8_EncodeCodePoint(DWORD dwCodePoint, LPBYTE Utf8Buffer);
+
+//-----------------------------------------------------------------------------
// Encryption and decryption functions
#define MPQ_HASH_TABLE_INDEX 0x000
@@ -327,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);
@@ -360,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/StormLib.h b/src/StormLib.h index 4392bc0..005cc46 100644 --- a/src/StormLib.h +++ b/src/StormLib.h @@ -1,7 +1,7 @@ /*****************************************************************************/ -/* StormLib.h Copyright (c) Ladislav Zezula 1999-2017 */ +/* StormLib.h Copyright (c) Ladislav Zezula 1999-2025 */ /*---------------------------------------------------------------------------*/ -/* StormLib library v 9.30 */ +/* StormLib library v 9.31 */ /* */ /* Author : Ladislav Zezula */ /* E-mail : ladik@zezula.net */ @@ -144,8 +144,8 @@ extern "C" { //----------------------------------------------------------------------------- // Defines -#define STORMLIB_VERSION 0x091E // Current version of StormLib -#define STORMLIB_VERSION_STRING "9.30" // Current version of StormLib as string +#define STORMLIB_VERSION 0x091F // Current version of StormLib +#define STORMLIB_VERSION_STRING "9.31" // Current version of StormLib as string #define ID_MPQ 0x1A51504D // MPQ archive header ID ('MPQ\x1A') #define ID_MPQ_USERDATA 0x1B51504D // MPQ userdata entry ('MPQ\x1B') @@ -292,6 +292,7 @@ extern "C" { // Signatures for HET and BET table #define HET_TABLE_SIGNATURE 0x1A544548 // 'HET\x1a' #define BET_TABLE_SIGNATURE 0x1A544542 // 'BET\x1a' +#define BET_TABLE_MAX_SIZE 0x00100000 // Maximum acceptable size of HET&BET tables // Decryption keys for MPQ tables #define MPQ_KEY_HASH_TABLE 0xC3AF3770 // Obtained by HashString("(hash table)", MPQ_HASH_FILE_KEY) @@ -631,10 +632,10 @@ typedef struct _TMPQHeader typedef struct _TMPQHash { // The hash of the file path, using method A. - DWORD dwName1; + DWORD dwHashCheck1; // The hash of the file path, using method B. - DWORD dwName2; + DWORD dwHashCheck2; #ifdef STORMLIB_LITTLE_ENDIAN @@ -645,11 +646,11 @@ typedef struct _TMPQHash // The platform the file is used for. 0 indicates the default platform. // No other values have been observed. BYTE Platform; - BYTE Reserved; + BYTE Flags; #else - BYTE Reserved; + BYTE Flags; BYTE Platform; USHORT Locale; @@ -1158,14 +1159,10 @@ DWORD WINAPI SMemFileNameToUTF8( size_t * pOutLength); // Pointer to a variable that receives the needed length in bytes (optional) //----------------------------------------------------------------------------- -// Non-Windows support for SetLastError/GetLastError +// Stormlib-specific support for SetLastError/GetLastError -#ifndef STORMLIB_WINDOWS - -void SetLastError(DWORD dwErrCode); -DWORD GetLastError(); - -#endif +void SErrSetLastError(DWORD dwErrCode); +DWORD SErrGetLastError(); //----------------------------------------------------------------------------- // Functions from Storm.dll. They use slightly different names for keeping diff --git a/src/StormPort.h b/src/StormPort.h index f00afd6..61affcd 100644 --- a/src/StormPort.h +++ b/src/StormPort.h @@ -27,10 +27,8 @@ #ifndef __STORMPORT_H__ #define __STORMPORT_H__ -#ifndef __cplusplus - #define bool char - #define true 1 - #define false 0 +#if !defined(__cplusplus) && !defined(_MSC_VER) + #include <stdbool.h> #endif //----------------------------------------------------------------------------- @@ -54,7 +52,9 @@ #include <stdio.h> // Suppress definitions of `min` and `max` macros by <windows.h>: + #ifndef NOMINMAX #define NOMINMAX 1 + #endif #include <windows.h> #include <wininet.h> diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt new file mode 100644 index 0000000..80c64c4 --- /dev/null +++ b/test/CMakeLists.txt @@ -0,0 +1,20 @@ +cmake_minimum_required(VERSION 3.10) + +set(TEST_SRC_FILES + StormTest.cpp +) + +# Option to use the legacy hardcoded paths +option(STORMTEST_USE_OLD_PATHS "Use hardcoded OS-specific default paths for WORK_PATH_ROOT" ON) + +if(NOT STORMTEST_USE_OLD_PATHS) + set(WORK_PATH_ROOT "${CMAKE_CURRENT_BINARY_DIR}/work") + add_compile_definitions(WORK_PATH_ROOT="${WORK_PATH_ROOT}") +endif() + +find_package(ALSA REQUIRED) +add_executable(StormLib_test ${TEST_SRC_FILES}) +target_link_libraries(StormLib_test storm ALSA::ALSA) +install(TARGETS StormLib_test RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) + +add_test(NAME StormLib_test COMMAND StormLib_test) diff --git a/test/StormTest.cpp b/test/StormTest.cpp index 5a442a5..bd07c88 100755 --- a/test/StormTest.cpp +++ b/test/StormTest.cpp @@ -1,4 +1,4 @@ -/*****************************************************************************/
+/*****************************************************************************/
/* StormTest.cpp Copyright (c) Ladislav Zezula 2003 */
/*---------------------------------------------------------------------------*/
/* Test module for StormLib */
@@ -155,16 +155,18 @@ typedef struct _WAVE_FILE_HEADER //------------------------------------------------------------------------------
// Local variables
-#ifdef STORMLIB_WINDOWS
-#define WORK_PATH_ROOT _T("\\Multimedia\\MPQs")
-#endif
+#ifndef WORK_PATH_ROOT
+ #ifdef STORMLIB_WINDOWS
+ #define WORK_PATH_ROOT _T("\\Multimedia\\MPQs")
+ #endif
-#ifdef STORMLIB_LINUX
-#define WORK_PATH_ROOT "/media/ladik/MPQs"
-#endif
+ #ifdef STORMLIB_LINUX
+ #define WORK_PATH_ROOT "/media/ladik/MPQs"
+ #endif
-#ifdef STORMLIB_HAIKU
-#define WORK_PATH_ROOT "~/StormLib/test"
+ #ifdef STORMLIB_HAIKU
+ #define WORK_PATH_ROOT "~/StormLib/test"
+ #endif
#endif
// Definition of the path separator
@@ -353,6 +355,13 @@ const char * GetFileText(PFILE_DATA pFileData) return szFileText;
}
+#ifdef STORMLIB_LINUX
+static void alsa_silent_error_handler(const char * file, int line, const char * function, int err, const char * fmt, ...)
+{
+ // Suppress ALSA error output, so do nothing
+}
+#endif
+
static void PlayWaveSound(PFILE_DATA pFileData)
{
#ifdef STORMLIB_WINDOWS
@@ -365,6 +374,10 @@ static void PlayWaveSound(PFILE_DATA pFileData) snd_pcm_t *pcm_handle;
unsigned int bitrate = pHeader->dwSamplesPerSec;
+ // Suppress ALSA error printing
+ snd_lib_error_set_handler(alsa_silent_error_handler);
+
+ // Open the default sound device and play the sound
if(snd_pcm_open(&pcm_handle, "default", SND_PCM_STREAM_PLAYBACK, 0) >= 0)
{
snd_pcm_format_t format = (pHeader->wBitsPerSample == 16) ? SND_PCM_FORMAT_S16_LE : SND_PCM_FORMAT_S8;
@@ -612,7 +625,7 @@ static DWORD CalculateFileHash(TLogHelper * pLogger, LPCTSTR szFullPath, LPTSTR cbBytesToRead = ((FileSize - ByteOffset) > cbFileBlock) ? cbFileBlock : (DWORD)(FileSize - ByteOffset);
if(!FileStream_Read(pStream, &ByteOffset, pbFileBlock, cbBytesToRead))
{
- dwErrCode = GetLastError();
+ dwErrCode = SErrGetLastError();
break;
}
@@ -856,7 +869,7 @@ static DWORD ForEachFile_VerifyFileHash(LPCTSTR szFullPath, void * lpContext) StringCopy(szHashTextA, _countof(szHashTextA), szHashText);
if(_strnicmp(szHashTextA, GetFileText(pFileData), (SHA256_DIGEST_SIZE * 2)))
{
- SetLastError(dwErrCode = ERROR_FILE_CORRUPT);
+ SErrSetLastError(dwErrCode = ERROR_FILE_CORRUPT);
pLogger->PrintError(_T("File hash check failed: %s"), szFullPath);
}
}
@@ -1038,7 +1051,7 @@ static DWORD GetFilePatchCount(TLogHelper * pLogger, HANDLE hMpq, LPCSTR szFileN }
else
{
- if(GetLastError() != ERROR_FILE_DELETED)
+ if(SErrGetLastError() != ERROR_FILE_DELETED)
{
pLogger->PrintError("Open failed: %s", szFileName);
}
@@ -1047,6 +1060,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;
@@ -1161,7 +1193,7 @@ static DWORD WriteMpqUserDataHeader( UserData.dwHeaderOffs = (dwByteCount + sizeof(TMPQUserData));
UserData.cbUserDataHeader = dwByteCount / 2;
if(!FileStream_Write(pStream, &ByteOffset, &UserData, sizeof(TMPQUserData)))
- dwErrCode = GetLastError();
+ dwErrCode = SErrGetLastError();
return dwErrCode;
}
@@ -1195,7 +1227,7 @@ static DWORD WriteFileData( // Write the data
if(!FileStream_Write(pStream, &ByteOffset, pbDataBuffer, cbToWrite))
{
- dwErrCode = GetLastError();
+ dwErrCode = SErrGetLastError();
break;
}
@@ -1233,14 +1265,14 @@ static DWORD CopyFileData( BytesToRead = ((EndOffset - ByteOffset) > BlockLength) ? BlockLength : (DWORD)(EndOffset - ByteOffset);
if(!FileStream_Read(pStream1, &ByteOffset, pbCopyBuffer, BytesToRead))
{
- dwErrCode = GetLastError();
+ dwErrCode = SErrGetLastError();
break;
}
// Write to the destination file
if(!FileStream_Write(pStream2, NULL, pbCopyBuffer, BytesToRead))
{
- dwErrCode = GetLastError();
+ dwErrCode = SErrGetLastError();
break;
}
@@ -1434,9 +1466,12 @@ static DWORD LoadMpqFile(TLogHelper & Logger, HANDLE hMpq, LPCSTR szFileName, LC DWORD dwBytesRead;
DWORD dwCrc32 = 0;
DWORD dwErrCode = ERROR_SUCCESS;
+ TCHAR szSafeName[1024];
- // Do nothing if the file name is invalid
- Logger.PrintProgress("Loading file %s ...", GetShortPlainName(szFileName));
+ // Print the file name to the console.
+ // Prevent bad UTF-8 sequences to go through
+ SMemUTF8ToFileName(szSafeName, _countof(szSafeName), szFileName, NULL, 0, NULL);
+ Logger.PrintProgress(_T("Loading file %s ..."), GetShortPlainName(szSafeName));
#if defined(_MSC_VER) && defined(_DEBUG)
//if(!_stricmp(szFileName, "(signature)"))
@@ -1514,7 +1549,7 @@ static DWORD LoadMpqFile(TLogHelper & Logger, HANDLE hMpq, LPCSTR szFileName, LC }
else
{
- if((dwSearchFlags & SEARCH_FLAG_IGNORE_ERRORS) == 0 && GetLastError() != ERROR_FILE_DELETED)
+ if((dwSearchFlags & SEARCH_FLAG_IGNORE_ERRORS) == 0 && SErrGetLastError() != ERROR_FILE_DELETED)
{
dwErrCode = Logger.PrintError("Open failed: %s", szFileName);
}
@@ -1658,7 +1693,7 @@ static DWORD SearchArchive( hFind = SFileFindFirstFile(hMpq, "*", &sf, szListFile);
if(hFind == NULL)
{
- dwErrCode = GetLastError();
+ dwErrCode = SErrGetLastError();
dwErrCode = (dwErrCode == ERROR_NO_MORE_FILES) ? ERROR_SUCCESS : dwErrCode;
return dwErrCode;
}
@@ -1861,11 +1896,11 @@ static DWORD OpenExistingArchive(TLogHelper * pLogger, LPCTSTR szFullPath, DWORD pLogger->PrintProgress(_T("Opening archive %s ..."), GetShortPlainName(szFullPath));
if(!SFileOpenArchive(szFullPath, 0, dwOpenFlags, &hMpq))
{
- switch(dwErrCode = GetLastError())
+ switch(dwErrCode = SErrGetLastError())
{
// case ERROR_BAD_FORMAT: // If the error is ERROR_BAD_FORMAT, try to open with MPQ_OPEN_FORCE_MPQ_V1
// bReopenResult = SFileOpenArchive(szMpqName, 0, dwFlags | MPQ_OPEN_FORCE_MPQ_V1, &hMpq);
-// dwErrCode = (bReopenResult == false) ? GetLastError() : ERROR_SUCCESS;
+// dwErrCode = (bReopenResult == false) ? SErrGetLastError() : ERROR_SUCCESS;
// break;
case ERROR_AVI_FILE: // Ignore the error if it's an AVI file or if the file is incomplete
@@ -1955,7 +1990,7 @@ static DWORD AddFileToMpq( }
else
{
- dwErrCode = GetLastError();
+ dwErrCode = SErrGetLastError();
}
// Check the expected error code
@@ -2001,7 +2036,7 @@ static DWORD AddLocalFileToMpq( {
if(bMustSucceed)
return pLogger->PrintError("Failed to add the file %s", szArchivedName);
- return GetLastError();
+ return SErrGetLastError();
}
// Verify the file unless it was lossy compression
@@ -2028,7 +2063,7 @@ static DWORD RemoveMpqFile(TLogHelper * pLogger, HANDLE hMpq, LPCSTR szFileName, // Perform the deletion
if(!SFileRemoveFile(hMpq, szFileName, 0))
- dwErrCode = GetLastError();
+ dwErrCode = SErrGetLastError();
if(dwErrCode != dwExpectedError)
return pLogger->PrintError("Unexpected result from SFileRemoveFile(%s)", szFileName);
@@ -2054,7 +2089,7 @@ static void TestGetFileInfo( // Call the get file info
bResult = SFileGetFileInfo(hMpqOrFile, InfoClass, pvFileInfo, cbFileInfo, pcbLengthNeeded);
if(!bResult)
- dwErrCode = GetLastError();
+ dwErrCode = SErrGetLastError();
// Check the expected results
if(bResult != bExpectedResult)
@@ -2753,7 +2788,7 @@ static DWORD TestOpenArchive( // Reset error code, if the failure is expected
if((dwErrCode != ERROR_SUCCESS || hMpq == NULL) && (dwFlags & TFLG_WILL_FAIL))
- SetLastError(dwErrCode = ERROR_SUCCESS);
+ SErrSetLastError(dwErrCode = ERROR_SUCCESS);
// Cleanup and exit
if(hMpq != NULL)
@@ -3052,6 +3087,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);
@@ -3087,7 +3177,7 @@ static DWORD TestCreateArchive_TestGaps(LPCTSTR szPlainName) SFileCloseFile(hFile);
}
else
- dwErrCode = GetLastError();
+ dwErrCode = SErrGetLastError();
}
}
@@ -3106,7 +3196,7 @@ static DWORD TestCreateArchive_TestGaps(LPCTSTR szPlainName) SFileCloseFile(hFile);
}
else
- dwErrCode = GetLastError();
+ dwErrCode = SErrGetLastError();
}
// Now check the positions
@@ -3317,6 +3407,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);
@@ -3864,30 +3955,40 @@ static DWORD TestUtf8Conversions(const BYTE * szTestString, const TCHAR * szList static void Test_PlayingSpace()
{
- HANDLE hFile = NULL;
- HANDLE hMpq = NULL;
+/*
+ HANDLE hMpq;
+ HANDLE hFile;
+ LPBYTE pbData;
+ DWORD dwFileSize = 529298;
+ DWORD dwBytesRead = 0;
- if(SFileOpenArchive(_T("E:\\DIABDAT.MPQ"), 0, 0, &hMpq))
+ if(SFileOpenArchive(_T("e:\\Ladik\\Incoming\\31525686D3A39C6B5CA4B2979367B809.w3x"), 0, 0, &hMpq))
{
- if(SFileOpenFileEx(hMpq, "d1221a.mpq", 0, &hFile))
+ if(SFileOpenFileEx(hMpq, "(listfile)", 0, &hFile))
{
- DWORD dwBytesRead = 0;
- BYTE Buffer[1024];
-
- SFileReadFile(hFile, Buffer, sizeof(Buffer), &dwBytesRead, NULL);
+ if((pbData = STORM_ALLOC(BYTE, dwFileSize)) != NULL)
+ {
+ SFileReadFile(hFile, pbData, dwFileSize, &dwBytesRead, NULL);
+ STORM_FREE(pbData);
+ }
SFileCloseFile(hFile);
}
SFileCloseArchive(hMpq);
}
+*/
}
//-----------------------------------------------------------------------------
// Tables
static LPCTSTR szSigned1 = _T("STANDARD.SNP");
-static LPCTSTR szSigned2 = _T("War2Patch_202.exe");
-static LPCTSTR szSigned3 = _T("WoW-1.2.3.4211-enUS-patch.exe");
+static LPCTSTR szSigned2 = _T("StarDat.mpq");
+static LPCTSTR szSigned3 = _T("War2Patch_202.exe");
static LPCTSTR szSigned4 = _T("(10)DustwallowKeys.w3m");
+static LPCTSTR szSigned5 = _T("WoW-1.2.3.4211-enUS-patch.exe");
+static LPCTSTR szSigned6 = _T("WoW-1.11.2.5464-to-1.12.0.5595-enUS-patch.exe");
+static LPCTSTR szSigned7 = _T("WoW-3.0.1.8337-to-3.0.1.8392-enGB-patch.exe");
+static LPCTSTR szSigned8 = _T("wow-final.MPQ");
static LPCTSTR szDiabdatMPQ = _T("MPQ_1997_v1_Diablo1_DIABDAT.MPQ");
@@ -4138,7 +4239,7 @@ static const TEST_INFO1 TestList_MasterMirror[] = static const TEST_INFO1 Test_OpenMpqs[] =
{
- // PoC's by Gabe Sherman from FuturesLab
+ // PoC's by Gabe Sherman, tinh0, Zao Yang
{_T("pocs/MPQ_2024_01_HeapOverrun.mpq"), NULL, "7008f95dcbc4e5d840830c176dec6969", 14},
{_T("pocs/MPQ_2024_02_StackOverflow.mpq"), NULL, "7093fcbcc9674b3e152e74e8e8a937bb", 4},
{_T("pocs/MPQ_2024_03_TooBigAlloc.mpq"), NULL, "--------------------------------", TFLG_WILL_FAIL},
@@ -4151,6 +4252,13 @@ static const TEST_INFO1 Test_OpenMpqs[] = {_T("pocs/MPQ_2024_10_HuffDecompressError.mpq"), NULL, "--------------------------------", TFLG_WILL_FAIL},
{_T("pocs/MPQ_2024_10_SparseDecompressError.mpq"), NULL, "--------------------------------", TFLG_WILL_FAIL},
{_T("pocs/MPQ_2024_11_HiBlockTablePosInvalid.mpq"), NULL, "--------------------------------", TFLG_WILL_FAIL},
+ {_T("pocs/MPQ_2025_01_SectorTableBeyondEOF.mpq"), NULL, "--------------------------------", TFLG_WILL_FAIL},
+ {_T("pocs/MPQ_2025_02_SectorOffsetSizeNotAligned.mpq"), NULL, "0cc175b9c0f1b6a831c399e269772661", TFLG_WILL_FAIL},
+ {_T("pocs/MPQ_2025_03_InvalidPatchInfo.mpq"), NULL, "93b885adfe0da089cdf634904fd59f71", TFLG_WILL_FAIL},
+ {_T("pocs/MPQ_2025_04_InvalidArchiveSize64.mpq"), NULL, "--------------------------------", TFLG_WILL_FAIL},
+ {_T("pocs/MPQ_2025_05_AddFileError.mpq"), NULL, "ce9b8afed4221a53663d391f10691ba6", TFLG_WILL_FAIL},
+ {_T("pocs/MPQ_2025_06_BadHashTableSize.mpq"), NULL, "00000000000000000000000000000000", TFLG_WILL_FAIL},
+ {_T("pocs/MPQ_2025_07_BadHetTableSize.mpq"), NULL, "00000000000000000000000000000000", TFLG_WILL_FAIL},
// Correct or damaged archives
{_T("MPQ_1997_v1_Diablo1_DIABDAT.MPQ"), NULL, "554b538541e42170ed41cb236483489e", 2910, &TwoFilesD1}, // Base MPQ from Diablo 1
@@ -4167,7 +4275,6 @@ static const TEST_INFO1 Test_OpenMpqs[] = {_T("MPQ_2002_v1_BlockTableCut.MPQ"), NULL, "a9499ab74d939303d8cda7c397c36275", 287}, // Truncated archive
{_T("MPQ_2010_v2_HasUserData.s2ma"), NULL, "feff9e2c86db716b6ff5ffc906181200", 52}, // MPQ that actually has user data
{_T("MPQ_2014_v1_AttributesOneEntryLess.w3x"), NULL, "90451b7052eb0f1d6f4bf69b2daff7f5", 116}, // Warcraft III map whose "(attributes)" file has (BlockTableSize-1) entries
- {_T("MPQ_2020_v1_AHF04patch.mix"), NULL, "d3c6aac48bc12813ef5ce4ad113e58bf", 2891}, // MIX file
{_T("MPQ_2010_v3_expansion-locale-frFR.MPQ"), NULL, "0c8fc921466f07421a281a05fad08b01", 53}, // MPQ archive v 3.0 (the only one I know)
{_T("mpqe-file://MPQ_2011_v2_EncryptedMpq.MPQE"), NULL, "10e4dcdbe95b7ad731c563ec6b71bc16", 82}, // Encrypted archive from Starcraft II installer
{_T("part-file://MPQ_2010_v2_HashTableCompressed.MPQ.part"),NULL, "d41d8cd98f00b204e9800998ecf8427e", 14263}, // Partial MPQ with compressed hash table
@@ -4178,10 +4285,10 @@ static const TEST_INFO1 Test_OpenMpqs[] = {_T("MPQ_2023_v1_Volcanis.scm"), NULL, "522c89ca96d6736427b01f7c80dd626f", 3}, // Map modified with unusual file compression: ZLIB+Huffman
{_T("MPQ_2023_v4_UTF8.s2ma"), NULL, "97b7a686650f3307d135e1d1b017a36a", 67}, // Map contaning files with Chinese names (UTF8-encoded)
{_T("MPQ_2023_v1_GreenTD.w3x"), NULL, "a8d91fc4e52d7c21ff7feb498c74781a", 2004}, // Corrupt sector checksum table in file #A0
+
{_T("MPQ_2023_v4_1F644C5A.SC2Replay"), NULL, "b225828ffbf5037553e6a1290187caab", 17}, // Corrupt patch info of the "(attributes)" file
{_T("<Chinese MPQ name>"), NULL, "67faeffd0c0aece205ac8b7282d8ad8e", 4697, &MpqUtf8}, // Chinese name of the MPQ
{_T("MPQ_2024_v1_BadUtf8_5.0.2.w3x"), NULL, "be34f9862758f021a1c6c77df3cd4f05", 6393, &LfBad1}, // Bad UTF-8 sequences in file names
-
// Protected archives
{_T("MPQ_2002_v1_ProtectedMap_InvalidUserData.w3x"), NULL, "b900364cc134a51ddeca21a13697c3ca", 79},
@@ -4215,11 +4322,13 @@ static const TEST_INFO1 Test_OpenMpqs[] = {_T("MPQ_2022_v1_OcOc_Bound_2.scx"), NULL, "25cad16a2fb4e883767a1f512fc1dce7", 16},
{_T("MPQ_2023_v1_Lusin2Rpg1.28.w3x"), NULL, "9c21352f06cf763fcf05e8a2691e6194", 10305, &HashVals},
{_T("MPQ_2024_v1_300TK2.09p.w3x"), NULL, "e442e3d2e7d457b9ba544544013b791f", 32588}, // Fake MPQ User data, fake MPQ header at offset 0x200
+ {_T("MPQ_2025_v1_Legion_TD_11_2d-BETA_2_TeamOZE.w3x"), NULL, "08efaaa11cafe5e8921a6f112b2fa458", 626}, // Fake MPQ User data, fake MPQ header at offset 0x200
// ASI plugins
- {_T("MPQ_2020_v1_HS0.1.asi"), NULL, "50cba7460a6e6d270804fb9776a7ec4f", 6022},
- {_T("MPQ_2022_v1_hs0.8.asi"), NULL, "6a40f733428001805bfe6e107ca9aec1", 11352}, // Items in hash table have platform = 0xFF
- {_T("MPQ_2022_v1_MoeMoeMod.asi"), NULL, "89b923c7cde06de48815844a5bbb0ec4", 2578},
+ {_T("mix-mpq/AHF04patch.mix"), NULL, "d3c6aac48bc12813ef5ce4ad113e58bf", 2891}, // MIX file
+ {_T("mix-mpq/hs0.1.asi"), NULL, "50cba7460a6e6d270804fb9776a7ec4f", 6022},
+ {_T("mix-mpq/hs0.8.asi"), NULL, "6a40f733428001805bfe6e107ca9aec1", 11352}, // Items in hash table have platform = 0xFF
+ {_T("mix-mpq/MoeMoeMod.asi"), NULL, "89b923c7cde06de48815844a5bbb0ec4", 2578},
// MPQ modifications from Chinese games
{_T("MPx_2013_v1_LongwuOnline.mpk"), NULL, "548f7db88284097f7e94c95a08c5bc24", 469}, // MPK archive from Longwu online
@@ -4244,11 +4353,14 @@ static const TEST_INFO1 Test_OpenMpqs[] = // Signed archives
{_T("MPQ_1997_v1_Diablo1_STANDARD.SNP"), szSigned1, "5ef18ef9a26b5704d8d46a344d976c89", 2 | TFLG_SIGCHECK_BEFORE},
- {_T("MPQ_1999_v1_WeakSignature.exe"), szSigned2, "c1084033d0bd5f7e2b9b78b600c0bba8", 24 | TFLG_SIGCHECK_BEFORE},
- {_T("MPQ_2003_v1_WeakSignatureEmpty.exe"), szSigned3, "97580f9f6d98ffc50191c2f07773e818", 12259 | TFLG_SIGCHECK_BEFORE},
+ {_T("MPQ_1998_v1_StarDat.mpq"), szSigned2, "2530cb937565fd41b1dc0443697096a2", 2925 | TFLG_SIGN_ARCHIVE | TFLG_SIGCHECK_AFTER},
+ {_T("MPQ_1999_v1_WeakSignature.exe"), szSigned3, "c1084033d0bd5f7e2b9b78b600c0bba8", 24 | TFLG_SIGCHECK_BEFORE},
+ {_T("MPQ_1999_v1_WeakSignature.exe"), szSigned3, "807fe2e4d38eccf5ee6bc88f5ee5940d", 25 | TFLG_SIGCHECK_BEFORE | TFLG_MODIFY | TFLG_SIGCHECK_AFTER},
{_T("MPQ_2002_v1_StrongSignature.w3m"), szSigned4, "7b725d87e07a2173c42fe2314b95fa6c", 17 | TFLG_SIGCHECK_BEFORE},
- {_T("MPQ_1998_v1_StarDat.mpq"), _T("MPQ_1998_v1_StarDat.mpq"), "2530cb937565fd41b1dc0443697096a2", 2925 | TFLG_SIGN_ARCHIVE | TFLG_SIGCHECK_AFTER},
- {_T("MPQ_1999_v1_WeakSignature.exe"), szSigned2, "807fe2e4d38eccf5ee6bc88f5ee5940d", 25 | TFLG_SIGCHECK_BEFORE | TFLG_MODIFY | TFLG_SIGCHECK_AFTER},
+ {_T("MPQ_2003_v1_WeakSignatureEmpty.exe"), szSigned5, "1e24a80dafa5285a0aee9470263e5b7c", 12259 | TFLG_SIGCHECK_BEFORE},
+ {_T("MPQ_2006_v1_WoW-1.11.2.5464-patch.exe_"), szSigned6, "6d1ccbfc344b6a2bc4ddf14867e45fea", 952 | TFLG_SIGCHECK_BEFORE},
+ {_T("MPQ_2007_v2_StrongSignature1.exe"), szSigned7, "c553320a2f841ccb86c0643f58d8488a", 23 | TFLG_SIGCHECK_BEFORE},
+ {_T("MPQ_2007_v2_StrongSignature2.MPQ"), szSigned8, "53cedaf7ba8c67b2e2ca95d5eb2b9380", 1622 | TFLG_SIGCHECK_BEFORE},
// Multi-file archive with wrong prefix to see how StormLib deals with it
{_T("flat-file://streaming/model.MPQ.0"), _T("flat-file://model.MPQ.0"), NULL, 0 | TFLG_WILL_FAIL},
@@ -4482,6 +4594,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/TLogHelper.cpp b/test/TLogHelper.cpp index 6eb97f6..dc8804b 100644 --- a/test/TLogHelper.cpp +++ b/test/TLogHelper.cpp @@ -17,6 +17,7 @@ #endif
#ifdef _MSC_VER
+#define fmt_I64u_w L"%I64u"
#define fmt_I64u_t _T("%I64u")
#define fmt_I64u_a "%I64u"
#define fmt_I64X_t _T("%I64X")
@@ -42,6 +43,58 @@ //-----------------------------------------------------------------------------
// Local functions
+template <typename XCHAR>
+XCHAR * StringEnd(XCHAR * sz)
+{
+ while(sz[0] != 0)
+ sz++;
+ return sz;
+}
+
+// ANSI version of the function - expects UTF-8 encoding
+size_t ConsoleLength(const char * ptr, const char * end)
+{
+ size_t ccBytesEaten;
+ size_t nLength = 0;
+ DWORD dwErrCode;
+
+ while(ptr < end)
+ {
+ DWORD dwCodePoint = 0;
+
+ // Decode a single UTF-8 character
+ dwErrCode = UTF8_DecodeCodePoint((BYTE *)(ptr), (BYTE *)(end), dwCodePoint, ccBytesEaten);
+ if(dwErrCode != ERROR_SUCCESS && dwErrCode != ERROR_NO_UNICODE_TRANSLATION)
+ break;
+
+ // Chinese chars occupy 1 extra char slot on console
+ if(0x5000 <= ptr[0] && ptr[0] <= 0xA000)
+ nLength++;
+ ptr += ccBytesEaten;
+ nLength++;
+ }
+ return nLength;
+}
+
+#ifdef TEST_PLATFORM_WINDOWS
+size_t ConsoleLength(const wchar_t * ptr, const wchar_t * end)
+{
+ size_t nLength = 0;
+
+ while(ptr < end)
+ {
+ DWORD dwCodePoint = ptr[0];
+
+ // Chinese chars occupy more space
+ if(0x5000 <= dwCodePoint && dwCodePoint <= 0xA000)
+ nLength++;
+ ptr += 1;
+ nLength++;
+ }
+ return nLength;
+}
+#endif
+
inline DWORD TestInterlockedIncrement(DWORD * PtrValue)
{
#ifdef TEST_PLATFORM_WINDOWS
@@ -55,35 +108,31 @@ inline DWORD TestInterlockedIncrement(DWORD * PtrValue) inline DWORD Test_GetLastError()
{
-#if defined(CASCLIB_PLATFORM_WINDOWS)
- return GetCascError();
-#else
- return GetLastError();
-#endif
+ return SErrGetLastError();
}
-#ifdef STORMLIB_WINDOWS
+#ifdef TEST_PLATFORM_WINDOWS
wchar_t * CopyFormatCharacter(wchar_t * szBuffer, const wchar_t *& szFormat)
{
- static const wchar_t * szStringFormat = _T("%s");
- static const wchar_t * szUint64Format = fmt_I64u_t;
+ static const wchar_t * szStringFormat = L"%s";
+ static const wchar_t * szUint64Format = fmt_I64u_w;
// String format
if(szFormat[0] == '%')
{
if(szFormat[1] == 's')
{
- _tcscpy(szBuffer, szStringFormat);
+ wcscpy(szBuffer, szStringFormat);
szFormat += 2;
- return szBuffer + _tcslen(szStringFormat);
+ return szBuffer + wcslen(szStringFormat);
}
// Replace %I64u with the proper platform-dependent suffix
if(szFormat[1] == 'I' && szFormat[2] == '6' && szFormat[3] == '4' && szFormat[4] == 'u')
{
- _tcscpy(szBuffer, szUint64Format);
+ wcscpy(szBuffer, szUint64Format);
szFormat += 5;
- return szBuffer + _tcslen(szUint64Format);
+ return szBuffer + wcslen(szUint64Format);
}
}
@@ -91,7 +140,7 @@ wchar_t * CopyFormatCharacter(wchar_t * szBuffer, const wchar_t *& szFormat) *szBuffer++ = *szFormat++;
return szBuffer;
}
-#endif // STORMLIB_WINDOWS
+#endif // TEST_PLATFORM_WINDOWS
char * CopyFormatCharacter(char * szBuffer, const char *& szFormat)
{
@@ -185,9 +234,7 @@ class TLogHelper #ifdef TEST_PLATFORM_WINDOWS
InitializeCriticalSection(&Locker);
TickCount = GetTickCount();
-#endif
-#ifdef STORMLIB_WINDOWS
SetConsoleOutputCP(CP_UTF8); // Set the UTF-8 code page to handle national-specific names
SetConsoleCP(CP_UTF8);
#endif
@@ -281,7 +328,7 @@ class TLogHelper va_start(argList, format);
int nLength = 0;
-#ifdef STORMLIB_WINDOWS
+#ifdef TEST_PLATFORM_WINDOWS
char * szBuffer;
int ccBuffer = 0x1000;
@@ -302,7 +349,7 @@ class TLogHelper return nLength;
}
-#ifdef STORMLIB_WINDOWS
+#ifdef TEST_PLATFORM_WINDOWS
int printf_console(const wchar_t * format, ...)
{
va_list argList;
@@ -329,19 +376,19 @@ class TLogHelper template <typename XCHAR>
DWORD PrintWithClreol(const XCHAR * szFormat, va_list argList, bool bPrintLastError, bool bPrintEndOfLine)
{
- char * szBufferPtr;
- char * szBufferEnd;
- size_t nNewPrinted;
+ XCHAR * szBufferPtr;
+ XCHAR * szBufferEnd;
size_t nLength = 0;
DWORD dwErrCode = Test_GetLastError();
- XCHAR szMessage[0x200];
- char szBuffer[0x200];
+ XCHAR szPercentS[] = {'%', 's', 0};
+ XCHAR szMessage[0x200] = {0};
+ XCHAR szBuffer[0x200] = {0};
bool bPrintPrefix = TEST_PRINT_PREFIX;
// Always start the buffer with '\r'
szBufferEnd = szBuffer + _countof(szBuffer);
- szBufferPtr = szBuffer;
- *szBufferPtr++ = '\r';
+ szBufferPtr = szBuffer + 1;
+ szBuffer[0] = '\r';
// Print the prefix, if needed
if(szMainTitle != NULL && bPrintPrefix)
@@ -356,49 +403,41 @@ class TLogHelper // Construct the message
TestStrPrintfV(szMessage, _countof(szMessage), szFormat, argList);
StringCopy(szBufferPtr, (szBufferEnd - szBufferPtr), szMessage);
- szBufferPtr = szBufferPtr + strlen(szBufferPtr);
+ szBufferPtr = StringEnd(szBufferPtr);
// Append the last error
if(bPrintLastError)
{
- nLength = TestStrPrintf(szBufferPtr, (szBufferEnd - szBufferPtr), " (error code: %u)", dwErrCode);
+ XCHAR szErrMsg[] = {' ', '(', 'e', 'r', 'r', 'o', 'r', ' ', 'c', 'o', 'd', 'e', ':', ' ', '%', 'u', ')', 0, 0};
+ nLength = TestStrPrintf(szBufferPtr, (szBufferEnd - szBufferPtr), szErrMsg, dwErrCode);
szBufferPtr += nLength;
}
- // Remember how much did we print
- nNewPrinted = (szBufferPtr - szBuffer);
-
- // Shall we pad the string?
- if((nLength = (szBufferPtr - szBuffer - 1)) < nPrevPrinted)
- {
- size_t nPadding = nPrevPrinted - nLength;
-
- if((size_t)(nLength + nPadding) > (size_t)(szBufferEnd - szBufferPtr))
- nPadding = (szBufferEnd - szBufferPtr);
+ // Pad the string with zeros, if needed
+ while(szBufferPtr < (szBuffer + nPrevPrinted))
+ *szBufferPtr++ = ' ';
- memset(szBufferPtr, ' ', nPadding);
- szBufferPtr += nPadding;
- }
+ // Remember how much did we print
+ nPrevPrinted = ConsoleLength(szBuffer, szBufferPtr);
- // Shall we add new line?
- if((bPrintEndOfLine != false) && (szBufferPtr < szBufferEnd))
- *szBufferPtr++ = '\n';
+ // Always add one extra space *AFTER* calculating length
+ if(szBufferPtr < szBufferEnd)
+ *szBufferPtr++ = ' ';
*szBufferPtr = 0;
- // Remember if we printed a message
- if(bPrintEndOfLine != false)
+ // Print the message to the console
+ printf_console(szPercentS, szBuffer);
+ nMessageCounter++;
+
+ // If we shall print the newline, do it
+ if(bPrintEndOfLine)
{
bMessagePrinted = true;
nPrevPrinted = 0;
- }
- else
- {
- nPrevPrinted = nNewPrinted;
+ printf("\n");
}
// Finally print the message
- printf_console("%s", szBuffer);
- nMessageCounter++;
return dwErrCode;
}
@@ -618,7 +657,7 @@ class TLogHelper const TCHAR * szSubTitle1; // Title of the text (can be name of the tested file)
const TCHAR * szSubTitle2; // Title of the text (can be name of the tested file)
size_t nMessageCounter;
- size_t nPrevPrinted; // Length of the previously printed message
+ size_t nPrevPrinted;
time_t dwPrevTickCount;
bool bMessagePrinted;
};
diff --git a/test/stormlib-test-001.txt b/test/stormlib-test-001.txt index a1b2449..a87e5ba 100644 --- a/test/stormlib-test-001.txt +++ b/test/stormlib-test-001.txt @@ -28,6 +28,16 @@ TestReadingMpq (pocs/MPQ_2024_09_InvalidSectorSize.mpq) succeeded. TestReadingMpq (pocs/MPQ_2024_10_HuffDecompressError.mpq) succeeded. TestReadingMpq (pocs/MPQ_2024_10_SparseDecompressError.mpq) succeeded. TestReadingMpq (pocs/MPQ_2024_11_HiBlockTablePosInvalid.mpq) succeeded. +TestReadingMpq: Error loading the file (listfile) (error code: 38) +TestReadingMpq (pocs/MPQ_2025_01_SectorTableBeyondEOF.mpq) succeeded. +TestReadingMpq: Warning: CRC32 error on (listfile) +TestReadingMpq: Warning: CRC32 error on (listfile) +TestReadingMpq (pocs/MPQ_2025_02_SectorOffsetSizeNotAligned.mpq) succeeded. +TestReadingMpq (pocs/MPQ_2025_03_InvalidPatchInfo.mpq) succeeded. +TestReadingMpq (pocs/MPQ_2025_04_InvalidArchiveSize64.mpq) succeeded. +TestReadingMpq (pocs/MPQ_2025_05_AddFileError.mpq) succeeded. +TestReadingMpq (pocs/MPQ_2025_06_BadHashTableSize.mpq) succeeded. +TestReadingMpq (pocs/MPQ_2025_07_BadHetTableSize.mpq) succeeded. TestReadingMpq (MPQ_1997_v1_Diablo1_DIABDAT.MPQ) succeeded. TestReadingMpq (MPQ_1997_v1_patch_rt_SC1B.mpq) succeeded. TestReadingMpq (MPQ_1997_v1_StarDat_SC1B.mpq) succeeded. @@ -47,7 +57,6 @@ TestReadingMpq: Warning: CRC32 error on (listfile) TestReadingMpq: Warning: CRC32 error on (listfile) TestReadingMpq: Warning: CRC32 error on File00000003.xxx TestReadingMpq (MPQ_2014_v1_AttributesOneEntryLess.w3x) succeeded. -TestReadingMpq (MPQ_2020_v1_AHF04patch.mix) succeeded. TestReadingMpq (MPQ_2010_v3_expansion-locale-frFR.MPQ) succeeded. TestReadingMpq (mpqe-file://MPQ_2011_v2_EncryptedMpq.MPQE) succeeded. TestReadingMpq (part-file://MPQ_2010_v2_HashTableCompressed.MPQ.part) succeeded. @@ -93,9 +102,11 @@ TestReadingMpq (MPQ_2022_v1_Sniper.scx) succeeded. TestReadingMpq (MPQ_2022_v1_OcOc_Bound_2.scx) succeeded. TestReadingMpq (MPQ_2023_v1_Lusin2Rpg1.28.w3x) succeeded. TestReadingMpq (MPQ_2024_v1_300TK2.09p.w3x) succeeded. -TestReadingMpq (MPQ_2020_v1_HS0.1.asi) succeeded. -TestReadingMpq (MPQ_2022_v1_hs0.8.asi) succeeded. -TestReadingMpq (MPQ_2022_v1_MoeMoeMod.asi) succeeded. +TestReadingMpq (MPQ_2025_v1_Legion_TD_11_2d-BETA_2_TeamOZE.w3x) succeeded. +TestReadingMpq (mix-mpq/AHF04patch.mix) succeeded. +TestReadingMpq (mix-mpq/hs0.1.asi) succeeded. +TestReadingMpq (mix-mpq/hs0.8.asi) succeeded. +TestReadingMpq (mix-mpq/MoeMoeMod.asi) succeeded. TestReadingMpq (MPx_2013_v1_LongwuOnline.mpk) succeeded. TestReadingMpq (MPx_2013_v1_WarOfTheImmortals.sqp) succeeded. TestReadingMpq (MPx_2022_v1_Music.mpk) succeeded. @@ -114,11 +125,16 @@ TestReadingMpq (MPQ_2013_v4_Mods#Liberty.SC2Mod#enGB.SC2Data) succeeded. TestReadingMpq (MPQ_2014_v4_base-Win.MPQ) succeeded. TestReadingMpq (MPQ_2014_v4_base-Win.MPQ) succeeded. TestReadingMpq (MPQ_1997_v1_Diablo1_STANDARD.SNP) succeeded. -TestReadingMpq (MPQ_1999_v1_WeakSignature.exe) succeeded. -TestReadingMpq (MPQ_2003_v1_WeakSignatureEmpty.exe) succeeded. -TestReadingMpq (MPQ_2002_v1_StrongSignature.w3m) succeeded. TestReadingMpq (MPQ_1998_v1_StarDat.mpq) succeeded. TestReadingMpq (MPQ_1999_v1_WeakSignature.exe) succeeded. +TestReadingMpq (MPQ_1999_v1_WeakSignature.exe) succeeded. +TestReadingMpq (MPQ_2002_v1_StrongSignature.w3m) succeeded. +TestReadingMpq (MPQ_2003_v1_WeakSignatureEmpty.exe) succeeded. +TestReadingMpq: Warning: CRC32 error on (signature) +TestReadingMpq: Warning: CRC32 error on (signature) +TestReadingMpq (MPQ_2006_v1_WoW-1.11.2.5464-patch.exe_) succeeded. +TestReadingMpq (MPQ_2007_v2_StrongSignature1.exe) succeeded. +TestReadingMpq (MPQ_2007_v2_StrongSignature2.MPQ) succeeded. TestReadingMpq (flat-file://streaming/model.MPQ.0) succeeded. TestReadingMpq (MPQ_2013_vX_Battle.net.MPQ) succeeded. TestReadingMpq (MPQ_1997_v1_Diablo1_DIABDAT.MPQ) succeeded. @@ -142,14 +158,15 @@ TestModifyMpq (MPQ_2023_v1_StarcraftMap.scm) succeeded. TestVerifyHash succeeded. CreateNewMpq (StormLibTest_EmptyMpq_v2.mpq) succeeded. CreateNewMpq (StormLibTest_EmptyMpq_v4.mpq) succeeded. -CreateNewMpq (StormLibTest_Český.mpq) succeeded. . -CreateNewMpq (StormLibTest_Русский.mpq) succeeded. ... +CreateNewMpq (StormLibTest_Český.mpq) succeeded. +CreateNewMpq (StormLibTest_Русский.mpq) succeeded. CreateNewMpq (StormLibTest_ελληνικά.mpq) succeeded. -CreateNewMpq (StormLibTest_日本語.mpq) succeeded. .. -CreateNewMpq (StormLibTest_简体中文.mpq) succeeded.... -CreateNewMpq (StormLibTest_الععربية.mpq) succeeded.... +CreateNewMpq (StormLibTest_日本語.mpq) succeeded. +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. |
