diff options
author | Brendan Forster <brendan@github.com> | 2015-03-30 09:17:35 +0200 |
---|---|---|
committer | Brendan Forster <brendan@github.com> | 2015-03-30 09:17:35 +0200 |
commit | 1173e0653c966d17dabb3bd7f80ed6c3a9072dd5 (patch) | |
tree | 8de1247eb73505d6512f7c85d4379f4fbc25df0c | |
parent | ccf8b2c173f2c5c11857cb026ee4d6a882a72b29 (diff) | |
download | libgit2-diff-fails-with-cpp-file.tar.gz |
added failing repodiff-fails-with-cpp-file
70 files changed, 3021 insertions, 0 deletions
diff --git a/tests/resources/issue_3020/.cproject b/tests/resources/issue_3020/.cproject new file mode 100644 index 000000000..31be12488 --- /dev/null +++ b/tests/resources/issue_3020/.cproject @@ -0,0 +1,145 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<?fileVersion 4.0.0?><cproject storage_type_id="org.eclipse.cdt.core.XmlProjectDescriptionStorage">
+ <storageModule moduleId="org.eclipse.cdt.core.settings">
+ <cconfiguration id="cdt.managedbuild.config.gnu.mingw.exe.debug.1091074575">
+ <storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="cdt.managedbuild.config.gnu.mingw.exe.debug.1091074575" moduleId="org.eclipse.cdt.core.settings" name="Debug">
+ <externalSettings/>
+ <extensions>
+ <extension id="org.eclipse.cdt.core.PE" point="org.eclipse.cdt.core.BinaryParser"/>
+ <extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+ <extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+ <extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+ </extensions>
+ </storageModule>
+ <storageModule moduleId="cdtBuildSystem" version="4.0.0">
+ <configuration artifactName="${ProjName}" buildArtefactType="org.eclipse.cdt.build.core.buildArtefactType.exe" buildProperties="org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.exe,org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.debug" cleanCommand="rm -rf" description="" id="cdt.managedbuild.config.gnu.mingw.exe.debug.1091074575" name="Debug" parent="cdt.managedbuild.config.gnu.mingw.exe.debug" prebuildStep="windres --language 0x0C09 ../resource.rc -o resource.o">
+ <folderInfo id="cdt.managedbuild.config.gnu.mingw.exe.debug.1091074575." name="/" resourcePath="">
+ <toolChain id="cdt.managedbuild.toolchain.gnu.mingw.exe.debug.1212365933" name="MinGW GCC" superClass="cdt.managedbuild.toolchain.gnu.mingw.exe.debug">
+ <targetPlatform id="cdt.managedbuild.target.gnu.platform.mingw.exe.debug.441467939" name="Debug Platform" superClass="cdt.managedbuild.target.gnu.platform.mingw.exe.debug"/>
+ <builder buildPath="${workspace_loc:/HashCheck}/Debug" id="cdt.managedbuild.tool.gnu.builder.mingw.base.314434993" keepEnvironmentInBuildfile="false" managedBuildOn="true" name="CDT Internal Builder" superClass="cdt.managedbuild.tool.gnu.builder.mingw.base"/>
+ <tool id="cdt.managedbuild.tool.gnu.assembler.mingw.exe.debug.399759892" name="GCC Assembler" superClass="cdt.managedbuild.tool.gnu.assembler.mingw.exe.debug">
+ <inputType id="cdt.managedbuild.tool.gnu.assembler.input.128467239" superClass="cdt.managedbuild.tool.gnu.assembler.input"/>
+ </tool>
+ <tool id="cdt.managedbuild.tool.gnu.archiver.mingw.base.964797068" name="GCC Archiver" superClass="cdt.managedbuild.tool.gnu.archiver.mingw.base"/>
+ <tool id="cdt.managedbuild.tool.gnu.cpp.compiler.mingw.exe.debug.577493578" name="GCC C++ Compiler" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.mingw.exe.debug">
+ <option id="gnu.cpp.compiler.mingw.exe.debug.option.optimization.level.1572524904" name="Optimization Level" superClass="gnu.cpp.compiler.mingw.exe.debug.option.optimization.level" useByScannerDiscovery="false" value="gnu.cpp.compiler.optimization.level.none" valueType="enumerated"/>
+ <option id="gnu.cpp.compiler.mingw.exe.debug.option.debugging.level.1751158473" name="Debug Level" superClass="gnu.cpp.compiler.mingw.exe.debug.option.debugging.level" useByScannerDiscovery="false" value="gnu.cpp.compiler.debugging.level.max" valueType="enumerated"/>
+ <option id="gnu.cpp.compiler.option.dialect.std.261474219" name="Language standard" superClass="gnu.cpp.compiler.option.dialect.std" value="gnu.cpp.compiler.dialect.c++11" valueType="enumerated"/>
+ <option id="gnu.cpp.compiler.option.preprocessor.def.426458244" name="Defined symbols (-D)" superClass="gnu.cpp.compiler.option.preprocessor.def" valueType="definedSymbols">
+ <listOptionValue builtIn="false" value="WINVER=0x0500"/>
+ <listOptionValue builtIn="false" value="UNICODE"/>
+ <listOptionValue builtIn="false" value="_UNICODE"/>
+ </option>
+ <inputType id="cdt.managedbuild.tool.gnu.cpp.compiler.input.999351736" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.input"/>
+ </tool>
+ <tool id="cdt.managedbuild.tool.gnu.c.compiler.mingw.exe.debug.190088868" name="GCC C Compiler" superClass="cdt.managedbuild.tool.gnu.c.compiler.mingw.exe.debug">
+ <option defaultValue="gnu.c.optimization.level.none" id="gnu.c.compiler.mingw.exe.debug.option.optimization.level.2111319354" name="Optimization Level" superClass="gnu.c.compiler.mingw.exe.debug.option.optimization.level" useByScannerDiscovery="false" valueType="enumerated"/>
+ <option id="gnu.c.compiler.mingw.exe.debug.option.debugging.level.1477168937" name="Debug Level" superClass="gnu.c.compiler.mingw.exe.debug.option.debugging.level" useByScannerDiscovery="false" value="gnu.c.debugging.level.max" valueType="enumerated"/>
+ <inputType id="cdt.managedbuild.tool.gnu.c.compiler.input.2145578564" superClass="cdt.managedbuild.tool.gnu.c.compiler.input"/>
+ </tool>
+ <tool id="cdt.managedbuild.tool.gnu.c.linker.mingw.exe.debug.223724342" name="MinGW C Linker" superClass="cdt.managedbuild.tool.gnu.c.linker.mingw.exe.debug"/>
+ <tool id="cdt.managedbuild.tool.gnu.cpp.linker.mingw.exe.debug.778390294" name="MinGW C++ Linker" superClass="cdt.managedbuild.tool.gnu.cpp.linker.mingw.exe.debug">
+ <option id="gnu.cpp.link.option.flags.1379394346" name="Linker flags" superClass="gnu.cpp.link.option.flags" value="-static -mwindows" valueType="string"/>
+ <option id="gnu.cpp.link.option.userobjs.1507009136" name="Other objects" superClass="gnu.cpp.link.option.userobjs" valueType="userObjs">
+ <listOptionValue builtIn="false" value="Debug\resource.o"/>
+ </option>
+ <option id="gnu.cpp.link.option.libs.109316457" name="Libraries (-l)" superClass="gnu.cpp.link.option.libs" valueType="libs">
+ <listOptionValue builtIn="false" value="comctl32"/>
+ <listOptionValue builtIn="false" value="ole32"/>
+ </option>
+ <inputType id="cdt.managedbuild.tool.gnu.cpp.linker.input.1851156384" superClass="cdt.managedbuild.tool.gnu.cpp.linker.input">
+ <additionalInput kind="additionalinputdependency" paths="$(USER_OBJS)"/>
+ <additionalInput kind="additionalinput" paths="$(LIBS)"/>
+ </inputType>
+ </tool>
+ </toolChain>
+ </folderInfo>
+ </configuration>
+ </storageModule>
+ <storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
+ </cconfiguration>
+ <cconfiguration id="cdt.managedbuild.config.gnu.mingw.exe.release.107885674">
+ <storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="cdt.managedbuild.config.gnu.mingw.exe.release.107885674" moduleId="org.eclipse.cdt.core.settings" name="Release">
+ <externalSettings/>
+ <extensions>
+ <extension id="org.eclipse.cdt.core.PE" point="org.eclipse.cdt.core.BinaryParser"/>
+ <extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+ <extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+ <extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+ </extensions>
+ </storageModule>
+ <storageModule moduleId="cdtBuildSystem" version="4.0.0">
+ <configuration artifactName="${ProjName}" buildArtefactType="org.eclipse.cdt.build.core.buildArtefactType.exe" buildProperties="org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.exe,org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.release" cleanCommand="rm -rf" description="" id="cdt.managedbuild.config.gnu.mingw.exe.release.107885674" name="Release" parent="cdt.managedbuild.config.gnu.mingw.exe.release" postbuildStep="../Tools/upx -9 HashCheck.exe" prebuildStep="windres --language 0x0C09 ../resource.rc -o resource.o">
+ <folderInfo id="cdt.managedbuild.config.gnu.mingw.exe.release.107885674." name="/" resourcePath="">
+ <toolChain id="cdt.managedbuild.toolchain.gnu.mingw.exe.release.730226646" name="MinGW GCC" superClass="cdt.managedbuild.toolchain.gnu.mingw.exe.release">
+ <targetPlatform id="cdt.managedbuild.target.gnu.platform.mingw.exe.release.550680648" name="Debug Platform" superClass="cdt.managedbuild.target.gnu.platform.mingw.exe.release"/>
+ <builder buildPath="${workspace_loc:/HashCheck}/Release" id="cdt.managedbuild.tool.gnu.builder.mingw.base.1824334986" keepEnvironmentInBuildfile="false" managedBuildOn="true" name="CDT Internal Builder" superClass="cdt.managedbuild.tool.gnu.builder.mingw.base"/>
+ <tool id="cdt.managedbuild.tool.gnu.assembler.mingw.exe.release.690093994" name="GCC Assembler" superClass="cdt.managedbuild.tool.gnu.assembler.mingw.exe.release">
+ <inputType id="cdt.managedbuild.tool.gnu.assembler.input.1352127665" superClass="cdt.managedbuild.tool.gnu.assembler.input"/>
+ </tool>
+ <tool id="cdt.managedbuild.tool.gnu.archiver.mingw.base.1854173426" name="GCC Archiver" superClass="cdt.managedbuild.tool.gnu.archiver.mingw.base"/>
+ <tool id="cdt.managedbuild.tool.gnu.cpp.compiler.mingw.exe.release.420350693" name="GCC C++ Compiler" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.mingw.exe.release">
+ <option id="gnu.cpp.compiler.mingw.exe.release.option.optimization.level.1631452254" name="Optimization Level" superClass="gnu.cpp.compiler.mingw.exe.release.option.optimization.level" useByScannerDiscovery="false" value="gnu.cpp.compiler.optimization.level.most" valueType="enumerated"/>
+ <option id="gnu.cpp.compiler.mingw.exe.release.option.debugging.level.1439656061" name="Debug Level" superClass="gnu.cpp.compiler.mingw.exe.release.option.debugging.level" useByScannerDiscovery="false" value="gnu.cpp.compiler.debugging.level.none" valueType="enumerated"/>
+ <option id="gnu.cpp.compiler.option.preprocessor.def.404719786" name="Defined symbols (-D)" superClass="gnu.cpp.compiler.option.preprocessor.def" useByScannerDiscovery="false" valueType="definedSymbols">
+ <listOptionValue builtIn="false" value="WINVER=0x0500"/>
+ <listOptionValue builtIn="false" value="UNICODE"/>
+ <listOptionValue builtIn="false" value="_UNICODE"/>
+ </option>
+ <option id="gnu.cpp.compiler.option.dialect.std.1173067960" name="Language standard" superClass="gnu.cpp.compiler.option.dialect.std" useByScannerDiscovery="true" value="gnu.cpp.compiler.dialect.c++11" valueType="enumerated"/>
+ <option id="gnu.cpp.compiler.option.other.other.1902866398" name="Other flags" superClass="gnu.cpp.compiler.option.other.other" useByScannerDiscovery="false" value="-c -fmessage-length=0" valueType="string"/>
+ <inputType id="cdt.managedbuild.tool.gnu.cpp.compiler.input.1293697913" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.input"/>
+ </tool>
+ <tool id="cdt.managedbuild.tool.gnu.c.compiler.mingw.exe.release.685010761" name="GCC C Compiler" superClass="cdt.managedbuild.tool.gnu.c.compiler.mingw.exe.release">
+ <option defaultValue="gnu.c.optimization.level.most" id="gnu.c.compiler.mingw.exe.release.option.optimization.level.61395149" name="Optimization Level" superClass="gnu.c.compiler.mingw.exe.release.option.optimization.level" useByScannerDiscovery="false" valueType="enumerated"/>
+ <option id="gnu.c.compiler.mingw.exe.release.option.debugging.level.953333000" name="Debug Level" superClass="gnu.c.compiler.mingw.exe.release.option.debugging.level" useByScannerDiscovery="false" value="gnu.c.debugging.level.none" valueType="enumerated"/>
+ <inputType id="cdt.managedbuild.tool.gnu.c.compiler.input.998887372" superClass="cdt.managedbuild.tool.gnu.c.compiler.input"/>
+ </tool>
+ <tool id="cdt.managedbuild.tool.gnu.c.linker.mingw.exe.release.221308893" name="MinGW C Linker" superClass="cdt.managedbuild.tool.gnu.c.linker.mingw.exe.release"/>
+ <tool id="cdt.managedbuild.tool.gnu.cpp.linker.mingw.exe.release.1671425636" name="MinGW C++ Linker" superClass="cdt.managedbuild.tool.gnu.cpp.linker.mingw.exe.release">
+ <option id="gnu.cpp.link.option.flags.2092716378" name="Linker flags" superClass="gnu.cpp.link.option.flags" value="-static -mwindows" valueType="string"/>
+ <option id="gnu.cpp.link.option.userobjs.1119100108" name="Other objects" superClass="gnu.cpp.link.option.userobjs" valueType="userObjs">
+ <listOptionValue builtIn="false" value=""Release\resource.o""/>
+ </option>
+ <option id="gnu.cpp.link.option.strip.1903154219" name="Omit all symbol information (-s)" superClass="gnu.cpp.link.option.strip" value="true" valueType="boolean"/>
+ <inputType id="cdt.managedbuild.tool.gnu.cpp.linker.input.206988463" superClass="cdt.managedbuild.tool.gnu.cpp.linker.input">
+ <additionalInput kind="additionalinputdependency" paths="$(USER_OBJS)"/>
+ <additionalInput kind="additionalinput" paths="$(LIBS)"/>
+ </inputType>
+ </tool>
+ </toolChain>
+ </folderInfo>
+ </configuration>
+ </storageModule>
+ <storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
+ </cconfiguration>
+ </storageModule>
+ <storageModule moduleId="cdtBuildSystem" version="4.0.0">
+ <project id="HashCheck.cdt.managedbuild.target.gnu.mingw.exe.1855875242" name="Executable" projectType="cdt.managedbuild.target.gnu.mingw.exe"/>
+ </storageModule>
+ <storageModule moduleId="scannerConfiguration">
+ <autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
+ <scannerConfigBuildInfo instanceId="cdt.managedbuild.config.gnu.mingw.exe.debug.1091074575;cdt.managedbuild.config.gnu.mingw.exe.debug.1091074575.;cdt.managedbuild.tool.gnu.cpp.compiler.mingw.exe.debug.577493578;cdt.managedbuild.tool.gnu.cpp.compiler.input.999351736">
+ <autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
+ </scannerConfigBuildInfo>
+ <scannerConfigBuildInfo instanceId="cdt.managedbuild.config.gnu.mingw.exe.debug.1091074575;cdt.managedbuild.config.gnu.mingw.exe.debug.1091074575.;cdt.managedbuild.tool.gnu.c.compiler.mingw.exe.debug.190088868;cdt.managedbuild.tool.gnu.c.compiler.input.2145578564">
+ <autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
+ </scannerConfigBuildInfo>
+ <scannerConfigBuildInfo instanceId="cdt.managedbuild.config.gnu.mingw.exe.release.107885674;cdt.managedbuild.config.gnu.mingw.exe.release.107885674.;cdt.managedbuild.tool.gnu.cpp.compiler.mingw.exe.release.420350693;cdt.managedbuild.tool.gnu.cpp.compiler.input.1293697913">
+ <autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
+ </scannerConfigBuildInfo>
+ <scannerConfigBuildInfo instanceId="cdt.managedbuild.config.gnu.mingw.exe.release.107885674;cdt.managedbuild.config.gnu.mingw.exe.release.107885674.;cdt.managedbuild.tool.gnu.c.compiler.mingw.exe.release.685010761;cdt.managedbuild.tool.gnu.c.compiler.input.998887372">
+ <autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
+ </scannerConfigBuildInfo>
+ </storageModule>
+ <storageModule moduleId="org.eclipse.cdt.core.LanguageSettingsProviders"/>
+ <storageModule moduleId="refreshScope" versionNumber="2">
+ <configuration configurationName="Debug">
+ <resource resourceType="PROJECT" workspacePath="/HashCheck"/>
+ </configuration>
+ <configuration configurationName="Release">
+ <resource resourceType="PROJECT" workspacePath="/HashCheck"/>
+ </configuration>
+ </storageModule>
+ <storageModule moduleId="org.eclipse.cdt.internal.ui.text.commentOwnerProjectMappings"/>
+</cproject>
diff --git a/tests/resources/issue_3020/.gitignore b/tests/resources/issue_3020/.gitignore new file mode 100644 index 000000000..0bec05e0a --- /dev/null +++ b/tests/resources/issue_3020/.gitignore @@ -0,0 +1,10 @@ +/Release/
+/Debug/
+/Test/
+*.user
+*.suo
+*.sdf
+*.opensdf
+*.aps
+checksum.*
+scratch.txt
diff --git a/tests/resources/issue_3020/.gitted/FETCH_HEAD b/tests/resources/issue_3020/.gitted/FETCH_HEAD new file mode 100644 index 000000000..fad9a6c10 --- /dev/null +++ b/tests/resources/issue_3020/.gitted/FETCH_HEAD @@ -0,0 +1 @@ +77e8039fba38e532bea5fba5f4f3be9940ea521b branch 'master' of https://github.com/macote/HashCheck diff --git a/tests/resources/issue_3020/.gitted/HEAD b/tests/resources/issue_3020/.gitted/HEAD new file mode 100644 index 000000000..cb089cd89 --- /dev/null +++ b/tests/resources/issue_3020/.gitted/HEAD @@ -0,0 +1 @@ +ref: refs/heads/master diff --git a/tests/resources/issue_3020/.gitted/config b/tests/resources/issue_3020/.gitted/config new file mode 100644 index 000000000..5d565d2b1 --- /dev/null +++ b/tests/resources/issue_3020/.gitted/config @@ -0,0 +1,8 @@ +[core] + repositoryformatversion = 0 + filemode = false + bare = false + logallrefupdates = true + symlinks = false + ignorecase = true + hideDotFiles = dotGitOnly
\ No newline at end of file diff --git a/tests/resources/issue_3020/.gitted/description b/tests/resources/issue_3020/.gitted/description new file mode 100644 index 000000000..498b267a8 --- /dev/null +++ b/tests/resources/issue_3020/.gitted/description @@ -0,0 +1 @@ +Unnamed repository; edit this file 'description' to name the repository. diff --git a/tests/resources/issue_3020/.gitted/hooks/applypatch-msg.sample b/tests/resources/issue_3020/.gitted/hooks/applypatch-msg.sample new file mode 100644 index 000000000..8b2a2fe84 --- /dev/null +++ b/tests/resources/issue_3020/.gitted/hooks/applypatch-msg.sample @@ -0,0 +1,15 @@ +#!/bin/sh +# +# An example hook script to check the commit log message taken by +# applypatch from an e-mail message. +# +# The hook should exit with non-zero status after issuing an +# appropriate message if it wants to stop the commit. The hook is +# allowed to edit the commit message file. +# +# To enable this hook, rename this file to "applypatch-msg". + +. git-sh-setup +test -x "$GIT_DIR/hooks/commit-msg" && + exec "$GIT_DIR/hooks/commit-msg" ${1+"$@"} +: diff --git a/tests/resources/issue_3020/.gitted/hooks/commit-msg.sample b/tests/resources/issue_3020/.gitted/hooks/commit-msg.sample new file mode 100644 index 000000000..b58d1184a --- /dev/null +++ b/tests/resources/issue_3020/.gitted/hooks/commit-msg.sample @@ -0,0 +1,24 @@ +#!/bin/sh +# +# An example hook script to check the commit log message. +# Called by "git commit" with one argument, the name of the file +# that has the commit message. The hook should exit with non-zero +# status after issuing an appropriate message if it wants to stop the +# commit. The hook is allowed to edit the commit message file. +# +# To enable this hook, rename this file to "commit-msg". + +# Uncomment the below to add a Signed-off-by line to the message. +# Doing this in a hook is a bad idea in general, but the prepare-commit-msg +# hook is more suited to it. +# +# SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p') +# grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1" + +# This example catches duplicate Signed-off-by lines. + +test "" = "$(grep '^Signed-off-by: ' "$1" | + sort | uniq -c | sed -e '/^[ ]*1[ ]/d')" || { + echo >&2 Duplicate Signed-off-by lines. + exit 1 +} diff --git a/tests/resources/issue_3020/.gitted/hooks/post-update.sample b/tests/resources/issue_3020/.gitted/hooks/post-update.sample new file mode 100644 index 000000000..ec17ec193 --- /dev/null +++ b/tests/resources/issue_3020/.gitted/hooks/post-update.sample @@ -0,0 +1,8 @@ +#!/bin/sh +# +# An example hook script to prepare a packed repository for use over +# dumb transports. +# +# To enable this hook, rename this file to "post-update". + +exec git update-server-info diff --git a/tests/resources/issue_3020/.gitted/hooks/pre-applypatch.sample b/tests/resources/issue_3020/.gitted/hooks/pre-applypatch.sample new file mode 100644 index 000000000..b1f187c2e --- /dev/null +++ b/tests/resources/issue_3020/.gitted/hooks/pre-applypatch.sample @@ -0,0 +1,14 @@ +#!/bin/sh +# +# An example hook script to verify what is about to be committed +# by applypatch from an e-mail message. +# +# The hook should exit with non-zero status after issuing an +# appropriate message if it wants to stop the commit. +# +# To enable this hook, rename this file to "pre-applypatch". + +. git-sh-setup +test -x "$GIT_DIR/hooks/pre-commit" && + exec "$GIT_DIR/hooks/pre-commit" ${1+"$@"} +: diff --git a/tests/resources/issue_3020/.gitted/hooks/pre-commit.sample b/tests/resources/issue_3020/.gitted/hooks/pre-commit.sample new file mode 100644 index 000000000..68d62d544 --- /dev/null +++ b/tests/resources/issue_3020/.gitted/hooks/pre-commit.sample @@ -0,0 +1,49 @@ +#!/bin/sh +# +# An example hook script to verify what is about to be committed. +# Called by "git commit" with no arguments. The hook should +# exit with non-zero status after issuing an appropriate message if +# it wants to stop the commit. +# +# To enable this hook, rename this file to "pre-commit". + +if git rev-parse --verify HEAD >/dev/null 2>&1 +then + against=HEAD +else + # Initial commit: diff against an empty tree object + against=4b825dc642cb6eb9a060e54bf8d69288fbee4904 +fi + +# If you want to allow non-ASCII filenames set this variable to true. +allownonascii=$(git config --bool hooks.allownonascii) + +# Redirect output to stderr. +exec 1>&2 + +# Cross platform projects tend to avoid non-ASCII filenames; prevent +# them from being added to the repository. We exploit the fact that the +# printable range starts at the space character and ends with tilde. +if [ "$allownonascii" != "true" ] && + # Note that the use of brackets around a tr range is ok here, (it's + # even required, for portability to Solaris 10's /usr/bin/tr), since + # the square bracket bytes happen to fall in the designated range. + test $(git diff --cached --name-only --diff-filter=A -z $against | + LC_ALL=C tr -d '[ -~]\0' | wc -c) != 0 +then + cat <<\EOF +Error: Attempt to add a non-ASCII file name. + +This can cause problems if you want to work with people on other platforms. + +To be portable it is advisable to rename the file. + +If you know what you are doing you can disable this check using: + + git config hooks.allownonascii true +EOF + exit 1 +fi + +# If there are whitespace errors, print the offending file names and fail. +exec git diff-index --check --cached $against -- diff --git a/tests/resources/issue_3020/.gitted/hooks/pre-push.sample b/tests/resources/issue_3020/.gitted/hooks/pre-push.sample new file mode 100644 index 000000000..1f3bcebfd --- /dev/null +++ b/tests/resources/issue_3020/.gitted/hooks/pre-push.sample @@ -0,0 +1,54 @@ +#!/bin/sh + +# An example hook script to verify what is about to be pushed. Called by "git +# push" after it has checked the remote status, but before anything has been +# pushed. If this script exits with a non-zero status nothing will be pushed. +# +# This hook is called with the following parameters: +# +# $1 -- Name of the remote to which the push is being done +# $2 -- URL to which the push is being done +# +# If pushing without using a named remote those arguments will be equal. +# +# Information about the commits which are being pushed is supplied as lines to +# the standard input in the form: +# +# <local ref> <local sha1> <remote ref> <remote sha1> +# +# This sample shows how to prevent push of commits where the log message starts +# with "WIP" (work in progress). + +remote="$1" +url="$2" + +z40=0000000000000000000000000000000000000000 + +IFS=' ' +while read local_ref local_sha remote_ref remote_sha +do + if [ "$local_sha" = $z40 ] + then + # Handle delete + : + else + if [ "$remote_sha" = $z40 ] + then + # New branch, examine all commits + range="$local_sha" + else + # Update to existing branch, examine new commits + range="$remote_sha..$local_sha" + fi + + # Check for WIP commit + commit=`git rev-list -n 1 --grep '^WIP' "$range"` + if [ -n "$commit" ] + then + echo "Found WIP commit in $local_ref, not pushing" + exit 1 + fi + fi +done + +exit 0 diff --git a/tests/resources/issue_3020/.gitted/hooks/pre-rebase.sample b/tests/resources/issue_3020/.gitted/hooks/pre-rebase.sample new file mode 100644 index 000000000..9773ed4cb --- /dev/null +++ b/tests/resources/issue_3020/.gitted/hooks/pre-rebase.sample @@ -0,0 +1,169 @@ +#!/bin/sh +# +# Copyright (c) 2006, 2008 Junio C Hamano +# +# The "pre-rebase" hook is run just before "git rebase" starts doing +# its job, and can prevent the command from running by exiting with +# non-zero status. +# +# The hook is called with the following parameters: +# +# $1 -- the upstream the series was forked from. +# $2 -- the branch being rebased (or empty when rebasing the current branch). +# +# This sample shows how to prevent topic branches that are already +# merged to 'next' branch from getting rebased, because allowing it +# would result in rebasing already published history. + +publish=next +basebranch="$1" +if test "$#" = 2 +then + topic="refs/heads/$2" +else + topic=`git symbolic-ref HEAD` || + exit 0 ;# we do not interrupt rebasing detached HEAD +fi + +case "$topic" in +refs/heads/??/*) + ;; +*) + exit 0 ;# we do not interrupt others. + ;; +esac + +# Now we are dealing with a topic branch being rebased +# on top of master. Is it OK to rebase it? + +# Does the topic really exist? +git show-ref -q "$topic" || { + echo >&2 "No such branch $topic" + exit 1 +} + +# Is topic fully merged to master? +not_in_master=`git rev-list --pretty=oneline ^master "$topic"` +if test -z "$not_in_master" +then + echo >&2 "$topic is fully merged to master; better remove it." + exit 1 ;# we could allow it, but there is no point. +fi + +# Is topic ever merged to next? If so you should not be rebasing it. +only_next_1=`git rev-list ^master "^$topic" ${publish} | sort` +only_next_2=`git rev-list ^master ${publish} | sort` +if test "$only_next_1" = "$only_next_2" +then + not_in_topic=`git rev-list "^$topic" master` + if test -z "$not_in_topic" + then + echo >&2 "$topic is already up-to-date with master" + exit 1 ;# we could allow it, but there is no point. + else + exit 0 + fi +else + not_in_next=`git rev-list --pretty=oneline ^${publish} "$topic"` + /usr/bin/perl -e ' + my $topic = $ARGV[0]; + my $msg = "* $topic has commits already merged to public branch:\n"; + my (%not_in_next) = map { + /^([0-9a-f]+) /; + ($1 => 1); + } split(/\n/, $ARGV[1]); + for my $elem (map { + /^([0-9a-f]+) (.*)$/; + [$1 => $2]; + } split(/\n/, $ARGV[2])) { + if (!exists $not_in_next{$elem->[0]}) { + if ($msg) { + print STDERR $msg; + undef $msg; + } + print STDERR " $elem->[1]\n"; + } + } + ' "$topic" "$not_in_next" "$not_in_master" + exit 1 +fi + +exit 0 + +################################################################ + +This sample hook safeguards topic branches that have been +published from being rewound. + +The workflow assumed here is: + + * Once a topic branch forks from "master", "master" is never + merged into it again (either directly or indirectly). + + * Once a topic branch is fully cooked and merged into "master", + it is deleted. If you need to build on top of it to correct + earlier mistakes, a new topic branch is created by forking at + the tip of the "master". This is not strictly necessary, but + it makes it easier to keep your history simple. + + * Whenever you need to test or publish your changes to topic + branches, merge them into "next" branch. + +The script, being an example, hardcodes the publish branch name +to be "next", but it is trivial to make it configurable via +$GIT_DIR/config mechanism. + +With this workflow, you would want to know: + +(1) ... if a topic branch has ever been merged to "next". Young + topic branches can have stupid mistakes you would rather + clean up before publishing, and things that have not been + merged into other branches can be easily rebased without + affecting other people. But once it is published, you would + not want to rewind it. + +(2) ... if a topic branch has been fully merged to "master". + Then you can delete it. More importantly, you should not + build on top of it -- other people may already want to + change things related to the topic as patches against your + "master", so if you need further changes, it is better to + fork the topic (perhaps with the same name) afresh from the + tip of "master". + +Let's look at this example: + + o---o---o---o---o---o---o---o---o---o "next" + / / / / + / a---a---b A / / + / / / / + / / c---c---c---c B / + / / / \ / + / / / b---b C \ / + / / / / \ / + ---o---o---o---o---o---o---o---o---o---o---o "master" + + +A, B and C are topic branches. + + * A has one fix since it was merged up to "next". + + * B has finished. It has been fully merged up to "master" and "next", + and is ready to be deleted. + + * C has not merged to "next" at all. + +We would want to allow C to be rebased, refuse A, and encourage +B to be deleted. + +To compute (1): + + git rev-list ^master ^topic next + git rev-list ^master next + + if these match, topic has not merged in next at all. + +To compute (2): + + git rev-list master..topic + + if this is empty, it is fully merged to "master". diff --git a/tests/resources/issue_3020/.gitted/hooks/prepare-commit-msg.sample b/tests/resources/issue_3020/.gitted/hooks/prepare-commit-msg.sample new file mode 100644 index 000000000..f093a02ec --- /dev/null +++ b/tests/resources/issue_3020/.gitted/hooks/prepare-commit-msg.sample @@ -0,0 +1,36 @@ +#!/bin/sh +# +# An example hook script to prepare the commit log message. +# Called by "git commit" with the name of the file that has the +# commit message, followed by the description of the commit +# message's source. The hook's purpose is to edit the commit +# message file. If the hook fails with a non-zero status, +# the commit is aborted. +# +# To enable this hook, rename this file to "prepare-commit-msg". + +# This hook includes three examples. The first comments out the +# "Conflicts:" part of a merge commit. +# +# The second includes the output of "git diff --name-status -r" +# into the message, just before the "git status" output. It is +# commented because it doesn't cope with --amend or with squashed +# commits. +# +# The third example adds a Signed-off-by line to the message, that can +# still be edited. This is rarely a good idea. + +case "$2,$3" in + merge,) + /usr/bin/perl -i.bak -ne 's/^/# /, s/^# #/#/ if /^Conflicts/ .. /#/; print' "$1" ;; + +# ,|template,) +# /usr/bin/perl -i.bak -pe ' +# print "\n" . `git diff --cached --name-status -r` +# if /^#/ && $first++ == 0' "$1" ;; + + *) ;; +esac + +# SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p') +# grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1" diff --git a/tests/resources/issue_3020/.gitted/hooks/update.sample b/tests/resources/issue_3020/.gitted/hooks/update.sample new file mode 100644 index 000000000..d84758373 --- /dev/null +++ b/tests/resources/issue_3020/.gitted/hooks/update.sample @@ -0,0 +1,128 @@ +#!/bin/sh +# +# An example hook script to blocks unannotated tags from entering. +# Called by "git receive-pack" with arguments: refname sha1-old sha1-new +# +# To enable this hook, rename this file to "update". +# +# Config +# ------ +# hooks.allowunannotated +# This boolean sets whether unannotated tags will be allowed into the +# repository. By default they won't be. +# hooks.allowdeletetag +# This boolean sets whether deleting tags will be allowed in the +# repository. By default they won't be. +# hooks.allowmodifytag +# This boolean sets whether a tag may be modified after creation. By default +# it won't be. +# hooks.allowdeletebranch +# This boolean sets whether deleting branches will be allowed in the +# repository. By default they won't be. +# hooks.denycreatebranch +# This boolean sets whether remotely creating branches will be denied +# in the repository. By default this is allowed. +# + +# --- Command line +refname="$1" +oldrev="$2" +newrev="$3" + +# --- Safety check +if [ -z "$GIT_DIR" ]; then + echo "Don't run this script from the command line." >&2 + echo " (if you want, you could supply GIT_DIR then run" >&2 + echo " $0 <ref> <oldrev> <newrev>)" >&2 + exit 1 +fi + +if [ -z "$refname" -o -z "$oldrev" -o -z "$newrev" ]; then + echo "usage: $0 <ref> <oldrev> <newrev>" >&2 + exit 1 +fi + +# --- Config +allowunannotated=$(git config --bool hooks.allowunannotated) +allowdeletebranch=$(git config --bool hooks.allowdeletebranch) +denycreatebranch=$(git config --bool hooks.denycreatebranch) +allowdeletetag=$(git config --bool hooks.allowdeletetag) +allowmodifytag=$(git config --bool hooks.allowmodifytag) + +# check for no description +projectdesc=$(sed -e '1q' "$GIT_DIR/description") +case "$projectdesc" in +"Unnamed repository"* | "") + echo "*** Project description file hasn't been set" >&2 + exit 1 + ;; +esac + +# --- Check types +# if $newrev is 0000...0000, it's a commit to delete a ref. +zero="0000000000000000000000000000000000000000" +if [ "$newrev" = "$zero" ]; then + newrev_type=delete +else + newrev_type=$(git cat-file -t $newrev) +fi + +case "$refname","$newrev_type" in + refs/tags/*,commit) + # un-annotated tag + short_refname=${refname##refs/tags/} + if [ "$allowunannotated" != "true" ]; then + echo "*** The un-annotated tag, $short_refname, is not allowed in this repository" >&2 + echo "*** Use 'git tag [ -a | -s ]' for tags you want to propagate." >&2 + exit 1 + fi + ;; + refs/tags/*,delete) + # delete tag + if [ "$allowdeletetag" != "true" ]; then + echo "*** Deleting a tag is not allowed in this repository" >&2 + exit 1 + fi + ;; + refs/tags/*,tag) + # annotated tag + if [ "$allowmodifytag" != "true" ] && git rev-parse $refname > /dev/null 2>&1 + then + echo "*** Tag '$refname' already exists." >&2 + echo "*** Modifying a tag is not allowed in this repository." >&2 + exit 1 + fi + ;; + refs/heads/*,commit) + # branch + if [ "$oldrev" = "$zero" -a "$denycreatebranch" = "true" ]; then + echo "*** Creating a branch is not allowed in this repository" >&2 + exit 1 + fi + ;; + refs/heads/*,delete) + # delete branch + if [ "$allowdeletebranch" != "true" ]; then + echo "*** Deleting a branch is not allowed in this repository" >&2 + exit 1 + fi + ;; + refs/remotes/*,commit) + # tracking branch + ;; + refs/remotes/*,delete) + # delete tracking branch + if [ "$allowdeletebranch" != "true" ]; then + echo "*** Deleting a tracking branch is not allowed in this repository" >&2 + exit 1 + fi + ;; + *) + # Anything else (is there anything else?) + echo "*** Update hook: unknown type of update to ref $refname of type $newrev_type" >&2 + exit 1 + ;; +esac + +# --- Finished +exit 0 diff --git a/tests/resources/issue_3020/.gitted/index b/tests/resources/issue_3020/.gitted/index Binary files differnew file mode 100644 index 000000000..a66a2de56 --- /dev/null +++ b/tests/resources/issue_3020/.gitted/index diff --git a/tests/resources/issue_3020/.gitted/info/exclude b/tests/resources/issue_3020/.gitted/info/exclude new file mode 100644 index 000000000..a5196d1be --- /dev/null +++ b/tests/resources/issue_3020/.gitted/info/exclude @@ -0,0 +1,6 @@ +# git ls-files --others --exclude-from=.git/info/exclude +# Lines that start with '#' are comments. +# For a project mostly in C, the following would be a good set of +# exclude patterns (uncomment them if you want to use them): +# *.[oa] +# *~ diff --git a/tests/resources/issue_3020/.gitted/logs/HEAD b/tests/resources/issue_3020/.gitted/logs/HEAD new file mode 100644 index 000000000..9ea36cfc3 --- /dev/null +++ b/tests/resources/issue_3020/.gitted/logs/HEAD @@ -0,0 +1 @@ +0000000000000000000000000000000000000000 77e8039fba38e532bea5fba5f4f3be9940ea521b Brendan Forster <brendan@github.com> 1427606421 +0200 clone: from https://github.com/macote/HashCheck.git diff --git a/tests/resources/issue_3020/.gitted/logs/refs/heads/master b/tests/resources/issue_3020/.gitted/logs/refs/heads/master new file mode 100644 index 000000000..9ea36cfc3 --- /dev/null +++ b/tests/resources/issue_3020/.gitted/logs/refs/heads/master @@ -0,0 +1 @@ +0000000000000000000000000000000000000000 77e8039fba38e532bea5fba5f4f3be9940ea521b Brendan Forster <brendan@github.com> 1427606421 +0200 clone: from https://github.com/macote/HashCheck.git diff --git a/tests/resources/issue_3020/.gitted/logs/refs/remotes/origin/HEAD b/tests/resources/issue_3020/.gitted/logs/refs/remotes/origin/HEAD new file mode 100644 index 000000000..9ea36cfc3 --- /dev/null +++ b/tests/resources/issue_3020/.gitted/logs/refs/remotes/origin/HEAD @@ -0,0 +1 @@ +0000000000000000000000000000000000000000 77e8039fba38e532bea5fba5f4f3be9940ea521b Brendan Forster <brendan@github.com> 1427606421 +0200 clone: from https://github.com/macote/HashCheck.git diff --git a/tests/resources/issue_3020/.gitted/objects/07/998b2304ff33b23683b63135dc36ba9f68ac57 b/tests/resources/issue_3020/.gitted/objects/07/998b2304ff33b23683b63135dc36ba9f68ac57 new file mode 100644 index 000000000..0d5592b9a --- /dev/null +++ b/tests/resources/issue_3020/.gitted/objects/07/998b2304ff33b23683b63135dc36ba9f68ac57 @@ -0,0 +1,2 @@ +xŽÁŽÂ0D÷ܯð±ØI“ÖÕ +írà?âÆ´jƒBúÿd—?À·yšÏœ—åVÁþ£Um"ã¸)0©FÒˆgމD˜YTqÝ=]+ƒŽh9I°£:kDƒkÂ¥>YQæ0$]Øê58µT+œsyT-ð%/ð}¹Õë&Ÿs^Ž@}ÛCh½‡¶ëm+ÿüï廟æýEW-¡j óïv‡Wíh†ÉúÉø ÿOˆO¢V¦
\ No newline at end of file diff --git a/tests/resources/issue_3020/.gitted/objects/3a/ea65954a4a13370a1f47df920d24cdef74cb49 b/tests/resources/issue_3020/.gitted/objects/3a/ea65954a4a13370a1f47df920d24cdef74cb49 Binary files differnew file mode 100644 index 000000000..841afce96 --- /dev/null +++ b/tests/resources/issue_3020/.gitted/objects/3a/ea65954a4a13370a1f47df920d24cdef74cb49 diff --git a/tests/resources/issue_3020/.gitted/objects/56/0e1db218db90db538be31f8d568465ac3362c2 b/tests/resources/issue_3020/.gitted/objects/56/0e1db218db90db538be31f8d568465ac3362c2 new file mode 100644 index 000000000..50cc0d299 --- /dev/null +++ b/tests/resources/issue_3020/.gitted/objects/56/0e1db218db90db538be31f8d568465ac3362c2 @@ -0,0 +1,2 @@ +xŽAnÃ0{ö+x/Ò’iKF´9ä¢E%A`+PäÿW…ž–îrç¼,÷ +f>jQg™…Rð¤I#Zœ}L$⽕Q¸{†¢k…qT‡Ö' Ö)[#¸-œúdE½ï±CÒ…ÞrssŰÂ%—WÕß²ƒŸë½Þ6ùšórê[>±M×hkùÿž¿ûÝj>\uÕªF0?¶'ì± =4Hè&ÄiÜÔ¢ÖV¦
\ No newline at end of file diff --git a/tests/resources/issue_3020/.gitted/objects/76/7dea87ec830714d0199d84deca33aee304735e b/tests/resources/issue_3020/.gitted/objects/76/7dea87ec830714d0199d84deca33aee304735e new file mode 100644 index 000000000..8ea38fae2 --- /dev/null +++ b/tests/resources/issue_3020/.gitted/objects/76/7dea87ec830714d0199d84deca33aee304735e @@ -0,0 +1 @@ +xŽÁNÄ0D9÷+|G°vR7u…pà?âÆÙ]¡6«þ?YíàÛ<ÍŒg-ÛvmàÂôÔªÌ>“›XyFŠBf‰,¡ÇUR&UQÓ <Übµ½A6£—¬ÑÏÆÞ©Eî‚󘽚Ȉ8Ò!íR*|õTŠ;|—ú۬›>ÀÇùÚ.‡¾®e{ûbžž±ßÐi_y÷ÿ/?|¼œm·›%иþ7xÔ.€þäää0,ì–‘îÄ?£V§
\ No newline at end of file diff --git a/tests/resources/issue_3020/.gitted/objects/83/f1265b5801a91eed1ed030c9df1bb999beb7b5 b/tests/resources/issue_3020/.gitted/objects/83/f1265b5801a91eed1ed030c9df1bb999beb7b5 Binary files differnew file mode 100644 index 000000000..f86b2cd2f --- /dev/null +++ b/tests/resources/issue_3020/.gitted/objects/83/f1265b5801a91eed1ed030c9df1bb999beb7b5 diff --git a/tests/resources/issue_3020/.gitted/objects/ab/027b9968d0363df52e7b26ac68b3cd69ef4342 b/tests/resources/issue_3020/.gitted/objects/ab/027b9968d0363df52e7b26ac68b3cd69ef4342 Binary files differnew file mode 100644 index 000000000..6c9679f22 --- /dev/null +++ b/tests/resources/issue_3020/.gitted/objects/ab/027b9968d0363df52e7b26ac68b3cd69ef4342 diff --git a/tests/resources/issue_3020/.gitted/objects/d8/91425b7207c6685fdd97ce26ffcb3c64577d82 b/tests/resources/issue_3020/.gitted/objects/d8/91425b7207c6685fdd97ce26ffcb3c64577d82 Binary files differnew file mode 100644 index 000000000..5d4f54ea6 --- /dev/null +++ b/tests/resources/issue_3020/.gitted/objects/d8/91425b7207c6685fdd97ce26ffcb3c64577d82 diff --git a/tests/resources/issue_3020/.gitted/objects/pack/pack-00716425456a3c9f631eae470013b68e941d6212.idx b/tests/resources/issue_3020/.gitted/objects/pack/pack-00716425456a3c9f631eae470013b68e941d6212.idx Binary files differnew file mode 100644 index 000000000..4594f9627 --- /dev/null +++ b/tests/resources/issue_3020/.gitted/objects/pack/pack-00716425456a3c9f631eae470013b68e941d6212.idx diff --git a/tests/resources/issue_3020/.gitted/objects/pack/pack-00716425456a3c9f631eae470013b68e941d6212.pack b/tests/resources/issue_3020/.gitted/objects/pack/pack-00716425456a3c9f631eae470013b68e941d6212.pack Binary files differnew file mode 100644 index 000000000..95b176530 --- /dev/null +++ b/tests/resources/issue_3020/.gitted/objects/pack/pack-00716425456a3c9f631eae470013b68e941d6212.pack diff --git a/tests/resources/issue_3020/.gitted/packed-refs b/tests/resources/issue_3020/.gitted/packed-refs new file mode 100644 index 000000000..8fa3d95a4 --- /dev/null +++ b/tests/resources/issue_3020/.gitted/packed-refs @@ -0,0 +1,2 @@ +# pack-refs with: peeled fully-peeled +77e8039fba38e532bea5fba5f4f3be9940ea521b refs/remotes/origin/master diff --git a/tests/resources/issue_3020/.gitted/refs/heads/master b/tests/resources/issue_3020/.gitted/refs/heads/master new file mode 100644 index 000000000..4d350260a --- /dev/null +++ b/tests/resources/issue_3020/.gitted/refs/heads/master @@ -0,0 +1 @@ +77e8039fba38e532bea5fba5f4f3be9940ea521b diff --git a/tests/resources/issue_3020/.gitted/refs/remotes/origin/HEAD b/tests/resources/issue_3020/.gitted/refs/remotes/origin/HEAD new file mode 100644 index 000000000..6efe28fff --- /dev/null +++ b/tests/resources/issue_3020/.gitted/refs/remotes/origin/HEAD @@ -0,0 +1 @@ +ref: refs/remotes/origin/master diff --git a/tests/resources/issue_3020/.project b/tests/resources/issue_3020/.project new file mode 100644 index 000000000..e3668ca7f --- /dev/null +++ b/tests/resources/issue_3020/.project @@ -0,0 +1,74 @@ +<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>HashCheck</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.cdt.managedbuilder.core.genmakebuilder</name>
+ <triggers>clean,full,incremental,</triggers>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder</name>
+ <triggers>full,incremental,</triggers>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.cdt.core.cnature</nature>
+ <nature>org.eclipse.cdt.core.ccnature</nature>
+ <nature>org.eclipse.cdt.managedbuilder.core.managedBuildNature</nature>
+ <nature>org.eclipse.cdt.managedbuilder.core.ScannerConfigNature</nature>
+ </natures>
+ <filteredResources>
+ <filter>
+ <id>1417569914325</id>
+ <name></name>
+ <type>6</type>
+ <matcher>
+ <id>org.eclipse.ui.ide.multiFilter</id>
+ <arguments>1.0-name-matches-false-false-*.sln</arguments>
+ </matcher>
+ </filter>
+ <filter>
+ <id>1417569914328</id>
+ <name></name>
+ <type>6</type>
+ <matcher>
+ <id>org.eclipse.ui.ide.multiFilter</id>
+ <arguments>1.0-name-matches-false-false-*.vcxproj*</arguments>
+ </matcher>
+ </filter>
+ <filter>
+ <id>1417569914330</id>
+ <name></name>
+ <type>6</type>
+ <matcher>
+ <id>org.eclipse.ui.ide.multiFilter</id>
+ <arguments>1.0-name-matches-false-false-*.*sdf</arguments>
+ </matcher>
+ </filter>
+ <filter>
+ <id>1417569914333</id>
+ <name></name>
+ <type>6</type>
+ <matcher>
+ <id>org.eclipse.ui.ide.multiFilter</id>
+ <arguments>1.0-name-matches-false-false-*.suo</arguments>
+ </matcher>
+ </filter>
+ <filter>
+ <id>1417569914338</id>
+ <name></name>
+ <type>6</type>
+ <matcher>
+ <id>org.eclipse.ui.ide.multiFilter</id>
+ <arguments>1.0-name-matches-false-false-checksum.*</arguments>
+ </matcher>
+ </filter>
+ </filteredResources>
+</projectDescription>
diff --git a/tests/resources/issue_3020/.settings/language.settings.xml b/tests/resources/issue_3020/.settings/language.settings.xml new file mode 100644 index 000000000..534786b83 --- /dev/null +++ b/tests/resources/issue_3020/.settings/language.settings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<project>
+ <configuration id="cdt.managedbuild.config.gnu.mingw.exe.debug.1091074575" name="Debug">
+ <extension point="org.eclipse.cdt.core.LanguageSettingsProvider">
+ <provider copy-of="extension" id="org.eclipse.cdt.ui.UserLanguageSettingsProvider"/>
+ <provider-reference id="org.eclipse.cdt.core.ReferencedProjectsLanguageSettingsProvider" ref="shared-provider"/>
+ <provider-reference id="org.eclipse.cdt.managedbuilder.core.MBSLanguageSettingsProvider" ref="shared-provider"/>
+ <provider class="org.eclipse.cdt.managedbuilder.internal.language.settings.providers.GCCBuiltinSpecsDetectorMinGW" console="false" env-hash="-682947582912623951" id="org.eclipse.cdt.managedbuilder.core.GCCBuiltinSpecsDetectorMinGW" keep-relative-paths="false" name="CDT GCC Built-in Compiler Settings MinGW" parameter="${COMMAND} ${FLAGS} -E -P -v -dD -std=c++11 "${INPUTS}"">
+ <language-scope id="org.eclipse.cdt.core.gcc"/>
+ <language-scope id="org.eclipse.cdt.core.g++"/>
+ </provider>
+ </extension>
+ </configuration>
+ <configuration id="cdt.managedbuild.config.gnu.mingw.exe.release.107885674" name="Release">
+ <extension point="org.eclipse.cdt.core.LanguageSettingsProvider">
+ <provider copy-of="extension" id="org.eclipse.cdt.ui.UserLanguageSettingsProvider"/>
+ <provider-reference id="org.eclipse.cdt.core.ReferencedProjectsLanguageSettingsProvider" ref="shared-provider"/>
+ <provider-reference id="org.eclipse.cdt.managedbuilder.core.MBSLanguageSettingsProvider" ref="shared-provider"/>
+ <provider class="org.eclipse.cdt.managedbuilder.internal.language.settings.providers.GCCBuiltinSpecsDetectorMinGW" console="false" env-hash="-682947582912623951" id="org.eclipse.cdt.managedbuilder.core.GCCBuiltinSpecsDetectorMinGW" keep-relative-paths="false" name="CDT GCC Built-in Compiler Settings MinGW" parameter="${COMMAND} ${FLAGS} -E -P -v -dD -std=c++11 "${INPUTS}"">
+ <language-scope id="org.eclipse.cdt.core.gcc"/>
+ <language-scope id="org.eclipse.cdt.core.g++"/>
+ </provider>
+ </extension>
+ </configuration>
+</project>
diff --git a/tests/resources/issue_3020/.settings/org.eclipse.cdt.managedbuilder.core.prefs b/tests/resources/issue_3020/.settings/org.eclipse.cdt.managedbuilder.core.prefs new file mode 100644 index 000000000..b1e46bcb5 --- /dev/null +++ b/tests/resources/issue_3020/.settings/org.eclipse.cdt.managedbuilder.core.prefs @@ -0,0 +1,25 @@ +eclipse.preferences.version=1
+environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.mingw.exe.debug.1091074575/CPATH/delimiter=;
+environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.mingw.exe.debug.1091074575/CPATH/operation=remove
+environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.mingw.exe.debug.1091074575/CPLUS_INCLUDE_PATH/delimiter=;
+environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.mingw.exe.debug.1091074575/CPLUS_INCLUDE_PATH/operation=remove
+environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.mingw.exe.debug.1091074575/C_INCLUDE_PATH/delimiter=;
+environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.mingw.exe.debug.1091074575/C_INCLUDE_PATH/operation=remove
+environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.mingw.exe.debug.1091074575/append=true
+environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.mingw.exe.debug.1091074575/appendContributed=true
+environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.mingw.exe.release.107885674/CPATH/delimiter=;
+environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.mingw.exe.release.107885674/CPATH/operation=remove
+environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.mingw.exe.release.107885674/CPLUS_INCLUDE_PATH/delimiter=;
+environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.mingw.exe.release.107885674/CPLUS_INCLUDE_PATH/operation=remove
+environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.mingw.exe.release.107885674/C_INCLUDE_PATH/delimiter=;
+environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.mingw.exe.release.107885674/C_INCLUDE_PATH/operation=remove
+environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.mingw.exe.release.107885674/append=true
+environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.mingw.exe.release.107885674/appendContributed=true
+environment/buildEnvironmentLibrary/cdt.managedbuild.config.gnu.mingw.exe.debug.1091074575/LIBRARY_PATH/delimiter=;
+environment/buildEnvironmentLibrary/cdt.managedbuild.config.gnu.mingw.exe.debug.1091074575/LIBRARY_PATH/operation=remove
+environment/buildEnvironmentLibrary/cdt.managedbuild.config.gnu.mingw.exe.debug.1091074575/append=true
+environment/buildEnvironmentLibrary/cdt.managedbuild.config.gnu.mingw.exe.debug.1091074575/appendContributed=true
+environment/buildEnvironmentLibrary/cdt.managedbuild.config.gnu.mingw.exe.release.107885674/LIBRARY_PATH/delimiter=;
+environment/buildEnvironmentLibrary/cdt.managedbuild.config.gnu.mingw.exe.release.107885674/LIBRARY_PATH/operation=remove
+environment/buildEnvironmentLibrary/cdt.managedbuild.config.gnu.mingw.exe.release.107885674/append=true
+environment/buildEnvironmentLibrary/cdt.managedbuild.config.gnu.mingw.exe.release.107885674/appendContributed=true
diff --git a/tests/resources/issue_3020/CRC32FileHash.cpp b/tests/resources/issue_3020/CRC32FileHash.cpp new file mode 100644 index 000000000..c34a2757b --- /dev/null +++ b/tests/resources/issue_3020/CRC32FileHash.cpp @@ -0,0 +1,100 @@ +/* Author: macote */
+
+#include "CRC32FileHash.h"
+
+const UINT32 CRC32FileHash::kCRC32Table[] = {
+ 0x000000000L, 0x077073096L, 0x0EE0E612CL, 0x0990951BAL,
+ 0x0076DC419L, 0x0706AF48FL, 0x0E963A535L, 0x09E6495A3L,
+ 0x00EDB8832L, 0x079DCB8A4L, 0x0E0D5E91EL, 0x097D2D988L,
+ 0x009B64C2BL, 0x07EB17CBDL, 0x0E7B82D07L, 0x090BF1D91L,
+ 0x01DB71064L, 0x06AB020F2L, 0x0F3B97148L, 0x084BE41DEL,
+ 0x01ADAD47DL, 0x06DDDE4EBL, 0x0F4D4B551L, 0x083D385C7L,
+ 0x0136C9856L, 0x0646BA8C0L, 0x0FD62F97AL, 0x08A65C9ECL,
+ 0x014015C4FL, 0x063066CD9L, 0x0FA0F3D63L, 0x08D080DF5L,
+ 0x03B6E20C8L, 0x04C69105EL, 0x0D56041E4L, 0x0A2677172L,
+ 0x03C03E4D1L, 0x04B04D447L, 0x0D20D85FDL, 0x0A50AB56BL,
+ 0x035B5A8FAL, 0x042B2986CL, 0x0DBBBC9D6L, 0x0ACBCF940L,
+ 0x032D86CE3L, 0x045DF5C75L, 0x0DCD60DCFL, 0x0ABD13D59L,
+ 0x026D930ACL, 0x051DE003AL, 0x0C8D75180L, 0x0BFD06116L,
+ 0x021B4F4B5L, 0x056B3C423L, 0x0CFBA9599L, 0x0B8BDA50FL,
+ 0x02802B89EL, 0x05F058808L, 0x0C60CD9B2L, 0x0B10BE924L,
+ 0x02F6F7C87L, 0x058684C11L, 0x0C1611DABL, 0x0B6662D3DL,
+ 0x076DC4190L, 0x001DB7106L, 0x098D220BCL, 0x0EFD5102AL,
+ 0x071B18589L, 0x006B6B51FL, 0x09FBFE4A5L, 0x0E8B8D433L,
+ 0x07807C9A2L, 0x00F00F934L, 0x09609A88EL, 0x0E10E9818L,
+ 0x07F6A0DBBL, 0x0086D3D2DL, 0x091646C97L, 0x0E6635C01L,
+ 0x06B6B51F4L, 0x01C6C6162L, 0x0856530D8L, 0x0F262004EL,
+ 0x06C0695EDL, 0x01B01A57BL, 0x08208F4C1L, 0x0F50FC457L,
+ 0x065B0D9C6L, 0x012B7E950L, 0x08BBEB8EAL, 0x0FCB9887CL,
+ 0x062DD1DDFL, 0x015DA2D49L, 0x08CD37CF3L, 0x0FBD44C65L,
+ 0x04DB26158L, 0x03AB551CEL, 0x0A3BC0074L, 0x0D4BB30E2L,
+ 0x04ADFA541L, 0x03DD895D7L, 0x0A4D1C46DL, 0x0D3D6F4FBL,
+ 0x04369E96AL, 0x0346ED9FCL, 0x0AD678846L, 0x0DA60B8D0L,
+ 0x044042D73L, 0x033031DE5L, 0x0AA0A4C5FL, 0x0DD0D7CC9L,
+ 0x05005713CL, 0x0270241AAL, 0x0BE0B1010L, 0x0C90C2086L,
+ 0x05768B525L, 0x0206F85B3L, 0x0B966D409L, 0x0CE61E49FL,
+ 0x05EDEF90EL, 0x029D9C998L, 0x0B0D09822L, 0x0C7D7A8B4L,
+ 0x059B33D17L, 0x02EB40D81L, 0x0B7BD5C3BL, 0x0C0BA6CADL,
+ 0x0EDB88320L, 0x09ABFB3B6L, 0x003B6E20CL, 0x074B1D29AL,
+ 0x0EAD54739L, 0x09DD277AFL, 0x004DB2615L, 0x073DC1683L,
+ 0x0E3630B12L, 0x094643B84L, 0x00D6D6A3EL, 0x07A6A5AA8L,
+ 0x0E40ECF0BL, 0x09309FF9DL, 0x00A00AE27L, 0x07D079EB1L,
+ 0x0F00F9344L, 0x08708A3D2L, 0x01E01F268L, 0x06906C2FEL,
+ 0x0F762575DL, 0x0806567CBL, 0x0196C3671L, 0x06E6B06E7L,
+ 0x0FED41B76L, 0x089D32BE0L, 0x010DA7A5AL, 0x067DD4ACCL,
+ 0x0F9B9DF6FL, 0x08EBEEFF9L, 0x017B7BE43L, 0x060B08ED5L,
+ 0x0D6D6A3E8L, 0x0A1D1937EL, 0x038D8C2C4L, 0x04FDFF252L,
+ 0x0D1BB67F1L, 0x0A6BC5767L, 0x03FB506DDL, 0x048B2364BL,
+ 0x0D80D2BDAL, 0x0AF0A1B4CL, 0x036034AF6L, 0x041047A60L,
+ 0x0DF60EFC3L, 0x0A867DF55L, 0x0316E8EEFL, 0x04669BE79L,
+ 0x0CB61B38CL, 0x0BC66831AL, 0x0256FD2A0L, 0x05268E236L,
+ 0x0CC0C7795L, 0x0BB0B4703L, 0x0220216B9L, 0x05505262FL,
+ 0x0C5BA3BBEL, 0x0B2BD0B28L, 0x02BB45A92L, 0x05CB36A04L,
+ 0x0C2D7FFA7L, 0x0B5D0CF31L, 0x02CD99E8BL, 0x05BDEAE1DL,
+ 0x09B64C2B0L, 0x0EC63F226L, 0x0756AA39CL, 0x0026D930AL,
+ 0x09C0906A9L, 0x0EB0E363FL, 0x072076785L, 0x005005713L,
+ 0x095BF4A82L, 0x0E2B87A14L, 0x07BB12BAEL, 0x00CB61B38L,
+ 0x092D28E9BL, 0x0E5D5BE0DL, 0x07CDCEFB7L, 0x00BDBDF21L,
+ 0x086D3D2D4L, 0x0F1D4E242L, 0x068DDB3F8L, 0x01FDA836EL,
+ 0x081BE16CDL, 0x0F6B9265BL, 0x06FB077E1L, 0x018B74777L,
+ 0x088085AE6L, 0x0FF0F6A70L, 0x066063BCAL, 0x011010B5CL,
+ 0x08F659EFFL, 0x0F862AE69L, 0x0616BFFD3L, 0x0166CCF45L,
+ 0x0A00AE278L, 0x0D70DD2EEL, 0x04E048354L, 0x03903B3C2L,
+ 0x0A7672661L, 0x0D06016F7L, 0x04969474DL, 0x03E6E77DBL,
+ 0x0AED16A4AL, 0x0D9D65ADCL, 0x040DF0B66L, 0x037D83BF0L,
+ 0x0A9BCAE53L, 0x0DEBB9EC5L, 0x047B2CF7FL, 0x030B5FFE9L,
+ 0x0BDBDF21CL, 0x0CABAC28AL, 0x053B39330L, 0x024B4A3A6L,
+ 0x0BAD03605L, 0x0CDD70693L, 0x054DE5729L, 0x023D967BFL,
+ 0x0B3667A2EL, 0x0C4614AB8L, 0x05D681B02L, 0x02A6F2B94L,
+ 0x0B40BBE37L, 0x0C30C8EA1L, 0x05A05DF1BL, 0x02D02EF8DL
+};
+
+void CRC32FileHash::Initialize()
+{
+ hash_ = 0;
+ hash_ = ~hash_;
+}
+
+void CRC32FileHash::Update(const UINT32 bytecount)
+{
+ PBYTE buffer = buffer_;
+ UINT32 bytesleft = bytecount;
+ while (bytesleft > 0)
+ {
+ hash_ = kCRC32Table[(hash_ ^ *buffer) & 0xFF] ^ (hash_ >> 8);
+ ++buffer;
+ --bytesleft;
+ }
+}
+
+void CRC32FileHash::Finalize()
+{
+ hash_ = ~hash_;
+}
+
+void CRC32FileHash::ConvertHashToDigestString()
+{
+ std::wstringstream wss;
+ wss << std::hex << std::setw(8) << std::setfill(L'0') << std::uppercase << hash_;
+ digest_.append(wss.str());
+}
diff --git a/tests/resources/issue_3020/CRC32FileHash.h b/tests/resources/issue_3020/CRC32FileHash.h new file mode 100644 index 000000000..37fe12c46 --- /dev/null +++ b/tests/resources/issue_3020/CRC32FileHash.h @@ -0,0 +1,30 @@ +/* Author: macote */
+
+#ifndef CRC32FILEHASH_H_
+#define CRC32FILEHASH_H_
+
+#include "FileHash.h"
+#include <iomanip>
+#include <sstream>
+#include <string>
+#include <Windows.h>
+
+class CRC32FileHash : public FileHash
+{
+public:
+#if _MSC_VER < 1900
+ CRC32FileHash(const std::wstring& filepath, const DWORD buffersize) : FileHash(filepath, buffersize) { };
+ CRC32FileHash(const std::wstring& filepath) : FileHash(filepath) { };
+#else
+ using FileHash::FileHash;
+#endif
+private:
+ void Initialize();
+ void Update(const UINT32 bytecount);
+ void Finalize();
+ void ConvertHashToDigestString();
+ const static UINT32 kCRC32Table[];
+ UINT32 hash_;
+};
+
+#endif /* CRC32FILEHASH_H_ */
diff --git a/tests/resources/issue_3020/FileHash.cpp b/tests/resources/issue_3020/FileHash.cpp new file mode 100644 index 000000000..9f6d70ce5 --- /dev/null +++ b/tests/resources/issue_3020/FileHash.cpp @@ -0,0 +1,49 @@ +/* Author: macote */
+
+#include "FileHash.h"
+
+void FileHash::AllocateBuffer()
+{
+ buffer_ = (PBYTE)VirtualAlloc(NULL, buffersize_, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
+}
+
+void FileHash::FreeBuffer()
+{
+ if (buffer_ != NULL)
+ {
+ VirtualFree(buffer_, 0, MEM_RELEASE);
+ }
+}
+
+void FileHash::Compute()
+{
+ Initialize();
+ DWORD bytesread = 0;
+ FileHashBytesProcessedEventArgs fhbpea;
+ fhbpea.bytesprocessed.QuadPart = 0;
+ DWORD runningnotificationblocksize = 0;
+ do
+ {
+ bytesread = filestream_.Read(buffer_, buffersize_);
+ if (bytesread > 0)
+ {
+ Update(bytesread);
+ }
+ if (bytesprocessedevent_ != nullptr)
+ {
+ fhbpea.bytesprocessed.QuadPart += bytesread;
+ runningnotificationblocksize += bytesread;
+ if (runningnotificationblocksize >= bytesprocessednotificationblocksize_ || bytesread == 0)
+ {
+ if (bytesread > 0)
+ {
+ runningnotificationblocksize -= bytesprocessednotificationblocksize_;
+ }
+ bytesprocessedevent_(fhbpea);
+ }
+ }
+ }
+ while (bytesread > 0);
+ Finalize();
+ ConvertHashToDigestString();
+}
diff --git a/tests/resources/issue_3020/FileHash.h b/tests/resources/issue_3020/FileHash.h new file mode 100644 index 000000000..4867dd914 --- /dev/null +++ b/tests/resources/issue_3020/FileHash.h @@ -0,0 +1,61 @@ +/* Author: macote */
+
+#ifndef FILEHASH_H_
+#define FILEHASH_H_
+
+#include "FileStream.h"
+#include <string>
+#include <functional>
+#include <Windows.h>
+
+struct FileHashBytesProcessedEventArgs
+{
+ LARGE_INTEGER bytesprocessed;
+};
+
+class FileHash
+{
+public:
+ static const DWORD kDefaultBufferSize = 32768;
+ static const DWORD kDefaultBytesProcessedNotificationBlockSize = 1048576;
+public:
+ FileHash(const std::wstring& filepath) : FileHash(filepath, kDefaultBufferSize) { };
+ FileHash(const std::wstring& filepath, const DWORD buffersize)
+ : buffersize_(buffersize), filestream_(FileStream(filepath, FileStream::Mode::OpenNoBuffering, buffersize))
+ {
+ bytesprocessedevent_ = nullptr;
+ AllocateBuffer();
+ }
+ virtual ~FileHash()
+ {
+ FreeBuffer();
+ };
+ void Compute();
+ std::wstring digest() const { return digest_; }
+ void SetBytesProcessedEventHandler(std::function<void(FileHashBytesProcessedEventArgs)> handler)
+ {
+ SetBytesProcessedEventHandler(handler, kDefaultBytesProcessedNotificationBlockSize);
+ }
+ void SetBytesProcessedEventHandler(std::function<void(FileHashBytesProcessedEventArgs)> handler,
+ const DWORD bytesprocessednotificationblocksize)
+ {
+ bytesprocessedevent_ = handler;
+ bytesprocessednotificationblocksize_ = bytesprocessednotificationblocksize;
+ }
+protected:
+ virtual void Initialize() = 0;
+ virtual void Update(const UINT32 bytes) = 0;
+ virtual void Finalize() = 0;
+ virtual void ConvertHashToDigestString() = 0;
+ PBYTE buffer_ = NULL;
+ std::wstring digest_;
+private:
+ void AllocateBuffer();
+ void FreeBuffer();
+ DWORD buffersize_;
+ FileStream filestream_;
+ DWORD bytesprocessednotificationblocksize_;
+ std::function<void(FileHashBytesProcessedEventArgs)> bytesprocessedevent_;
+};
+
+#endif /* FILEHASH_H_ */
diff --git a/tests/resources/issue_3020/FileHashFactory.h b/tests/resources/issue_3020/FileHashFactory.h new file mode 100644 index 000000000..90bd27bb9 --- /dev/null +++ b/tests/resources/issue_3020/FileHashFactory.h @@ -0,0 +1,42 @@ +/* Author: macote */
+
+#ifndef FILEHASHFACTORY_H_
+#define FILEHASHFACTORY_H_
+
+#include "FileHash.h"
+#include "HashType.h"
+#include "CRC32FileHash.h"
+#include "MD5FileHash.h"
+#include "SHA1FileHash.h"
+#include <string>
+#include <memory>
+#include <Windows.h>
+
+class FileHashFactory
+{
+public:
+ static std::unique_ptr<FileHash> Create(HashType hashtype, const std::wstring& filepath)
+ {
+ if (hashtype == HashType::SHA1)
+ {
+ //return std::make_unique<SHA1FileHash>(filepath);
+ return std::unique_ptr<SHA1FileHash>(new SHA1FileHash(filepath));
+ }
+ else if (hashtype == HashType::MD5)
+ {
+ //return std::make_unique<MD5FileHash>(filepath);
+ return std::unique_ptr<MD5FileHash>(new MD5FileHash(filepath));
+ }
+ else if (hashtype == HashType::CRC32)
+ {
+ //return std::make_unique<CRC32FileHash>(filepath);
+ return std::unique_ptr<CRC32FileHash>(new CRC32FileHash(filepath));
+ }
+ else
+ {
+ throw std::runtime_error("FileHashFactory.Create(): selected hash type is not supported.");
+ }
+ };
+};
+
+#endif /* FILEHASHFACTORY_H_ */
diff --git a/tests/resources/issue_3020/FileStream.cpp b/tests/resources/issue_3020/FileStream.cpp new file mode 100644 index 000000000..a92e09adc --- /dev/null +++ b/tests/resources/issue_3020/FileStream.cpp @@ -0,0 +1,184 @@ +/* Author: macote */
+/* Portions of this code was inspired by dotnet/corefx's Win32FileStream.cs */
+/*
+
+The MIT License (MIT)
+
+Copyright (c) Microsoft Corporation
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+*/
+
+#include "FileStream.h"
+
+void FileStream::AllocateBuffer()
+{
+ buffer_ = (PBYTE)VirtualAlloc(NULL, buffersize_, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
+}
+
+void FileStream::FreeBuffer()
+{
+ if (buffer_ != NULL)
+ {
+ VirtualFree(buffer_, 0, MEM_RELEASE);
+ }
+}
+
+void FileStream::OpenFile()
+{
+ DWORD desiredaccess = (mode_ >= Mode::Create) ? GENERIC_WRITE : GENERIC_READ;
+ DWORD createdisposition;
+ switch (mode_)
+ {
+ case FileStream::Mode::Create:
+ createdisposition = CREATE_NEW;
+ break;
+ case FileStream::Mode::Truncate:
+ createdisposition = CREATE_ALWAYS;
+ break;
+ default:
+ createdisposition = OPEN_EXISTING;
+ break;
+ }
+ DWORD flagsandattributes = FILE_ATTRIBUTE_NORMAL;
+ if (mode_ == Mode::OpenNoBuffering)
+ {
+ flagsandattributes |= FILE_FLAG_NO_BUFFERING;
+ }
+ filehandle_ = CreateFileW(filepath_.c_str(), desiredaccess, FILE_SHARE_READ,
+ NULL, createdisposition, flagsandattributes, NULL);
+ if (filehandle_ == INVALID_HANDLE_VALUE)
+ {
+ std::stringstream ss;
+ ss << "FileStream.Open(CreateFileW()) failed with error ";
+ ss << "0x" << std::hex << std::setw(8) << std::setfill('0') << std::uppercase;
+ ss << GetLastError();
+ throw std::runtime_error(ss.str());
+ }
+}
+
+DWORD FileStream::Read(PBYTE buffer, DWORD offset, DWORD count)
+{
+ DWORD bytesread = 0;
+ ReadFile(filehandle_, buffer + offset, count, &bytesread, NULL);
+ return bytesread;
+}
+
+DWORD FileStream::Write(PBYTE buffer, DWORD offset, DWORD count)
+{
+ DWORD byteswritten = 0;
+ WriteFile(filehandle_, buffer + offset, count, &byteswritten, NULL);
+ return byteswritten;
+}
+
+void FileStream::FlushWrite()
+{
+ Write(buffer_, 0, writeindex_);
+ writeindex_ = 0;
+}
+
+void FileStream::CloseFile()
+{
+ if (filehandle_ != INVALID_HANDLE_VALUE)
+ {
+ CloseHandle(filehandle_);
+ filehandle_ = INVALID_HANDLE_VALUE;
+ }
+}
+
+DWORD FileStream::Read(PBYTE buffer, DWORD count)
+{
+ DWORD bufferbytes = readlength_ - readindex_;
+ BOOL eof = FALSE;
+ if (bufferbytes == 0)
+ {
+ DWORD bytesread;
+ if (count >= buffersize_)
+ {
+ bytesread = Read(buffer, 0, count);
+ readindex_ = readlength_ = 0;
+ return bytesread;
+ }
+ bytesread = Read(buffer_, 0, buffersize_);
+ if (bytesread == 0) return 0;
+ readindex_ = 0;
+ readlength_ = bufferbytes = bytesread;
+ eof = bytesread < buffersize_;
+ }
+ if (bufferbytes > count)
+ {
+ bufferbytes = count;
+ }
+ CopyMemory(buffer, buffer_ + readindex_, bufferbytes);
+ readindex_ += bufferbytes;
+ if (bufferbytes < count && !eof)
+ {
+ DWORD bytesread = Read(buffer, bufferbytes, count - bufferbytes);
+ bufferbytes += bytesread;
+ readindex_ = readlength_ = 0;
+ }
+ return bufferbytes;
+}
+
+void FileStream::Write(PBYTE buffer, DWORD count)
+{
+ DWORD bufferindex = 0;
+ if (writeindex_ > 0)
+ {
+ DWORD bufferbytes = buffersize_ - writeindex_;
+ if (bufferbytes > 0)
+ {
+ if (bufferbytes > count)
+ {
+ bufferbytes = count;
+ }
+ CopyMemory(buffer_ + writeindex_, buffer, bufferbytes);
+ writeindex_ += bufferbytes;
+ if (bufferbytes == count) return;
+ bufferindex = bufferbytes;
+ count -= bufferbytes;
+ }
+ Write(buffer_, 0, writeindex_);
+ writeindex_ = 0;
+ }
+ if (count >= buffersize_)
+ {
+ Write(buffer, 0, count);
+ }
+ else if (count > 0)
+ {
+ CopyMemory(buffer_ + writeindex_, buffer + bufferindex, count);
+ writeindex_ = count;
+ }
+}
+
+void FileStream::Flush()
+{
+ if (writeindex_ > 0)
+ {
+ FlushWrite();
+ }
+}
+
+void FileStream::Close()
+{
+ Flush();
+ CloseFile();
+}
diff --git a/tests/resources/issue_3020/FileStream.h b/tests/resources/issue_3020/FileStream.h new file mode 100644 index 000000000..baf8c291b --- /dev/null +++ b/tests/resources/issue_3020/FileStream.h @@ -0,0 +1,61 @@ +/* Author: macote */
+
+#ifndef FILESTREAM_H_
+#define FILESTREAM_H_
+
+#include <iomanip>
+#include <sstream>
+#include <stdexcept>
+#include <string>
+#include <Windows.h>
+
+class FileStream
+{
+public:
+ static const DWORD kDefaultBufferSize = 32768;
+public:
+ enum class Mode
+ {
+ Open,
+ OpenNoBuffering,
+ Create,
+ Truncate,
+ Append
+ };
+ FileStream(const std::wstring& filepath, Mode mode) : FileStream(filepath, mode, kDefaultBufferSize) { };
+ FileStream(const std::wstring& filepath, Mode mode, const DWORD buffersize) : filepath_(filepath), mode_(mode), buffersize_(buffersize)
+ {
+ AllocateBuffer();
+ OpenFile();
+ };
+ virtual ~FileStream()
+ {
+ Flush();
+ CloseFile();
+ FreeBuffer();
+ };
+ DWORD Read(PBYTE buffer, DWORD count);
+ void Write(PBYTE buffer, DWORD count);
+ void Flush();
+ void Close();
+ DWORD lasterror() const { return lasterror_; }
+private:
+ void AllocateBuffer();
+ void OpenFile();
+ DWORD Read(PBYTE buffer, DWORD offset, DWORD count);
+ DWORD Write(PBYTE buffer, DWORD offset, DWORD count);
+ void FlushWrite();
+ void CloseFile();
+ void FreeBuffer();
+ DWORD readindex_ = 0;
+ DWORD readlength_ = 0;
+ DWORD writeindex_ = 0;
+ PBYTE buffer_ = NULL;
+ const std::wstring filepath_;
+ Mode mode_;
+ const DWORD buffersize_;
+ HANDLE filehandle_ = NULL;
+ DWORD lasterror_ = 0;
+};
+
+#endif /* FILESTREAM_H_ */
diff --git a/tests/resources/issue_3020/FileTree.cpp b/tests/resources/issue_3020/FileTree.cpp new file mode 100644 index 000000000..85e5021ff --- /dev/null +++ b/tests/resources/issue_3020/FileTree.cpp @@ -0,0 +1,31 @@ +/* Author: macote */
+
+#include "FileTree.h"
+
+void FileTree::ProcessTree(const std::wstring& path) const
+{
+ WIN32_FIND_DATAW findfiledata;
+ HANDLE hFind;
+ std::wstring pattern = path + L"*";
+ hFind = FindFirstFileW(pattern.c_str(), &findfiledata);
+ if (hFind != INVALID_HANDLE_VALUE)
+ {
+ do
+ {
+ if (findfiledata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+ {
+ if (lstrcmpW(findfiledata.cFileName, L".") != 0 && lstrcmpW(findfiledata.cFileName, L"..") != 0)
+ {
+ std::wstring currentpath(path + findfiledata.cFileName + L"\\");
+ ProcessTree(currentpath);
+ }
+ }
+ else
+ {
+ std::wstring currentfile(path + findfiledata.cFileName);
+ fileaction_.ProcessFile(currentfile);
+ }
+ } while (FindNextFileW(hFind, &findfiledata));
+ FindClose(hFind);
+ }
+}
diff --git a/tests/resources/issue_3020/FileTree.h b/tests/resources/issue_3020/FileTree.h new file mode 100644 index 000000000..48b77817e --- /dev/null +++ b/tests/resources/issue_3020/FileTree.h @@ -0,0 +1,30 @@ +/* Author: macote */
+
+#ifndef FILETREE_H_
+#define FILETREE_H_
+
+#include <string>
+#include <Windows.h>
+
+class IFileTreeAction
+{
+public:
+ virtual ~IFileTreeAction() { }
+ virtual void ProcessFile(const std::wstring& filepath) = 0;
+};
+
+class FileTree
+{
+public:
+ FileTree(const std::wstring basepath, IFileTreeAction& fileaction) : basepath_(basepath), fileaction_(fileaction) { };
+ void Process() const
+ {
+ ProcessTree(basepath_);
+ }
+private:
+ void ProcessTree(const std::wstring& path) const;
+ const std::wstring basepath_;
+ IFileTreeAction& fileaction_;
+};
+
+#endif /* FILETREE_H_ */
diff --git a/tests/resources/issue_3020/HashCheck.cpp b/tests/resources/issue_3020/HashCheck.cpp new file mode 100644 index 000000000..9edc029fc --- /dev/null +++ b/tests/resources/issue_3020/HashCheck.cpp @@ -0,0 +1,259 @@ +/* Author: macote */
+
+#include "HashCheck.h"
+
+LPCWSTR HashCheck::kHashFileBaseName = L"checksum";
+
+void HashCheck::Initialize()
+{
+ silent_ = checking_ = updating_ = skipcheck_ = FALSE;
+ hashtype_ = HashType::Undefined;
+ appfilename_ = GetAppFileName(args_[0].c_str());
+
+ args_.erase(args_.begin());
+ if (args_.size() > 0)
+ {
+ std::vector<std::wstring>::iterator it;
+ it = std::find(args_.begin(), args_.end(), L"-u");
+ if (it != args_.end())
+ {
+ updating_ = TRUE;
+ args_.erase(it);
+ }
+ it = std::find(args_.begin(), args_.end(), L"-sm");
+ if (it != args_.end())
+ {
+ skipcheck_ = TRUE;
+ args_.erase(it);
+ }
+ it = std::find(args_.begin(), args_.end(), L"-sha1");
+ if (it != args_.end())
+ {
+ hashtype_ = HashType::SHA1;
+ args_.erase(it);
+ }
+ it = std::find(args_.begin(), args_.end(), L"-md5");
+ if (it != args_.end())
+ {
+ hashtype_ = HashType::MD5;
+ args_.erase(it);
+ }
+ it = std::find(args_.begin(), args_.end(), L"-crc32");
+ if (it != args_.end())
+ {
+ hashtype_ = HashType::CRC32;
+ args_.erase(it);
+ }
+ }
+
+ WIN32_FIND_DATAW findfiledata;
+ HANDLE hFind;
+
+ if (args_.size() > 0)
+ {
+ std::wstring tmp(args_[0]);
+ if (*(tmp.end() - 1) != L'\\')
+ {
+ tmp += L'\\';
+ }
+ tmp += L"*";
+ hFind = FindFirstFileW(tmp.c_str(), &findfiledata);
+ if (hFind != INVALID_HANDLE_VALUE) {
+ FindClose(hFind);
+ basepath_ = args_[0] + L'\\';
+ }
+ else
+ {
+ silent_ = TRUE;
+ }
+ }
+
+ std::wstring baseFilename = kHashFileBaseName;
+ if (hashtype_ == HashType::SHA1)
+ hashfilename_ = baseFilename + L".sha1";
+ else if (hashtype_ == HashType::MD5)
+ hashfilename_ = baseFilename + L".md5";
+ else if (hashtype_ == HashType::CRC32)
+ hashfilename_ = baseFilename + L".crc32";
+ else
+ {
+ hashfilename_ = baseFilename + L".sha1";
+ hFind = FindFirstFileW(hashfilename_.c_str(), &findfiledata);
+ if (hFind != INVALID_HANDLE_VALUE)
+ {
+ FindClose(hFind);
+ hashtype_ = HashType::SHA1;
+ }
+ else
+ {
+ hashfilename_ = baseFilename + L".md5";
+ hFind = FindFirstFileW(hashfilename_.c_str(), &findfiledata);
+ if (hFind != INVALID_HANDLE_VALUE)
+ {
+ FindClose(hFind);
+ hashtype_ = HashType::MD5;
+ }
+ else
+ {
+ hashfilename_ = baseFilename + L".crc32";
+ hFind = FindFirstFileW(hashfilename_.c_str(), &findfiledata);
+ if (hFind != INVALID_HANDLE_VALUE)
+ {
+ FindClose(hFind);
+ hashtype_ = HashType::CRC32;
+ }
+ else
+ {
+ hashfilename_ = baseFilename + L".sha1";
+ hashtype_ = HashType::SHA1;
+ }
+ }
+ }
+ }
+
+ hFind = FindFirstFileW(hashfilename_.c_str(), &findfiledata);
+ if (hFind != INVALID_HANDLE_VALUE)
+ {
+ FindClose(hFind);
+ if (!(findfiledata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
+ {
+ checking_ = !updating_;
+ }
+ else
+ {
+ if (!silent_)
+ {
+ std::wstring msg = L"Error: Can't create hash file. Delete '" + hashfilename_ + L"' folder.";
+ MessageBoxW(NULL, msg.c_str(), L"HashCheck", MB_ICONERROR | MB_SYSTEMMODAL);
+ }
+ else
+ {
+ // ...
+ }
+ ExitProcess(0);
+ }
+ }
+ else
+ {
+ updating_ = FALSE;
+ }
+
+}
+
+int HashCheck::Process() const
+{
+ auto mode = HashFileProcessor::Mode::Create;
+ if (checking_)
+ {
+ mode = HashFileProcessor::Mode::Verify;
+ }
+ else if (updating_)
+ {
+ mode = HashFileProcessor::Mode::Update;
+ }
+
+ auto hashtype = HashType::Undefined;
+ switch (hashtype_)
+ {
+ case HashType::CRC32:
+ hashtype = HashType::CRC32;
+ break;
+ case HashType::MD5:
+ hashtype = HashType::MD5;
+ break;
+ case HashType::SHA1:
+ hashtype = HashType::SHA1;
+ break;
+ default:
+ break;
+ }
+
+ HashFileProcessor hashfileprocessor(mode, hashtype, hashfilename_, appfilename_, basepath_);
+ auto result = hashfileprocessor.ProcessTree();
+ BOOL viewreport = FALSE;
+ int exitcode = 0;
+ switch (result)
+ {
+ case HashFileProcessor::ProcessResult::FilesAreMissing:
+ if (updating_)
+ {
+ MessageBoxW(NULL, L"Error: Can't update because files are missing.", L"HashCheck", MB_ICONERROR | MB_SYSTEMMODAL);
+ }
+ viewreport = TRUE;
+ exitcode = -1;
+ break;
+ case HashFileProcessor::ProcessResult::ErrorsOccurredWhileProcessing:
+ viewreport = TRUE;
+ exitcode = -2;
+ break;
+ case HashFileProcessor::ProcessResult::CouldNotOpenHashFile:
+ MessageBoxW(NULL, L"Error: Could not open hash file.", L"HashCheck", MB_ICONERROR | MB_SYSTEMMODAL);
+ exitcode = -3;
+ break;
+ case HashFileProcessor::ProcessResult::NoFileToProcess:
+ MessageBoxW(NULL, L"Error: No file to process.", L"HashCheck", MB_ICONERROR | MB_SYSTEMMODAL);
+ exitcode = -4;
+ break;
+ case HashFileProcessor::ProcessResult::NothingToUpdate:
+ MessageBoxW(NULL, L"Error: Nothing to update.", L"HashCheck", MB_ICONERROR | MB_SYSTEMMODAL);
+ exitcode = -5;
+ break;
+ case HashFileProcessor::ProcessResult::Success:
+ if (checking_)
+ {
+ MessageBoxW(NULL, L"All files OK.", L"HashCheck", MB_ICONINFORMATION | MB_SYSTEMMODAL);
+ }
+ else if (updating_)
+ {
+ MessageBoxW(NULL, L"Hash file was updated successfully.", L"HashCheck", MB_ICONINFORMATION | MB_SYSTEMMODAL);
+ }
+ else
+ {
+ MessageBoxW(NULL, L"Hash file was created successfully.", L"HashCheck", MB_ICONINFORMATION | MB_SYSTEMMODAL);
+ }
+ break;
+ default:
+ break;
+ }
+
+ if (viewreport)
+ {
+ WCHAR tempfile[MAX_PATH];
+ WCHAR tempfolder[MAX_PATH];
+ GetTempPathW(MAX_PATH, tempfolder);
+ GetTempFileNameW(tempfolder, L"HashCheck", 0, tempfile);
+ hashfileprocessor.SaveReport(tempfile);
+ ViewReport(tempfile);
+ }
+
+ return exitcode;
+}
+
+std::wstring HashCheck::GetAppFileName(LPCWSTR apptitle) const
+{
+ std::wstring temp = apptitle;
+ auto pos1 = temp.rfind(L"\\") + 1;
+ auto pos2 = temp.rfind(L".") + 4 - pos1;
+ return temp.substr(pos1, pos2);
+}
+
+BOOL HashCheck::ViewReport(LPCWSTR filepath) const
+{
+ WCHAR cmdline[255];
+ lstrcpyW(cmdline, L"notepad.exe ");
+ lstrcatW(cmdline, filepath);
+ STARTUPINFOW si;
+ ZeroMemory(&si, sizeof(si));
+ si.cb = sizeof(si);
+ PROCESS_INFORMATION pi;
+ ZeroMemory(&pi, sizeof(pi));
+ if (CreateProcessW(NULL, cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi))
+ {
+ WaitForSingleObject(pi.hProcess, INFINITE);
+ CloseHandle(pi.hProcess);
+ CloseHandle(pi.hThread);
+ return TRUE;
+ }
+ return FALSE;
+}
+
diff --git a/tests/resources/issue_3020/HashCheck.h b/tests/resources/issue_3020/HashCheck.h new file mode 100644 index 000000000..91d7869ee --- /dev/null +++ b/tests/resources/issue_3020/HashCheck.h @@ -0,0 +1,41 @@ +/* Author: macote */
+
+#ifndef HASHCHECK_H_
+#define HASHCHECK_H_
+
+#define _CRT_SECURE_NO_WARNINGS
+
+#include "HashType.h"
+#include "HashFileProcessor.h"
+#include <vector>
+#include <string>
+#include <algorithm>
+#include <Windows.h>
+
+class HashCheck
+{
+private:
+ static LPCWSTR kHashFileBaseName;
+public:
+ HashCheck(std::vector<std::wstring> args) : args_(args)
+ {
+ Initialize();
+ };
+ int Process() const;
+private:
+ void Initialize();
+ std::wstring GetAppFileName(LPCWSTR apptitle) const;
+ BOOL ViewReport(LPCWSTR filepath) const;
+private:
+ std::vector<std::wstring> args_;
+ std::wstring hashfilename_;
+ std::wstring basepath_;
+ std::wstring appfilename_;
+ HashType hashtype_;
+ BOOL silent_;
+ BOOL checking_;
+ BOOL updating_;
+ BOOL skipcheck_;
+};
+
+#endif /* HASHCHECK_H_ */
diff --git a/tests/resources/issue_3020/HashCheck.ico b/tests/resources/issue_3020/HashCheck.ico Binary files differnew file mode 100644 index 000000000..766cc897e --- /dev/null +++ b/tests/resources/issue_3020/HashCheck.ico diff --git a/tests/resources/issue_3020/HashCheckWindow.cpp b/tests/resources/issue_3020/HashCheckWindow.cpp new file mode 100644 index 000000000..bedbaa46c --- /dev/null +++ b/tests/resources/issue_3020/HashCheckWindow.cpp @@ -0,0 +1,50 @@ +/* Author: macote */
+
+#include "HashCheckWindow.h"
+
+LRESULT HashCheckWindow::OnCreate()
+{
+ return 0;
+}
+
+LRESULT HashCheckWindow::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ switch (uMsg)
+ {
+ case WM_CREATE:
+ return OnCreate();
+ case WM_NCDESTROY:
+ // Death of the root window ends the thread
+ PostQuitMessage(0);
+ break;
+ case WM_SIZE:
+ if (hwndChild_)
+ {
+ SetWindowPos(hwndChild_, NULL, 0, 0, GET_X_LPARAM(lParam),
+ GET_Y_LPARAM(lParam), SWP_NOZORDER | SWP_NOACTIVATE);
+ }
+ return 0;
+ case WM_SETFOCUS:
+ if (hwndChild_)
+ {
+ SetFocus(hwndChild_);
+ }
+ return 0;
+ }
+ return Window::HandleMessage(uMsg, wParam, lParam);
+}
+
+HashCheckWindow* HashCheckWindow::Create(HINSTANCE hInst)
+{
+ auto self = new HashCheckWindow(hInst);
+ if (self != NULL)
+ {
+ if (self->WinCreateWindow(0, L"HashCheckWindow", WS_OVERLAPPEDWINDOW,
+ CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL))
+ {
+ return self;
+ }
+ delete self;
+ }
+ return NULL;
+}
diff --git a/tests/resources/issue_3020/HashCheckWindow.h b/tests/resources/issue_3020/HashCheckWindow.h new file mode 100644 index 000000000..f0ea3d6fa --- /dev/null +++ b/tests/resources/issue_3020/HashCheckWindow.h @@ -0,0 +1,27 @@ +/* Author: macote */
+
+#ifndef HASHCHECKWINDOW_H_
+#define HASHCHECKWINDOW_H_
+
+#include "Window.h"
+#include <Windows.h>
+#include <windowsx.h>
+
+class HashCheckWindow : public Window
+{
+public:
+#if _MSC_VER < 1900
+ HashCheckWindow(HINSTANCE hinst) : Window(hinst) { };
+#else
+ using Window::Window;
+#endif
+ virtual LPCWSTR ClassName() { return L"HashCheckWindow"; }
+ static HashCheckWindow *Create(HINSTANCE hInst);
+protected:
+ LRESULT HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam);
+ LRESULT OnCreate();
+private:
+ HWND hwndChild_;
+};
+
+#endif /* HASHCHECKWINDOW_H_ */
\ No newline at end of file diff --git a/tests/resources/issue_3020/HashFile.cpp b/tests/resources/issue_3020/HashFile.cpp new file mode 100644 index 000000000..c0f2aef32 --- /dev/null +++ b/tests/resources/issue_3020/HashFile.cpp @@ -0,0 +1,110 @@ +/* Author: macote */
+
+#include "HashFile.h"
+
+const FileEntry HashFile::kFileEntryNull = FileEntry(L"", LARGE_INTEGER(), L"");
+
+void HashFile::Load(const std::wstring& hashfilepath)
+{
+ FileStream hashfile(hashfilepath.c_str(), FileStream::Mode::Open);
+ StreamLineReader hashfilereader(hashfile);
+ WCHAR buffer[2048];
+ std::wstring line, key, sizetemp, filepath, digest;
+ std::wstring::size_type pos1, pos2;
+ LARGE_INTEGER size;
+ // hash line format: <filepath>|<size>|<digest>
+ do
+ {
+ line = hashfilereader.ReadLine();
+ if (IsValidHashLine(line))
+ {
+ pos1 = line.find('|', 0);
+ filepath = line.substr(0, pos1);
+ lstrcpyW(buffer, filepath.c_str());
+ key = CharUpperW(buffer);
+ pos2 = line.find('|', pos1 + 1);
+ sizetemp = line.substr(pos1 + 1, pos2 - (pos1 + 1));
+ std::wstringstream wss(sizetemp);
+ wss >> size.QuadPart;
+ digest = line.substr(pos2 + 1, line.size() - pos2);
+ files_.insert(std::pair<std::wstring, FileEntry>(key, FileEntry(filepath, size, digest)));
+ }
+ } while (!hashfilereader.EndOfStream());
+}
+
+void HashFile::Save(const std::wstring& hashfilepath) const
+{
+ FileStream hashfile(hashfilepath, FileStream::Mode::Create);
+ StreamLineWriter hashfilewriter(hashfile);
+ for (auto& item : files_)
+ {
+ auto fileentry = item.second;
+ hashfilewriter.WriteLine(fileentry.filepath() + L"|" + LargeIntToString(fileentry.size()) + L"|" + fileentry.digest());
+ }
+}
+
+void HashFile::AddFileEntry(const std::wstring filepath, const LARGE_INTEGER size, const std::wstring digest)
+{
+ files_.insert(std::pair<std::wstring, FileEntry>(filepath, FileEntry(filepath, size, digest)));
+}
+
+std::map<std::wstring, FileEntry, std::less<std::wstring>>::const_iterator HashFile::FindEntry(const std::wstring& filepath) const
+{
+ WCHAR key[2048];
+ lstrcpyW(key, filepath.c_str());
+ CharUpperW(key);
+ return files_.find(key);
+}
+
+void HashFile::RemoveFileEntry(const std::wstring& filepath)
+{
+ auto i = FindEntry(filepath);
+ if (i != files_.end())
+ {
+ files_.erase(i);
+ }
+}
+
+BOOL HashFile::ContainsFileEntry(const std::wstring& filepath) const
+{
+ auto i = FindEntry(filepath);
+ return i != files_.end();
+}
+
+const FileEntry& HashFile::GetFileEntry(const std::wstring& filepath) const
+{
+ auto i = FindEntry(filepath);
+ if (i != files_.end())
+ {
+ return (*i).second;
+ }
+ else
+ {
+ return kFileEntryNull;
+ }
+}
+
+std::list<std::wstring> HashFile::GetFilePaths() const
+{
+ std::list<std::wstring> filepaths;
+ for (auto& item : files_)
+ {
+ filepaths.push_back(item.second.filepath());
+ }
+ return filepaths;
+}
+
+BOOL HashFile::IsValidHashLine(const std::wstring& fileentryline) const
+{
+ if (fileentryline.size() == 0) return FALSE;
+ if (fileentryline.size() > 2176) return FALSE;
+ // TODO: implement proper hash line validation
+ return TRUE;
+}
+
+std::wstring HashFile::LargeIntToString(const LARGE_INTEGER& li) const
+{
+ std::wstringstream wss;
+ wss << li.QuadPart;
+ return wss.str();
+}
diff --git a/tests/resources/issue_3020/HashFile.h b/tests/resources/issue_3020/HashFile.h new file mode 100644 index 000000000..f6bb6b64a --- /dev/null +++ b/tests/resources/issue_3020/HashFile.h @@ -0,0 +1,55 @@ +/* Author: macote */
+
+#ifndef HASHFILE_H_
+#define HASHFILE_H_
+
+#include "FileStream.h"
+#include "StreamLineReader.h"
+#include "StreamLineWriter.h"
+#include <sstream>
+#include <list>
+#include <map>
+#include <string>
+#include <Windows.h>
+
+class FileEntry
+{
+public:
+ FileEntry(const std::wstring filepath, const LARGE_INTEGER size, const std::wstring digest)
+ : filepath_(filepath), size_(size), digest_(digest) { };
+ std::wstring filepath() const { return filepath_; }
+ LARGE_INTEGER size() const { return size_; }
+ std::wstring digest() const { return digest_; }
+private:
+ const std::wstring filepath_;
+ const LARGE_INTEGER size_;
+ const std::wstring digest_;
+};
+
+class HashFile
+{
+public:
+ static const FileEntry kFileEntryNull;
+public:
+ HashFile() { };
+ ~HashFile()
+ {
+ files_.clear();
+ }
+ void Save(const std::wstring& hashfilepath) const;
+ void Load(const std::wstring& hashfilepath);
+ void AddFileEntry(const std::wstring filepath, const LARGE_INTEGER li, const std::wstring digest);
+ void RemoveFileEntry(const std::wstring& filepath);
+ BOOL IsEmpty() const { return files_.size() == 0; }
+ BOOL ContainsFileEntry(const std::wstring& filepath) const;
+ const FileEntry& GetFileEntry(const std::wstring& filepath) const;
+ std::list<std::wstring> GetFilePaths() const;
+private:
+ std::map<std::wstring, FileEntry, std::less<std::wstring>>::const_iterator FindEntry(const std::wstring& filepath) const;
+ BOOL IsValidHashLine(const std::wstring& fileentryline) const;
+ std::wstring LargeIntToString(const LARGE_INTEGER& li) const;
+private:
+ std::map<std::wstring, FileEntry, std::less<std::wstring>> files_;
+};
+
+#endif /* HASHFILE_H_ */
diff --git a/tests/resources/issue_3020/HashFileProcessor.cpp b/tests/resources/issue_3020/HashFileProcessor.cpp new file mode 100644 index 000000000..772f1a92a --- /dev/null +++ b/tests/resources/issue_3020/HashFileProcessor.cpp @@ -0,0 +1,157 @@ +/* Author: macote */
+
+#include "HashFileProcessor.h"
+
+HashFileProcessor::ProcessResult HashFileProcessor::ProcessTree()
+{
+ auto result = ProcessResult::Success;
+ newfilesupdated_ = FALSE;
+ if (mode_ == HashFileProcessor::Mode::Verify || mode_ == HashFileProcessor::Mode::Update)
+ {
+ try
+ {
+ hashfile_.Load(hashfilename_);
+ }
+ catch (...)
+ {
+ result = ProcessResult::CouldNotOpenHashFile;
+ return result;
+ }
+ }
+ FileTree filetree(basepath_, *this);
+ filetree.Process();
+ if (mode_ == HashFileProcessor::Mode::Create)
+ {
+ if (hashfile_.IsEmpty())
+ {
+ result = ProcessResult::NoFileToProcess;
+ }
+ else if (!report_.IsEmpty())
+ {
+ result = ProcessResult::ErrorsOccurredWhileProcessing;
+ }
+ else
+ {
+ hashfile_.Save(hashfilename_);
+ }
+ }
+ else if (mode_ == HashFileProcessor::Mode::Verify || mode_ == HashFileProcessor::Mode::Update)
+ {
+ if (!hashfile_.IsEmpty())
+ {
+ for (auto& relativefilepath : hashfile_.GetFilePaths())
+ {
+ // TODO: replace hardcoded text
+ report_.AddLine(L"Missing : " + relativefilepath);
+ }
+ result = ProcessResult::FilesAreMissing;
+ }
+ else if (!report_.IsEmpty())
+ {
+ result = ProcessResult::ErrorsOccurredWhileProcessing;
+ }
+ else if (mode_ == HashFileProcessor::Mode::Update)
+ {
+ if (!newfilesupdated_)
+ {
+ result = ProcessResult::NothingToUpdate;
+ }
+ else
+ {
+ // replace old hash file
+ DeleteFileW(hashfilename_.c_str());
+ newhashfile_.Save(hashfilename_);
+ }
+ }
+ }
+ return result;
+}
+
+void HashFileProcessor::ProcessFile(const std::wstring& filepath)
+{
+ if (lstrcmpiW(appfilepath_.c_str(), filepath.c_str()) == 0 || lstrcmpiW(hashfilename_.c_str(), filepath.c_str()) == 0)
+ {
+ // skip self and current hash file
+ return;
+ }
+ auto relativefilepath = filepath.substr(basepath_.length(), filepath.length());
+ const FileEntry& fileentry = hashfile_.GetFileEntry(relativefilepath);
+ if (mode_ == HashFileProcessor::Mode::Verify)
+ {
+ if (&fileentry == &HashFile::kFileEntryNull)
+ {
+ report_.AddLine(L"Unknown : " + relativefilepath);
+ return;
+ }
+ }
+ else if (mode_ == HashFileProcessor::Mode::Update)
+ {
+ if (&fileentry == &HashFile::kFileEntryNull)
+ {
+ newhashfile_.AddFileEntry(fileentry.filepath(), fileentry.size(), fileentry.digest());
+ hashfile_.RemoveFileEntry(relativefilepath);
+ return;
+ }
+ }
+ LARGE_INTEGER size;
+ size.QuadPart = 0;
+ auto file = CreateFileW(filepath.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL,
+ OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+ if (file != INVALID_HANDLE_VALUE)
+ {
+ GetFileSizeEx(file, &size);
+ CloseHandle(file);
+ }
+ else
+ {
+ report_.AddLine(L"Error opening file : " + relativefilepath);
+ if (mode_ == HashFileProcessor::Mode::Verify)
+ {
+ hashfile_.RemoveFileEntry(relativefilepath);
+ }
+ return;
+ }
+ if (mode_ == HashFileProcessor::Mode::Verify)
+ {
+ if (size.QuadPart != fileentry.size().QuadPart)
+ {
+ report_.AddLine(L"Incorrect file size : " + relativefilepath);
+ hashfile_.RemoveFileEntry(relativefilepath);
+ return;
+ }
+ }
+ auto filehash = FileHashFactory::Create(hashtype_, filepath);
+ if (progressevent_ != nullptr)
+ {
+ hfppea_.bytesprocessed.QuadPart = 0;
+ hfppea_.relativefilepath = relativefilepath;
+ progressevent_(hfppea_);
+ filehash->SetBytesProcessedEventHandler([this](FileHashBytesProcessedEventArgs fhbea) {
+ this->hfppea_.bytesprocessed = fhbea.bytesprocessed;
+ this->progressevent_(hfppea_);
+ }, bytesprocessednotificationblocksize_);
+ }
+ filehash->Compute();
+ std::wstring digest = filehash->digest();
+ if (mode_ == HashFileProcessor::Mode::Create)
+ {
+ hashfile_.AddFileEntry(relativefilepath, size, digest);
+ }
+ else if (mode_ == HashFileProcessor::Mode::Update)
+ {
+ newhashfile_.AddFileEntry(relativefilepath, size, digest);
+ newfilesupdated_ = TRUE;
+ }
+ else if (mode_ == HashFileProcessor::Mode::Verify)
+ {
+ if (size.QuadPart != fileentry.size().QuadPart)
+ {
+ report_.AddLine(L"Incorrect file size : " + relativefilepath);
+ }
+ else if (digest != fileentry.digest())
+ {
+ report_.AddLine(L"Incorrect hash : " + relativefilepath);
+ }
+ hashfile_.RemoveFileEntry(relativefilepath);
+ }
+}
diff --git a/tests/resources/issue_3020/HashFileProcessor.h b/tests/resources/issue_3020/HashFileProcessor.h new file mode 100644 index 000000000..98c996709 --- /dev/null +++ b/tests/resources/issue_3020/HashFileProcessor.h @@ -0,0 +1,67 @@ +/* Author: macote */
+
+#include "HashFile.h"
+#include "FileTree.h"
+#include "HashType.h"
+#include "FileHashFactory.h"
+#include "Report.h"
+
+struct HashFileProcessorProgressEventArgs
+{
+ std::wstring relativefilepath;
+ LARGE_INTEGER bytesprocessed;
+};
+
+class HashFileProcessor : public IFileTreeAction
+{
+public:
+ static const DWORD kDefaultBytesProcessedNotificationBlockSize = 1048576;
+public:
+ enum class Mode
+ {
+ Create,
+ Update,
+ Verify,
+ Undefined
+ };
+ enum class ProcessResult
+ {
+ FilesAreMissing,
+ NothingToUpdate,
+ CouldNotOpenHashFile,
+ ErrorsOccurredWhileProcessing,
+ NoFileToProcess,
+ Success
+ };
+ HashFileProcessor(Mode mode, HashType hashtype, std::wstring hashfilename, std::wstring appfilepath, std::wstring basepath)
+ : mode_(mode), hashtype_(hashtype), hashfilename_(hashfilename), appfilepath_(appfilepath), basepath_(basepath)
+ {
+ progressevent_ = nullptr;
+ };
+ ProcessResult ProcessTree();
+ void ProcessFile(const std::wstring& filepath);
+ void SaveReport(const std::wstring& reportpath) const { report_.Save(reportpath); }
+ void SetProgressEventHandler(std::function<void(HashFileProcessorProgressEventArgs)> handler)
+ {
+ SetProgressEventHandler(handler, kDefaultBytesProcessedNotificationBlockSize);
+ }
+ void SetProgressEventHandler(std::function<void(HashFileProcessorProgressEventArgs)> handler,
+ const DWORD bytesprocessednotificationblocksize)
+ {
+ progressevent_ = handler;
+ bytesprocessednotificationblocksize_ = bytesprocessednotificationblocksize;
+ }
+private:
+ Mode mode_;
+ HashType hashtype_;
+ HashFile hashfile_;
+ HashFile newhashfile_;
+ std::wstring hashfilename_;
+ std::wstring appfilepath_;
+ std::wstring basepath_;
+ BOOL newfilesupdated_ = FALSE;
+ Report report_;
+ HashFileProcessorProgressEventArgs hfppea_;
+ DWORD bytesprocessednotificationblocksize_;
+ std::function<void(HashFileProcessorProgressEventArgs)> progressevent_;
+};
diff --git a/tests/resources/issue_3020/HashType.h b/tests/resources/issue_3020/HashType.h new file mode 100644 index 000000000..5ee9c5189 --- /dev/null +++ b/tests/resources/issue_3020/HashType.h @@ -0,0 +1,14 @@ +/* Author: macote */
+
+#ifndef HASHTYPE_H_
+#define HASHTYPE_H_
+
+enum class HashType
+{
+ CRC32,
+ MD5,
+ SHA1,
+ Undefined
+};
+
+#endif /* HASHTYPE_H_ */
diff --git a/tests/resources/issue_3020/MD5FileHash.cpp b/tests/resources/issue_3020/MD5FileHash.cpp new file mode 100644 index 000000000..3aea65954 --- /dev/null +++ b/tests/resources/issue_3020/MD5FileHash.cpp @@ -0,0 +1,177 @@ +
+
+void MD5FileHash::Update(const UINT32 bytecount)
+{
+ UINT32 index = context_.count[0]; // update bitcount
+ context_.count[0] = index + (bytecount << 3);
+ if (context_.count[0] < index)
+ {
+ context_.count[1]++; // carry from low to high
+ }
+ context_.count[1] += bytecount >> 29;
+ index = (index >> 3) & 63; // bytes already in shsInfo->data
+ UINT32 bytesleft = bytecount;
+ if (index > 0)
+ {
+ // handle any leading odd-sized chunks
+ PBYTE ctxbuffer = (PBYTE)context_.buffer + index;
+ index = 64 - index;
+ if (bytecount < index)
+ {
+ CopyMemory(ctxbuffer, buffer_, bytecount);
+ return;
+ }
+ CopyMemory(ctxbuffer, buffer_, index);
+ Transform(context_.state, (PUINT32)context_.buffer);
+ ctxbuffer += index;
+ bytesleft -= index;
+ }
+ // process data in 64-byte chunks
+ PBYTE buffer = buffer_;
+ while (bytesleft >= 64)
+ {
+ CopyMemory(context_.buffer, buffer, sizeof(context_.buffer));
+ Transform(context_.state, (PUINT32)context_.buffer);
+ buffer += 64;
+ bytesleft -= 64;
+ }
+ // handle any remaining bytes of data.
+ CopyMemory(context_.buffer, buffer, bytesleft);
+}
+
+void MD5FileHash::Finalize()
+{
+ UINT32 index = (context_.count[0] >> 3) & 63; // compute number of bytes mod 64
+ // set the first char of padding to 0x80. this is safe since there is
+ // always at least one byte free
+ PBYTE ctxbuffer = context_.buffer + index;
+ *ctxbuffer++ = 0x80;
+ index = 64 - 1 - index; // bytes of padding needed to make 64 bytes
+ // pad out to 56 mod 64
+ if (index < 8)
+ {
+ // two lots of padding: pad the first block to 64 bytes
+ ZeroMemory(ctxbuffer, index);
+ Transform(context_.state, (PUINT32)context_.buffer);
+ // now fill the next block with 56 bytes
+ ZeroMemory(context_.buffer, 56);
+ }
+ else
+ {
+ ZeroMemory(ctxbuffer, index - 8); // pad block to 56 bytes
+ }
+ // append length in bits and transform
+ typedef union
+ {
+ BYTE c[64];
+ UINT32 l[16];
+ } CHAR64LONG16, *PCHAR64LONG16;
+ PCHAR64LONG16 bufferlong = (PCHAR64LONG16)context_.buffer;
+ bufferlong->l[14] = context_.count[0];
+ bufferlong->l[15] = context_.count[1];
+ Transform(context_.state, (PUINT32)context_.buffer);
+ CopyMemory(hash_, context_.state, sizeof(hash_));
+}
+
+void MD5FileHash::ConvertHashToDigestString()
+{
+ std::wstringstream wss;
+ wss << std::hex << std::setw(2) << std::setfill(L'0') << std::uppercase;
+ for (UINT i = 0; i < sizeof(hash_); i++)
+ {
+ wss << hash_[i];
+ }
+ digest_.append(wss.str());
+}
+
+void MD5FileHash::Transform(UINT32 state[4], PUINT32 buffer)
+{
+ register UINT32 a, b, c, d;
+
+ a = state[0];
+ b = state[1];
+ c = state[2];
+ d = state[3];
+
+#define F1(x, y, z) (z ^ (x & (y ^ z)))
+#define F2(x, y, z) F1(z, x, y)
+#define F3(x, y, z) (x ^ y ^ z)
+#define F4(x, y, z) (y ^ (x | ~z))
+
+#define MD5STEP(f, w, x, y, z, data, s) (w += f(x, y, z) + data, w = w << s | w >> (32 - s), w += x)
+
+ MD5STEP(F1, a, b, c, d, buffer[0] + 0xD76AA478L, 7);
+ MD5STEP(F1, d, a, b, c, buffer[1] + 0xE8C7B756L, 12);
+ MD5STEP(F1, c, d, a, b, buffer[2] + 0x242070DBL, 17);
+ MD5STEP(F1, b, c, d, a, buffer[3] + 0xC1BDCEEEL, 22);
+ MD5STEP(F1, a, b, c, d, buffer[4] + 0xF57C0FAFL, 7);
+ MD5STEP(F1, d, a, b, c, buffer[5] + 0x4787C62AL, 12);
+ MD5STEP(F1, c, d, a, b, buffer[6] + 0xA8304613L, 17);
+ MD5STEP(F1, b, c, d, a, buffer[7] + 0xFD469501L, 22);
+ MD5STEP(F1, a, b, c, d, buffer[8] + 0x698098D8L, 7);
+ MD5STEP(F1, d, a, b, c, buffer[9] + 0x8B44F7AFL, 12);
+ MD5STEP(F1, c, d, a, b, buffer[10] + 0xFFFF5BB1L, 17);
+ MD5STEP(F1, b, c, d, a, buffer[11] + 0x895CD7BEL, 22);
+ MD5STEP(F1, a, b, c, d, buffer[12] + 0x6B901122L, 7);
+ MD5STEP(F1, d, a, b, c, buffer[13] + 0xFD987193L, 12);
+ MD5STEP(F1, c, d, a, b, buffer[14] + 0xA679438EL, 17);
+ MD5STEP(F1, b, c, d, a, buffer[15] + 0x49B40821L, 22);
+
+ MD5STEP(F2, a, b, c, d, buffer[1] + 0xF61E2562L, 5);
+ MD5STEP(F2, d, a, b, c, buffer[6] + 0xC040B340L, 9);
+ MD5STEP(F2, c, d, a, b, buffer[11] + 0x265E5A51L, 14);
+ MD5STEP(F2, b, c, d, a, buffer[0] + 0xE9B6C7AAL, 20);
+ MD5STEP(F2, a, b, c, d, buffer[5] + 0xD62F105DL, 5);
+ MD5STEP(F2, d, a, b, c, buffer[10] + 0x02441453L, 9);
+ MD5STEP(F2, c, d, a, b, buffer[15] + 0xD8A1E681L, 14);
+ MD5STEP(F2, b, c, d, a, buffer[4] + 0xE7D3FBC8L, 20);
+ MD5STEP(F2, a, b, c, d, buffer[9] + 0x21E1CDE6L, 5);
+ MD5STEP(F2, d, a, b, c, buffer[14] + 0xC33707D6L, 9);
+ MD5STEP(F2, c, d, a, b, buffer[3] + 0xF4D50D87L, 14);
+ MD5STEP(F2, b, c, d, a, buffer[8] + 0x455A14EDL, 20);
+ MD5STEP(F2, a, b, c, d, buffer[13] + 0xA9E3E905L, 5);
+ MD5STEP(F2, d, a, b, c, buffer[2] + 0xFCEFA3F8L, 9);
+ MD5STEP(F2, c, d, a, b, buffer[7] + 0x676F02D9L, 14);
+ MD5STEP(F2, b, c, d, a, buffer[12] + 0x8D2A4C8AL, 20);
+
+ MD5STEP(F3, a, b, c, d, buffer[5] + 0xFFFA3942L, 4);
+ MD5STEP(F3, d, a, b, c, buffer[8] + 0x8771F681L, 11);
+ MD5STEP(F3, c, d, a, b, buffer[11] + 0x6D9D6122L, 16);
+ MD5STEP(F3, b, c, d, a, buffer[14] + 0xFDE5380CL, 23);
+ MD5STEP(F3, a, b, c, d, buffer[1] + 0xA4BEEA44L, 4);
+ MD5STEP(F3, d, a, b, c, buffer[4] + 0x4BDECFA9L, 11);
+ MD5STEP(F3, c, d, a, b, buffer[7] + 0xF6BB4B60L, 16);
+ MD5STEP(F3, b, c, d, a, buffer[10] + 0xBEBFBC70L, 23);
+ MD5STEP(F3, a, b, c, d, buffer[13] + 0x289B7EC6L, 4);
+ MD5STEP(F3, d, a, b, c, buffer[0] + 0xEAA127FAL, 11);
+ MD5STEP(F3, c, d, a, b, buffer[3] + 0xD4EF3085L, 16);
+ MD5STEP(F3, b, c, d, a, buffer[6] + 0x04881D05L, 23);
+ MD5STEP(F3, a, b, c, d, buffer[9] + 0xD9D4D039L, 4);
+ MD5STEP(F3, d, a, b, c, buffer[12] + 0xE6DB99E5L, 11);
+ MD5STEP(F3, c, d, a, b, buffer[15] + 0x1FA27CF8L, 16);
+ MD5STEP(F3, b, c, d, a, buffer[2] + 0xC4AC5665L, 23);
+
+ MD5STEP(F4, a, b, c, d, buffer[0] + 0xF4292244L, 6);
+ MD5STEP(F4, d, a, b, c, buffer[7] + 0x432AFF97L, 10);
+ MD5STEP(F4, c, d, a, b, buffer[14] + 0xAB9423A7L, 15);
+ MD5STEP(F4, b, c, d, a, buffer[5] + 0xFC93A039L, 21);
+ MD5STEP(F4, a, b, c, d, buffer[12] + 0x655B59C3L, 6);
+ MD5STEP(F4, d, a, b, c, buffer[3] + 0x8F0CCC92L, 10);
+ MD5STEP(F4, c, d, a, b, buffer[10] + 0xFFEFF47DL, 15);
+ MD5STEP(F4, b, c, d, a, buffer[1] + 0x85845DD1L, 21);
+ MD5STEP(F4, a, b, c, d, buffer[8] + 0x6FA87E4FL, 6);
+ MD5STEP(F4, d, a, b, c, buffer[15] + 0xFE2CE6E0L, 10);
+ MD5STEP(F4, c, d, a, b, buffer[6] + 0xA3014314L, 15);
+ MD5STEP(F4, b, c, d, a, buffer[13] + 0x4E0811A1L, 21);
+ MD5STEP(F4, a, b, c, d, buffer[4] + 0xF7537E82L, 6);
+ MD5STEP(F4, d, a, b, c, buffer[11] + 0xBD3AF235L, 10);
+ MD5STEP(F4, c, d, a, b, buffer[2] + 0x2AD7D2BBL, 15);
+ MD5STEP(F4, b, c, d, a, buffer[9] + 0xEB86D391L, 21);
+
+ state[0] += a;
+ state[1] += b;
+ state[2] += c;
+ state[3] += d;
+
+ a = b = c = d = 0;
+}
diff --git a/tests/resources/issue_3020/MD5FileHash.h b/tests/resources/issue_3020/MD5FileHash.h new file mode 100644 index 000000000..b008070f9 --- /dev/null +++ b/tests/resources/issue_3020/MD5FileHash.h @@ -0,0 +1,38 @@ +/* Author: macote */
+
+#ifndef MD5FILEHASH_H_
+#define MD5FILEHASH_H_
+
+#include "FileHash.h"
+#include <iomanip>
+#include <sstream>
+#include <string>
+#include <Windows.h>
+
+struct MD5Context
+{
+ UINT32 state[4]; // state (ABCD)
+ UINT32 count[2]; // number of bits, modulo 2^64 (lsb first)
+ BYTE buffer[64]; // input buffer
+};
+
+class MD5FileHash : public FileHash
+{
+public:
+#if _MSC_VER < 1900
+ MD5FileHash(const std::wstring& filepath, const DWORD buffersize) : FileHash(filepath, buffersize) { };
+ MD5FileHash(const std::wstring& filepath) : FileHash(filepath) { };
+#else
+ using FileHash::FileHash;
+#endif
+private:
+ void Initialize();
+ void Update(const UINT32 bytecount);
+ void Finalize();
+ void Transform(UINT32 state[4], PUINT32 buffer);
+ void ConvertHashToDigestString();
+ BYTE hash_[16];
+ MD5Context context_;
+};
+
+#endif /* MD5FILEHASH_H_ */
diff --git a/tests/resources/issue_3020/Program.cpp b/tests/resources/issue_3020/Program.cpp new file mode 100644 index 000000000..b765e0c03 --- /dev/null +++ b/tests/resources/issue_3020/Program.cpp @@ -0,0 +1,53 @@ +/* Author: macote */
+
+#ifndef UNICODE
+#define UNICODE
+#endif
+#ifndef _UNICODE
+#define _UNICODE
+#endif
+
+#define WIN32_LEAN_AND_MEAN
+
+#include "HashCheck.h"
+#include "HashCheckWindow.h"
+#include <string>
+#include <vector>
+#include <Windows.h>
+#include <Ole2.h>
+#include <CommCtrl.h>
+#include <shellapi.h>
+
+int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
+{
+ int argscount;
+ auto args = CommandLineToArgvW(GetCommandLineW(), &argscount);
+ std::vector<std::wstring> argsvector;
+ for (int i = 0; i < argscount; ++i)
+ {
+ argsvector.push_back(args[i]);
+ }
+ LocalFree(args);
+
+ //if (SUCCEEDED(CoInitialize(NULL)))
+ //{
+ // InitCommonControls();
+ // HashCheckWindow *hcw = HashCheckWindow::Create(hInstance);
+ // if (hcw)
+ // {
+ // ShowWindow(hcw->GetHWND(), nCmdShow);
+ // MSG msg;
+ // while (GetMessage(&msg, NULL, 0, 0))
+ // {
+ // TranslateMessage(&msg);
+ // DispatchMessage(&msg);
+ // }
+ // }
+ // CoUninitialize();
+ //}
+
+ HashCheck hc(argsvector);
+ auto result = hc.Process();
+
+ return result;
+}
diff --git a/tests/resources/issue_3020/README.md b/tests/resources/issue_3020/README.md new file mode 100644 index 000000000..37e3522b5 --- /dev/null +++ b/tests/resources/issue_3020/README.md @@ -0,0 +1,48 @@ +HashCheck for Windows
+=====================
+
+HashCheck is a Windows application that creates and verifies file checksums.
+
+
+How to build
+------------
+
+This project is compatible with:
+- Visual Studio 2013
+- Eclipse Luna CDT with MinGW (GCC 4.8.1)
+
+
+Usage
+-----
+
+Launch the executable to create a checksum file if it does not already exists.
+
+Launch the executable to verify file integrity against a checksum file if it exists.
+
+
+License
+-------
+
+Hashing code found on the Internet is in the public domain:
+
+MD5: Colin Plumb (1993) / John Walker (2003)
+
+SHA1: Steve Reid (199?) / ... / Ralph Giles (2002)
+
+FileStream code inspired by dotnet/corefx's Win32FileStream.cs. See FileStream.cpp for licensing information.
+
+
+FAQ
+---
+
+### Why MinGW?
+
+I wanted to have an executable having the least runtime dependencies possible.
+
+### Why FileStream?
+
+MinGW's fstream can't open WCHAR filenames and I was not interested in changing fstream's implementation.
+
+### What's the coding style?
+
+The coding style is inspired from Google C++ [coding style guide](http://google-styleguide.googlecode.com/svn/trunk/cppguide.html "Google C++ Style Guide").
diff --git a/tests/resources/issue_3020/Report.h b/tests/resources/issue_3020/Report.h new file mode 100644 index 000000000..98b0b0d1f --- /dev/null +++ b/tests/resources/issue_3020/Report.h @@ -0,0 +1,30 @@ +/* Author: macote */
+
+#ifndef REPORT_H_
+#define REPORT_H_
+
+#include "FileStream.h"
+#include "StreamLineWriter.h"
+#include <string>
+#include <list>
+#include <Windows.h>
+
+class Report
+{
+public:
+ void AddLine(const std::wstring line) { report_.push_back(line); };
+ void Save(const std::wstring& reportpath) const
+ {
+ FileStream reportfile(reportpath, FileStream::Mode::Truncate);
+ StreamLineWriter reportfilewriter(reportfile);
+ for (auto& item : report_)
+ {
+ reportfilewriter.WriteLine(item);
+ }
+ };
+ BOOL IsEmpty() { return report_.size() == 0; }
+private:
+ std::list<std::wstring> report_;
+};
+
+#endif /* REPORT_H_ */
\ No newline at end of file diff --git a/tests/resources/issue_3020/SHA1FileHash.cpp b/tests/resources/issue_3020/SHA1FileHash.cpp new file mode 100644 index 000000000..661e27aae --- /dev/null +++ b/tests/resources/issue_3020/SHA1FileHash.cpp @@ -0,0 +1,132 @@ +/* Author: macote */
+
+#include "SHA1FileHash.h"
+
+void SHA1FileHash::Initialize()
+{
+ context_.state[0] = 0x67452301;
+ context_.state[1] = 0xEFCDAB89;
+ context_.state[2] = 0x98BADCFE;
+ context_.state[3] = 0x10325476;
+ context_.state[4] = 0xC3D2E1F0;
+ context_.count[0] = context_.count[1] = 0;
+}
+
+void SHA1FileHash::Update(const UINT32 bytecount)
+{
+ UINT32 i, index = (context_.count[0] >> 3) & 63;
+ if ((context_.count[0] += bytecount << 3) < (bytecount << 3))
+ {
+ context_.count[1]++;
+ }
+ context_.count[1] += (bytecount >> 29);
+ if ((index + bytecount) > 63)
+ {
+ i = 64 - index;
+ CopyMemory(&context_.buffer[index], buffer_, i);
+ Transform(context_.state, (PUINT32)context_.buffer);
+ for (; i + 63 < bytecount; i += 64)
+ {
+ Transform(context_.state, (PUINT32)(buffer_ + i));
+ }
+ index = 0;
+ }
+ else
+ {
+ i = 0;
+ }
+ CopyMemory(&context_.buffer[index], buffer_ + i, bytecount - i);
+}
+
+void SHA1FileHash::Finalize()
+{
+ BYTE finalcount[8];
+ for (UINT i = 0; i < 8; i++)
+ {
+ finalcount[i] = (BYTE)((context_.count[(i >= 4 ? 0 : 1)] >> ((3 - (i & 3)) * 8)) & 255);
+ }
+ CopyMemory(buffer_, "\200", 1);
+ Update(1);
+ CopyMemory(buffer_, "\0", 1);
+ while ((context_.count[0] & 504) != 448)
+ {
+ Update(1);
+ }
+ CopyMemory(buffer_, finalcount, sizeof(finalcount));
+ Update(8);
+ for (UINT i = 0; i < sizeof(hash_); i++)
+ {
+ hash_[i] = (BYTE)((context_.state[i >> 2] >> ((3 - (i & 3)) * 8)) & 255);
+ }
+}
+
+void SHA1FileHash::ConvertHashToDigestString()
+{
+ std::wstringstream wss;
+ wss << std::hex << std::setw(2) << std::setfill(L'0') << std::uppercase;
+ for (UINT i = 0; i < sizeof(hash_); i++)
+ {
+ wss << hash_[i];
+ }
+ digest_.append(wss.str());
+}
+
+void SHA1FileHash::Transform(UINT32 state[5], PUINT32 buffer)
+{
+ typedef union {
+ BYTE c[64];
+ UINT32 l[16];
+ } CHAR64LONG16, *PCHAR64LONG16;
+ PCHAR64LONG16 block;
+ block = (PCHAR64LONG16)buffer;
+
+ register UINT32 a, b, c, d, e;
+ a = state[0];
+ b = state[1];
+ c = state[2];
+ d = state[3];
+ e = state[4];
+
+#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
+#define blk0(i) (block->l[i] = (rol(block->l[i], 24) & 0xFF00FF00) \
+ | (rol(block->l[i], 8) & 0x00FF00FF))
+#define blk(i) (block->l[i & 15] = rol(block->l[(i + 13) & 15] ^ block->l[(i + 8) & 15] \
+ ^ block->l[(i + 2) & 15] ^ block->l[i & 15], 1))
+#define R0(v, w, x, y, z, i) z += ((w & (x ^ y)) ^ y) + blk0(i) + 0x5A827999 + rol(v, 5); w = rol(w, 30);
+#define R1(v, w, x, y, z, i) z += ((w & (x ^ y)) ^ y) + blk(i) + 0x5A827999 + rol(v, 5); w = rol(w, 30);
+#define R2(v, w, x, y, z, i) z += (w ^ x ^ y) + blk(i) + 0x6ED9EBA1 + rol(v, 5); w = rol(w, 30);
+#define R3(v, w, x, y, z, i) z += (((w | x) & y) | (w & x)) + blk(i) + 0x8F1BBCDC + rol(v, 5); w = rol(w, 30);
+#define R4(v, w, x, y, z, i) z += (w ^ x ^ y) + blk(i) + 0xCA62C1D6 + rol(v, 5); w = rol(w, 30);
+
+ R0(a, b, c, d, e, 0); R0(e, a, b, c, d, 1); R0(d, e, a, b, c, 2); R0(c, d, e, a, b, 3);
+ R0(b, c, d, e, a, 4); R0(a, b, c, d, e, 5); R0(e, a, b, c, d, 6); R0(d, e, a, b, c, 7);
+ R0(c, d, e, a, b, 8); R0(b, c, d, e, a, 9); R0(a, b, c, d, e, 10); R0(e, a, b, c, d, 11);
+ R0(d, e, a, b, c, 12); R0(c, d, e, a, b, 13); R0(b, c, d, e, a, 14); R0(a, b, c, d, e, 15);
+ R1(e, a, b, c, d, 16); R1(d, e, a, b, c, 17); R1(c, d, e, a, b, 18); R1(b, c, d, e, a, 19);
+ R2(a, b, c, d, e, 20); R2(e, a, b, c, d, 21); R2(d, e, a, b, c, 22); R2(c, d, e, a, b, 23);
+ R2(b, c, d, e, a, 24); R2(a, b, c, d, e, 25); R2(e, a, b, c, d, 26); R2(d, e, a, b, c, 27);
+ R2(c, d, e, a, b, 28); R2(b, c, d, e, a, 29); R2(a, b, c, d, e, 30); R2(e, a, b, c, d, 31);
+ R2(d, e, a, b, c, 32); R2(c, d, e, a, b, 33); R2(b, c, d, e, a, 34); R2(a, b, c, d, e, 35);
+ R2(e, a, b, c, d, 36); R2(d, e, a, b, c, 37); R2(c, d, e, a, b, 38); R2(b, c, d, e, a, 39);
+ R3(a, b, c, d, e, 40); R3(e, a, b, c, d, 41); R3(d, e, a, b, c, 42); R3(c, d, e, a, b, 43);
+ R3(b, c, d, e, a, 44); R3(a, b, c, d, e, 45); R3(e, a, b, c, d, 46); R3(d, e, a, b, c, 47);
+ R3(c, d, e, a, b, 48); R3(b, c, d, e, a, 49); R3(a, b, c, d, e, 50); R3(e, a, b, c, d, 51);
+ R3(d, e, a, b, c, 52); R3(c, d, e, a, b, 53); R3(b, c, d, e, a, 54); R3(a, b, c, d, e, 55);
+ R3(e, a, b, c, d, 56); R3(d, e, a, b, c, 57); R3(c, d, e, a, b, 58); R3(b, c, d, e, a, 59);
+ R4(a, b, c, d, e, 60); R4(e, a, b, c, d, 61); R4(d, e, a, b, c, 62); R4(c, d, e, a, b, 63);
+ R4(b, c, d, e, a, 64); R4(a, b, c, d, e, 65); R4(e, a, b, c, d, 66); R4(d, e, a, b, c, 67);
+ R4(c, d, e, a, b, 68); R4(b, c, d, e, a, 69); R4(a, b, c, d, e, 70); R4(e, a, b, c, d, 71);
+ R4(d, e, a, b, c, 72); R4(c, d, e, a, b, 73); R4(b, c, d, e, a, 74); R4(a, b, c, d, e, 75);
+ R4(e, a, b, c, d, 76); R4(d, e, a, b, c, 77); R4(c, d, e, a, b, 78); R4(b, c, d, e, a, 79);
+
+ state[0] += a;
+ state[1] += b;
+ state[2] += c;
+ state[3] += d;
+ state[4] += e;
+
+ a = b = c = d = e = 0;
+}
+
+
+
diff --git a/tests/resources/issue_3020/SHA1FileHash.h b/tests/resources/issue_3020/SHA1FileHash.h new file mode 100644 index 000000000..ff147ae8b --- /dev/null +++ b/tests/resources/issue_3020/SHA1FileHash.h @@ -0,0 +1,38 @@ +/* Author: macote */
+
+#ifndef SHA1FILEHASH_H_
+#define SHA1FILEHASH_H_
+
+#include "FileHash.h"
+#include <iomanip>
+#include <sstream>
+#include <string>
+#include <Windows.h>
+
+struct SHA1Context
+{
+ UINT32 state[5]; // state (ABCDE)
+ UINT32 count[2]; // bits
+ BYTE buffer[64]; // input buffer
+};
+
+class SHA1FileHash : public FileHash
+{
+public:
+#if _MSC_VER < 1900
+ SHA1FileHash(const std::wstring& filepath, const DWORD buffersize) : FileHash(filepath, buffersize) { };
+ SHA1FileHash(const std::wstring& filepath) : FileHash(filepath) { };
+#else
+ using FileHash::FileHash;
+#endif
+private:
+ void Initialize();
+ void Update(const UINT32 bytecount);
+ void Finalize();
+ void Transform(UINT32 state[5], PUINT32 buffer);
+ void ConvertHashToDigestString();
+ BYTE hash_[20];
+ SHA1Context context_;
+};
+
+#endif /* SHA1FILEHASH_H_ */
diff --git a/tests/resources/issue_3020/StreamLineReader.cpp b/tests/resources/issue_3020/StreamLineReader.cpp new file mode 100644 index 000000000..fcdcac43f --- /dev/null +++ b/tests/resources/issue_3020/StreamLineReader.cpp @@ -0,0 +1,78 @@ +/* Author: macote */
+
+#include "StreamLineReader.h"
+
+void StreamLineReader::AllocateBuffer()
+{
+ buffer_ = (PBYTE)VirtualAlloc(NULL, buffersize_, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
+}
+
+void StreamLineReader::FreeBuffer()
+{
+ if (buffer_ != NULL)
+ {
+ VirtualFree(buffer_, 0, MEM_RELEASE);
+ }
+}
+
+DWORD StreamLineReader::ReadBytes()
+{
+ if (readlength_ - readindex_ == 0)
+ {
+ readindex_ = 0;
+ readlength_ = filestream_.Read(buffer_, buffersize_);
+ }
+ return readlength_;
+}
+
+std::wstring StreamLineReader::ReadLine()
+{
+ BOOL eol = FALSE;
+ std::string raw;
+ while (!eol)
+ {
+ DWORD bufferbytes = readlength_ - readindex_;
+ if (bufferbytes == 0)
+ {
+ bufferbytes = ReadBytes();
+ if (bufferbytes == 0) break;
+ }
+ char* p = (char *)buffer_ + readindex_;
+ while (*p != '\r' && *p != '\n' && p <= (char *)buffer_ + readindex_)
+ {
+ raw.append(p, 1);
+ readindex_++;
+ if (readlength_ - readindex_ == 0) break;
+ p++;
+ }
+ if (*p == '\r' || *p == '\n')
+ {
+ eol = TRUE;
+ readindex_++;
+ if (*p == '\r' && (readlength_ - readindex_ > 0) && *(p + 1) == '\n')
+ {
+ readindex_++;
+ }
+ }
+ }
+ if (raw.size() > 0)
+ {
+ DWORD cchWideChar = MultiByteToWideChar(CP_UTF8, 0, raw.c_str(), -1, NULL, 0);
+ WCHAR* wideChars = (WCHAR *)HeapAlloc(GetProcessHeap(), 0, cchWideChar * sizeof(WCHAR));
+ cchWideChar = MultiByteToWideChar(CP_UTF8, 0, raw.c_str(), -1, wideChars, cchWideChar);
+ std::wstring line(wideChars);
+ HeapFree(GetProcessHeap(), 0, wideChars);
+ return line;
+ }
+ return L"";
+}
+
+BOOL StreamLineReader::EndOfStream()
+{
+ return ReadBytes() == 0;
+}
+
+void StreamLineReader::Close()
+{
+ filestream_.Close();
+}
\ No newline at end of file diff --git a/tests/resources/issue_3020/StreamLineReader.h b/tests/resources/issue_3020/StreamLineReader.h new file mode 100644 index 000000000..1312b8495 --- /dev/null +++ b/tests/resources/issue_3020/StreamLineReader.h @@ -0,0 +1,44 @@ +/* Author: macote */
+
+#ifndef STREAMLINEREADER_H_
+#define STREAMLINEREADER_H_
+
+#include "FileStream.h"
+#include <string>
+#include <Windows.h>
+
+class StreamLineReader
+{
+private:
+ static const DWORD kDefaultBufferSize = 32768;
+public:
+ enum class Encoding
+ {
+ UTF8
+ };
+ StreamLineReader(FileStream& filestream, Encoding encoding, const DWORD buffersize) : filestream_(filestream), encoding_(encoding), buffersize_(buffersize)
+ {
+ AllocateBuffer();
+ }
+ StreamLineReader(FileStream& filestream, Encoding encoding) : StreamLineReader(filestream, Encoding::UTF8, kDefaultBufferSize) { }
+ StreamLineReader(FileStream& filestream) : StreamLineReader(filestream, Encoding::UTF8) { }
+ ~StreamLineReader()
+ {
+ FreeBuffer();
+ }
+ std::wstring ReadLine();
+ BOOL EndOfStream();
+ void Close();
+private:
+ void AllocateBuffer();
+ void FreeBuffer();
+ DWORD ReadBytes();
+ FileStream& filestream_;
+ Encoding encoding_;
+ PBYTE buffer_;
+ DWORD buffersize_;
+ DWORD readindex_ = 0;
+ DWORD readlength_ = 0;
+};
+
+#endif /* STREAMLINEREADER_H_ */
diff --git a/tests/resources/issue_3020/StreamLineWriter.cpp b/tests/resources/issue_3020/StreamLineWriter.cpp new file mode 100644 index 000000000..6fd1a3212 --- /dev/null +++ b/tests/resources/issue_3020/StreamLineWriter.cpp @@ -0,0 +1,31 @@ +/* Author: macote */
+
+#include "StreamLineWriter.h"
+
+void StreamLineWriter::Write(std::wstring line)
+{
+ if (line.size() > 0)
+ {
+ DWORD cbMultiByte = WideCharToMultiByte(CP_UTF8, 0, line.c_str(), -1, NULL, 0, NULL, NULL);
+ LPSTR bytes = (LPSTR)HeapAlloc(GetProcessHeap(), 0, cbMultiByte);
+ cbMultiByte = WideCharToMultiByte(CP_UTF8, 0, line.c_str(), -1, bytes, cbMultiByte, NULL, NULL);
+ filestream_.Write((PBYTE)bytes, cbMultiByte - 1);
+ HeapFree(GetProcessHeap(), 0, bytes);
+ }
+}
+
+void StreamLineWriter::WriteLine(std::wstring line)
+{
+ Write(line);
+ WriteEOL();
+}
+
+void StreamLineWriter::WriteEOL()
+{
+ filestream_.Write((PBYTE)"\r\n", 2);
+}
+
+void StreamLineWriter::Close()
+{
+ filestream_.Close();
+}
\ No newline at end of file diff --git a/tests/resources/issue_3020/StreamLineWriter.h b/tests/resources/issue_3020/StreamLineWriter.h new file mode 100644 index 000000000..310d4eca7 --- /dev/null +++ b/tests/resources/issue_3020/StreamLineWriter.h @@ -0,0 +1,32 @@ +/* Author: macote */
+
+#ifndef STREAMLINEWRITER_H_
+#define STREAMLINEWRITER_H_
+
+#include "FileStream.h"
+#include <string>
+#include <Windows.h>
+
+class StreamLineWriter
+{
+public:
+ enum class Encoding
+ {
+ UTF8
+ };
+ StreamLineWriter(FileStream& filestream, Encoding encoding) : filestream_(filestream), encoding_(encoding) { }
+ StreamLineWriter(FileStream& filestream) : StreamLineWriter(filestream, Encoding::UTF8) { }
+ ~StreamLineWriter()
+ {
+ Close();
+ }
+ void Write(std::wstring line);
+ void WriteLine(std::wstring line);
+ void Close();
+private:
+ void WriteEOL();
+ FileStream& filestream_;
+ Encoding encoding_;
+};
+
+#endif /* STREAMLINEWRITER_H_ */
diff --git a/tests/resources/issue_3020/Window.cpp b/tests/resources/issue_3020/Window.cpp new file mode 100644 index 000000000..b5da4009e --- /dev/null +++ b/tests/resources/issue_3020/Window.cpp @@ -0,0 +1,79 @@ +/* Author: macote */
+
+#include "Window.h"
+
+void Window::Register()
+{
+ WNDCLASS wc;
+ wc.style = 0;
+ wc.lpfnWndProc = Window::WndProc;
+ wc.cbClsExtra = 0;
+ wc.cbWndExtra = 0;
+ wc.hInstance = hinst_;
+ wc.hIcon = NULL;
+ wc.hCursor = LoadCursorW(NULL, IDC_ARROW);
+ wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
+ wc.lpszMenuName = NULL;
+ wc.lpszClassName = ClassName();
+ WinRegisterClass(&wc);
+}
+
+LRESULT CALLBACK Window::WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ Window *self;
+ if (uMsg == WM_NCCREATE)
+ {
+ auto lpcs = reinterpret_cast<LPCREATESTRUCT>(lParam);
+ self = reinterpret_cast<Window *>(lpcs->lpCreateParams);
+ self->hwnd_ = hwnd;
+ SetWindowLongPtrW(hwnd, GWLP_USERDATA, reinterpret_cast<LPARAM>(self));
+ }
+ else
+ {
+ self = reinterpret_cast<Window *>(GetWindowLongPtrW(hwnd, GWLP_USERDATA));
+ }
+ if (self)
+ {
+ return self->HandleMessage(uMsg, wParam, lParam);
+ }
+ else
+ {
+ return DefWindowProcW(hwnd, uMsg, wParam, lParam);
+ }
+}
+
+LRESULT Window::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ LRESULT lres;
+ switch (uMsg)
+ {
+ case WM_NCDESTROY:
+ lres = DefWindowProcW(hwnd_, uMsg, wParam, lParam);
+ SetWindowLongPtrW(hwnd_, GWLP_USERDATA, 0);
+ delete this;
+ return lres;
+ case WM_PAINT:
+ OnPaint();
+ return 0;
+ case WM_PRINTCLIENT:
+ OnPrintClient(reinterpret_cast<HDC>(wParam));
+ return 0;
+ }
+ return DefWindowProcW(hwnd_, uMsg, wParam, lParam);
+}
+
+void Window::OnPaint()
+{
+ PAINTSTRUCT ps;
+ BeginPaint(hwnd_, &ps);
+ PaintContent(&ps);
+ EndPaint(hwnd_, &ps);
+}
+
+void Window::OnPrintClient(HDC hdc)
+{
+ PAINTSTRUCT ps;
+ ps.hdc = hdc;
+ GetClientRect(hwnd_, &ps.rcPaint);
+ PaintContent(&ps);
+}
\ No newline at end of file diff --git a/tests/resources/issue_3020/Window.h b/tests/resources/issue_3020/Window.h new file mode 100644 index 000000000..296246ee6 --- /dev/null +++ b/tests/resources/issue_3020/Window.h @@ -0,0 +1,38 @@ +/* Author: macote */
+
+#ifndef WINDOW_H_
+#define WINDOW_H_
+
+#include <Windows.h>
+
+class Window
+{
+public:
+ HWND GetHWND() const { return hwnd_; }
+ Window(HINSTANCE hinst) : hinst_(hinst) { }
+protected:
+ virtual LRESULT HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam);
+ virtual void PaintContent(PAINTSTRUCT *pps) { }
+ virtual LPCWSTR ClassName() = 0;
+ virtual BOOL WinRegisterClass(WNDCLASS *pwc)
+ {
+ return RegisterClassW(pwc);
+ }
+ virtual ~Window() { }
+ HWND WinCreateWindow(DWORD dwExStyle, LPCWSTR pszName, DWORD dwStyle,
+ int x, int y, int cx, int cy, HWND hwndParent, HMENU hmenu)
+ {
+ Register();
+ return CreateWindowExW(dwExStyle, ClassName(), pszName, dwStyle,
+ x, y, cx, cy, hwndParent, hmenu, hinst_, this);
+ }
+ HWND hwnd_;
+ HINSTANCE hinst_;
+private:
+ void Register();
+ void OnPaint();
+ void OnPrintClient(HDC hdc);
+ static LRESULT CALLBACK WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
+};
+
+#endif /* WINDOW_H_ */
\ No newline at end of file diff --git a/tests/resources/issue_3020/application.manifest b/tests/resources/issue_3020/application.manifest new file mode 100644 index 000000000..7f607ebd9 --- /dev/null +++ b/tests/resources/issue_3020/application.manifest @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
+ <trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
+ <security>
+ <requestedPrivileges>
+ <requestedExecutionLevel level="asInvoker" uiAccess="false"/>
+ </requestedPrivileges>
+ </security>
+ </trustInfo>
+ <dependency>
+ <dependentAssembly>
+ <assemblyIdentity type="Win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0"
+ processorArchitecture="*" publicKeyToken="6595b64144ccf1df" language="*"/>
+ </dependentAssembly>
+ </dependency>
+</assembly>
\ No newline at end of file diff --git a/tests/resources/issue_3020/resource.h b/tests/resources/issue_3020/resource.h new file mode 100644 index 000000000..b7c181852 --- /dev/null +++ b/tests/resources/issue_3020/resource.h @@ -0,0 +1,8 @@ +/* Author: macote */
+
+#ifndef RESOURCE_H_
+#define RESOURCE_H_
+
+#define IDI_ICON1 101
+
+#endif /* RESOURCE_H_ */
diff --git a/tests/resources/issue_3020/resource.rc b/tests/resources/issue_3020/resource.rc new file mode 100644 index 000000000..aedff6506 --- /dev/null +++ b/tests/resources/issue_3020/resource.rc @@ -0,0 +1,6 @@ +#include "resource.h"
+
+IDI_ICON1 ICON "HashCheck.ico"
+
+CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "application.manifest"
+
|