aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--PostBuild.bat34
-rw-r--r--StormLib_vs08.vcproj32
-rw-r--r--StormLib_vs19.vcxproj66
-rw-r--r--StormLib_vs19_dll.vcxproj12
-rw-r--r--StormLib_vs19_test.vcxproj12
-rw-r--r--make-msvc.bat28
-rw-r--r--make.bat8
-rw-r--r--src/SBaseCommon.cpp5
-rw-r--r--src/SBaseFileTable.cpp12
-rw-r--r--src/SBaseSubTypes.cpp27
-rw-r--r--src/SFileAddFile.cpp2
-rw-r--r--src/SFileCreateArchive.cpp29
-rw-r--r--src/SFileFindFile.cpp4
-rw-r--r--src/SFileOpenArchive.cpp31
-rw-r--r--src/SFileReadFile.cpp10
-rw-r--r--src/StormCommon.h1
-rw-r--r--src/StormLib.h13
-rw-r--r--test/StormTest.cpp403
-rw-r--r--test/TLogHelper.cpp83
19 files changed, 445 insertions, 367 deletions
diff --git a/PostBuild.bat b/PostBuild.bat
deleted file mode 100644
index c2d2534..0000000
--- a/PostBuild.bat
+++ /dev/null
@@ -1,34 +0,0 @@
-@echo off
-rem Post-build batch for StormLib project
-rem Called as PostBuild.bat $(ProjectName) $(PlatformName) $(ConfigurationName) [vs2008]
-rem Example: PostBuild.bat StormLib_dll x64 Debug vs2008
-
-rem Select build type
-if "%1" == "StormLib_dll" goto PostBuild_DLL
-if "%1" == "StormLib" goto PostBuild_LIB
-goto:eof
-
-:PostBuild_DLL
-
-rem Build steps for the DLL. On 32-bit Release version, increment the build number
-if not "x%2" == "xWin32" goto:eof
-if not "x%3" == "xRelease" goto:eof
-PostBuild.exe .\src\DllMain.rc
-goto:eof
-
-:PostBuild_LIB
-
-rem Set target folders
-if "x%2" == "xWin32" set TARGET_DIR_LEVEL2=lib32
-if "x%2" == "xx64" set TARGET_DIR_LEVEL2=lib64
-if "x%4" == "xvs2008" set TARGET_DIR_LEVEL3=vs2008
-
-rem Check & create target folder structure
-if not exist ..\aaa goto:eof
-if not exist ..\aaa\%TARGET_DIR_LEVEL2% md ..\aaa\%TARGET_DIR_LEVEL2%
-if not exist ..\aaa\%TARGET_DIR_LEVEL2%\%TARGET_DIR_LEVEL3% md ..\aaa\%TARGET_DIR_LEVEL2%\%TARGET_DIR_LEVEL3%
-
-rem Copy include and LIB files to the target folder
-copy /Y .\src\StormLib.h ..\aaa\inc >nul
-copy /Y .\src\StormPort.h ..\aaa\inc >nul
-copy /Y .\bin\%1\%2\%3\StormLib???.lib ..\aaa\%TARGET_DIR_LEVEL2%\%TARGET_DIR_LEVEL3% >nul
diff --git a/StormLib_vs08.vcproj b/StormLib_vs08.vcproj
index 0c02e13..4f59a1b 100644
--- a/StormLib_vs08.vcproj
+++ b/StormLib_vs08.vcproj
@@ -80,7 +80,7 @@
/>
<Tool
Name="VCPostBuildEventTool"
- CommandLine="PostBuild.bat $(ProjectName) $(PlatformName) $(ConfigurationName) vs2008"
+ CommandLine=""
/>
</Configuration>
<Configuration
@@ -145,7 +145,7 @@
/>
<Tool
Name="VCPostBuildEventTool"
- CommandLine="PostBuild.bat $(ProjectName) $(PlatformName) $(ConfigurationName) vs2008"
+ CommandLine=""
/>
</Configuration>
<Configuration
@@ -209,7 +209,7 @@
/>
<Tool
Name="VCPostBuildEventTool"
- CommandLine="PostBuild.bat $(ProjectName) $(PlatformName) $(ConfigurationName) vs2008"
+ CommandLine=""
/>
</Configuration>
<Configuration
@@ -274,7 +274,7 @@
/>
<Tool
Name="VCPostBuildEventTool"
- CommandLine="PostBuild.bat $(ProjectName) $(PlatformName) $(ConfigurationName) vs2008"
+ CommandLine=""
/>
</Configuration>
<Configuration
@@ -336,7 +336,7 @@
/>
<Tool
Name="VCPostBuildEventTool"
- CommandLine="PostBuild.bat $(ProjectName) $(PlatformName) $(ConfigurationName) vs2008"
+ CommandLine=""
/>
</Configuration>
<Configuration
@@ -399,7 +399,7 @@
/>
<Tool
Name="VCPostBuildEventTool"
- CommandLine="PostBuild.bat $(ProjectName) $(PlatformName) $(ConfigurationName) vs2008"
+ CommandLine=""
/>
</Configuration>
<Configuration
@@ -461,7 +461,7 @@
/>
<Tool
Name="VCPostBuildEventTool"
- CommandLine="PostBuild.bat $(ProjectName) $(PlatformName) $(ConfigurationName) vs2008"
+ CommandLine=""
/>
</Configuration>
<Configuration
@@ -524,7 +524,7 @@
/>
<Tool
Name="VCPostBuildEventTool"
- CommandLine="PostBuild.bat $(ProjectName) $(PlatformName) $(ConfigurationName) vs2008"
+ CommandLine=""
/>
</Configuration>
<Configuration
@@ -588,7 +588,7 @@
/>
<Tool
Name="VCPostBuildEventTool"
- CommandLine="PostBuild.bat $(ProjectName) $(PlatformName) $(ConfigurationName) vs2008"
+ CommandLine=""
/>
</Configuration>
<Configuration
@@ -653,7 +653,7 @@
/>
<Tool
Name="VCPostBuildEventTool"
- CommandLine="PostBuild.bat $(ProjectName) $(PlatformName) $(ConfigurationName) vs2008"
+ CommandLine=""
/>
</Configuration>
<Configuration
@@ -717,7 +717,7 @@
/>
<Tool
Name="VCPostBuildEventTool"
- CommandLine="PostBuild.bat $(ProjectName) $(PlatformName) $(ConfigurationName) vs2008"
+ CommandLine=""
/>
</Configuration>
<Configuration
@@ -782,7 +782,7 @@
/>
<Tool
Name="VCPostBuildEventTool"
- CommandLine="PostBuild.bat $(ProjectName) $(PlatformName) $(ConfigurationName) vs2008"
+ CommandLine=""
/>
</Configuration>
<Configuration
@@ -844,7 +844,7 @@
/>
<Tool
Name="VCPostBuildEventTool"
- CommandLine="PostBuild.bat $(ProjectName) $(PlatformName) $(ConfigurationName) vs2008"
+ CommandLine=""
/>
</Configuration>
<Configuration
@@ -907,7 +907,7 @@
/>
<Tool
Name="VCPostBuildEventTool"
- CommandLine="PostBuild.bat $(ProjectName) $(PlatformName) $(ConfigurationName) vs2008"
+ CommandLine=""
/>
</Configuration>
<Configuration
@@ -969,7 +969,7 @@
/>
<Tool
Name="VCPostBuildEventTool"
- CommandLine="PostBuild.bat $(ProjectName) $(PlatformName) $(ConfigurationName) vs2008"
+ CommandLine=""
/>
</Configuration>
<Configuration
@@ -1032,7 +1032,7 @@
/>
<Tool
Name="VCPostBuildEventTool"
- CommandLine="PostBuild.bat $(ProjectName) $(PlatformName) $(ConfigurationName) vs2008"
+ CommandLine=""
/>
</Configuration>
</Configurations>
diff --git a/StormLib_vs19.vcxproj b/StormLib_vs19.vcxproj
index ffcf960..eba3ea2 100644
--- a/StormLib_vs19.vcxproj
+++ b/StormLib_vs19.vcxproj
@@ -73,7 +73,7 @@
<XPDeprecationWarning>false</XPDeprecationWarning>
<WindowsTargetPlatformVersion>10.0.17134.0</WindowsTargetPlatformVersion>
<ConfigurationType>StaticLibrary</ConfigurationType>
- <PlatformToolset>v141</PlatformToolset>
+ <PlatformToolset>v141_xp</PlatformToolset>
<UseOfMfc>false</UseOfMfc>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
@@ -269,12 +269,14 @@
<PrecompiledHeader />
<WarningLevel>Level1</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile>
<Lib>
<OutputFile>./bin/$(ProjectName)/$(Platform)/$(Configuration)/$(TargetName).lib</OutputFile>
</Lib>
<PostBuildEvent>
- <Command>PostBuild.bat $(ProjectName) $(Platform) $(Configuration)</Command>
+ <Command>
+ </Command>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='DebugAD|x64'">
@@ -289,12 +291,14 @@
<PrecompiledHeader />
<WarningLevel>Level1</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile>
<Lib>
<OutputFile>./bin/$(ProjectName)/$(Platform)/$(Configuration)/$(TargetName).lib</OutputFile>
</Lib>
<PostBuildEvent>
- <Command>PostBuild.bat $(ProjectName) $(Platform) $(Configuration)</Command>
+ <Command>
+ </Command>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='DebugAS|Win32'">
@@ -306,12 +310,14 @@
<PrecompiledHeader />
<WarningLevel>Level1</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile>
<Lib>
<OutputFile>./bin/$(ProjectName)/$(Platform)/$(Configuration)/$(TargetName).lib</OutputFile>
</Lib>
<PostBuildEvent>
- <Command>PostBuild.bat $(ProjectName) $(Platform) $(Configuration)</Command>
+ <Command>
+ </Command>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='DebugAS|x64'">
@@ -326,12 +332,14 @@
<PrecompiledHeader />
<WarningLevel>Level1</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile>
<Lib>
<OutputFile>./bin/$(ProjectName)/$(Platform)/$(Configuration)/$(TargetName).lib</OutputFile>
</Lib>
<PostBuildEvent>
- <Command>PostBuild.bat $(ProjectName) $(Platform) $(Configuration)</Command>
+ <Command>
+ </Command>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseAD|Win32'">
@@ -342,12 +350,14 @@
<PrecompiledHeader />
<WarningLevel>Level1</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile>
<Lib>
<OutputFile>./bin/$(ProjectName)/$(Platform)/$(Configuration)/$(TargetName).lib</OutputFile>
</Lib>
<PostBuildEvent>
- <Command>PostBuild.bat $(ProjectName) $(Platform) $(Configuration)</Command>
+ <Command>
+ </Command>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseAD|x64'">
@@ -361,12 +371,14 @@
<PrecompiledHeader />
<WarningLevel>Level1</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile>
<Lib>
<OutputFile>./bin/$(ProjectName)/$(Platform)/$(Configuration)/$(TargetName).lib</OutputFile>
</Lib>
<PostBuildEvent>
- <Command>PostBuild.bat $(ProjectName) $(Platform) $(Configuration)</Command>
+ <Command>
+ </Command>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseAS|Win32'">
@@ -377,12 +389,14 @@
<PrecompiledHeader />
<WarningLevel>Level1</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile>
<Lib>
<OutputFile>./bin/$(ProjectName)/$(Platform)/$(Configuration)/$(TargetName).lib</OutputFile>
</Lib>
<PostBuildEvent>
- <Command>PostBuild.bat $(ProjectName) $(Platform) $(Configuration)</Command>
+ <Command>
+ </Command>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseAS|x64'">
@@ -396,12 +410,14 @@
<PrecompiledHeader />
<WarningLevel>Level1</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile>
<Lib>
<OutputFile>./bin/$(ProjectName)/$(Platform)/$(Configuration)/$(TargetName).lib</OutputFile>
</Lib>
<PostBuildEvent>
- <Command>PostBuild.bat $(ProjectName) $(Platform) $(Configuration)</Command>
+ <Command>
+ </Command>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='DebugUD|Win32'">
@@ -413,12 +429,14 @@
<PrecompiledHeader />
<WarningLevel>Level1</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile>
<Lib>
<OutputFile>./bin/$(ProjectName)/$(Platform)/$(Configuration)/$(TargetName).lib</OutputFile>
</Lib>
<PostBuildEvent>
- <Command>PostBuild.bat $(ProjectName) $(Platform) $(Configuration)</Command>
+ <Command>
+ </Command>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='DebugUD|x64'">
@@ -433,12 +451,14 @@
<PrecompiledHeader />
<WarningLevel>Level1</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile>
<Lib>
<OutputFile>./bin/$(ProjectName)/$(Platform)/$(Configuration)/$(TargetName).lib</OutputFile>
</Lib>
<PostBuildEvent>
- <Command>PostBuild.bat $(ProjectName) $(Platform) $(Configuration)</Command>
+ <Command>
+ </Command>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='DebugUS|Win32'">
@@ -450,12 +470,14 @@
<PrecompiledHeader />
<WarningLevel>Level1</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile>
<Lib>
<OutputFile>./bin/$(ProjectName)/$(Platform)/$(Configuration)/$(TargetName).lib</OutputFile>
</Lib>
<PostBuildEvent>
- <Command>PostBuild.bat $(ProjectName) $(Platform) $(Configuration)</Command>
+ <Command>
+ </Command>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='DebugUS|x64'">
@@ -470,12 +492,14 @@
<PrecompiledHeader />
<WarningLevel>Level1</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile>
<Lib>
<OutputFile>./bin/$(ProjectName)/$(Platform)/$(Configuration)/$(TargetName).lib</OutputFile>
</Lib>
<PostBuildEvent>
- <Command>PostBuild.bat $(ProjectName) $(Platform) $(Configuration)</Command>
+ <Command>
+ </Command>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseUD|Win32'">
@@ -486,12 +510,14 @@
<PrecompiledHeader />
<WarningLevel>Level1</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile>
<Lib>
<OutputFile>./bin/$(ProjectName)/$(Platform)/$(Configuration)/$(TargetName).lib</OutputFile>
</Lib>
<PostBuildEvent>
- <Command>PostBuild.bat $(ProjectName) $(Platform) $(Configuration)</Command>
+ <Command>
+ </Command>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseUD|x64'">
@@ -505,12 +531,14 @@
<PrecompiledHeader />
<WarningLevel>Level1</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile>
<Lib>
<OutputFile>./bin/$(ProjectName)/$(Platform)/$(Configuration)/$(TargetName).lib</OutputFile>
</Lib>
<PostBuildEvent>
- <Command>PostBuild.bat $(ProjectName) $(Platform) $(Configuration)</Command>
+ <Command>
+ </Command>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseUS|Win32'">
@@ -521,12 +549,14 @@
<PrecompiledHeader />
<WarningLevel>Level1</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile>
<Lib>
<OutputFile>./bin/$(ProjectName)/$(Platform)/$(Configuration)/$(TargetName).lib</OutputFile>
</Lib>
<PostBuildEvent>
- <Command>PostBuild.bat $(ProjectName) $(Platform) $(Configuration)</Command>
+ <Command>
+ </Command>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseUS|x64'">
@@ -540,12 +570,14 @@
<PrecompiledHeader />
<WarningLevel>Level1</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile>
<Lib>
<OutputFile>./bin/$(ProjectName)/$(Platform)/$(Configuration)/$(TargetName).lib</OutputFile>
</Lib>
<PostBuildEvent>
- <Command>PostBuild.bat $(ProjectName) $(Platform) $(Configuration)</Command>
+ <Command>
+ </Command>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemGroup>
diff --git a/StormLib_vs19_dll.vcxproj b/StormLib_vs19_dll.vcxproj
index 712b427..ba888e9 100644
--- a/StormLib_vs19_dll.vcxproj
+++ b/StormLib_vs19_dll.vcxproj
@@ -28,24 +28,24 @@
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
- <PlatformToolset>v141</PlatformToolset>
+ <PlatformToolset>v141_xp</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
- <PlatformToolset>v141</PlatformToolset>
+ <PlatformToolset>v141_xp</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
- <PlatformToolset>v141</PlatformToolset>
+ <PlatformToolset>v141_xp</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
- <PlatformToolset>v141</PlatformToolset>
+ <PlatformToolset>v141_xp</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
@@ -100,6 +100,7 @@
<PrecompiledHeader />
<WarningLevel>Level1</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile>
<Link>
<OutputFile>$(OutDir)StormLib.dll</OutputFile>
@@ -123,6 +124,7 @@
<PrecompiledHeader />
<WarningLevel>Level1</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile>
<Link>
<OutputFile>$(OutDir)StormLib.dll</OutputFile>
@@ -141,6 +143,7 @@
<PrecompiledHeader />
<WarningLevel>Level1</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile>
<Link>
<OutputFile>$(OutDir)StormLib.dll</OutputFile>
@@ -164,6 +167,7 @@
<PrecompiledHeader />
<WarningLevel>Level1</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile>
<Link>
<OutputFile>$(OutDir)StormLib.dll</OutputFile>
diff --git a/StormLib_vs19_test.vcxproj b/StormLib_vs19_test.vcxproj
index 3bd8248..d293549 100644
--- a/StormLib_vs19_test.vcxproj
+++ b/StormLib_vs19_test.vcxproj
@@ -28,24 +28,24 @@
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
- <PlatformToolset>v141</PlatformToolset>
+ <PlatformToolset>v141_xp</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
- <PlatformToolset>v141</PlatformToolset>
+ <PlatformToolset>v141_xp</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
- <PlatformToolset>v141</PlatformToolset>
+ <PlatformToolset>v141_xp</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
- <PlatformToolset>v141</PlatformToolset>
+ <PlatformToolset>v141_xp</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
@@ -98,6 +98,7 @@
<WarningLevel>Level1</WarningLevel>
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
<CompileAs>Default</CompileAs>
+ <MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
@@ -121,6 +122,7 @@
<WarningLevel>Level1</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<CompileAs>Default</CompileAs>
+ <MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
@@ -138,6 +140,7 @@
<PrecompiledHeader />
<WarningLevel>Level1</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
@@ -160,6 +163,7 @@
<PrecompiledHeader />
<WarningLevel>Level1</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
diff --git a/make-msvc.bat b/make-msvc.bat
index 9a2ea8e..099fc19 100644
--- a/make-msvc.bat
+++ b/make-msvc.bat
@@ -21,8 +21,8 @@ if exist "%PROGRAM_FILES_DIR%\Microsoft Visual Studio\2019\Professional\VC\Auxil
if exist "%PROGRAM_FILES_DIR%\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" set VCVARS_2019=%PROGRAM_FILES_DIR%\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvarsall.bat
::Build all libraries using Visual Studio 2008 and 2017
-call :BuildLibs "%VCVARS_2008%" x86 %LIB_NAME%_vs08.sln
-call :BuildLibs "%VCVARS_2008%" x64 %LIB_NAME%_vs08.sln
+call :BuildLibs "%VCVARS_2008%" x86 %LIB_NAME%_vs08.sln \vs2008
+call :BuildLibs "%VCVARS_2008%" x64 %LIB_NAME%_vs08.sln \vs2008
call :BuildLibs "%VCVARS_2019%" x86 %LIB_NAME%_vs19.sln
call :BuildLibs "%VCVARS_2019%" x64 %LIB_NAME%_vs19.sln
goto:eof
@@ -35,21 +35,42 @@ goto:eof
:: %1 Full path to the VCVARS.BAT file
:: %2 Target build platform (x86 or x64)
:: %3 Plain name of the /sln solution file
+:: %4 Subdirectory for the target folder of the library ("\vs2008" or "")
::
:BuildLibs
-::set VSCMD_DEBUG=1
call %1 %2
if "%2" == "x86" set SLN_TRG=Win32
+if "%2" == "x86" set LIB_TRG=lib32
if "%2" == "x64" set SLN_TRG=x64
+if "%2" == "x64" set LIB_TRG=lib64
+
+xcopy.exe /Y /D .\src\StormLib.h ..\aaa\inc
+xcopy.exe /Y /D .\src\StormPort.h ..\aaa\inc
+
devenv.com %3 /project "%LIB_NAME%" /rebuild "DebugAD|%SLN_TRG%"
+xcopy.exe /Y /D .\bin\StormLib\%SLN_TRG%\DebugAD\*.lib ..\aaa\%LIB_TRG%%4
+
devenv.com %3 /project "%LIB_NAME%" /rebuild "DebugAS|%SLN_TRG%"
+xcopy.exe /Y /D .\bin\StormLib\%SLN_TRG%\DebugAS\*.lib ..\aaa\%LIB_TRG%%4
+
devenv.com %3 /project "%LIB_NAME%" /rebuild "DebugUD|%SLN_TRG%"
+xcopy.exe /Y /D .\bin\StormLib\%SLN_TRG%\DebugUD\*.lib ..\aaa\%LIB_TRG%%4
+
devenv.com %3 /project "%LIB_NAME%" /rebuild "DebugUS|%SLN_TRG%"
+xcopy.exe /Y /D .\bin\StormLib\%SLN_TRG%\DebugUS\*.lib ..\aaa\%LIB_TRG%%4
+
devenv.com %3 /project "%LIB_NAME%" /rebuild "ReleaseAD|%SLN_TRG%"
+xcopy.exe /Y /D .\bin\StormLib\%SLN_TRG%\ReleaseAD\*.lib ..\aaa\%LIB_TRG%%4
+
devenv.com %3 /project "%LIB_NAME%" /rebuild "ReleaseAS|%SLN_TRG%"
+xcopy.exe /Y /D .\bin\StormLib\%SLN_TRG%\ReleaseAS\*.lib ..\aaa\%LIB_TRG%%4
+
devenv.com %3 /project "%LIB_NAME%" /rebuild "ReleaseUD|%SLN_TRG%"
+xcopy.exe /Y /D .\bin\StormLib\%SLN_TRG%\ReleaseUD\*.lib ..\aaa\%LIB_TRG%%4
+
devenv.com %3 /project "%LIB_NAME%" /rebuild "ReleaseUS|%SLN_TRG%"
+xcopy.exe /Y /D .\bin\StormLib\%SLN_TRG%\ReleaseUS\*.lib ..\aaa\%LIB_TRG%%4
:: Restore environment variables to the old level
set INCLUDE=%SAVE_INCLUDE%
@@ -58,3 +79,4 @@ set PATH=%SAVE_PATH%
set VSINSTALLDIR=
set VCINSTALLDIR=
set DevEnvDir=
+goto:eof
diff --git a/make.bat b/make.bat
index 8765eb5..7b29207 100644
--- a/make.bat
+++ b/make.bat
@@ -35,10 +35,10 @@ del buildfre_wlh_amd64.log
echo.
:COPY_LIBS
-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 .\src\StormPort.h ..\aaa\inc >nul
-copy /Y .\src\StormLib.h ..\aaa\inc >nul
+xcopy /Y /D .\src\StormLib.h ..\aaa\inc >nul
+xcopy /Y /D .\src\StormPort.h ..\aaa\inc >nul
+xcopy /Y /D .\objfre_w2k_x86\i386\%LIBRARY_NAME%.lib ..\aaa\lib32\%LIBRARY_NAME%.lib >nul
+xcopy /Y /D .\objfre_wlh_amd64\amd64\%LIBRARY_NAME%.lib ..\aaa\lib64\%LIBRARY_NAME%.lib >nul
:CLEANUP
if exist sources-cpp.cpp del sources-cpp.cpp
diff --git a/src/SBaseCommon.cpp b/src/SBaseCommon.cpp
index a1aa78e..98d541a 100644
--- a/src/SBaseCommon.cpp
+++ b/src/SBaseCommon.cpp
@@ -1334,11 +1334,12 @@ DWORD AllocateSectorOffsets(TMPQFile * hf, bool bLoadFromFile)
// They are mostly empty on WoW release MPQs, but on MPQs from PTR,
// they contain random non-zero data. Their meaning is unknown.
//
- // These extra values are, however, include in the dwCmpSize in the file
+ // These extra values are, however, included in the dwCmpSize in the file
// table. We cannot ignore them, because compacting archive would fail
//
- if(hf->SectorOffsets[0] > dwSectorOffsLen)
+ // Clear the lower 2 bits in order to make sure that the value is aligned to 4 bytes
+ 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))
diff --git a/src/SBaseFileTable.cpp b/src/SBaseFileTable.cpp
index 7d52f7c..97fa3a2 100644
--- a/src/SBaseFileTable.cpp
+++ b/src/SBaseFileTable.cpp
@@ -893,15 +893,11 @@ static DWORD BuildFileTableFromBlockTable(
TMPQHash * pHash;
LPDWORD DefragmentTable = NULL;
DWORD dwItemCount = 0;
- DWORD dwFlagMask;
// Sanity checks
assert(ha->pFileTable != NULL);
assert(ha->dwFileTableSize >= ha->dwMaxFileCount);
- // MPQs for Warcraft III doesn't know some flags, namely MPQ_FILE_SINGLE_UNIT and MPQ_FILE_PATCH_FILE
- dwFlagMask = (ha->dwFlags & MPQ_FLAG_WAR3_MAP) ? MPQ_FILE_VALID_FLAGS_W3X : MPQ_FILE_VALID_FLAGS;
-
// Defragment the hash table, if needed
if(ha->dwFlags & MPQ_FLAG_HASH_TABLE_CUT)
{
@@ -976,10 +972,12 @@ static DWORD BuildFileTableFromBlockTable(
if(pFileEntry->ByteOffset == 0 && pBlock->dwFSize == 0)
pFileEntry->ByteOffset = ha->pHeader->dwHeaderSize;
+ // Clear file flags that are unknown to this type of map.
+ pFileEntry->dwFlags = pBlock->dwFlags & ha->dwValidFileFlags;
+
// Fill the rest of the file entry
- pFileEntry->dwFileSize = pBlock->dwFSize;
- pFileEntry->dwCmpSize = pBlock->dwCSize;
- pFileEntry->dwFlags = pBlock->dwFlags & dwFlagMask;
+ pFileEntry->dwFileSize = pBlock->dwFSize;
+ pFileEntry->dwCmpSize = pBlock->dwCSize;
}
}
diff --git a/src/SBaseSubTypes.cpp b/src/SBaseSubTypes.cpp
index 6ab4a99..9808ef3 100644
--- a/src/SBaseSubTypes.cpp
+++ b/src/SBaseSubTypes.cpp
@@ -201,6 +201,9 @@ TMPQHash * LoadSqpHashTable(TMPQArchive * ha)
// Ignore free entries
if(pSqpHash->dwBlockIndex != HASH_ENTRY_FREE)
{
+ // Store the hash entry to a temporary variable
+ TSQPHash TempEntry = *pSqpHash;
+
// Check block index against the size of the block table
if(pHeader->dwBlockTableSize <= MPQ_BLOCK_INDEX(pSqpHash) && pSqpHash->dwBlockIndex < HASH_ENTRY_DELETED)
dwErrCode = ERROR_FILE_CORRUPT;
@@ -209,15 +212,13 @@ TMPQHash * LoadSqpHashTable(TMPQArchive * ha)
if(pSqpHash->dwAlwaysZero != 0 && pSqpHash->dwAlwaysZero != HASH_ENTRY_FREE)
dwErrCode = ERROR_FILE_CORRUPT;
- // Store the file name hash
- pMpqHash->dwName1 = pSqpHash->dwName1;
- pMpqHash->dwName2 = pSqpHash->dwName2;
-
- // Store the rest. Note that this must be done last,
- // because block index corresponds to pMpqHash->dwName2
- pMpqHash->dwBlockIndex = MPQ_BLOCK_INDEX(pSqpHash);
+ // Copy the entry to the MPQ hash entry
+ pMpqHash->dwName1 = TempEntry.dwName1;
+ pMpqHash->dwName2 = TempEntry.dwName2;
+ pMpqHash->dwBlockIndex = MPQ_BLOCK_INDEX(&TempEntry);
pMpqHash->Platform = 0;
pMpqHash->lcLocale = 0;
+ pMpqHash->Reserved = 0;
}
}
@@ -241,7 +242,6 @@ TMPQBlock * LoadSqpBlockTable(TMPQArchive * ha)
TSQPBlock * pSqpBlockEnd;
TSQPBlock * pSqpBlock;
TMPQBlock * pMpqBlock;
- DWORD dwFlags;
DWORD dwErrCode = ERROR_SUCCESS;
// Load the hash table
@@ -253,15 +253,18 @@ TMPQBlock * LoadSqpBlockTable(TMPQArchive * ha)
pMpqBlock = (TMPQBlock *)pSqpBlockTable;
for(pSqpBlock = pSqpBlockTable; pSqpBlock < pSqpBlockEnd; pSqpBlock++, pMpqBlock++)
{
+ // Store the block entry to a temporary variable
+ TSQPBlock TempEntry = *pSqpBlock;
+
// Check for valid flags
if(pSqpBlock->dwFlags & ~MPQ_FILE_VALID_FLAGS)
dwErrCode = ERROR_FILE_CORRUPT;
// Convert SQP block table entry to MPQ block table entry
- dwFlags = pSqpBlock->dwFlags;
- pMpqBlock->dwCSize = pSqpBlock->dwCSize;
- pMpqBlock->dwFSize = pSqpBlock->dwFSize;
- pMpqBlock->dwFlags = dwFlags;
+ pMpqBlock->dwFilePos = TempEntry.dwFilePos;
+ pMpqBlock->dwCSize = TempEntry.dwCSize;
+ pMpqBlock->dwFSize = TempEntry.dwFSize;
+ pMpqBlock->dwFlags = TempEntry.dwFlags;
}
// If an error occured, we need to free the hash table
diff --git a/src/SFileAddFile.cpp b/src/SFileAddFile.cpp
index 7b88c12..9c7331b 100644
--- a/src/SFileAddFile.cpp
+++ b/src/SFileAddFile.cpp
@@ -795,7 +795,7 @@ bool WINAPI SFileCreateFile(
if(dwErrCode == ERROR_SUCCESS)
{
// Mask all unsupported flags out
- dwFlags &= (ha->dwFlags & MPQ_FLAG_WAR3_MAP) ? MPQ_FILE_VALID_FLAGS_W3X : MPQ_FILE_VALID_FLAGS;
+ dwFlags &= ha->dwValidFileFlags;
// Check for valid flag combinations
if((dwFlags & (MPQ_FILE_IMPLODE | MPQ_FILE_COMPRESS)) == (MPQ_FILE_IMPLODE | MPQ_FILE_COMPRESS))
diff --git a/src/SFileCreateArchive.cpp b/src/SFileCreateArchive.cpp
index 742b829..4266070 100644
--- a/src/SFileCreateArchive.cpp
+++ b/src/SFileCreateArchive.cpp
@@ -202,20 +202,21 @@ bool WINAPI SFileCreateArchive2(const TCHAR * szMpqName, PSFILE_CREATE_MPQ pCrea
if(dwErrCode == ERROR_SUCCESS)
{
memset(ha, 0, sizeof(TMPQArchive));
- ha->pfnHashString = HashStringSlash;
- ha->pStream = pStream;
- ha->dwSectorSize = pCreateInfo->dwSectorSize;
- ha->UserDataPos = MpqPos;
- ha->MpqPos = MpqPos;
- ha->pHeader = pHeader = (TMPQHeader *)ha->HeaderData;
- ha->dwMaxFileCount = dwHashTableSize;
- ha->dwFileTableSize = 0;
- ha->dwReservedFiles = dwReservedFiles;
- ha->dwFileFlags1 = pCreateInfo->dwFileFlags1;
- ha->dwFileFlags2 = pCreateInfo->dwFileFlags2;
- ha->dwFileFlags3 = pCreateInfo->dwFileFlags3 ? MPQ_FILE_EXISTS : 0;
- ha->dwAttrFlags = pCreateInfo->dwAttrFlags;
- ha->dwFlags = dwMpqFlags | MPQ_FLAG_CHANGED;
+ ha->pfnHashString = HashStringSlash;
+ ha->pStream = pStream;
+ ha->dwSectorSize = pCreateInfo->dwSectorSize;
+ ha->UserDataPos = MpqPos;
+ ha->MpqPos = MpqPos;
+ ha->pHeader = pHeader = (TMPQHeader *)ha->HeaderData;
+ ha->dwMaxFileCount = dwHashTableSize;
+ ha->dwFileTableSize = 0;
+ ha->dwReservedFiles = dwReservedFiles;
+ ha->dwValidFileFlags = (pCreateInfo->dwMpqVersion > 1) ? MPQ_FILE_VALID_FLAGS : MPQ_FILE_VALID_FLAGS_W3X;
+ ha->dwFileFlags1 = pCreateInfo->dwFileFlags1;
+ ha->dwFileFlags2 = pCreateInfo->dwFileFlags2;
+ ha->dwFileFlags3 = pCreateInfo->dwFileFlags3 ? MPQ_FILE_EXISTS : 0;
+ ha->dwAttrFlags = pCreateInfo->dwAttrFlags;
+ ha->dwFlags = dwMpqFlags | MPQ_FLAG_CHANGED;
pStream = NULL;
// Fill the MPQ header
diff --git a/src/SFileFindFile.cpp b/src/SFileFindFile.cpp
index ef8b834..223e194 100644
--- a/src/SFileFindFile.cpp
+++ b/src/SFileFindFile.cpp
@@ -221,7 +221,7 @@ static bool DoMPQSearch_FileEntry(
if((pFileEntry->dwFlags & hs->dwFlagMask) == MPQ_FILE_EXISTS)
{
// Ignore fake files which are not compressed but have size higher than the archive
- if ((pFileEntry->dwFlags & MPQ_FILE_COMPRESS_MASK) == 0 && (pFileEntry->dwFileSize > ha->FileSize))
+ if((pFileEntry->dwFlags & MPQ_FILE_COMPRESS_MASK) == 0 && (pFileEntry->dwFileSize > ha->FileSize))
return false;
// Now we have to check if this file was not enumerated before
@@ -236,8 +236,6 @@ static bool DoMPQSearch_FileEntry(
// Prepare the block index
dwBlockIndex = (DWORD)(pFileEntry - ha->pFileTable);
- if(dwBlockIndex == 569)
- szNameBuff[0] = 'F';
// Get the file name. If it's not known, we will create pseudo-name
szFileName = pFileEntry->szFileName;
diff --git a/src/SFileOpenArchive.cpp b/src/SFileOpenArchive.cpp
index ea29850..52e1a39 100644
--- a/src/SFileOpenArchive.cpp
+++ b/src/SFileOpenArchive.cpp
@@ -35,21 +35,28 @@ static MTYPE CheckMapType(LPCTSTR szFileName, LPBYTE pbHeaderBuffer, size_t cbHe
DWORD DwordValue2 = BSWAP_INT32_UNSIGNED(HeaderInt32[2]);
DWORD DwordValue3 = BSWAP_INT32_UNSIGNED(HeaderInt32[3]);
- // Test for AVI files (Warcraft III cinematics) - 'RIFF', 'AVI ' or 'LIST'
- if(DwordValue0 == 0x46464952 && DwordValue2 == 0x20495641 && DwordValue3 == 0x5453494C)
- return MapTypeAviFile;
-
- // Check for Starcraft II maps
+ // Check maps by extension (Starcraft, Starcraft II). We must do this before
+ // checking actual data, because the "NP_Protect" protector places
+ // fake Warcraft III header into the Starcraft II maps
if((szExtension = _tcsrchr(szFileName, _T('.'))) != NULL)
{
- // The "NP_Protect" protector places fake Warcraft III header
- // into the Starcraft II maps, whilst SC2 maps have no other header but MPQ v4
+ // 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")))
+ {
+ return MapTypeStarcraft;
+ }
}
+ // Test for AVI files (Warcraft III cinematics) - 'RIFF', 'AVI ' or 'LIST'
+ if(DwordValue0 == 0x46464952 && DwordValue2 == 0x20495641 && DwordValue3 == 0x5453494C)
+ return MapTypeAviFile;
+
// Check for Warcraft III maps
if(DwordValue0 == 0x57334D48 && DwordValue1 == 0x00000000)
return MapTypeWarcraft3;
@@ -271,6 +278,7 @@ bool WINAPI SFileOpenArchive(
bool bSearchComplete = false;
memset(ha, 0, sizeof(TMPQArchive));
+ ha->dwValidFileFlags = MPQ_FILE_VALID_FLAGS;
ha->pfnHashString = HashStringSlash;
ha->pStream = pStream;
pStream = NULL;
@@ -288,6 +296,8 @@ bool WINAPI SFileOpenArchive(
// Limit the header searching to about 130 MB of data
if(EndOfSearch > 0x08000000)
EndOfSearch = 0x08000000;
+ if(FileSize < HEADER_SEARCH_BUFFER_SIZE)
+ memset(pbHeaderBuffer, 0, HEADER_SEARCH_BUFFER_SIZE);
// Find the offset of MPQ header within the file
while(bSearchComplete == false && ByteOffset < EndOfSearch)
@@ -438,7 +448,14 @@ bool WINAPI SFileOpenArchive(
// Remember whether whis is a map for Warcraft III
if(MapType == MapTypeWarcraft3)
+ {
+ ha->dwValidFileFlags = MPQ_FILE_VALID_FLAGS_W3X;
ha->dwFlags |= MPQ_FLAG_WAR3_MAP;
+ }
+
+ // If this is starcraft map, set the flag mask
+ if(MapType == MapTypeStarcraft)
+ ha->dwValidFileFlags = MPQ_FILE_VALID_FLAGS_SCX;
// Set the size of file sector
ha->dwSectorSize = (0x200 << ha->pHeader->wSectorSize);
diff --git a/src/SFileReadFile.cpp b/src/SFileReadFile.cpp
index 34edc06..1703748 100644
--- a/src/SFileReadFile.cpp
+++ b/src/SFileReadFile.cpp
@@ -663,7 +663,8 @@ static DWORD ReadMpqFileLocalFile(TMPQFile * hf, void * pvBuffer, DWORD dwFilePo
bool WINAPI SFileReadFile(HANDLE hFile, void * pvBuffer, DWORD dwToRead, LPDWORD pdwRead, LPOVERLAPPED lpOverlapped)
{
- TMPQFile * hf = (TMPQFile *)hFile;
+ TFileEntry * pFileEntry;
+ TMPQFile * hf;
DWORD dwBytesRead = 0; // Number of bytes read
DWORD dwErrCode = ERROR_SUCCESS;
@@ -673,7 +674,7 @@ bool WINAPI SFileReadFile(HANDLE hFile, void * pvBuffer, DWORD dwToRead, LPDWORD
lpOverlapped = lpOverlapped;
// Check valid parameters
- if(!IsValidFileHandle(hFile))
+ if((hf = IsValidFileHandle(hFile)) == NULL)
{
SetLastError(ERROR_INVALID_HANDLE);
return false;
@@ -697,6 +698,7 @@ bool WINAPI SFileReadFile(HANDLE hFile, void * pvBuffer, DWORD dwToRead, LPDWORD
}
// Clear the last used compression
+ pFileEntry = hf->pFileEntry;
hf->dwCompression0 = 0;
// If the file is local file, read the data directly from the stream
@@ -706,7 +708,7 @@ bool WINAPI SFileReadFile(HANDLE hFile, void * pvBuffer, DWORD dwToRead, LPDWORD
}
// If the file is a patch file, we have to read it special way
- else if(hf->hfPatch != NULL && (hf->pFileEntry->dwFlags & MPQ_FILE_PATCH_FILE) == 0)
+ else if(hf->hfPatch != NULL && (pFileEntry->dwFlags & MPQ_FILE_PATCH_FILE) == 0)
{
dwErrCode = ReadMpqFilePatchFile(hf, pvBuffer, hf->dwFilePos, dwToRead, &dwBytesRead);
}
@@ -718,7 +720,7 @@ bool WINAPI SFileReadFile(HANDLE hFile, void * pvBuffer, DWORD dwToRead, LPDWORD
}
// If the file is single unit file, redirect it to read file
- else if(hf->pFileEntry->dwFlags & MPQ_FILE_SINGLE_UNIT)
+ else if(pFileEntry->dwFlags & MPQ_FILE_SINGLE_UNIT)
{
dwErrCode = ReadMpqFileSingleUnit(hf, pvBuffer, hf->dwFilePos, dwToRead, &dwBytesRead);
}
diff --git a/src/StormCommon.h b/src/StormCommon.h
index e9187f9..f452112 100644
--- a/src/StormCommon.h
+++ b/src/StormCommon.h
@@ -81,6 +81,7 @@ typedef enum _MTYPE
MapTypeNotChecked, // The map type was not checked yet
MapTypeNotRecognized, // The file does not seems to be a map
MapTypeAviFile, // The file is actually an AVI file (Warcraft III cinematics)
+ MapTypeStarcraft, // The file is a Starcraft map
MapTypeWarcraft3, // The file is a Warcraft III map
MapTypeStarcraft2 // The file is a Starcraft II map
} MTYPE, *PMTYPE;
diff --git a/src/StormLib.h b/src/StormLib.h
index 0e4c411..1335f0e 100644
--- a/src/StormLib.h
+++ b/src/StormLib.h
@@ -25,7 +25,7 @@
/* hash table */
/* 08.12.03 4.11 DCH Fixed bug in reading file sector larger than 0x1000 */
/* on certain files. */
-/* Fixed bug in AddFile with MPQ_FILE_REPLACE_EXISTING */
+/* Fixed bug in AddFile with MPQ_FILE_REPLACEEXISTING */
/* (Thanx Daniel Chiamarello, dchiamarello@madvawes.com)*/
/* 21.12.03 4.50 Lad Completed port for Mac */
/* Fixed bug in compacting (if fsize is mul of 0x1000) */
@@ -193,7 +193,7 @@ extern "C" {
#define MPQ_FLAG_CHECK_SECTOR_CRC 0x00000020 // Checking sector CRC when reading files
#define MPQ_FLAG_SAVING_TABLES 0x00000040 // If set, we are saving MPQ internal files and MPQ tables
#define MPQ_FLAG_PATCH 0x00000080 // If set, this MPQ is a patch archive
-#define MPQ_FLAG_WAR3_MAP 0x00000100 // If set, this MPQ is a map for Warcraft III
+#define MPQ_FLAG_WAR3_MAP 0x00000100 // If set, this MPQ is a Warcraft III map
#define MPQ_FLAG_LISTFILE_NONE 0x00000200 // Set when no (listfile) was found in InvalidateInternalFiles
#define MPQ_FLAG_LISTFILE_NEW 0x00000400 // Set when (listfile) invalidated by InvalidateInternalFiles
#define MPQ_FLAG_LISTFILE_FORCE 0x00000800 // Save updated listfile on exit
@@ -250,12 +250,18 @@ extern "C" {
MPQ_FILE_SIGNATURE | \
MPQ_FILE_EXISTS)
+#define MPQ_FILE_VALID_FLAGS_SCX (MPQ_FILE_IMPLODE | \
+ MPQ_FILE_COMPRESS | \
+ MPQ_FILE_ENCRYPTED | \
+ MPQ_FILE_FIX_KEY | \
+ MPQ_FILE_EXISTS)
+
// We need to mask out the upper 4 bits of the block table index.
// This is because it gets shifted out when calculating block table offset
// BlockTableOffset = pHash->dwBlockIndex << 0x04
// Malformed MPQ maps may contain block indexes like 0x40000001 or 0xF0000023
#define BLOCK_INDEX_MASK 0x0FFFFFFF
-#define MPQ_BLOCK_INDEX(pHash) (pHash->dwBlockIndex & BLOCK_INDEX_MASK)
+#define MPQ_BLOCK_INDEX(pHash) ((pHash)->dwBlockIndex & BLOCK_INDEX_MASK)
// Compression types for multiple compressions
#define MPQ_COMPRESSION_HUFFMANN 0x01 // Huffmann compression (used on WAVE files only)
@@ -839,6 +845,7 @@ typedef struct _TMPQArchive
DWORD dwFileFlags2; // Flags for (attributes)
DWORD dwFileFlags3; // Flags for (signature)
DWORD dwAttrFlags; // Flags for the (attributes) file, see MPQ_ATTRIBUTE_XXX
+ DWORD dwValidFileFlags; // Valid flags for the current MPQ
DWORD dwFlags; // See MPQ_FLAG_XXXXX
DWORD dwSubType; // See MPQ_SUBTYPE_XXX
diff --git a/test/StormTest.cpp b/test/StormTest.cpp
index 651d8e9..4342e10 100644
--- a/test/StormTest.cpp
+++ b/test/StormTest.cpp
@@ -35,16 +35,18 @@
//------------------------------------------------------------------------------
// Local structures
-#define TEST_FLAG_PROTECTED 0x01000000
-#define TEST_FLAG_FILE_COUNT 0x00FFFFFF
+#define TFLG_COUNT_HASH 0x01000000 // There is file count in the lower 24-bits, then hash
+#define TFLG_WILL_FAIL 0x02000000 // The process is expected to fail
+#define TFLG_COUNT_MASK 0x00FFFFFF // Mask for file count
+#define TEST_DATA(hash, num) (num | TFLG_COUNT_HASH), hash
typedef struct _TEST_INFO
{
LPCTSTR szMpqName1;
LPCTSTR szMpqName2;
DWORD dwFlags;
- LPCSTR szFileName1;
- LPCSTR szFileName2;
+ const void * param1;
+ const void * param2;
} TEST_INFO, *PTEST_INFO;
typedef struct _LINE_INFO
@@ -80,6 +82,8 @@ static const TCHAR szListFileDir[] = { '1', '9', '9', '5', ' ', '-', ' ', 'T', '
// Global for the work MPQ
static LPCTSTR szMpqSubDir = _T("1995 - Test MPQs");
static LPCTSTR szMpqPatchDir = _T("1995 - Test MPQs\\patches");
+static LPCSTR IntToHexChar = "0123456789abcdef";
+
typedef DWORD (*FIND_FILE_CALLBACK)(LPCTSTR szFullPath);
@@ -353,23 +357,27 @@ static bool IsMpqExtension(LPCTSTR szFileName)
return false;
}
-static void BinaryFromString(LPCSTR szBinary, LPBYTE pbBuffer, DWORD cbBuffer)
+// Converts binary array to string.
+// The caller must ensure that the buffer has at least ((cbBinary * 2) + 1) characters
+template <typename xchar>
+xchar * StringFromBinary(LPBYTE pbBinary, size_t cbBinary, xchar * szBuffer)
{
- LPBYTE pbBufferEnd = pbBuffer + cbBuffer;
- char * szTemp;
- char szHexaDigit[4];
+ xchar * szSaveBuffer = szBuffer;
- while(szBinary[0] != 0 && pbBuffer < pbBufferEnd)
+ // Verify the binary pointer
+ if(pbBinary && cbBinary)
{
- // Get the 2-byte chunk
- szHexaDigit[0] = szBinary[0];
- szHexaDigit[1] = szBinary[1];
- szHexaDigit[2] = 0;
-
- // Convert to integer
- *pbBuffer++ = (BYTE)strtoul(szHexaDigit, &szTemp, 16);
- szBinary += 2;
+ // Convert the bytes to string array
+ for(size_t i = 0; i < cbBinary; i++)
+ {
+ *szBuffer++ = IntToHexChar[pbBinary[i] >> 0x04];
+ *szBuffer++ = IntToHexChar[pbBinary[i] & 0x0F];
+ }
}
+
+ // Terminate the string
+ *szBuffer = 0;
+ return szSaveBuffer;
}
static void AddStringBeforeExtension(char * szBuffer, LPCSTR szFileName, LPCSTR szExtraString)
@@ -922,23 +930,23 @@ static DWORD GetFilePatchCount(TLogHelper * pLogger, HANDLE hMpq, LPCSTR szFileN
return nPatchCount;
}
-static DWORD VerifyFilePatchCount(TLogHelper * pLogger, HANDLE hMpq, LPCSTR szFileName, int nExpectedPatchCount)
+static DWORD VerifyFilePatchCount(TLogHelper * pLogger, HANDLE hMpq, LPCSTR szFileName, DWORD dwExpectedPatchCount)
{
- int nPatchCount = 0;
+ DWORD dwPatchCount = 0;
// Retrieve the patch count
pLogger->PrintProgress(_T("Verifying patch count for %s ..."), szFileName);
- nPatchCount = GetFilePatchCount(pLogger, hMpq, szFileName);
+ dwPatchCount = GetFilePatchCount(pLogger, hMpq, szFileName);
// Check if there are any patches at all
- if(nExpectedPatchCount != 0 && nPatchCount == 0)
+ if(dwExpectedPatchCount != 0 && dwPatchCount == 0)
{
pLogger->PrintMessage("There are no patches for %s", szFileName);
return ERROR_FILE_CORRUPT;
}
// Check if the number of patches fits
- if(nPatchCount != nExpectedPatchCount)
+ if(dwPatchCount != dwExpectedPatchCount)
{
pLogger->PrintMessage("Unexpected number of patches for %s", szFileName);
return ERROR_FILE_CORRUPT;
@@ -2452,12 +2460,12 @@ static DWORD TestArchive(
LPCTSTR szPlainName, // Plain name of the MPQ
LPCTSTR szListFile, // Listfile name (NULL if none)
DWORD dwFlags, // Flags
- LPCSTR szFileName1,
- LPCSTR szFileName2)
+ LPCSTR szParam1,
+ LPCSTR szParam2)
{
- TFileData * pFileData1 = NULL;
- TFileData * pFileData2 = NULL;
+ TFileData * FileDataList[2] = {NULL};
TLogHelper Logger("TestMpq", szPlainName);
+ LPCSTR FileNameList[2] = {NULL};
LPCSTR szExpectedMD5 = NULL;
HANDLE hMpq = NULL;
DWORD dwFileCount = 0;
@@ -2467,8 +2475,7 @@ static DWORD TestArchive(
DWORD dwExpectedFileCount = 0;
DWORD dwMpqFlags = 0;
TCHAR szFullName[MAX_PATH];
- BYTE ExpectedMD5[MD5_DIGEST_SIZE];
- BYTE OverallMD5[MD5_DIGEST_SIZE];
+ BYTE ObtainedMD5[MD5_DIGEST_SIZE] = {0};
bool bIgnoreOpedwErrCodes = false;
// If the file is a partial MPQ, don't load all files
@@ -2476,14 +2483,18 @@ static DWORD TestArchive(
dwSearchFlags |= SEARCH_FLAG_LOAD_FILES;
// If the MPQ is a protected MPQ, do different tests
- if(dwFlags & TEST_FLAG_PROTECTED)
+ if(dwFlags & TFLG_COUNT_HASH)
{
- dwExpectedFileCount = (dwFlags & TEST_FLAG_FILE_COUNT);
- if((szExpectedMD5 = szFileName1) != NULL)
+ if((szExpectedMD5 = szParam1) != NULL)
dwSearchFlags |= SEARCH_FLAG_HASH_FILES;
- szFileName2 = szFileName1 = NULL;
+ dwExpectedFileCount = (dwFlags & TFLG_COUNT_MASK);
+ szParam1 = NULL;
}
+ // Put all file names into list
+ FileNameList[0] = szParam1;
+ FileNameList[1] = szParam2;
+
// Copy the archive so we won't fuck up the original one
dwErrCode = OpenExistingArchiveWithCopy(&Logger, szPlainName, NULL, &hMpq);
while(dwErrCode == ERROR_SUCCESS)
@@ -2510,49 +2521,43 @@ static DWORD TestArchive(
if(dwErrCode != ERROR_SUCCESS)
break;
- // If szFileName1 was given, load it and check its CRC
- if(szFileName1 && szFileName1[0])
+ // For every file name given, load it and check its CRC
+ for(size_t i = 0; i < _countof(FileNameList); i++)
{
- // Test setting position
- dwErrCode = TestArchive_SetPos(hMpq, szFileName1);
- if(dwErrCode != ERROR_SUCCESS)
- break;
+ TFileData * pFileData;
+ LPCSTR szFileName = FileNameList[i];
- // Load the entire file 1
- pFileData1 = LoadMpqFile(&Logger, hMpq, szFileName1);
- if(pFileData1 == NULL)
+ if(szFileName && szFileName[0])
{
- dwErrCode = Logger.PrintError("Failed to load the file %s", szFileName1);
- break;
- }
+ // Test setting position
+ dwErrCode = TestArchive_SetPos(hMpq, szFileName);
+ if(dwErrCode != ERROR_SUCCESS)
+ break;
- // Check the CRC of file1, if available
- if(pFileData1->dwCrc32)
- {
- // Compare the CRC32, if available
- dwCrc32 = crc32(0, (Bytef *)pFileData1->FileData, (uInt)pFileData1->dwFileSize);
- if(dwCrc32 != pFileData1->dwCrc32)
- Logger.PrintError("Warning: CRC32 error on %s", szFileName1);
- }
- }
+ // Load the entire file 1
+ FileDataList[i] = pFileData = LoadMpqFile(&Logger, hMpq, szFileName);
+ if(pFileData == NULL)
+ {
+ dwErrCode = Logger.PrintError("Failed to load the file %s", szFileName);
+ break;
+ }
- // If szFileName2 was given, load it
- if(szFileName2 && szFileName2[0])
- {
- // Load the entire file 2
- pFileData2 = LoadMpqFile(&Logger, hMpq, szFileName2);
- if(pFileData2 == NULL)
- {
- dwErrCode = Logger.PrintError("Failed to load the file %s", szFileName2);
- break;
+ // Check the CRC of file1, if available
+ if(pFileData->dwCrc32)
+ {
+ // Compare the CRC32, if available
+ dwCrc32 = crc32(0, (Bytef *)pFileData->FileData, (uInt)pFileData->dwFileSize);
+ if(dwCrc32 != pFileData->dwCrc32)
+ Logger.PrintError("Warning: CRC32 error on %s", szFileName);
+ }
}
}
// If two files were given, compare them
- if(pFileData1 && pFileData2)
+ if(FileDataList[0] && FileDataList[1])
{
// Compare both files
- if(!CompareTwoFiles(&Logger, pFileData1, pFileData2))
+ if(!CompareTwoFiles(&Logger, FileDataList[0], FileDataList[1]))
{
dwErrCode = Logger.PrintError("The file has different size/content of files");
break;
@@ -2560,41 +2565,41 @@ static DWORD TestArchive(
}
// Search the archive
- dwErrCode = SearchArchive(&Logger, hMpq, dwSearchFlags, &dwFileCount, OverallMD5);
+ dwErrCode = SearchArchive(&Logger, hMpq, dwSearchFlags, &dwFileCount, ObtainedMD5);
// Shall we check the file count and overall MD5?
- if(dwExpectedFileCount != 0)
+ if(dwFlags & TFLG_COUNT_HASH)
{
if(dwFileCount != dwExpectedFileCount)
{
- Logger.PrintMessage("File count mismatch(expected: %u, found:%u)", dwExpectedFileCount, dwFileCount);
+ Logger.PrintMessage("File count mismatch(expected: %u, found: %u)", dwExpectedFileCount, dwFileCount);
dwErrCode = ERROR_CAN_NOT_COMPLETE;
- break;
}
}
// Shall we check overall MD5?
if(szExpectedMD5 && szExpectedMD5[0])
{
- BinaryFromString(szExpectedMD5, ExpectedMD5, MD5_DIGEST_SIZE);
- if(memcmp(ExpectedMD5, OverallMD5, MD5_DIGEST_SIZE))
+ char szObtainedMD5[0x40];
+
+ StringFromBinary(ObtainedMD5, MD5_DIGEST_SIZE, szObtainedMD5);
+ if(_stricmp(szObtainedMD5, szExpectedMD5))
{
- Logger.PrintMessage("Extracted files MD5 mismatch");
+ Logger.PrintMessage("Extracted files MD5 mismatch (expected: %s, obtained: %s)", szExpectedMD5, szObtainedMD5);
dwErrCode = ERROR_CAN_NOT_COMPLETE;
- break;
}
}
break;
}
// Common cleanup
- if(pFileData2 != NULL)
- STORM_FREE(pFileData2);
- if(pFileData1 != NULL)
- STORM_FREE(pFileData1);
+ if(FileDataList[1] != NULL)
+ STORM_FREE(FileDataList[1]);
+ if(FileDataList[0] != NULL)
+ STORM_FREE(FileDataList[0]);
if(hMpq != NULL)
SFileCloseArchive(hMpq);
- return dwErrCode;
+ return Logger.PrintVerdict(dwErrCode);
}
// Open an empty archive (found in WoW cache - it's just a header)
@@ -2639,15 +2644,17 @@ static DWORD TestOpenArchive_Corrupt(LPCTSTR szPlainName)
// Opens a patched MPQ archive
-static DWORD TestOpenArchive_Patched(LPCTSTR PatchList[], LPCSTR szPatchedFile, int nExpectedPatchCount, bool bExpectedToFail = false)
+static DWORD TestArchive_Patched(LPCTSTR PatchList[], LPCSTR szPatchedFile, DWORD dwFlags)
{
- TLogHelper Logger("OpenPatchedMpqTest", PatchList[0]);
+ TLogHelper Logger("PatchedMPQ", PatchList[0]);
HANDLE hMpq;
HANDLE hFile;
BYTE Buffer[0x100];
+ DWORD dwExpectedPatchCount = (dwFlags & TFLG_COUNT_MASK);
DWORD dwFileCount = 0;
DWORD BytesRead = 0;
DWORD dwErrCode;
+ bool bExpectedToFail = (dwFlags & TFLG_WILL_FAIL) ? true : false;
// Open a patched MPQ archive
dwErrCode = OpenPatchedArchive(&Logger, &hMpq, PatchList);
@@ -2655,7 +2662,7 @@ static DWORD TestOpenArchive_Patched(LPCTSTR PatchList[], LPCSTR szPatchedFile,
{
// Check patch count
if(szPatchedFile != NULL)
- dwErrCode = VerifyFilePatchCount(&Logger, hMpq, szPatchedFile, nExpectedPatchCount);
+ dwErrCode = VerifyFilePatchCount(&Logger, hMpq, szPatchedFile, dwExpectedPatchCount);
// Try to open and read the file
if(dwErrCode == ERROR_SUCCESS)
@@ -4198,6 +4205,9 @@ static DWORD TestModifyArchive_ReplaceFile(LPCTSTR szMpqPlainName, LPCTSTR szFil
//-----------------------------------------------------------------------------
// Tables
+static LPCTSTR szBliz = _T("ListFile_Blizzard.txt");
+static LPCTSTR szWotI = _T("ListFile_WarOfTheImmortals.txt");
+
static const TEST_INFO TestList_StreamOps[] =
{
{_T("MPQ_2013_v4_alternate-original.MPQ"), NULL, 0},
@@ -4223,54 +4233,69 @@ static const TEST_INFO TestList_MasterMirror[] =
static const TEST_INFO Test_Mpqs[] =
{
-
// Correct or damaged archives
- {_T("MPQ_1997_v1_Diablo1_DIABDAT.MPQ"), NULL, 0, "music\\dintro.wav", "File00000023.xxx"},
- {_T("MPQ_2016_v1_D2XP_IX86_1xx_114a.mpq"), NULL, 0, "waitingroombkgd.dc6"}, // Update MPQ from Diablo II (patch 2016)
- {_T("MPQ_2018_v1_icon_error.w3m"), NULL, 0, "file00000002.blp"},
- {_T("MPQ_1997_v1_Diablo1_STANDARD.SNP"), _T("ListFile_Blizzard.txt")}, // File whose archive's (signature) file has flags = 0x90000000
- {_T("MPQ_2012_v2_EmptyMpq.MPQ") }, // Empty archive (found in WoW cache - it's just a header)
- {_T("MPQ_2013_v4_EmptyMpq.MPQ") }, // Empty archive (created artificially - it's just a header)
- {_T("MPQ_2013_v4_patch-base-16357.MPQ") }, // Empty archive (found in WoW cache - it's just a header)
- {_T("MPQ_2011_v4_InvalidHetEntryCount.MPQ") }, // Empty archive (A buggy MPQ with invalid HET entry count)
- {_T("MPQ_2002_v1_BlockTableCut.MPQ") }, // Truncated archive
- {_T("MPQ_2010_v2_HasUserData.s2ma") }, // MPQ that actually has user data
- {_T("MPQ_2014_v1_AttributesOneEntryLess.w3x") }, // Warcraft III map whose "(attributes)" file has (BlockTableSize-1) entries
- {_T("MPQ_2020_v1_AHF04patch.mix") }, // MIX file
- {_T("MPQ_2010_v3_expansion-locale-frFR.MPQ") }, // MPQ archive v 3.0
- {_T("mpqe-file://MPQ_2011_v2_EncryptedMpq.MPQE") }, // Encrypted archive from Starcraft II installer
- {_T("MPx_2013_v1_LongwuOnline.mpk") }, // MPK archive from Longwu online
- {_T("MPx_2013_v1_WarOfTheImmortals.sqp"), _T("ListFile_WarOfTheImmortals.txt") }, // SQP archive from War of the Immortals
- {_T("part-file://MPQ_2010_v2_HashTableCompressed.MPQ.part") }, // Partial MPQ with compressed hash table
- {_T("blk4-file://streaming/model.MPQ.0")}, // Archive that is merged with multiple files
- {_T("MPQ_2002_v1_ProtectedMap_InvalidUserData.w3x")},
- {_T("MPQ_2002_v1_ProtectedMap_InvalidMpqFormat.w3x")},
- {_T("MPQ_2002_v1_ProtectedMap_Spazzler.w3x")}, // Warcraft III map locked by the Spazzler protector
- {_T("MPQ_2014_v1_ProtectedMap_Spazzler2.w3x")}, // Warcraft III map locked by the Spazzler protector
- {_T("MPQ_2014_v1_ProtectedMap_Spazzler3.w3x")}, // Warcraft III map locked by the Spazzler protector
- {_T("MPQ_2002_v1_ProtectedMap_BOBA.w3m")}, // Warcraft III map locked by the BOBA protector
- {_T("MPQ_2015_v1_ProtectedMap_KangTooJee.w3x")},
- {_T("MPQ_2015_v1_ProtectedMap_Somj2hM16.w3x")},
- {_T("MPQ_2015_v1_ProtectedMap_Spazy.w3x")}, // Warcraft III map locked by Spazy protector
- {_T("MPQ_2015_v1_MessListFile.mpq")},
- {_T("MPQ_2016_v1_ProtectedMap_TableSizeOverflow.w3x")},
- {_T("MPQ_2016_v1_ProtectedMap_HashOffsIsZero.w3x")},
- {_T("MPQ_2016_v1_ProtectedMap_Somj2.w3x")}, // Something like Somj 2.0
- {_T("MPQ_2016_v1_WME4_4.w3x")}, // Protector from China (2016-05-27)
- {_T("MPQ_2016_v1_SP_(4)Adrenaline.w3x")},
- {_T("MPQ_2016_v1_ProtectedMap_1.4.w3x")},
- {_T("MPQ_2016_v1_KoreanFile.w3m")},
- {_T("MPQ_2017_v1_Eden_RPG_S2_2.5J.w3x")}, // Load map protected by PG1.11.973
- {_T("MPQ_2017_v1_BigDummyFiles.w3x")},
- {_T("MPQ_2017_v1_TildeInFileName.mpq")},
- {_T("MPQ_2018_v1_EWIX_v8_7.w3x"), NULL, 0, "BlueCrystal.mdx"},
- {_T("MPQ_2020_v4_FakeMpqHeaders.SC2Mod")}, // Archive that has two fake headers before the real one
- {_T("MPQ_2020_v4_NP_Protect_1.s2ma")}, // SC2 map that is protected by the NP_Protect
- {_T("MPQ_2020_v4_NP_Protect_2.s2ma")}, // SC2 map that is protected by the NP_Protect
+ {_T("MPQ_1997_v1_Diablo1_DIABDAT.MPQ"), NULL, 0, "music\\dintro.wav", "File00000023.xxx"},
+ {_T("MPQ_2016_v1_D2XP_IX86_1xx_114a.mpq"), NULL, TEST_DATA("255d87a62f3c9518f72cf723a1818946", 221), "waitingroombkgd.dc6"}, // Update MPQ from Diablo II (patch 2016)
+ {_T("MPQ_2018_v1_icon_error.w3m"), NULL, TEST_DATA("fcefa25fb50c391e8714f2562d1e10ff", 19), "file00000002.blp"},
+ {_T("MPQ_1997_v1_Diablo1_STANDARD.SNP"), szBliz, TEST_DATA("5ef18ef9a26b5704d8d46a344d976c89", 2)}, // File whose archive's (signature) file has flags = 0x90000000
+ {_T("MPQ_2012_v2_EmptyMpq.MPQ"), NULL, TEST_DATA("00000000000000000000000000000000", 0)}, // Empty archive (found in WoW cache - it's just a header)
+ {_T("MPQ_2013_v4_EmptyMpq.MPQ"), NULL, TEST_DATA("00000000000000000000000000000000", 0)}, // Empty archive (created artificially - it's just a header)
+ {_T("MPQ_2013_v4_patch-base-16357.MPQ"), NULL, TEST_DATA("d41d8cd98f00b204e9800998ecf8427e", 1)}, // Empty archive (found in WoW cache - it's just a header)
+ {_T("MPQ_2011_v4_InvalidHetEntryCount.MPQ"), NULL, TEST_DATA("be4b49ecc3942d1957249f9da0021659", 6)}, // Empty archive (with invalid HET entry count)
+ {_T("MPQ_2002_v1_BlockTableCut.MPQ"), NULL, TEST_DATA("a9499ab74d939303d8cda7c397c36275", 287)}, // Truncated archive
+ {_T("MPQ_2010_v2_HasUserData.s2ma"), NULL, TEST_DATA("feff9e2c86db716b6ff5ffc906181200", 52)}, // MPQ that actually has user data
+ {_T("MPQ_2014_v1_AttributesOneEntryLess.w3x"), NULL, TEST_DATA("90451b7052eb0f1d6f4bf69b2daff7f5", 116)}, // Warcraft III map whose "(attributes)" file has (BlockTableSize-1) entries
+ {_T("MPQ_2020_v1_AHF04patch.mix"), NULL, TEST_DATA("d3c6aac48bc12813ef5ce4ad113e58bf", 2891)}, // MIX file
+ {_T("MPQ_2010_v3_expansion-locale-frFR.MPQ"), NULL, TEST_DATA("0c8fc921466f07421a281a05fad08b01", 53)}, // MPQ archive v 3.0 (the only one I know)
+ {_T("mpqe-file://MPQ_2011_v2_EncryptedMpq.MPQE"), NULL, TEST_DATA("10e4dcdbe95b7ad731c563ec6b71bc16", 82)}, // Encrypted archive from Starcraft II installer
+ {_T("MPx_2013_v1_LongwuOnline.mpk"), NULL, TEST_DATA("548f7db88284097f7e94c95a08c5bc24", 469)}, // MPK archive from Longwu online
+ {_T("MPx_2013_v1_WarOfTheImmortals.sqp"), szWotI, TEST_DATA("a048f37f7c6162a96253d8081722b6d9", 9396)}, // SQP archive from War of the Immortals
+ {_T("part-file://MPQ_2010_v2_HashTableCompressed.MPQ.part"),0, TEST_DATA("d41d8cd98f00b204e9800998ecf8427e", 14263)}, // Partial MPQ with compressed hash table
+ {_T("blk4-file://streaming/model.MPQ.0"), NULL, TEST_DATA("e06b00efb2fc7e7469dd8b3b859ae15d", 39914)}, // Archive that is merged with multiple files
// Protected archives
- {_T("MPQ_2015_v1_flem1.w3x"), NULL, TEST_FLAG_PROTECTED | 20, "1c4c13e627658c473e84d94371e31f37"},
- {_T("MPQ_2002_v1_ProtectedMap_HashTable_FakeValid.w3x"), NULL, TEST_FLAG_PROTECTED | 114, "5250975ed917375fc6540d7be436d4de"},
+ {_T("MPQ_2002_v1_ProtectedMap_InvalidUserData.w3x"), NULL, TEST_DATA("b900364cc134a51ddeca21a13697c3ca", 79)},
+ {_T("MPQ_2002_v1_ProtectedMap_InvalidMpqFormat.w3x"), NULL, TEST_DATA("db67e894da9de618a1cdf86d02d315ff", 117)},
+ {_T("MPQ_2002_v1_ProtectedMap_Spazzler.w3x"), NULL, TEST_DATA("72d7963aa799a7fb4117c55b7beabaf9", 470)}, // Warcraft III map locked by the Spazzler protector
+ {_T("MPQ_2014_v1_ProtectedMap_Spazzler2.w3x"), NULL, TEST_DATA("72d7963aa799a7fb4117c55b7beabaf9", 470)}, // Warcraft III map locked by the Spazzler protector
+ {_T("MPQ_2014_v1_ProtectedMap_Spazzler3.w3x"), NULL, TEST_DATA("e55aad2dd33cf68b372ca8e30dcb78a7", 130)}, // Warcraft III map locked by the Spazzler protector
+ {_T("MPQ_2002_v1_ProtectedMap_BOBA.w3m"), NULL, TEST_DATA("7b725d87e07a2173c42fe2314b95fa6c", 17)}, // Warcraft III map locked by the BOBA protector
+ {_T("MPQ_2015_v1_ProtectedMap_KangTooJee.w3x"), NULL, TEST_DATA("c7ca4d2d0b1e58db5c784f522506c897", 1578)},
+ {_T("MPQ_2015_v1_ProtectedMap_Somj2hM16.w3x"), NULL, TEST_DATA("b411f9a51a6e9a9a509150c8d66ba359", 92)},
+ {_T("MPQ_2015_v1_ProtectedMap_Spazy.w3x"), NULL, TEST_DATA("6e491bd055511435dcb4d9c8baed0516", 4089)}, // Warcraft III map locked by Spazy protector
+ {_T("MPQ_2015_v1_MessListFile.mpq"), NULL, TEST_DATA("15e25d5be124d8ad71519f967997efc2", 8)},
+ {_T("MPQ_2016_v1_ProtectedMap_TableSizeOverflow.w3x"), NULL, TEST_DATA("ad81b43cbd37bbfa27e4bed4c17e6a81", 176)},
+ {_T("MPQ_2016_v1_ProtectedMap_HashOffsIsZero.w3x"), NULL, TEST_DATA("d6e712c275a26dc51f16b3a02f6187df", 228)},
+ {_T("MPQ_2016_v1_ProtectedMap_Somj2.w3x"), NULL, TEST_DATA("457cdbf97a9ca41cfe8ea130dafaa0bb", 21)}, // Something like Somj 2.0
+ {_T("MPQ_2016_v1_WME4_4.w3x"), NULL, TEST_DATA("e85e1c0ccb4465a30ffd07cae3260254", 382)}, // Protector from China (2016-05-27)
+ {_T("MPQ_2016_v1_SP_(4)Adrenaline.w3x"), NULL, TEST_DATA("b6f6d56f4f8aaef04c2c4b1f08881a8b", 16)},
+ {_T("MPQ_2016_v1_ProtectedMap_1.4.w3x"), NULL, TEST_DATA("3c7908b29d3feac9ec952282390a242d", 5027)},
+ {_T("MPQ_2016_v1_KoreanFile.w3m"), NULL, TEST_DATA("805d1f75712472a81c6df27b2a71f946", 18)},
+ {_T("MPQ_2017_v1_Eden_RPG_S2_2.5J.w3x"), NULL, TEST_DATA("7a7f0749b47b5f05a8b63ecba2488a3e", 16300)}, // Protected by PG1.11.973
+ {_T("MPQ_2017_v1_BigDummyFiles.w3x"), NULL, TEST_DATA("f4d2ee9d85d2c4107e0b2d00ff302dd7", 9086)},
+ {_T("MPQ_2017_v1_TildeInFileName.mpq"), NULL, TEST_DATA("f203e3979247a4dbf7f3828695ac810c", 5)},
+ {_T("MPQ_2018_v1_EWIX_v8_7.w3x"), NULL, TEST_DATA("12c0f4e15c7361b7c13acd37a181d83b", 857), "BlueCrystal.mdx"},
+ {_T("MPQ_2020_v4_FakeMpqHeaders.SC2Mod"), NULL, TEST_DATA("f45392f6523250c943990a017c230b41", 24)}, // Archive that has two fake headers before the real one
+ {_T("MPQ_2020_v4_NP_Protect_1.s2ma"), NULL, TEST_DATA("1a1ea40ac1165bcdb4f2e434edfc7636", 21)}, // SC2 map that is protected by the NP_Protect
+ {_T("MPQ_2020_v4_NP_Protect_2.s2ma"), NULL, TEST_DATA("7d1a379da8bd966da1f4fa6e4646049b", 55)}, // SC2 map that is protected by the NP_Protect
+ {_T("MPQ_2015_v1_flem1.w3x"), NULL, TEST_DATA("1c4c13e627658c473e84d94371e31f37", 20)},
+ {_T("MPQ_2002_v1_ProtectedMap_HashTable_FakeValid.w3x"), NULL, TEST_DATA("5250975ed917375fc6540d7be436d4de", 114)},
+ {_T("MPQ_2021_v1_CantExtractCHK.scx"), NULL, TEST_DATA("c9a7ded9f93d883b9419a52bec6087f7", 28)},
+};
+
+static const TEST_INFO Patched_Mpqs[] =
+{
+ {NULL, NULL, 0, PatchList_StarCraft, "music\\terran1.wav"},
+ {NULL, NULL, 2, PatchList_WoW_OldWorld13286, "OldWorld\\World\\Model.blob"},
+ {NULL, NULL, 8, PatchList_WoW_15050, "World\\Model.blob"},
+ {NULL, NULL, 0, PatchList_WoW_16965, "DBFilesClient\\BattlePetNPCTeamMember.db2"},
+ {NULL, NULL, 6, PatchList_SC2_32283, "TriggerLibs\\natives.galaxy"},
+ {NULL, NULL, 2, PatchList_SC2_34644, "TriggerLibs\\GameData\\GameData.galaxy"},
+ {NULL, NULL, 3, PatchList_SC2_34644_Maps, "Maps\\Campaign\\THorner03.SC2Map\\BankList.xml"},
+ {NULL, NULL, TFLG_WILL_FAIL, PatchList_SC2_32283_enGB, "Assets\\Textures\\startupimage.dds"},
+ {NULL, NULL, 6, PatchList_SC2_36281_enGB, "LocalizedData\\GameHotkeys.txt"},
+ {NULL, NULL, 1, PatchList_HS_3604_enGB, "Hearthstone.exe"},
+ {NULL, NULL, 10, PatchList_HS_6898_enGB, "Hearthstone_Data\\Managed\\Assembly-Csharp.dll"}
};
//-----------------------------------------------------------------------------
@@ -4291,77 +4316,97 @@ int _tmain(int argc, TCHAR * argv[])
//
// Tests on a local listfile
//
- /*
+
if(dwErrCode == ERROR_SUCCESS)
{
TestOnLocalListFile(_T("FLAT-MAP:ListFile_Blizzard.txt"));
dwErrCode = TestOnLocalListFile(_T("ListFile_Blizzard.txt"));
}
- */
+
//
// Open all files from the command line
//
- TestArchive(_T("ProblemMpqArchive.SC2Replay"), NULL, 0, "replay.game.events", NULL);
for(int i = 1; i < argc; i++)
{
- TestOpenArchive_CompactArchive(argv[i], _T("TestArchiveCopy.mpq"), false);
+ TestArchive(_T("MPQ_2021_v1_CantExtractCHK.scx"), _T("Listfile_Blizzard.txt"), 0, NULL, NULL);
}
//
// Search all testing archives and verify their SHA1 hash
//
- if(dwErrCode == ERROR_SUCCESS)
- {
- dwErrCode = FindFiles(ForEachFile_VerifyFileChecksum, szMpqSubDir);
- }
+ //if(dwErrCode == ERROR_SUCCESS)
+ //{
+ // dwErrCode = FindFiles(ForEachFile_VerifyFileChecksum, szMpqSubDir);
+ //}
//
// Test file stream operations
//
- if(dwErrCode == ERROR_SUCCESS)
- {
- for(size_t i = 0; i < _countof(TestList_StreamOps); i++)
- {
- dwErrCode = TestFileStreamOperations(TestList_StreamOps[i].szMpqName1, TestList_StreamOps[i].dwFlags);
- if(dwErrCode != ERROR_SUCCESS)
- break;
- }
- }
+ //if(dwErrCode == ERROR_SUCCESS)
+ //{
+ // for(size_t i = 0; i < _countof(TestList_StreamOps); i++)
+ // {
+ // dwErrCode = TestFileStreamOperations(TestList_StreamOps[i].szMpqName1, TestList_StreamOps[i].dwFlags);
+ // if(dwErrCode != ERROR_SUCCESS)
+ // break;
+ // }
+ //}
//
// Test master-mirror reading operations
//
+ //if(dwErrCode == ERROR_SUCCESS)
+ //{
+ // for(size_t i = 0; i < _countof(TestList_MasterMirror); i++)
+ // {
+ // dwErrCode = TestReadFile_MasterMirror(TestList_MasterMirror[i].szMpqName1,
+ // TestList_MasterMirror[i].szMpqName2,
+ // TestList_MasterMirror[i].dwFlags != 0);
+ // if(dwErrCode != ERROR_SUCCESS)
+ // break;
+ // }
+ //}
+
+ //
+ // Test opening various archives - correct, damaged, protected
+ //
+
if(dwErrCode == ERROR_SUCCESS)
{
- for(size_t i = 0; i < _countof(TestList_MasterMirror); i++)
+ for(size_t i = 0; i < _countof(Test_Mpqs); i++)
{
- dwErrCode = TestReadFile_MasterMirror(TestList_MasterMirror[i].szMpqName1,
- TestList_MasterMirror[i].szMpqName2,
- TestList_MasterMirror[i].dwFlags != 0);
- if(dwErrCode != ERROR_SUCCESS)
- break;
+ dwErrCode = TestArchive(Test_Mpqs[i].szMpqName1, // Plain archive name
+ Test_Mpqs[i].szMpqName2, // List file (NULL if none)
+ Test_Mpqs[i].dwFlags, // What exactly to do
+ (LPCSTR)Test_Mpqs[i].param1, // The 1st parameter
+ (LPCSTR)Test_Mpqs[i].param2); // The 2nd parameter
+// if(dwErrCode != ERROR_SUCCESS)
+// break;
+ dwErrCode = ERROR_SUCCESS;
}
}
//
- // Test opening various archives - correct, damaged, protected
+ // Test opening patched archives - correct, damaged, protected
//
if(dwErrCode == ERROR_SUCCESS)
{
- for(size_t i = 0; i < _countof(Test_Mpqs); i++)
+ for(size_t i = 0; i < _countof(Patched_Mpqs); i++)
{
- dwErrCode = TestArchive(Test_Mpqs[i].szMpqName1, // Plain archive name
- Test_Mpqs[i].szMpqName2, // List file (NULL if none)
- Test_Mpqs[i].dwFlags, // What exactly to do
- Test_Mpqs[i].szFileName1, // The first name of the open file
- Test_Mpqs[i].szFileName2); // The second name of the open file
- if(dwErrCode != ERROR_SUCCESS)
- break;
+ LPCTSTR * PatchList = (LPCTSTR *)Patched_Mpqs[i].param1;
+ LPCSTR szFileName = (LPCSTR)Patched_Mpqs[i].param2;
+
+ dwErrCode = TestArchive_Patched(PatchList, // List of patches
+ szFileName, // Name of a file
+ Patched_Mpqs[i].dwFlags);
+// if(dwErrCode != ERROR_SUCCESS)
+// break;
+ dwErrCode = ERROR_SUCCESS;
}
}
@@ -4377,50 +4422,6 @@ int _tmain(int argc, TCHAR * argv[])
if(dwErrCode == ERROR_SUCCESS)
dwErrCode = TestOpenArchive_Corrupt(_T("MPQ_2013_vX_Battle.net.MPQ"));
- // Open a patched archive
- if(dwErrCode == ERROR_SUCCESS)
- dwErrCode = TestOpenArchive_Patched(PatchList_StarCraft, "music\\terran1.wav", 0);
-
- // Open a patched archive
- if(dwErrCode == ERROR_SUCCESS)
- dwErrCode = TestOpenArchive_Patched(PatchList_WoW_OldWorld13286, "OldWorld\\World\\Model.blob", 2);
-
- // Open a patched archive
- if(dwErrCode == ERROR_SUCCESS)
- dwErrCode = TestOpenArchive_Patched(PatchList_WoW_15050, "World\\Model.blob", 8);
-
- // Open a patched archive
- if(dwErrCode == ERROR_SUCCESS)
- dwErrCode = TestOpenArchive_Patched(PatchList_WoW_16965, "DBFilesClient\\BattlePetNPCTeamMember.db2", 0);
-
- // Open a patched archive
- if(dwErrCode == ERROR_SUCCESS)
- dwErrCode = TestOpenArchive_Patched(PatchList_SC2_32283, "TriggerLibs\\natives.galaxy", 6);
-
- // Open a patched archive
- if(dwErrCode == ERROR_SUCCESS)
- dwErrCode = TestOpenArchive_Patched(PatchList_SC2_34644, "TriggerLibs\\GameData\\GameData.galaxy", 2);
-
- // Open a patched archive with new format of BSDIFF patch
- if(dwErrCode == ERROR_SUCCESS)
- dwErrCode = TestOpenArchive_Patched(PatchList_SC2_34644_Maps, "Maps\\Campaign\\THorner03.SC2Map\\BankList.xml", 3);
-
- // Open a patched archive
- if(dwErrCode == ERROR_SUCCESS)
- dwErrCode = TestOpenArchive_Patched(PatchList_SC2_32283_enGB, "Assets\\Textures\\startupimage.dds", 0, true);
-
- // Open a patched archive where the "StreamingBuckets.txt" in the patch doesn't contain MPQ_FILE_PATCH_FILE
- if(dwErrCode == ERROR_SUCCESS)
- dwErrCode = TestOpenArchive_Patched(PatchList_SC2_36281_enGB, "LocalizedData\\GameHotkeys.txt", 6);
-
- // Open a patched archive
- if(dwErrCode == ERROR_SUCCESS)
- dwErrCode = TestOpenArchive_Patched(PatchList_HS_3604_enGB, "Hearthstone.exe", 1);
-
- // Open a patched archive
- if(dwErrCode == ERROR_SUCCESS)
- dwErrCode = TestOpenArchive_Patched(PatchList_HS_6898_enGB, "Hearthstone_Data\\Managed\\Assembly-Csharp.dll", 10);
-
// Check the opening archive for read-only
if(dwErrCode == ERROR_SUCCESS)
dwErrCode = TestOpenArchive_ReadOnly(_T("MPQ_1997_v1_Diablo1_DIABDAT.MPQ"), true);
diff --git a/test/TLogHelper.cpp b/test/TLogHelper.cpp
index cd10a3c..3a82368 100644
--- a/test/TLogHelper.cpp
+++ b/test/TLogHelper.cpp
@@ -36,6 +36,9 @@ class TLogHelper
DWORD PrintErrorVa(const char * szFormat, ...);
DWORD PrintError(const char * szFormat, const char * szFileName = NULL);
+ // Print final verdict
+ DWORD PrintVerdict(DWORD dwErrCode = ERROR_SUCCESS);
+
const char * UserString;
unsigned int UserCount;
unsigned int UserTotal;
@@ -108,39 +111,16 @@ TLogHelper::TLogHelper(const char * szNewMainTitle, const TCHAR * szNewSubTitle1
TLogHelper::~TLogHelper()
{
- const TCHAR * szSaveSubTitle1 = szSubTitle1;
- const TCHAR * szSaveSubTitle2 = szSubTitle2;
- TCHAR szSaveMainTitle[0x80];
-
- // Set both to NULL so they won't be printed
- StringCopy(szSaveMainTitle, _countof(szSaveMainTitle), szMainTitle);
- szSubTitle1 = NULL;
- szSubTitle2 = NULL;
- szMainTitle = NULL;
-
- // Print the final information
- if(szSaveMainTitle != NULL && bMessagePrinted == false)
+ // Print a verdict, if no verdict was printed yet
+ if(bMessagePrinted == false)
{
- if(bDontPrintResult == false)
- {
- if(szSaveSubTitle1 != NULL && szSaveSubTitle2 != NULL)
- PrintMessage(_T("%s (%s+%s) succeeded."), szSaveMainTitle, szSaveSubTitle1, szSaveSubTitle2);
- else if(szSaveSubTitle1 != NULL)
- PrintMessage(_T("%s (%s) succeeded."), szSaveMainTitle, szSaveSubTitle1);
- else
- PrintMessage(_T("%s succeeded."), szSaveMainTitle);
- }
- else
- {
- PrintProgress(" ");
- printf("\r");
- }
+ PrintVerdict(ERROR_SUCCESS);
}
#if defined(_MSC_VER) && defined(_DEBUG)
if(_CrtDumpMemoryLeaks())
{
- PrintMessage(_T("Memory leak(s) detected after %s.\n"), szSaveMainTitle);
+ PrintMessage(_T("Memory leak(s) detected.\n"));
}
#endif // _MSC_VER
}
@@ -361,18 +341,59 @@ DWORD TLogHelper::PrintError(const char * szFormat, const char * szFileName)
}
//-----------------------------------------------------------------------------
+// Print final verdict
+
+DWORD TLogHelper::PrintVerdict(DWORD dwErrCode)
+{
+ LPCTSTR szSaveSubTitle1 = szSubTitle1;
+ LPCTSTR szSaveSubTitle2 = szSubTitle2;
+ TCHAR szSaveMainTitle[0x80];
+
+ // Set both to NULL so they won't be printed
+ StringCopy(szSaveMainTitle, _countof(szSaveMainTitle), szMainTitle);
+ szSubTitle1 = NULL;
+ szSubTitle2 = NULL;
+ szMainTitle = NULL;
+
+ // Print the final information
+ if(szSaveMainTitle[0] != 0)
+ {
+ if(bDontPrintResult == false)
+ {
+ LPCTSTR szVerdict = (dwErrCode == ERROR_SUCCESS) ? _T("succeeded") : _T("failed");
+
+ if(szSaveSubTitle1 != NULL && szSaveSubTitle2 != NULL)
+ PrintMessage(_T("%s (%s+%s) %s."), szSaveMainTitle, szSaveSubTitle1, szSaveSubTitle2, szVerdict);
+ else if(szSaveSubTitle1 != NULL)
+ PrintMessage(_T("%s (%s) %s."), szSaveMainTitle, szSaveSubTitle1, szVerdict);
+ else
+ PrintMessage(_T("%s %s."), szSaveMainTitle, szVerdict);
+ }
+ else
+ {
+ PrintProgress(" ");
+ printf("\r");
+ }
+ }
+
+ // Return the error code so the caller can pass it fuhrter
+ return dwErrCode;
+}
+
+//-----------------------------------------------------------------------------
// Protected functions
#ifdef _UNICODE
TCHAR * TLogHelper::CopyFormatCharacter(TCHAR * szBuffer, const TCHAR *& szFormat)
{
- static const TCHAR * szStringFormat = _T("\"%s\"");
- static const TCHAR * szUint64Format = I64u_t;
+// static LPCTSTR szStringFormat = _T("\"%s\"");
+ static LPCTSTR szStringFormat = _T("%s");
+ static LPCTSTR szUint64Format = I64u_t;
// String format
if(szFormat[0] == '%')
{
- if(szFormat[1] == 's' && szFormat[2] != ')')
+ if(szFormat[1] == 's')
{
_tcscpy(szBuffer, szStringFormat);
szFormat += 2;
@@ -402,7 +423,7 @@ char * TLogHelper::CopyFormatCharacter(char * szBuffer, const char *& szFormat)
// String format
if(szFormat[0] == '%')
{
- if(szFormat[1] == 's' && szFormat[2] != ')')
+ if(szFormat[1] == 's')
{
strcpy(szBuffer, szStringFormat);
szFormat += 2;