diff --git a/.gitmodules b/.gitmodules index cd2562f2..5294ada6 100644 --- a/.gitmodules +++ b/.gitmodules @@ -12,7 +12,7 @@ url = https://github.com/mwasplund/Json11.git [submodule "Dependencies/toml11"] path = Dependencies/toml11 - url = https://github.com/mwasplund/toml11.gits + url = https://github.com/mwasplund/toml11.git [submodule "Dependencies/cpp-httplib"] path = Dependencies/cpp-httplib url = https://github.com/mwasplund/cpp-httplib.git @@ -28,3 +28,6 @@ [submodule "Dependencies/Opal"] path = Dependencies/Opal url = https://github.com/mwasplund/Opal.git +[submodule "Dependencies/Detours"] + path = Dependencies/Detours + url = https://github.com/mwasplund/Detours.git diff --git a/.vscode/settings.json b/.vscode/settings.json index eb354598..9399a942 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -89,6 +89,7 @@ "string_view": "cpp", "complex": "cpp", "*.inc": "cpp", - "compare": "cpp" + "compare": "cpp", + "cwctype": "cpp" } } \ No newline at end of file diff --git a/Dependencies/Detours b/Dependencies/Detours new file mode 160000 index 00000000..51cf823f --- /dev/null +++ b/Dependencies/Detours @@ -0,0 +1 @@ +Subproject commit 51cf823fc302393ee9123ad3ac21562f03e2428d diff --git a/Dependencies/Opal b/Dependencies/Opal index 30bbf5aa..30fd7ea6 160000 --- a/Dependencies/Opal +++ b/Dependencies/Opal @@ -1 +1 @@ -Subproject commit 30bbf5aa73aa3b7cd714b7d22770d21b15fec70b +Subproject commit 30fd7ea6c2131aba28811b05a2358df9913a9b19 diff --git a/Dependencies/SoupSyntax b/Dependencies/SoupSyntax index 88d5a937..7bf8618e 160000 --- a/Dependencies/SoupSyntax +++ b/Dependencies/SoupSyntax @@ -1 +1 @@ -Subproject commit 88d5a93700be4a15b5cd7b5b3e7d8b8e3e9b0f16 +Subproject commit 7bf8618e7429cf8663b4a3ad27bb0dcf287453cd diff --git a/Dependencies/cpp-httplib b/Dependencies/cpp-httplib index 4199e5b5..de388a12 160000 --- a/Dependencies/cpp-httplib +++ b/Dependencies/cpp-httplib @@ -1 +1 @@ -Subproject commit 4199e5b5100f697a1d876bb58165981c7f9ab80c +Subproject commit de388a124ca8ee817d3874ca9f4dcd9a2494eb68 diff --git a/Docs/Samples/Simple-Build-Extension.md b/Docs/Samples/Simple-Build-Extension.md index 3d4d61c4..c814c098 100644 --- a/Docs/Samples/Simple-Build-Extension.md +++ b/Docs/Samples/Simple-Build-Extension.md @@ -12,7 +12,7 @@ Version = "1.0.0" Dependencies = [ "Opal@0.1.2", "Soup.Build@0.3.0", - "Soup.Build.Extensions@0.3.0", + "Soup.Build.Utilities@0.3.0", ] Source = [ @@ -63,7 +63,7 @@ namespace SimpleBuildExtension Soup::Build::ApiCallResult Execute( Soup::Build::IBuildState& buildState) noexcept override final { - auto buildStateWrapper = Soup::Build::Extensions::BuildStateWrapper(buildState); + auto buildStateWrapper = Soup::Build::Utilities::BuildStateWrapper(buildState); try { @@ -83,20 +83,20 @@ namespace SimpleBuildExtension /// /// The Core Execute task /// - void Execute(Soup::Build::Extensions::BuildStateWrapper& buildState) + void Execute(Soup::Build::Utilities::BuildStateWrapper& buildState) { buildState.LogHighPriority("Running After Build!"); } private: - static Soup::Build::Extensions::StringList _runBeforeList; - static Soup::Build::Extensions::StringList _runAfterList; + static Soup::Build::Utilities::StringList _runBeforeList; + static Soup::Build::Utilities::StringList _runAfterList; }; - Soup::Build::Extensions::StringList AfterBuildTask::_runBeforeList = - Soup::Build::Extensions::StringList(); - Soup::Build::Extensions::StringList AfterBuildTask::_runAfterList = - Soup::Build::Extensions::StringList({ + Soup::Build::Utilities::StringList AfterBuildTask::_runBeforeList = + Soup::Build::Utilities::StringList(); + Soup::Build::Utilities::StringList AfterBuildTask::_runAfterList = + Soup::Build::Utilities::StringList({ "Build", }); } @@ -145,7 +145,7 @@ namespace SimpleBuildExtension Soup::Build::ApiCallResult Execute( Soup::Build::IBuildState& buildState) noexcept override final { - auto buildStateWrapper = Soup::Build::Extensions::BuildStateWrapper(buildState); + auto buildStateWrapper = Soup::Build::Utilities::BuildStateWrapper(buildState); try { @@ -165,7 +165,7 @@ namespace SimpleBuildExtension /// /// The Core Execute task /// - void Execute(Soup::Build::Extensions::BuildStateWrapper& buildState) + void Execute(Soup::Build::Utilities::BuildStateWrapper& buildState) { buildState.LogHighPriority("Running Before Build!"); auto rootTable = buildState.GetActiveState(); @@ -180,16 +180,16 @@ namespace SimpleBuildExtension } private: - static Soup::Build::Extensions::StringList _runBeforeList; - static Soup::Build::Extensions::StringList _runAfterList; + static Soup::Build::Utilities::StringList _runBeforeList; + static Soup::Build::Utilities::StringList _runAfterList; }; - Soup::Build::Extensions::StringList BeforeBuildTask::_runBeforeList = - Soup::Build::Extensions::StringList({ + Soup::Build::Utilities::StringList BeforeBuildTask::_runBeforeList = + Soup::Build::Utilities::StringList({ "Build", }); - Soup::Build::Extensions::StringList BeforeBuildTask::_runAfterList = - Soup::Build::Extensions::StringList(); + Soup::Build::Utilities::StringList BeforeBuildTask::_runAfterList = + Soup::Build::Utilities::StringList(); } ``` @@ -200,7 +200,7 @@ The Cpp file that implements the predefined `RegisterBuildExtension` C method to import Opal; import Soup.Build; -import Soup.Build.Extensions; +import Soup.Build.Utilities; #include "AfterBuildTask.h" #include "BeforeBuildTask.h" diff --git a/Samples/SimpleBuildExtension/Extension/AfterBuildTask.h b/Samples/SimpleBuildExtension/Extension/AfterBuildTask.h index f964b1d4..980d8fb9 100644 --- a/Samples/SimpleBuildExtension/Extension/AfterBuildTask.h +++ b/Samples/SimpleBuildExtension/Extension/AfterBuildTask.h @@ -38,7 +38,7 @@ namespace SimpleBuildExtension Soup::Build::ApiCallResult Execute( Soup::Build::IBuildState& buildState) noexcept override final { - auto buildStateWrapper = Soup::Build::Extensions::BuildStateWrapper(buildState); + auto buildStateWrapper = Soup::Build::Utilities::BuildStateWrapper(buildState); try { @@ -58,20 +58,20 @@ namespace SimpleBuildExtension /// /// The Core Execute task /// - void Execute(Soup::Build::Extensions::BuildStateWrapper& buildState) + void Execute(Soup::Build::Utilities::BuildStateWrapper& buildState) { buildState.LogHighPriority("Running After Build!"); } private: - static Soup::Build::Extensions::StringList _runBeforeList; - static Soup::Build::Extensions::StringList _runAfterList; + static Soup::Build::Utilities::StringList _runBeforeList; + static Soup::Build::Utilities::StringList _runAfterList; }; - Soup::Build::Extensions::StringList AfterBuildTask::_runBeforeList = - Soup::Build::Extensions::StringList(); - Soup::Build::Extensions::StringList AfterBuildTask::_runAfterList = - Soup::Build::Extensions::StringList({ + Soup::Build::Utilities::StringList AfterBuildTask::_runBeforeList = + Soup::Build::Utilities::StringList(); + Soup::Build::Utilities::StringList AfterBuildTask::_runAfterList = + Soup::Build::Utilities::StringList({ "Build", }); } diff --git a/Samples/SimpleBuildExtension/Extension/BeforeBuildTask.h b/Samples/SimpleBuildExtension/Extension/BeforeBuildTask.h index 54e81724..69096b26 100644 --- a/Samples/SimpleBuildExtension/Extension/BeforeBuildTask.h +++ b/Samples/SimpleBuildExtension/Extension/BeforeBuildTask.h @@ -38,7 +38,7 @@ namespace SimpleBuildExtension Soup::Build::ApiCallResult Execute( Soup::Build::IBuildState& buildState) noexcept override final { - auto buildStateWrapper = Soup::Build::Extensions::BuildStateWrapper(buildState); + auto buildStateWrapper = Soup::Build::Utilities::BuildStateWrapper(buildState); try { @@ -58,7 +58,7 @@ namespace SimpleBuildExtension /// /// The Core Execute task /// - void Execute(Soup::Build::Extensions::BuildStateWrapper& buildState) + void Execute(Soup::Build::Utilities::BuildStateWrapper& buildState) { buildState.LogHighPriority("Running Before Build!"); auto rootTable = buildState.GetActiveState(); @@ -73,14 +73,14 @@ namespace SimpleBuildExtension } private: - static Soup::Build::Extensions::StringList _runBeforeList; - static Soup::Build::Extensions::StringList _runAfterList; + static Soup::Build::Utilities::StringList _runBeforeList; + static Soup::Build::Utilities::StringList _runAfterList; }; - Soup::Build::Extensions::StringList BeforeBuildTask::_runBeforeList = - Soup::Build::Extensions::StringList({ + Soup::Build::Utilities::StringList BeforeBuildTask::_runBeforeList = + Soup::Build::Utilities::StringList({ "Build", }); - Soup::Build::Extensions::StringList BeforeBuildTask::_runAfterList = - Soup::Build::Extensions::StringList(); + Soup::Build::Utilities::StringList BeforeBuildTask::_runAfterList = + Soup::Build::Utilities::StringList(); } diff --git a/Samples/SimpleBuildExtension/Extension/Recipe.toml b/Samples/SimpleBuildExtension/Extension/Recipe.toml index 42f41801..e73afc2d 100644 --- a/Samples/SimpleBuildExtension/Extension/Recipe.toml +++ b/Samples/SimpleBuildExtension/Extension/Recipe.toml @@ -4,7 +4,7 @@ Version = "1.0.0" Dependencies = [ "Opal@0.1.2", "Soup.Build@0.3.0", - "Soup.Build.Extensions@0.3.0", + "Soup.Build.Utilities@0.3.0", ] Source = [ diff --git a/Samples/SimpleBuildExtension/Extension/Register.cpp b/Samples/SimpleBuildExtension/Extension/Register.cpp index 2ae67f3c..144e8d7a 100644 --- a/Samples/SimpleBuildExtension/Extension/Register.cpp +++ b/Samples/SimpleBuildExtension/Extension/Register.cpp @@ -2,7 +2,7 @@ import Opal; import Soup.Build; -import Soup.Build.Extensions; +import Soup.Build.Utilities; #include "AfterBuildTask.h" #include "BeforeBuildTask.h" diff --git a/Scripts/Build.cmd b/Scripts/Build.cmd new file mode 100644 index 00000000..d0bd2016 --- /dev/null +++ b/Scripts/Build.cmd @@ -0,0 +1,24 @@ +@echo off +SET Flavor=%1 +SET ScriptsDir=%~dp0 +SET SourceDir=%ScriptsDir%..\Source +SET ClientCLIDir=%SourceDir%\Client\CLI +SET DetoursDir=%SourceDir%\Monitor\Detours +SET BinaryDirectorPath=out\bin\MSVC\%Flavor%\win32 +SET ClientCLIBinaryDirectory=%ClientCLIDir%\%BinaryDirectorPath% +SET DetoursBinaryDirectory=%DetoursDir%\%BinaryDirectorPath% +REM - Build the host +echo soup build %ClientCLIDir% -flavor %Flavor% +call soup build %ClientCLIDir% -flavor %Flavor% +if %ERRORLEVEL% NEQ 0 exit /B %ERRORLEVEL% +REM - Build Each version of the detours dll +echo soup build %DetoursDir% -architecture x64 -flavor %Flavor% +call soup build %DetoursDir% -architecture x64 -flavor %Flavor% +if %ERRORLEVEL% NEQ 0 exit /B %ERRORLEVEL% +echo copy %DetoursBinaryDirectory%\x64\Monitor.Detours.dll %ClientCLIBinaryDirectory%\x64\Monitor.Detours.64.dll +copy %DetoursBinaryDirectory%\x64\Monitor.Detours.dll %ClientCLIBinaryDirectory%\x64\Monitor.Detours.64.dll > nul +echo soup build %DetoursDir% -architecture x86 -flavor %Flavor% +call soup build %DetoursDir% -architecture x86 -flavor %Flavor% +if %ERRORLEVEL% NEQ 0 exit /B %ERRORLEVEL% +echo copy %DetoursBinaryDirectory%\x86\Monitor.Detours.dll %ClientCLIBinaryDirectory%\x64\Monitor.Detours.32.dll +copy %DetoursBinaryDirectory%\x86\Monitor.Detours.dll %ClientCLIBinaryDirectory%\x64\Monitor.Detours.32.dll > nul \ No newline at end of file diff --git a/Scripts/alltest.cmd b/Scripts/alltest.cmd index 1c93351c..baf3d1bb 100644 --- a/Scripts/alltest.cmd +++ b/Scripts/alltest.cmd @@ -1,28 +1,95 @@ @echo off SET ScriptsDir=%~dp0 -SET SourceDir=%ScriptsDir%..\Source\ +SET SourceDir=%ScriptsDir%..\Source -pushd %SourceDir%\Build\Extensions.UnitTests\ +echo %SourceDir%\Build\Execute.UnitTests\ +pushd %SourceDir%\Build\Execute.UnitTests\ +if %ERRORLEVEL% NEQ 0 exit /B %ERRORLEVEL% call soup build +if %ERRORLEVEL% NEQ 0 ( + popd + exit /B %ERRORLEVEL% +) call soup run +if %ERRORLEVEL% NEQ 0 ( + echo Failed + popd + exit /B %ERRORLEVEL% +) popd +echo %SourceDir%\Build\Utilities.UnitTests\ +pushd %SourceDir%\Build\Utilities.UnitTests\ +if %ERRORLEVEL% NEQ 0 exit /B %ERRORLEVEL% +call soup build +if %ERRORLEVEL% NEQ 0 ( + popd + exit /B %ERRORLEVEL% +) +call soup run +if %ERRORLEVEL% NEQ 0 ( + popd + exit /B %ERRORLEVEL% +) +popd + +echo %SourceDir%\Extensions\Compiler\Core.UnitTests\ pushd %SourceDir%\Extensions\Compiler\Core.UnitTests\ +if %ERRORLEVEL% NEQ 0 exit /B %ERRORLEVEL% call soup build +if %ERRORLEVEL% NEQ 0 ( + popd + exit /B %ERRORLEVEL% +) call soup run +if %ERRORLEVEL% NEQ 0 ( + popd + exit /B %ERRORLEVEL% +) popd +echo %SourceDir%\Extensions\Compiler\Clang.UnitTests\ pushd %SourceDir%\Extensions\Compiler\Clang.UnitTests\ +if %ERRORLEVEL% NEQ 0 exit /B %ERRORLEVEL% call soup build +if %ERRORLEVEL% NEQ 0 ( + popd + exit /B %ERRORLEVEL% +) call soup run +if %ERRORLEVEL% NEQ 0 ( + echo Failed + popd + exit /B %ERRORLEVEL% +) popd +echo %SourceDir%\Extensions\Compiler\MSVC.UnitTests\ pushd %SourceDir%\Extensions\Compiler\MSVC.UnitTests\ +if %ERRORLEVEL% NEQ 0 exit /B %ERRORLEVEL% call soup build +if %ERRORLEVEL% NEQ 0 ( + popd + exit /B %ERRORLEVEL% +) call soup run +if %ERRORLEVEL% NEQ 0 ( + popd + exit /B %ERRORLEVEL% +) popd +echo %SourceDir%\Client\Core.UnitTests\ pushd %SourceDir%\Client\Core.UnitTests\ +if %ERRORLEVEL% NEQ 0 exit /B %ERRORLEVEL% call soup build +if %ERRORLEVEL% NEQ 0 ( + popd + exit /B %ERRORLEVEL% +) call soup run +if %ERRORLEVEL% NEQ 0 ( + popd + exit /B %ERRORLEVEL% +) popd \ No newline at end of file diff --git a/Scripts/soup b/Scripts/soup deleted file mode 100755 index d1117488..00000000 --- a/Scripts/soup +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/bash - -CONFIG=Debug -ScriptsDir="$(dirname "${BASH_SOURCE[0]}")" -RootDir="$(dirname "$ScriptsDir")" - -dotnet $RootDir/bin/Soup.Client/$CONFIG/netcoreapp2.1/Soup.dll "$@" -#dotnet run -no-build -p $RootDir/Source/Client "$@" diff --git a/Scripts/soup.cmd b/Scripts/soup.cmd index 9105dc05..3e6bac8a 100644 --- a/Scripts/soup.cmd +++ b/Scripts/soup.cmd @@ -5,6 +5,7 @@ SET OutDir=%ClientDir%\out SET BinaryDir=%OutDir%\bin SET RunDir=%OutDir%\run REM - Use a copy of the final binary in case we are re-buiding itself -xcopy /s /Y %BinaryDir%\MSVC\Release\* %RunDir%\ > nul +rmdir /S /Q %RunDir% +xcopy /s /Y %BinaryDir%\MSVC\release\win32\x64\* %RunDir%\ > nul copy %ClientDir%\LocalUserConfig.json %RunDir%\LocalUserConfig.json > nul %RunDir%\Soup.exe %* \ No newline at end of file diff --git a/Scripts/soupd.cmd b/Scripts/soupd.cmd index dae382b2..ca3a4362 100644 --- a/Scripts/soupd.cmd +++ b/Scripts/soupd.cmd @@ -5,6 +5,7 @@ SET OutDir=%ClientDir%\out SET BinaryDir=%OutDir%\bin SET RunDir=%OutDir%\run REM - Use a copy of the final binary in case we are re-buiding itself -xcopy /s /Y %BinaryDir%\MSVC\Debug\* %RunDir%\ > nul +rmdir /S /Q %RunDir% +xcopy /s /Y %BinaryDir%\MSVC\debug\win32\x64\* %RunDir%\ > nul copy %ClientDir%\LocalUserConfig.json %RunDir%\LocalUserConfig.json > nul %RunDir%\Soup.exe %* \ No newline at end of file diff --git a/Source/Build/Core/ApiCallResult.h b/Source/Build/Contracts/ApiCallResult.h similarity index 100% rename from Source/Build/Core/ApiCallResult.h rename to Source/Build/Contracts/ApiCallResult.h diff --git a/Source/Build/Core/IBuildOperation.h b/Source/Build/Contracts/IBuildOperation.h similarity index 100% rename from Source/Build/Core/IBuildOperation.h rename to Source/Build/Contracts/IBuildOperation.h diff --git a/Source/Build/Core/IBuildState.h b/Source/Build/Contracts/IBuildState.h similarity index 100% rename from Source/Build/Core/IBuildState.h rename to Source/Build/Contracts/IBuildState.h diff --git a/Source/Build/Core/IBuildSystem.h b/Source/Build/Contracts/IBuildSystem.h similarity index 100% rename from Source/Build/Core/IBuildSystem.h rename to Source/Build/Contracts/IBuildSystem.h diff --git a/Source/Build/Core/IBuildTask.h b/Source/Build/Contracts/IBuildTask.h similarity index 100% rename from Source/Build/Core/IBuildTask.h rename to Source/Build/Contracts/IBuildTask.h diff --git a/Source/Build/Core/IList.h b/Source/Build/Contracts/IList.h similarity index 100% rename from Source/Build/Core/IList.h rename to Source/Build/Contracts/IList.h diff --git a/Source/Build/Core/IReadOnlyList.h b/Source/Build/Contracts/IReadOnlyList.h similarity index 100% rename from Source/Build/Core/IReadOnlyList.h rename to Source/Build/Contracts/IReadOnlyList.h diff --git a/Source/Build/Core/IValue.h b/Source/Build/Contracts/IValue.h similarity index 100% rename from Source/Build/Core/IValue.h rename to Source/Build/Contracts/IValue.h diff --git a/Source/Build/Core/IValueList.h b/Source/Build/Contracts/IValueList.h similarity index 100% rename from Source/Build/Core/IValueList.h rename to Source/Build/Contracts/IValueList.h diff --git a/Source/Build/Core/IValuePrimitive.h b/Source/Build/Contracts/IValuePrimitive.h similarity index 100% rename from Source/Build/Core/IValuePrimitive.h rename to Source/Build/Contracts/IValuePrimitive.h diff --git a/Source/Build/Core/IValueTable.h b/Source/Build/Contracts/IValueTable.h similarity index 100% rename from Source/Build/Core/IValueTable.h rename to Source/Build/Contracts/IValueTable.h diff --git a/Source/Build/Core/Module.cpp b/Source/Build/Contracts/Module.cpp similarity index 100% rename from Source/Build/Core/Module.cpp rename to Source/Build/Contracts/Module.cpp diff --git a/Source/Build/Contracts/Recipe.toml b/Source/Build/Contracts/Recipe.toml new file mode 100644 index 00000000..04366ec3 --- /dev/null +++ b/Source/Build/Contracts/Recipe.toml @@ -0,0 +1,11 @@ +Name = "Soup.Build" +Description = """The core Soup Build Contracts used to define +the stable Binary Interface layer between the Build Evaluation +engine and the Extensions.""" +Version = "0.3.0" +Dependencies = [ + "../../../Dependencies/Opal/Source/", + # "Opal@0.1.2", +] + +Public = "Module.cpp" diff --git a/Source/Build/Core/Recipe.toml b/Source/Build/Core/Recipe.toml deleted file mode 100644 index 0c1329ef..00000000 --- a/Source/Build/Core/Recipe.toml +++ /dev/null @@ -1,8 +0,0 @@ -Name = "Soup.Build" -Version = "0.3.0" -Dependencies = [ - "../../../Dependencies/Opal/Source/", - # "Opal@0.1.2", -] - -Public = "Module.cpp" diff --git a/Source/Build/Runtime/BuildSimpleList.h b/Source/Build/Evaluate/BuildSimpleList.h similarity index 92% rename from Source/Build/Runtime/BuildSimpleList.h rename to Source/Build/Evaluate/BuildSimpleList.h index d67f0349..5c54181f 100644 --- a/Source/Build/Runtime/BuildSimpleList.h +++ b/Source/Build/Evaluate/BuildSimpleList.h @@ -4,7 +4,7 @@ #pragma once -namespace Soup::Build::Runtime +namespace Soup::Build::Evaluate { /// /// Build list implementation for simple objects diff --git a/Source/Build/Runtime/BuildState.h b/Source/Build/Evaluate/BuildState.h similarity index 92% rename from Source/Build/Runtime/BuildState.h rename to Source/Build/Evaluate/BuildState.h index 075a52d8..d9b445e1 100644 --- a/Source/Build/Runtime/BuildState.h +++ b/Source/Build/Evaluate/BuildState.h @@ -5,7 +5,7 @@ #pragma once #include "ValueTable.h" -namespace Soup::Build::Runtime +namespace Soup::Build::Evaluate { /// /// Build State Extension interface @@ -107,7 +107,7 @@ namespace Soup::Build::Runtime } private: - Extensions::BuildOperationList _rootOperations; + Utilities::BuildOperationList _rootOperations; ValueTable _activeState; ValueTable _sharedState; }; diff --git a/Source/Build/Runtime/BuildSystem.h b/Source/Build/Evaluate/BuildSystem.h similarity index 93% rename from Source/Build/Runtime/BuildSystem.h rename to Source/Build/Evaluate/BuildSystem.h index 06c1bb91..f0fcf7f9 100644 --- a/Source/Build/Runtime/BuildSystem.h +++ b/Source/Build/Evaluate/BuildSystem.h @@ -5,7 +5,7 @@ #pragma once #include "BuildState.h" -namespace Soup::Build::Runtime +namespace Soup::Build::Evaluate { class BuildTaskContainer { @@ -55,9 +55,9 @@ namespace Soup::Build::Runtime Log::Diag("RegisterTask: " + taskName); // TODO: Remove const casts - auto runBeforeList = Extensions::ReadOnlyStringListWrapper( + auto runBeforeList = Utilities::ReadOnlyStringListWrapper( ourTask->GetRunBeforeList()); - auto runAfterList = Extensions::ReadOnlyStringListWrapper( + auto runAfterList = Utilities::ReadOnlyStringListWrapper( ourTask->GetRunAfterList()); auto taskContainer = BuildTaskContainer( ourTask, diff --git a/Source/Build/Runtime/Module.cpp b/Source/Build/Evaluate/Module.cpp similarity index 78% rename from Source/Build/Runtime/Module.cpp rename to Source/Build/Evaluate/Module.cpp index 377f553f..d34b380f 100644 --- a/Source/Build/Runtime/Module.cpp +++ b/Source/Build/Evaluate/Module.cpp @@ -8,11 +8,11 @@ #include #include -export module Soup.Build.Runtime; +export module Soup.Build.Evaluate; import Opal; import Soup.Build; -import Soup.Build.Extensions; +import Soup.Build.Utilities; using namespace Opal; diff --git a/Source/Build/Evaluate/Recipe.toml b/Source/Build/Evaluate/Recipe.toml new file mode 100644 index 00000000..a7022a66 --- /dev/null +++ b/Source/Build/Evaluate/Recipe.toml @@ -0,0 +1,17 @@ +Name = "Soup.Build.Evaluate" +Description = """The Build Evaluation implementation of the contract classes that are +used inside the primary Build Evaluation Engine.""" +Version = "0.1.0" +Dependencies = [ + "../Contracts/", + # "Soup.Build@0.3.0", + "../Utilities/", + # "Soup.Build.Utilities@0.3.0", + "../../../Dependencies/Opal/Source/", + # "Opal@0.1.2", +] + +Public = "Module.cpp" +Source = [ + "Value.cpp", +] diff --git a/Source/Build/Runtime/Value.cpp b/Source/Build/Evaluate/Value.cpp similarity index 94% rename from Source/Build/Runtime/Value.cpp rename to Source/Build/Evaluate/Value.cpp index c6c5c688..11572bfe 100644 --- a/Source/Build/Runtime/Value.cpp +++ b/Source/Build/Evaluate/Value.cpp @@ -11,11 +11,11 @@ module; #include #include -module Soup.Build.Runtime; +module Soup.Build.Evaluate; using namespace Opal; -namespace Soup::Build::Runtime +namespace Soup::Build::Evaluate { Value::Value() : diff --git a/Source/Build/Runtime/Value.h b/Source/Build/Evaluate/Value.h similarity index 94% rename from Source/Build/Runtime/Value.h rename to Source/Build/Evaluate/Value.h index 466ec292..636c07aa 100644 --- a/Source/Build/Runtime/Value.h +++ b/Source/Build/Evaluate/Value.h @@ -4,7 +4,7 @@ #pragma once -namespace Soup::Build::Runtime +namespace Soup::Build::Evaluate { export class ValueTable; export class ValueList; diff --git a/Source/Build/Runtime/ValueList.h b/Source/Build/Evaluate/ValueList.h similarity index 92% rename from Source/Build/Runtime/ValueList.h rename to Source/Build/Evaluate/ValueList.h index 509636d5..00680bd2 100644 --- a/Source/Build/Runtime/ValueList.h +++ b/Source/Build/Evaluate/ValueList.h @@ -4,7 +4,7 @@ #pragma once -namespace Soup::Build::Runtime +namespace Soup::Build::Evaluate { /// /// Build list implementation for simple objects diff --git a/Source/Build/Runtime/ValuePrimitive.h b/Source/Build/Evaluate/ValuePrimitive.h similarity index 93% rename from Source/Build/Runtime/ValuePrimitive.h rename to Source/Build/Evaluate/ValuePrimitive.h index e2dd4529..62a23517 100644 --- a/Source/Build/Runtime/ValuePrimitive.h +++ b/Source/Build/Evaluate/ValuePrimitive.h @@ -6,7 +6,7 @@ #include "Value.h" #include "ValueList.h" -namespace Soup::Build::Runtime +namespace Soup::Build::Evaluate { /// /// Build State Extension interface diff --git a/Source/Build/Runtime/ValueTable.h b/Source/Build/Evaluate/ValueTable.h similarity index 93% rename from Source/Build/Runtime/ValueTable.h rename to Source/Build/Evaluate/ValueTable.h index 3693b9c4..37c184ab 100644 --- a/Source/Build/Runtime/ValueTable.h +++ b/Source/Build/Evaluate/ValueTable.h @@ -6,7 +6,7 @@ #include "Value.h" #include "ValueList.h" -namespace Soup::Build::Runtime +namespace Soup::Build::Evaluate { /// /// Build State Extension interface @@ -188,7 +188,7 @@ namespace Soup::Build::Runtime } private: - Extensions::StringList _keyList; + Utilities::StringList _keyList; std::map _values; }; } diff --git a/Source/Client/Core.UnitTests/Build/Runner/BuildHistoryCheckerTests.h b/Source/Build/Execute.UnitTests/BuildHistoryCheckerTests.h similarity index 99% rename from Source/Client/Core.UnitTests/Build/Runner/BuildHistoryCheckerTests.h rename to Source/Build/Execute.UnitTests/BuildHistoryCheckerTests.h index ac6c5516..73a1eb86 100644 --- a/Source/Client/Core.UnitTests/Build/Runner/BuildHistoryCheckerTests.h +++ b/Source/Build/Execute.UnitTests/BuildHistoryCheckerTests.h @@ -3,8 +3,9 @@ // #pragma once +#include "Helpers.h" -namespace Soup::Build::UnitTests +namespace Soup::Build::Execute::UnitTests { class BuildHistoryCheckerTests { diff --git a/Source/Client/Core.UnitTests/Build/Runner/BuildHistoryJsonTests.h b/Source/Build/Execute.UnitTests/BuildHistoryJsonTests.h similarity index 98% rename from Source/Client/Core.UnitTests/Build/Runner/BuildHistoryJsonTests.h rename to Source/Build/Execute.UnitTests/BuildHistoryJsonTests.h index 9d03aa5d..92ff3e95 100644 --- a/Source/Client/Core.UnitTests/Build/Runner/BuildHistoryJsonTests.h +++ b/Source/Build/Execute.UnitTests/BuildHistoryJsonTests.h @@ -4,7 +4,7 @@ #pragma once -namespace Soup::Build::UnitTests +namespace Soup::Build::Execute::UnitTests { class BuildHistoryJsonTests { diff --git a/Source/Client/Core.UnitTests/Build/Runner/BuildHistoryManagerTests.h b/Source/Build/Execute.UnitTests/BuildHistoryManagerTests.h similarity index 98% rename from Source/Client/Core.UnitTests/Build/Runner/BuildHistoryManagerTests.h rename to Source/Build/Execute.UnitTests/BuildHistoryManagerTests.h index dd1e3d89..84d5efc4 100644 --- a/Source/Client/Core.UnitTests/Build/Runner/BuildHistoryManagerTests.h +++ b/Source/Build/Execute.UnitTests/BuildHistoryManagerTests.h @@ -4,7 +4,7 @@ #pragma once -namespace Soup::Build::UnitTests +namespace Soup::Build::Execute::UnitTests { class BuildHistoryManagerTests { diff --git a/Source/Client/Core.UnitTests/Build/Runner/BuildHistoryTests.h b/Source/Build/Execute.UnitTests/BuildHistoryTests.h similarity index 99% rename from Source/Client/Core.UnitTests/Build/Runner/BuildHistoryTests.h rename to Source/Build/Execute.UnitTests/BuildHistoryTests.h index 986d082c..d1a0e9db 100644 --- a/Source/Client/Core.UnitTests/Build/Runner/BuildHistoryTests.h +++ b/Source/Build/Execute.UnitTests/BuildHistoryTests.h @@ -4,7 +4,7 @@ #pragma once -namespace Soup::Build::UnitTests +namespace Soup::Build::Execute::UnitTests { class BuildHistoryTests { diff --git a/Source/Client/Core.UnitTests/Build/Runner/BuildRunnerTests.h b/Source/Build/Execute.UnitTests/BuildRunnerTests.h similarity index 91% rename from Source/Client/Core.UnitTests/Build/Runner/BuildRunnerTests.h rename to Source/Build/Execute.UnitTests/BuildRunnerTests.h index 5288b2cf..e49df76f 100644 --- a/Source/Client/Core.UnitTests/Build/Runner/BuildRunnerTests.h +++ b/Source/Build/Execute.UnitTests/BuildRunnerTests.h @@ -4,7 +4,7 @@ #pragma once -namespace Soup::Build::UnitTests +namespace Soup::Build::Execute::UnitTests { class BuildRunnerTests { @@ -33,11 +33,11 @@ namespace Soup::Build::UnitTests auto uut = BuildRunner(Path("C:/BuildDirectory/")); // Setup the input build state - auto operations = Extensions::BuildOperationList(); + auto operations = Utilities::BuildOperationList(); auto objectDirectory = Path("out/obj/release/"); auto forceBuild = true; uut.Execute( - Extensions::BuildOperationListWrapper(operations), + Utilities::BuildOperationListWrapper(operations), objectDirectory, forceBuild); @@ -86,11 +86,11 @@ namespace Soup::Build::UnitTests auto uut = BuildRunner(Path("C:/BuildDirectory/")); // Setup the input build state - auto operations = Extensions::BuildOperationList(); + auto operations = Utilities::BuildOperationList(); auto objectDirectory = Path("out/obj/release/"); auto forceBuild = false; uut.Execute( - Extensions::BuildOperationListWrapper(operations), + Utilities::BuildOperationListWrapper(operations), objectDirectory, forceBuild); @@ -143,9 +143,9 @@ namespace Soup::Build::UnitTests auto uut = BuildRunner(Path("C:/BuildDirectory/")); // Setup the input build state - auto operations = Extensions::BuildOperationList( - std::vector>({ - new Extensions::BuildOperation( + auto operations = Utilities::BuildOperationList( + std::vector>({ + new Utilities::BuildOperation( "TestCommand: 1", Path("Command.exe"), "Arguments", @@ -160,7 +160,7 @@ namespace Soup::Build::UnitTests auto objectDirectory = Path("out/obj/release/"); bool forceBuild = true; uut.Execute( - Extensions::BuildOperationListWrapper(operations), + Utilities::BuildOperationListWrapper(operations), objectDirectory, forceBuild); @@ -189,7 +189,12 @@ namespace Soup::Build::UnitTests // Verify expected process requests Assert::AreEqual( std::vector({ - "Execute: [C:/TestWorkingDirectory/] Command.exe Arguments", + "CreateProcess: 1 [C:/TestWorkingDirectory/] Command.exe Arguments", + "ProcessStart: 1", + "WaitForExit: 1", + "GetStandardOutput: 1", + "GetStandardError: 1", + "GetExitCode: 1", }), processManager->GetRequests(), "Verify process manager requests match expected."); @@ -213,9 +218,9 @@ namespace Soup::Build::UnitTests auto uut = BuildRunner(Path("C:/BuildDirectory/")); // Setup the input build state - auto operations = Extensions::BuildOperationList( - std::vector>({ - new Extensions::BuildOperation( + auto operations = Utilities::BuildOperationList( + std::vector>({ + new Utilities::BuildOperation( "TestCommand: 1", Path("Command.exe"), "Arguments", @@ -230,7 +235,7 @@ namespace Soup::Build::UnitTests auto objectDirectory = Path("out/obj/debug/"); auto forceBuild = false; uut.Execute( - Extensions::BuildOperationListWrapper(operations), + Utilities::BuildOperationListWrapper(operations), objectDirectory, forceBuild); @@ -263,7 +268,12 @@ namespace Soup::Build::UnitTests // Verify expected process requests Assert::AreEqual( std::vector({ - "Execute: [C:/TestWorkingDirectory/] Command.exe Arguments", + "CreateProcess: 1 [C:/TestWorkingDirectory/] Command.exe Arguments", + "ProcessStart: 1", + "WaitForExit: 1", + "GetStandardOutput: 1", + "GetStandardError: 1", + "GetExitCode: 1", }), processManager->GetRequests(), "Verify process manager requests match expected."); @@ -295,9 +305,9 @@ namespace Soup::Build::UnitTests auto uut = BuildRunner(Path("C:/BuildDirectory/")); // Setup the input build state - auto operations = Extensions::BuildOperationList( - std::vector>({ - new Extensions::BuildOperation( + auto operations = Utilities::BuildOperationList( + std::vector>({ + new Utilities::BuildOperation( "TestCommand: 1", Path("Command.exe"), "Arguments", @@ -312,7 +322,7 @@ namespace Soup::Build::UnitTests auto objectDirectory = Path("out/obj/debug/"); auto forceBuild = false; uut.Execute( - Extensions::BuildOperationListWrapper(operations), + Utilities::BuildOperationListWrapper(operations), objectDirectory, forceBuild); @@ -378,9 +388,9 @@ namespace Soup::Build::UnitTests auto uut = BuildRunner(Path("C:/BuildDirectory/")); // Setup the input build state - auto operations = Extensions::BuildOperationList( - std::vector>({ - new Extensions::BuildOperation( + auto operations = Utilities::BuildOperationList( + std::vector>({ + new Utilities::BuildOperation( "TestCommand: 1", Path("Command.exe"), "Arguments", @@ -395,7 +405,7 @@ namespace Soup::Build::UnitTests auto objectDirectory = Path("out/obj/debug/"); auto forceBuild = false; uut.Execute( - Extensions::BuildOperationListWrapper(operations), + Utilities::BuildOperationListWrapper(operations), objectDirectory, forceBuild); @@ -469,9 +479,9 @@ namespace Soup::Build::UnitTests auto uut = BuildRunner(Path("C:/BuildDirectory/")); // Setup the input build state - auto operations = Extensions::BuildOperationList( - std::vector>({ - new Extensions::BuildOperation( + auto operations = Utilities::BuildOperationList( + std::vector>({ + new Utilities::BuildOperation( "TestCommand: 1", Path("Command.exe"), "Arguments", @@ -486,7 +496,7 @@ namespace Soup::Build::UnitTests auto objectDirectory = Path("out/obj/debug/"); auto forceBuild = false; uut.Execute( - Extensions::BuildOperationListWrapper(operations), + Utilities::BuildOperationListWrapper(operations), objectDirectory, forceBuild); @@ -565,9 +575,9 @@ namespace Soup::Build::UnitTests auto uut = BuildRunner(Path("C:/BuildDirectory/")); // Setup the input build state - auto operations = Extensions::BuildOperationList( - std::vector>({ - new Extensions::BuildOperation( + auto operations = Utilities::BuildOperationList( + std::vector>({ + new Utilities::BuildOperation( "TestCommand: 1", Path("Command.exe"), "Arguments", @@ -582,7 +592,7 @@ namespace Soup::Build::UnitTests auto objectDirectory = Path("out/obj/debug/"); auto forceBuild = false; uut.Execute( - Extensions::BuildOperationListWrapper(operations), + Utilities::BuildOperationListWrapper(operations), objectDirectory, forceBuild); diff --git a/Source/Build/Execute.UnitTests/Helpers.h b/Source/Build/Execute.UnitTests/Helpers.h new file mode 100644 index 00000000..e23496db --- /dev/null +++ b/Source/Build/Execute.UnitTests/Helpers.h @@ -0,0 +1,23 @@ +// +// Copyright (c) Soup. All rights reserved. +// + +#pragma once + +namespace Soup::Build::Execute::UnitTests +{ + std::time_t CreateDateTime(int year, int month, int day, int hour, int minutes) + { + std::tm timeInfo = std::tm(); + + // Year is offset from 1900 + timeInfo.tm_year = year - 1900; + timeInfo.tm_mon = month; + timeInfo.tm_mday = day; + timeInfo.tm_hour = hour; + timeInfo.tm_min = minutes; + + std::time_t time = std::mktime(&timeInfo); + return time; + } +} \ No newline at end of file diff --git a/Source/Build/Execute.UnitTests/Recipe.toml b/Source/Build/Execute.UnitTests/Recipe.toml new file mode 100644 index 00000000..78045669 --- /dev/null +++ b/Source/Build/Execute.UnitTests/Recipe.toml @@ -0,0 +1,17 @@ +Name = "Soup.Build.Execute.UnitTests" +Version = "1.0.0" +Type = "Executable" +Dependencies = [ + # "../../Dependencies/json11/", + "json11@1.0.0", + # "../../Dependencies/SoupTest/Assert/", + "SoupTest@0.1.0", + "../Execute/", + "../../TestUtilities/", +] +Source = [ + "gen/Main.cpp" +] +IncludePaths = [ + "./", +] diff --git a/Source/Client/Core.UnitTests/gen/Build/Runner/BuildHistoryCheckerTests.gen.h b/Source/Build/Execute.UnitTests/gen/BuildHistoryCheckerTests.gen.h similarity index 87% rename from Source/Client/Core.UnitTests/gen/Build/Runner/BuildHistoryCheckerTests.gen.h rename to Source/Build/Execute.UnitTests/gen/BuildHistoryCheckerTests.gen.h index d0692f95..9bb3236b 100644 --- a/Source/Client/Core.UnitTests/gen/Build/Runner/BuildHistoryCheckerTests.gen.h +++ b/Source/Build/Execute.UnitTests/gen/BuildHistoryCheckerTests.gen.h @@ -1,10 +1,10 @@ #pragma once -#include "Build/Runner/BuildHistoryCheckerTests.h" +#include "BuildHistoryCheckerTests.h" TestState RunBuildHistoryCheckerTests() { auto className = "BuildHistoryCheckerTests"; - auto testClass = std::make_shared(); + auto testClass = std::make_shared(); TestState state = { 0, 0 }; state += SoupTest::RunTest(className, "IsOutdated_ZeroInput_Throws", [&testClass]() { testClass->IsOutdated_ZeroInput_Throws(); }); state += SoupTest::RunTest(className, "IsOutdated_SingleInput_MissingTarget", [&testClass]() { testClass->IsOutdated_SingleInput_MissingTarget(); }); diff --git a/Source/Client/Core.UnitTests/gen/Build/Runner/BuildHistoryJsonTests.gen.h b/Source/Build/Execute.UnitTests/gen/BuildHistoryJsonTests.gen.h similarity index 88% rename from Source/Client/Core.UnitTests/gen/Build/Runner/BuildHistoryJsonTests.gen.h rename to Source/Build/Execute.UnitTests/gen/BuildHistoryJsonTests.gen.h index 262acdb7..fcca59c7 100644 --- a/Source/Client/Core.UnitTests/gen/Build/Runner/BuildHistoryJsonTests.gen.h +++ b/Source/Build/Execute.UnitTests/gen/BuildHistoryJsonTests.gen.h @@ -1,10 +1,10 @@ #pragma once -#include "Build/Runner/BuildHistoryJsonTests.h" +#include "BuildHistoryJsonTests.h" TestState RunBuildHistoryJsonTests() { auto className = "BuildHistoryJsonTests"; - auto testClass = std::make_shared(); + auto testClass = std::make_shared(); TestState state = { 0, 0 }; state += SoupTest::RunTest(className, "Deserialize_GarbageThrows", [&testClass]() { testClass->Deserialize_GarbageThrows(); }); state += SoupTest::RunTest(className, "Deserialize_MissingKnownFiles", [&testClass]() { testClass->Deserialize_MissingKnownFiles(); }); diff --git a/Source/Client/Core.UnitTests/gen/Build/Runner/BuildHistoryManagerTests.gen.h b/Source/Build/Execute.UnitTests/gen/BuildHistoryManagerTests.gen.h similarity index 78% rename from Source/Client/Core.UnitTests/gen/Build/Runner/BuildHistoryManagerTests.gen.h rename to Source/Build/Execute.UnitTests/gen/BuildHistoryManagerTests.gen.h index bfe897e1..6c1921aa 100644 --- a/Source/Client/Core.UnitTests/gen/Build/Runner/BuildHistoryManagerTests.gen.h +++ b/Source/Build/Execute.UnitTests/gen/BuildHistoryManagerTests.gen.h @@ -1,10 +1,10 @@ #pragma once -#include "Build/Runner/BuildHistoryManagerTests.h" +#include "BuildHistoryManagerTests.h" TestState RunBuildHistoryManagerTests() { auto className = "BuildHistoryManagerTests"; - auto testClass = std::make_shared(); + auto testClass = std::make_shared(); TestState state = { 0, 0 }; state += SoupTest::RunTest(className, "TryLoadFromFile_MissingFile", [&testClass]() { testClass->TryLoadFromFile_MissingFile(); }); state += SoupTest::RunTest(className, "TryLoadFromFile_GarbageFile", [&testClass]() { testClass->TryLoadFromFile_GarbageFile(); }); diff --git a/Source/Client/Core.UnitTests/gen/Build/Runner/BuildHistoryTests.gen.h b/Source/Build/Execute.UnitTests/gen/BuildHistoryTests.gen.h similarity index 87% rename from Source/Client/Core.UnitTests/gen/Build/Runner/BuildHistoryTests.gen.h rename to Source/Build/Execute.UnitTests/gen/BuildHistoryTests.gen.h index 56c156d1..8ae5e057 100644 --- a/Source/Client/Core.UnitTests/gen/Build/Runner/BuildHistoryTests.gen.h +++ b/Source/Build/Execute.UnitTests/gen/BuildHistoryTests.gen.h @@ -1,10 +1,10 @@ #pragma once -#include "Build/Runner/BuildHistoryTests.h" +#include "BuildHistoryTests.h" TestState RunBuildHistoryTests() { auto className = "BuildHistoryTests"; - auto testClass = std::make_shared(); + auto testClass = std::make_shared(); TestState state = { 0, 0 }; state += SoupTest::RunTest(className, "TryBuildIncludeClosure_SourceFileMissingFails", [&testClass]() { testClass->TryBuildIncludeClosure_SourceFileMissingFails(); }); state += SoupTest::RunTest(className, "TryBuildIncludeClosure_DependencyFileMissingFails", [&testClass]() { testClass->TryBuildIncludeClosure_DependencyFileMissingFails(); }); diff --git a/Source/Client/Core.UnitTests/gen/Build/Runner/BuildRunnerTests.gen.h b/Source/Build/Execute.UnitTests/gen/BuildRunnerTests.gen.h similarity index 91% rename from Source/Client/Core.UnitTests/gen/Build/Runner/BuildRunnerTests.gen.h rename to Source/Build/Execute.UnitTests/gen/BuildRunnerTests.gen.h index f71a43be..b6c1808a 100644 --- a/Source/Client/Core.UnitTests/gen/Build/Runner/BuildRunnerTests.gen.h +++ b/Source/Build/Execute.UnitTests/gen/BuildRunnerTests.gen.h @@ -1,10 +1,10 @@ #pragma once -#include "Build/Runner/BuildRunnerTests.h" +#include "BuildRunnerTests.h" TestState RunBuildRunnerTests() { auto className = "BuildRunnerTests"; - auto testClass = std::make_shared(); + auto testClass = std::make_shared(); TestState state = { 0, 0 }; state += SoupTest::RunTest(className, "Initialize", [&testClass]() { testClass->Initialize(); }); state += SoupTest::RunTest(className, "Execute_NoOperations_ForceBuild", [&testClass]() { testClass->Execute_NoOperations_ForceBuild(); }); diff --git a/Source/Build/Execute.UnitTests/gen/Main.cpp b/Source/Build/Execute.UnitTests/gen/Main.cpp new file mode 100644 index 00000000..98262481 --- /dev/null +++ b/Source/Build/Execute.UnitTests/gen/Main.cpp @@ -0,0 +1,47 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +import Opal; +import Soup.Build.Execute; +import json11; +import SoupTest; +import SoupTestUtilities; + +using namespace Opal; +using namespace Opal::System; +using namespace SoupTest; + +#include "BuildHistoryCheckerTests.gen.h" +#include "BuildHistoryJsonTests.gen.h" +#include "BuildHistoryTests.gen.h" +#include "BuildHistoryManagerTests.gen.h" +#include "BuildRunnerTests.gen.h" + +int main() +{ + std::cout << "Running Tests..." << std::endl; + + TestState state = { 0, 0 }; + + state += RunBuildHistoryCheckerTests(); + state += RunBuildHistoryJsonTests(); + state += RunBuildHistoryTests(); + state += RunBuildHistoryManagerTests(); + state += RunBuildRunnerTests(); + + std::cout << state.PassCount << " PASSED." << std::endl; + std::cout << state.FailCount << " FAILED." << std::endl; + + if (state.FailCount > 0) + return 1; + else + return 0; +} diff --git a/Source/Build/Execute/BuildHistory.h b/Source/Build/Execute/BuildHistory.h new file mode 100644 index 00000000..9eb85a41 --- /dev/null +++ b/Source/Build/Execute/BuildHistory.h @@ -0,0 +1,96 @@ +// +// Copyright (c) Soup. All rights reserved. +// + +#pragma once + +namespace Soup::Build::Execute +{ + export class OperationInfo + { + public: + /// + /// Initializes a new instance of the class. + /// + OperationInfo() : + Command(), + Input(), + Output() + { + } + + /// + /// Initializes a new instance of the class. + /// + OperationInfo(std::string command, std::vector input, std::vector output) : + Command(std::move(command)), + Input(std::move(input)), + Output(std::move(output)) + { + } + + std::string Command; + std::vector Input; + std::vector Output; + }; + + export class BuildHistory + { + public: + /// + /// Initializes a new instance of the class. + /// + BuildHistory() : + _operations() + { + } + + /// + /// Initializes a new instance of the class. + /// + BuildHistory(std::vector operations) + { + _operations.clear(); + for (auto& info : operations) + { + _operations.emplace(info.Command, std::move(info)); + } + } + + /// + /// Get Operations + /// + const std::unordered_map& GetOperations() const + { + return _operations; + } + + /// + /// Find an operation info + /// + bool TryFindOperationInfo(const std::string& command, const OperationInfo*& operation) const + { + auto findResult = _operations.find(command); + if (findResult != _operations.end()) + { + operation = &findResult->second; + return true; + } + else + { + return false; + } + } + + /// + /// Add an operation info + /// + void AddOperationInfo(OperationInfo operation) + { + _operations.emplace(operation.Command, std::move(operation)); + } + + private: + std::unordered_map _operations; + }; +} diff --git a/Source/Client/Core/Build/Runner/BuildHistoryChecker.h b/Source/Build/Execute/BuildHistoryChecker.h similarity index 92% rename from Source/Client/Core/Build/Runner/BuildHistoryChecker.h rename to Source/Build/Execute/BuildHistoryChecker.h index 7c13bcbd..ff5283b9 100644 --- a/Source/Client/Core/Build/Runner/BuildHistoryChecker.h +++ b/Source/Build/Execute/BuildHistoryChecker.h @@ -5,7 +5,7 @@ #pragma once #include "BuildHistory.h" -namespace Soup::Build +namespace Soup::Build::Execute { export class BuildHistoryChecker { @@ -24,8 +24,9 @@ namespace Soup::Build const std::vector& inputFiles, const Path& rootPath) { + // If there are no input files then the output can never be outdated if (inputFiles.empty()) - throw std::runtime_error("Cannot check outdated with no input files."); + return false; for (auto& targetFile : targetFiles) { diff --git a/Source/Build/Execute/BuildHistoryJson.h b/Source/Build/Execute/BuildHistoryJson.h new file mode 100644 index 00000000..93ef75fa --- /dev/null +++ b/Source/Build/Execute/BuildHistoryJson.h @@ -0,0 +1,172 @@ +// +// Copyright (c) Soup. All rights reserved. +// + +#pragma once +#include "BuildHistory.h" + +namespace Soup::Build::Execute +{ + /// + /// The build state json serializer + /// + export class BuildHistoryJson + { + private: + static constexpr const char* Property_Operations = "operations"; + static constexpr const char* Property_Command = "command"; + static constexpr const char* Property_Input = "input"; + static constexpr const char* Property_Output = "output"; + + public: + /// + /// Load from stream + /// + static BuildHistory Deserialize(std::istream& stream) + { + // Read the entire file into a string + std::string content( + (std::istreambuf_iterator(stream)), + std::istreambuf_iterator()); + + // Read the contents of the build state file + std::string error = ""; + auto jsonRoot = json11::Json::parse(content, error); + if (jsonRoot.is_null()) + { + auto message = "Failed to parse the build state json: " + error; + throw std::runtime_error(std::move(message)); + } + else + { + return LoadJsonBuildHistory(jsonRoot); + } + } + + /// + /// Save the BuildHistory to the root file + /// + static void Serialize(const BuildHistory& state, std::ostream& stream) + { + // Serialize the contents of the build state + json11::Json json = BuildJsonBuildHistory(state); + + stream << json.dump(); + } + + private: + static BuildHistory LoadJsonBuildHistory(const json11::Json& value) + { + auto operations = std::vector(); + + if (!value[Property_Operations].is_null()) + { + for (auto& value : value[Property_Operations].array_items()) + { + auto operationInfo = LoadJsonOperationInfo(value); + operations.push_back(std::move(operationInfo)); + } + } + else + { + throw std::runtime_error("Missing Required field: knownFiles."); + } + + return BuildHistory( + std::move(operations)); + } + + static OperationInfo LoadJsonOperationInfo(const json11::Json& value) + { + std::string command; + std::vector input; + std::vector output; + + if (!value[Property_Command].is_null()) + { + command = value[Property_Command].string_value(); + } + else + { + throw std::runtime_error("Missing Required field: file."); + } + + if (!value[Property_Input].is_null()) + { + auto values = std::vector(); + for (auto& value : value[Property_Input].array_items()) + { + values.push_back(Path(value.string_value())); + } + + input = std::move(values); + } + else + { + throw std::runtime_error("Missing Required field: input."); + } + + if (!value[Property_Output].is_null()) + { + auto values = std::vector(); + for (auto& value : value[Property_Output].array_items()) + { + values.push_back(Path(value.string_value())); + } + + output = std::move(values); + } + else + { + throw std::runtime_error("Missing Required field: output."); + } + + return OperationInfo( + std::move(command), + std::move(input), + std::move(output)); + } + + static json11::Json BuildJsonBuildHistory(const BuildHistory& state) + { + json11::Json::object result = {}; + + // Add required fields + json11::Json::array operations; + for (auto& value : state.GetOperations()) + { + operations.push_back(BuildJsonOperationInfo(value.second)); + } + + result[Property_Operations] = std::move(operations); + + return result; + } + + static json11::Json BuildJsonOperationInfo(const OperationInfo& info) + { + json11::Json::object result = {}; + + // Add required fields + result[Property_Command] = info.Command; + + json11::Json::array input; + for (auto& value : info.Input) + { + input.push_back(value.ToString()); + } + + result[Property_Input] = std::move(input); + + json11::Json::array output; + for (auto& value : info.Output) + { + output.push_back(value.ToString()); + } + + result[Property_Output] = std::move(output); + + return result; + } + }; +} diff --git a/Source/Client/Core/Build/Runner/BuildHistoryManager.h b/Source/Build/Execute/BuildHistoryManager.h similarity index 86% rename from Source/Client/Core/Build/Runner/BuildHistoryManager.h rename to Source/Build/Execute/BuildHistoryManager.h index 49b0704f..ef30b154 100644 --- a/Source/Client/Core/Build/Runner/BuildHistoryManager.h +++ b/Source/Build/Execute/BuildHistoryManager.h @@ -5,9 +5,8 @@ #pragma once #include "BuildHistory.h" #include "BuildHistoryJson.h" -#include "Constants.h" -namespace Soup::Build +namespace Soup::Build::Execute { /// /// The build state manager @@ -16,17 +15,19 @@ namespace Soup::Build { private: static constexpr std::string_view BuildHistoryFileName = "BuildHistory.json"; + static constexpr std::string_view ProjectGenerateFolderName = ".soup"; public: /// /// Load the build state from the provided directory /// static bool TryLoadState( - const Path& directory, BuildHistory& result) + const Path& directory, + BuildHistory& result) { // Verify the requested file exists auto BuildHistoryFile = directory + - Path(Constants::ProjectGenerateFolderName) + + Path(ProjectGenerateFolderName) + Path(BuildHistoryFileName); if (!System::IFileSystem::Current().Exists(BuildHistoryFile)) { @@ -61,7 +62,7 @@ namespace Soup::Build static void SaveState(const Path& directory, const BuildHistory& state) { auto buildProjectGenerateFolder = directory + - Path(Constants::ProjectGenerateFolderName); + Path(ProjectGenerateFolderName); auto BuildHistoryFile = buildProjectGenerateFolder + Path(BuildHistoryFileName); diff --git a/Source/Build/Execute/BuildRunner.h b/Source/Build/Execute/BuildRunner.h new file mode 100644 index 00000000..7b87c927 --- /dev/null +++ b/Source/Build/Execute/BuildRunner.h @@ -0,0 +1,266 @@ +// +// Copyright (c) Soup. All rights reserved. +// + +#pragma once +#include "BuildHistory.h" +#include "SystemAccessTracker.h" + +namespace Soup::Build::Execute +{ + /// + /// The build runner + /// + export class BuildRunner + { + public: + /// + /// Initializes a new instance of the class. + /// + BuildRunner(Path workingDirectory) : + _workingDirectory(std::move(workingDirectory)), + _dependencyCounts(), + _buildHistory(), + _stateChecker() + { + } + + // TODO: Convert vector to const when we have a const version of the operation wrapper. + void Execute( + Utilities::BuildOperationListWrapper& operations, + const Path& objectDirectory, + bool forceBuild) + { + // Load the previous build state if performing an incremental build + auto targetDirectory = _workingDirectory + objectDirectory; + if (!forceBuild) + { + Log::Diag("Loading previous build state"); + if (!BuildHistoryManager::TryLoadState(targetDirectory, _buildHistory)) + { + Log::Info("No previous state found, full rebuild required"); + _buildHistory = BuildHistory(); + forceBuild = true; + } + } + + // Build the initial operation dependency set to + // ensure operations are built in the correct order + // and that there are no cycles + auto emptyParentSet = std::set(); + BuildDependencies(operations, emptyParentSet); + + // Run all build operations in the correct order with incremental build checks + CheckExecuteOperations(operations, forceBuild); + + Log::Info("Saving updated build state"); + BuildHistoryManager::SaveState(targetDirectory, _buildHistory); + + Log::HighPriority("Done"); + } + + private: + /// + /// Build dependencies + /// + void BuildDependencies( + Utilities::BuildOperationListWrapper& operations, + const std::set& parentSet) + { + for (auto i = 0; i < operations.GetSize(); i++) + { + // Make sure there are no cycles using the address as a unique id + auto operation = operations.GetValueAt(i); + auto operationId = reinterpret_cast(operation.GetRaw()); + if (parentSet.contains(operationId)) + throw std::runtime_error("A build operation graph must be acyclic."); + + // Check if the operation was already a child from a different path + auto currentOperationSearch = _dependencyCounts.find(operationId); + if (currentOperationSearch != _dependencyCounts.end()) + { + // Increment the dependency count + currentOperationSearch->second++; + } + else + { + // Insert a new entry with a single count + _dependencyCounts.emplace(operationId, 1); + + // Recurse to children only the first time we see an operation + auto updatedParentSet = parentSet; + updatedParentSet.insert(operationId); + BuildDependencies(operation.GetChildList(), updatedParentSet); + } + } + } + + /// + /// Execute the collection of build operations + /// + void CheckExecuteOperations( + Utilities::BuildOperationListWrapper& operations, + bool forceBuild) + { + for (auto i = 0; i < operations.GetSize(); i++) + { + // Check if the operation was already a child from a different path + // Make sure there are no cycles using the address as a unique id + auto operation = operations.GetValueAt(i); + auto operationId = reinterpret_cast(operation.GetRaw()); + auto currentOperationSearch = _dependencyCounts.find(operationId); + if (currentOperationSearch != _dependencyCounts.end()) + { + auto remainingCount = --currentOperationSearch->second; + if (remainingCount == 0) + { + ExecuteOperation(operation, forceBuild); + } + else + { + // This operation will be executed from a different path + } + } + else + { + throw std::runtime_error("A operation id was missing from the dependency collection."); + } + } + } + + /// + /// Execute a single build operation and all of its children + /// + void ExecuteOperation( + Utilities::BuildOperationWrapper& operation, + bool forceBuild) + { + // Build up the operation unique command + std::stringstream commandBuilder; + commandBuilder << operation.GetWorkingDirectory() << " : " << operation.GetExecutable() << " " << operation.GetArguments(); + auto command = commandBuilder.str(); + + bool buildRequired = forceBuild; + if (!forceBuild) + { + // Check if each source file is out of date and requires a rebuild + Log::Diag("Check for updated source"); + + // Check if this operation is in the build history + const OperationInfo* operationInfo; + if (_buildHistory.TryFindOperationInfo(command, operationInfo)) + { + // Check if any of the input files have changed since last build + if (_stateChecker.IsOutdated( + operationInfo->Output, + operationInfo->Input, + Path(operation.GetWorkingDirectory()))) + { + buildRequired = true; + } + else + { + Log::Info("Up to date"); + } + } + else + { + // The build command has not been run before + buildRequired = true; + } + } + + if (buildRequired) + { + Log::HighPriority(operation.GetTitle()); + auto executable = Path(operation.GetExecutable()); + auto arguments = std::string(operation.GetArguments()); + auto workingDirectory = Path(operation.GetWorkingDirectory()); + auto message = "Execute: " + executable.ToString() + " " + arguments; + Log::Diag(message); + + auto callback = std::make_shared(); + auto process = Monitor::IDetourProcessManager::Current().CreateDetourProcess( + executable, + arguments, + workingDirectory, + callback); + + process->Start(); + process->WaitForExit(); + + auto stdOut = process->GetStandardOutput(); + auto stdErr = process->GetStandardError(); + auto exitCode = process->GetExitCode(); + + // Retrieve the input/output files + // TODO: Verify opertation output matches input + auto runtimeInput = callback->GetInput(); + for (auto& value : operation.GetInputFileList().CopyAsStringVector()) + { + runtimeInput.insert(value); + } + + auto input = std::vector(); + for (auto& value : runtimeInput) + { + input.push_back(Path(value)); + } + + auto runtimeOutput = callback->GetOutput(); + for (auto& value : operation.GetOutputFileList().CopyAsStringVector()) + { + runtimeOutput.insert(value); + } + + auto output = std::vector(); + for (auto& value : runtimeOutput) + { + output.push_back(Path(value)); + } + + // Save off the build history for future builds + auto operationInfo = OperationInfo( + command, + std::move(input), + std::move(output)); + _buildHistory.AddOperationInfo(std::move(operationInfo)); + + if (!stdOut.empty()) + { + // Upgrade output to a warning if the command fails + if (exitCode != 0) + Log::Warning(stdOut); + else + Log::Info(stdOut); + } + + // If there was any error output then the build failed + // TODO: Find warnings + errors + if (!stdErr.empty()) + { + Log::Error(stdErr); + } + + if (exitCode != 0) + { + throw std::runtime_error("Compiler Object Error: " + std::to_string(exitCode)); + } + } + else + { + Log::Info(operation.GetTitle()); + } + + // Recursively build all of the operation children + // Note: Force build if this operation was built + CheckExecuteOperations(operation.GetChildList(), buildRequired); + } + + private: + Path _workingDirectory; + std::map _dependencyCounts; + BuildHistory _buildHistory; + BuildHistoryChecker _stateChecker; + }; +} diff --git a/Source/Build/Execute/Module.cpp b/Source/Build/Execute/Module.cpp new file mode 100644 index 00000000..f2c2a192 --- /dev/null +++ b/Source/Build/Execute/Module.cpp @@ -0,0 +1,35 @@ +module; + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +export module Soup.Build.Execute; + +import json11; +import Monitor.Shared; +import Opal; +import Soup.Build; +import Soup.Build.Utilities; + +using namespace Opal; + +#include "BuildHistory.h" +#include "BuildHistoryChecker.h" +#include "BuildHistoryJson.h" +#include "BuildHistoryManager.h" +#include "BuildRunner.h" diff --git a/Source/Build/Execute/Recipe.toml b/Source/Build/Execute/Recipe.toml new file mode 100644 index 00000000..6328e0b2 --- /dev/null +++ b/Source/Build/Execute/Recipe.toml @@ -0,0 +1,18 @@ +Name = "Soup.Build.Execute" +Description = """The Build Execution engine that is responsible for Execution of the minumum +set of Build Operations for a fully consistent build.""" +Version = "0.1.0" +Dependencies = [ + # "../../../Dependencies/json11/", + "json11@1.0.0", + "../../../Dependencies/Opal/Source/", + # "Opal@0.1.2", + "../Contracts/", + # "Soup.Build@0.3.0", + "../Utilities/", + # "Soup.Build.Utilities@0.3.0", + "../../Monitor/Shared/", +] +Public = "Module.cpp" +Source = [ +] diff --git a/Source/Build/Execute/SystemAccessTracker.h b/Source/Build/Execute/SystemAccessTracker.h new file mode 100644 index 00000000..27474898 --- /dev/null +++ b/Source/Build/Execute/SystemAccessTracker.h @@ -0,0 +1,1090 @@ +#pragma once + +namespace Soup::Build +{ + class SystemAccessTracker : public Monitor::IDetourCallback + { + public: + SystemAccessTracker() : + m_input(), + m_output() + { + } + + std::set GetInput() + { + return m_input; + } + + std::set GetOutput() + { + return m_output; + } + + void OnShutdown() override final + { + } + + void OnError(std::string_view message) override final + { + Log::Error("SystemAccessTracker Error: " + std::string(message)); + } + + // FileApi + void OnAreFileApisANSI(bool result) override final + { + } + + void OnCompareFileTime(int32_t result) override final + { + } + + void OnCreateDirectoryA(std::string_view pathName, bool result) override final + { + TouchFileWrite(pathName); + } + + void OnCreateDirectoryW(std::wstring_view pathName, bool result) override final + { + TouchFileWrite(pathName); + } + + void OnCreateFile2( + std::wstring_view fileName, + uint32_t desiredAccess, + uint32_t sharedMode, + uint32_t creationDisposition, + uint64_t result) override final + { + bool isRead = (desiredAccess & GENERIC_READ) != 0; + bool isWrite = (desiredAccess & GENERIC_WRITE) != 0; + if (isWrite) + { + TouchFileWrite(fileName); + } + else + { + bool exists = result != (uint64_t)INVALID_HANDLE_VALUE; + TouchFileRead(fileName, exists); + } + } + + void OnCreateFileA( + std::string_view fileName, + uint32_t desiredAccess, + uint32_t sharedMode, + uint32_t creationDisposition, + uint32_t flagsAndAttributes, + uint64_t result) override final + { + bool isRead = (desiredAccess & GENERIC_READ) != 0; + bool isWrite = (desiredAccess & GENERIC_WRITE) != 0; + if (isWrite) + { + TouchFileWrite(fileName); + } + else + { + bool exists = result != (uint64_t)INVALID_HANDLE_VALUE; + TouchFileRead(fileName, exists); + } + } + + void OnCreateFileW( + std::wstring_view fileName, + uint32_t desiredAccess, + uint32_t sharedMode, + uint32_t creationDisposition, + uint32_t flagsAndAttributes, + uint64_t result) override final + { + bool isRead = (desiredAccess & GENERIC_READ) != 0; + bool isWrite = (desiredAccess & GENERIC_WRITE) != 0; + if (isWrite) + { + TouchFileWrite(fileName); + } + else + { + bool exists = result != (uint64_t)INVALID_HANDLE_VALUE; + TouchFileRead(fileName, exists); + } + } + + void OnDefineDosDeviceW(uint32_t flags, std::wstring_view deviceName, std::wstring_view targetPath, bool result) override final + { + } + + void OnDeleteFileA(std::string_view fileName, bool result) override final + { + TouchFileDelete(fileName); + } + + void OnDeleteFileW(std::wstring_view fileName, bool result) override final + { + TouchFileDelete(fileName); + } + + void OnDeleteVolumeMountPointW(std::wstring_view volumeMountPoint, bool result) override final + { + } + + void OnFileTimeToLocalFileTime(bool result) override final + { + } + + void OnFindClose(bool result) override final + { + } + + void OnFindCloseChangeNotification(bool result) override final + { + } + + void OnFindFirstChangeNotificationA(std::string_view pathName, bool watchSubtree, uint32_t notifyFilter) override final + { + // TODO: Track search paths + } + + void OnFindFirstChangeNotificationW(std::wstring_view pathName, bool watchSubtree, uint32_t notifyFilter) override final + { + // TODO: Track search paths + } + + void OnFindFirstFileA(std::string_view fileName) override final + { + // TODO: Track search paths + } + + void OnFindFirstFileW(std::wstring_view fileName) override final + { + // TODO: Track search paths + } + + void OnFindFirstFileExA(std::string_view fileName) override final + { + // TODO: Track search paths + } + + void OnFindFirstFileExW(std::wstring_view fileName) override final + { + // TODO: Track search paths + } + + void OnFindFirstFileNameW(std::wstring_view fileName, uint32_t flags) override final + { + // TODO: Track search paths + } + + void OnFindFirstStreamW(std::wstring_view fileName) override final + { + // TODO: Track search paths + } + + void OnFindFirstVolumeW(std::wstring_view fileName) override final + { + } + + void OnFindNextChangeNotification(bool result) override final + { + } + + void OnFindNextFileA(bool result) override final + { + } + + void OnFindNextFileW(bool result) override final + { + } + + void OnFindNextFileNameW(bool result) override final + { + } + + void OnFindNextStreamW(bool result) override final + { + } + + void OnFindNextVolumeW(bool result) override final + { + } + + void OnFindVolumeClose(bool result) override final + { + } + + void OnFlushFileBuffers(bool result) override final + { + } + + void OnGetCompressedFileSizeA(std::string_view fileName, uint32_t result) override final + { + throw std::runtime_error("OnGetCompressedFileSizeA Not implemented"); + } + + void OnGetCompressedFileSizeW(std::wstring_view fileName, uint32_t result) override final + { + throw std::runtime_error("OnGetCompressedFileSizeW Not implemented"); + } + + void OnGetDiskFreeSpaceA(std::string_view rootPathName, bool result) override final + { + } + + void OnGetDiskFreeSpaceW(std::wstring_view rootPathName, bool result) override final + { + } + + void OnGetDiskFreeSpaceExA(std::string_view directoryName, bool result) override final + { + } + + void OnGetDiskFreeSpaceExW(std::wstring_view directoryName, bool result) override final + { + } + + void OnGetDriveTypeA(std::string_view rootPathName, uint32_t result) override final + { + } + + void OnGetDriveTypeW(std::wstring_view rootPathName, uint32_t result) override final + { + } + + void OnGetFileAttributesA(std::string_view fileName, uint32_t result) override final + { + auto exists = result != INVALID_FILE_ATTRIBUTES; + TouchFileRead(fileName, exists); + } + + void OnGetFileAttributesW(std::wstring_view fileName, uint32_t result) override final + { + auto exists = result != INVALID_FILE_ATTRIBUTES; + TouchFileRead(fileName, exists); + } + + void OnGetFileAttributesExA(std::string_view fileName, bool result) override final + { + TouchFileRead(fileName, result); + } + + void OnGetFileAttributesExW(std::wstring_view fileName, bool result) override final + { + TouchFileRead(fileName, result); + } + + void OnGetFileInformationByHandle(bool result) override final + { + } + + void OnGetFileSize(uint32_t result) override final + { + } + + void OnGetFileSizeEx(uint32_t result) override final + { + } + + void OnGetFileTime(bool result) override final + { + } + + void OnGetFileType(uint32_t result) override final + { + } + + void OnGetFinalPathNameByHandleA(uint32_t result) override final + { + } + + void OnGetFinalPathNameByHandleW(uint32_t result) override final + { + } + + void OnGetFullPathNameA(std::string_view fileName, uint32_t result) override final + { + } + + void OnGetFullPathNameW(std::wstring_view fileName, std::wstring_view buffer, uint32_t result) override final + { + } + + void OnGetLogicalDrives(uint32_t result) override final + { + } + + void OnGetLogicalDriveStringsW(std::wstring_view buffer, uint32_t result) override final + { + } + + void OnGetLongPathNameA(std::string_view shortPath, std::string_view longPath, uint32_t result) override final + { + } + + void OnGetLongPathNameW(std::wstring_view shortPath, std::wstring_view longPath, uint32_t result) override final + { + } + + void OnGetShortPathNameW(std::wstring_view longPath, std::wstring_view shortPath, uint32_t result) override final + { + } + + void OnGetTempFileNameA(std::string_view pathName, std::string_view prefixString, uint32_t unique, std::string_view tempFileName, uint32_t result) override final + { + } + + void OnGetTempFileNameW(std::wstring_view pathName, std::wstring_view prefixString, uint32_t unique, std::wstring_view tempFileName, uint32_t result) override final + { + } + + void OnGetTempPathA(std::string_view buffer, uint32_t result) override final + { + } + + void OnGetTempPathW(std::wstring_view buffer, uint32_t result) override final + { + } + + void OnGetVolumeInformationA(bool result) override final + { + } + + void OnGetVolumeInformationW(bool result) override final + { + } + + void OnGetVolumeInformationByHandleW(bool result) override final + { + } + + void OnGetVolumeNameForVolumeMountPointW(bool result) override final + { + } + + void OnGetVolumePathNamesForVolumeNameW(bool result) override final + { + } + + void OnGetVolumePathNameW(std::wstring_view filename, bool result) override final + { + } + + void OnLocalFileTimeToFileTime(bool result) override final + { + } + + void OnLockFile(bool result) override final + { + } + + void OnLockFileEx(bool result) override final + { + } + + void OnQueryDosDeviceW(std::wstring_view deviceName, uint32_t result) override final + { + } + + void OnReadFile(bool result) override final + { + } + + void OnReadFileEx(bool result) override final + { + } + + void OnReadFileScatter(bool result) override final + { + } + + void OnRemoveDirectoryA(std::string_view pathName, bool result) override final + { + throw std::runtime_error("OnRemoveDirectoryA Not implemented"); + } + + void OnRemoveDirectoryW(std::wstring_view pathName, bool result) override final + { + throw std::runtime_error("OnRemoveDirectoryW Not implemented"); + } + + void OnSetEndOfFile(bool result) override final + { + } + + void OnSetFileApisToANSI() override final + { + } + + void OnSetFileApisToOEM() override final + { + } + + void OnSetFileAttributesA(std::string_view fileName, bool result) override final + { + TouchFileWrite(fileName); + } + + void OnSetFileAttributesW(std::wstring_view fileName, bool result) override final + { + TouchFileWrite(fileName); + } + + void OnSetFileInformationByHandle(bool result) override final + { + } + + void OnSetFileIoOverlappedRange(bool result) override final + { + } + + void OnSetFilePointer(uint32_t result) override final + { + } + + void OnSetFilePointerEx(bool result) override final + { + } + + void OnSetFileTime(bool result) override final + { + } + + void OnSetFileValidData(bool result) override final + { + } + + void OnUnlockFile(bool result) override final + { + } + + void OnUnlockFileEx(bool result) override final + { + } + + void OnWriteFile(bool result) override final + { + } + + void OnWriteFileEx(bool result) override final + { + } + + void OnWriteFileGather(bool result) override final + { + } + + // LibLoaderApi + void OnLoadLibraryA(std::string_view libFileName) override final + { + } + + void OnLoadLibraryW(std::wstring_view libFileName) override final + { + } + + void OnLoadLibraryExA(std::string_view libFileName) override final + { + } + + void OnLoadLibraryExW(std::wstring_view libFileName) override final + { + } + + // ProcessEnv + void OnSearchPathA(std::string_view path, std::string_view fileName, std::string_view extension, uint32_t result) override final + { + throw std::runtime_error("OnSearchPathA Not implemented"); + } + + void OnSearchPathW(std::wstring_view path, std::wstring_view fileName, std::wstring_view extension, uint32_t result) override final + { + throw std::runtime_error("OnSearchPathW Not implemented"); + } + + // ProcessThreadsApi + void OnCreateProcessA(std::string_view applicationName, bool result) override final + { + } + + void OnCreateProcessW(std::wstring_view applicationName, bool result) override final + { + } + + void OnCreateProcessAsUserA(std::string_view applicationName, bool result) override final + { + } + + void OnCreateProcessAsUserW(std::wstring_view applicationName, bool result) override final + { + } + + void OnExitProcess(uint32_t exitCode) override final + { + } + + // UndocumentedApi + void OnPrivCopyFileExA(std::string_view existingFileName, std::string_view newFileName, bool result) override final + { + // TODO: May want to check the last error for ERROR_FILE_NOT_FOUND + TouchFileRead(existingFileName, result); + TouchFileWrite(newFileName); + } + + void OnPrivCopyFileExW(std::wstring_view existingFileName, std::wstring_view newFileName, bool result) override final + { + // TODO: May want to check the last error for ERROR_FILE_NOT_FOUND + TouchFileRead(existingFileName, result); + TouchFileWrite(newFileName); + } + + // WinBase + void OnCopyFileA( + std::string_view existingFileName, + std::string_view newFileName, + bool failIfExists, + bool result) override final + { + // TODO: May want to check the last error for ERROR_FILE_NOT_FOUND + TouchFileRead(existingFileName, result); + TouchFileWrite(newFileName); + } + + void OnCopyFileW( + std::wstring_view existingFileName, + std::wstring_view newFileName, + bool failIfExists, + bool result) override final + { + // TODO: May want to check the last error for ERROR_FILE_NOT_FOUND + TouchFileRead(existingFileName, result); + TouchFileWrite(newFileName); + } + + void OnCopyFile2(std::wstring_view existingFileName, std::wstring_view newFileName, uint64_t result) override final + { + bool exists = result != (uint64_t)INVALID_HANDLE_VALUE; + TouchFileRead(existingFileName, exists); + TouchFileWrite(newFileName); + } + + void OnCopyFileExA(std::string_view existingFileName, std::string_view newFileName, bool result) override final + { + // TODO: May want to check the last error for ERROR_FILE_NOT_FOUND + TouchFileRead(existingFileName, result); + TouchFileWrite(newFileName); + } + + void OnCopyFileExW(std::wstring_view existingFileName, std::wstring_view newFileName, bool result) override final + { + // TODO: May want to check the last error for ERROR_FILE_NOT_FOUND + TouchFileRead(existingFileName, result); + TouchFileWrite(newFileName); + } + + void OnCopyFileTransactedA(std::string_view existingFileName, std::string_view newFileName, bool result) override final + { + // TODO: May want to check the last error for ERROR_FILE_NOT_FOUND + TouchFileRead(existingFileName, result); + TouchFileWrite(newFileName); + } + + void OnCopyFileTransactedW(std::wstring_view existingFileName, std::wstring_view newFileName, bool result) override final + { + // TODO: May want to check the last error for ERROR_FILE_NOT_FOUND + TouchFileRead(existingFileName, result); + TouchFileWrite(newFileName); + } + + void OnCreateDirectoryExA(std::string_view templateDirectory, std::string_view newDirectory, bool result) override final + { + TouchFileWrite(newDirectory); + } + + void OnCreateDirectoryExW(std::wstring_view templateDirectory, std::wstring_view newDirectory, bool result) override final + { + TouchFileWrite(newDirectory); + } + + void OnCreateDirectoryTransactedA(std::string_view templateDirectory, std::string_view newDirectory, bool result) override final + { + TouchFileWrite(newDirectory); + } + + void OnCreateDirectoryTransactedW(std::wstring_view templateDirectory, std::wstring_view newDirectory, bool result) override final + { + TouchFileWrite(newDirectory); + } + + void OnCreateFileTransactedA(std::string_view fileName, uint32_t desiredAccess, uint32_t shareMode, uint64_t result) override final + { + bool isRead = (desiredAccess & GENERIC_READ) != 0; + bool isWrite = (desiredAccess & GENERIC_WRITE) != 0; + if (isWrite) + { + TouchFileWrite(fileName); + } + else + { + bool exists = result != (uint64_t)INVALID_HANDLE_VALUE; + TouchFileRead(fileName, exists); + } + } + + void OnCreateFileTransactedW(std::wstring_view fileName, uint32_t desiredAccess, uint32_t shareMode, uint64_t result) override final + { + bool isRead = (desiredAccess & GENERIC_READ) != 0; + bool isWrite = (desiredAccess & GENERIC_WRITE) != 0; + if (isWrite) + { + TouchFileWrite(fileName); + } + else + { + bool exists = result != (uint64_t)INVALID_HANDLE_VALUE; + TouchFileRead(fileName, exists); + } + } + + void OnCreateHardLinkA(std::string_view fileName, std::string_view existingFileName, bool result) override final + { + throw std::runtime_error("OnCreateHardLinkA Not implemented"); + } + + void OnCreateHardLinkW(std::wstring_view fileName, std::wstring_view existingFileName, bool result) override final + { + throw std::runtime_error("OnCreateHardLinkW Not implemented"); + } + + void OnCreateHardLinkTransactedA(std::string_view fileName, std::string_view existingFileName, bool result) override final + { + throw std::runtime_error("OnCreateHardLinkTransactedA Not implemented"); + } + + void OnCreateHardLinkTransactedW(std::wstring_view fileName, std::wstring_view existingFileName, bool result) override final + { + throw std::runtime_error("OnCreateHardLinkTransactedW Not implemented"); + } + + void OnCreateProcessWithLogonW(std::wstring_view applicationName, bool result) override final + { + } + + void OnCreateProcessWithTokenW(std::wstring_view applicationName, bool result) override final + { + } + + void OnCreateSymbolicLinkA(std::string_view symlinkFileName, std::string_view targetFileName, uint32_t flags, bool result) override final + { + throw std::runtime_error("OnCreateSymbolicLinkA Not implemented"); + } + + void OnCreateSymbolicLinkW(std::wstring_view symlinkFileName, std::wstring_view targetFileName, uint32_t flags, bool result) override final + { + throw std::runtime_error("OnCreateSymbolicLinkW Not implemented"); + } + + void OnCreateSymbolicLinkTransactedA(std::string_view symlinkFileName, std::string_view targetFileName, uint32_t flags, bool result) override final + { + throw std::runtime_error("OnCreateSymbolicLinkTransactedA Not implemented"); + } + + void OnCreateSymbolicLinkTransactedW(std::wstring_view symlinkFileName, std::wstring_view targetFileName, uint32_t flags, bool result) override final + { + throw std::runtime_error("OnCreateSymbolicLinkTransactedW Not implemented"); + } + + void OnDecryptFileA(std::string_view fileName, bool result) override final + { + throw std::runtime_error("OnDecryptFileA Not implemented"); + } + + void OnDecryptFileW(std::wstring_view fileName, bool result) override final + { + throw std::runtime_error("OnDecryptFileW Not implemented"); + } + + void OnDeleteFileTransactedA(std::string_view fileName, bool result) override final + { + TouchFileDelete(fileName); + } + + void OnDeleteFileTransactedW(std::wstring_view fileName, bool result) override final + { + TouchFileDelete(fileName); + } + + void OnEncryptFileA(std::string_view fileName, bool result) override final + { + throw std::runtime_error("OnEncryptFileA Not implemented"); + } + + void OnEncryptFileW(std::wstring_view fileName, bool result) override final + { + throw std::runtime_error("OnEncryptFileW Not implemented"); + } + + void OnFileEncryptionStatusA(std::string_view fileName, bool result) override final + { + throw std::runtime_error("OnFileEncryptionStatusA Not implemented"); + } + + void OnFileEncryptionStatusW(std::wstring_view fileName, bool result) override final + { + throw std::runtime_error("OnFileEncryptionStatusW Not implemented"); + } + + void OnFindFirstFileNameTransactedW(std::wstring_view fileName, bool result) override final + { + throw std::runtime_error("OnFindFirstFileNameTransactedW Not implemented"); + } + + void OnFindFirstFileTransactedA(std::string_view fileName) override final + { + throw std::runtime_error("OnFindFirstFileTransactedA Not implemented"); + } + + void OnFindFirstFileTransactedW(std::wstring_view fileName) override final + { + throw std::runtime_error("OnFindFirstFileTransactedW Not implemented"); + } + + void OnFindFirstStreamTransactedW(std::wstring_view fileName) override final + { + throw std::runtime_error("OnFindFirstStreamTransactedW Not implemented"); + } + + void OnGetBinaryTypeA(std::string_view applicationName, bool result) override final + { + } + + void OnGetBinaryTypeW(std::wstring_view applicationName, bool result) override final + { + } + + void OnGetCompressedFileSizeTransactedA(std::string_view fileName, uint32_t result) override final + { + throw std::runtime_error("OnGetCompressedFileSizeTransactedA Not implemented"); + } + + void OnGetCompressedFileSizeTransactedW(std::wstring_view fileName, uint32_t result) override final + { + throw std::runtime_error("OnGetCompressedFileSizeTransactedW Not implemented"); + } + + void OnGetDllDirectoryA(uint32_t result) override final + { + } + + void OnGetDllDirectoryW(uint32_t result) override final + { + } + + void OnGetFileAttributesTransactedA(std::string_view fileName, uint32_t result) override final + { + auto exists = result != INVALID_FILE_ATTRIBUTES; + TouchFileRead(fileName, exists); + } + + void OnGetFileAttributesTransactedW(std::wstring_view fileName, uint32_t result) override final + { + auto exists = result != INVALID_FILE_ATTRIBUTES; + TouchFileRead(fileName, exists); + } + + void OnGetFileBandwidthReservation(bool result) override final + { + } + + void OnGetFileInformationByHandleEx(bool result) override final + { + } + + void OnGetFileSecurityA(std::string_view fileName, bool result) override final + { + TouchFileRead(fileName, result); + } + + void OnGetFullPathNameTransactedA(std::string_view fileName, uint32_t result) override final + { + throw std::runtime_error("OnGetFullPathNameTransactedA Not implemented"); + } + + void OnGetFullPathNameTransactedW(std::wstring_view fileName, uint32_t result) override final + { + throw std::runtime_error("OnGetFullPathNameTransactedW Not implemented"); + } + + void OnGetLongPathNameTransactedA(std::string_view shortPath, std::string_view longPath, uint32_t result) override final + { + } + + void OnGetLongPathNameTransactedW(std::wstring_view shortPath, std::wstring_view longPath, uint32_t result) override final + { + } + + void OnGetQueuedCompletionStatus(bool result) override final + { + } + + void OnGetQueuedCompletionStatusEx(bool result) override final + { + } + + void OnGetShortPathNameA(std::string_view longPath, std::string_view shortPath, uint32_t result) override final + { + } + + void OnLoadModule(std::string_view moduleName, uint32_t result) override final + { + } + + void OnLoadPackagedLibrary(std::string_view libFileName) override final + { + } + + void OnMoveFileA(std::string_view existingFileName, std::string_view newFileName, bool result) override final + { + // TODO: May want to check the last error for ERROR_FILE_NOT_FOUND + TouchFileRead(existingFileName, result); + TouchFileWrite(newFileName); + } + + void OnMoveFileW(std::wstring_view existingFileName, std::wstring_view newFileName, bool result) override final + { + // TODO: May want to check the last error for ERROR_FILE_NOT_FOUND + TouchFileRead(existingFileName, result); + TouchFileWrite(newFileName); + } + + void OnMoveFileExA(std::string_view existingFileName, std::string_view newFileName, uint32_t flags, bool result) override final + { + // TODO: May want to check the last error for ERROR_FILE_NOT_FOUND + TouchFileRead(existingFileName, result); + TouchFileWrite(newFileName); + } + + void OnMoveFileExW(std::wstring_view existingFileName, std::wstring_view newFileName, uint32_t flags, bool result) override final + { + // TODO: May want to check the last error for ERROR_FILE_NOT_FOUND + TouchFileRead(existingFileName, result); + TouchFileWrite(newFileName); + } + + void OnMoveFileTransactedA(std::string_view existingFileName, std::string_view newFileName, uint32_t flags, bool result) override final + { + // TODO: May want to check the last error for ERROR_FILE_NOT_FOUND + TouchFileRead(existingFileName, result); + TouchFileWrite(newFileName); + } + + void OnMoveFileTransactedW(std::wstring_view existingFileName, std::wstring_view newFileName, uint32_t flags, bool result) override final + { + // TODO: May want to check the last error for ERROR_FILE_NOT_FOUND + TouchFileRead(existingFileName, result); + TouchFileWrite(newFileName); + } + + void OnMoveFileWithProgressA(std::string_view existingFileName, std::string_view newFileName, uint32_t flags, bool result) override final + { + // TODO: May want to check the last error for ERROR_FILE_NOT_FOUND + TouchFileRead(existingFileName, result); + TouchFileWrite(newFileName); + } + + void OnMoveFileWithProgressW(std::wstring_view existingFileName, std::wstring_view newFileName, uint32_t flags, bool result) override final + { + // TODO: May want to check the last error for ERROR_FILE_NOT_FOUND + TouchFileRead(existingFileName, result); + TouchFileWrite(newFileName); + } + + void OnOpenEncryptedFileRawA(std::string_view fileName, uint32_t flags, uint32_t result) override final + { + throw std::runtime_error("OnOpenEncryptedFileRawA Not implemented"); + } + + void OnOpenEncryptedFileRawW(std::wstring_view fileName, uint32_t flags, uint32_t result) override final + { + throw std::runtime_error("OnOpenEncryptedFileRawW Not implemented"); + } + + void OnOpenFile(std::string_view fileName) override final + { + throw std::runtime_error("OnOpenFile Not implemented"); + } + + void OnOpenFileById() override final + { + throw std::runtime_error("OnOpenFileById Not implemented"); + } + + void OnReadEncryptedFileRaw(uint32_t result) override final + { + } + + void OnRemoveDirectoryTransactedA(std::string_view pathName, bool result) override final + { + throw std::runtime_error("OnRemoveDirectoryTransactedA Not implemented"); + } + + void OnRemoveDirectoryTransactedW(std::wstring_view pathName, bool result) override final + { + throw std::runtime_error("OnRemoveDirectoryTransactedW Not implemented"); + } + + void OnReOpenFile() override final + { + throw std::runtime_error("OnReOpenFile Not implemented"); + } + + void OnReplaceFileA(std::string_view replacedFileName, std::string_view replacementFileName, std::string_view backupFileName, uint32_t replaceFlags, bool result) override final + { + throw std::runtime_error("OnReplaceFileA Not implemented"); + } + + void OnReplaceFileW(std::wstring_view replacedFileName, std::wstring_view replacementFileName, std::wstring_view backupFileName, uint32_t replaceFlags, bool result) override final + { + throw std::runtime_error("OnReplaceFileW Not implemented"); + } + + void OnSetCurrentDirectoryA(std::string_view pathName, bool result) override final + { + // Will need to update paths for files when changed + throw std::runtime_error("OnSetCurrentDirectoryA Not implemented"); + } + + void OnSetCurrentDirectoryW(std::wstring_view pathName, bool result) override final + { + // Will need to update paths for files when changed + throw std::runtime_error("OnSetCurrentDirectoryW Not implemented"); + } + + void OnSetDllDirectoryA(std::string_view pathName, bool result) override final + { + throw std::runtime_error("OnSetDllDirectoryA Not implemented"); + } + + void OnSetDllDirectoryW(std::wstring_view pathName, bool result) override final + { + throw std::runtime_error("OnSetDllDirectoryW Not implemented"); + } + + void OnSetFileAttributesTransactedA(std::string_view pathName, uint32_t fileAttributes, bool result) override final + { + throw std::runtime_error("OnSetFileAttributesTransactedA Not implemented"); + } + + void OnSetFileAttributesTransactedW(std::wstring_view pathName, uint32_t fileAttributes, bool result) override final + { + throw std::runtime_error("OnSetFileAttributesTransactedW Not implemented"); + } + + void OnSetFileBandwidthReservation(bool result) override final + { + throw std::runtime_error("OnSetFileBandwidthReservation Not implemented"); + } + + void OnSetFileCompletionNotificationModes(bool result) override final + { + } + + void OnSetFileSecurityA(std::string_view fileName, bool result) override final + { + throw std::runtime_error("OnSetFileSecurityA Not implemented"); + } + + void OnSetFileShortNameA(std::string_view shortName, bool result) override final + { + throw std::runtime_error("OnSetFileShortNameA Not implemented"); + } + + void OnSetFileShortNameW(std::wstring_view shortName, bool result) override final + { + throw std::runtime_error("OnSetFileShortNameW Not implemented"); + } + + void OnSetSearchPathMode(uint32_t flags, bool result) override final + { + } + + void OnWriteEncryptedFileRaw(uint32_t result) override final + { + } + + private: + void TouchFileRead(std::wstring_view fileName, bool exists) + { + std::wstring_convert, wchar_t> converter; + TouchFileRead(converter.to_bytes(fileName.data()), exists); + } + + void TouchFileRead(std::string_view fileName, bool exists) + { + // Verify not a special file + if (!IsSpecialFile(fileName)) + { + auto filePath = Path(fileName); + auto filePathString = filePath.ToString(); + if (exists) + { + m_input.insert(filePathString); + } + else + { + m_inputMissing.insert(filePathString); + } + } + } + + void TouchFileWrite(std::wstring_view fileName) + { + std::wstring_convert, wchar_t> converter; + TouchFileWrite(converter.to_bytes(fileName.data())); + } + + void TouchFileWrite(std::string_view fileName) + { + // Verify not a special file + if (!IsSpecialFile(fileName)) + { + auto filePath = Path(fileName); + auto filePathString = filePath.ToString(); + + m_output.insert(filePathString); + } + } + + void TouchFileDelete(std::string_view fileName) + { + auto filePath = Path(fileName); + TouchFileDelete(filePath); + } + + void TouchFileDelete(std::wstring_view fileName) + { + std::wstring_convert, wchar_t> converter; + auto filePath = Path(converter.to_bytes(fileName.data())); + TouchFileDelete(filePath); + } + + void TouchFileDelete(Path& filePath) + { + // If this was an output file extract it as it was a transient file + // TODO: May want to track if we created the file + auto extractOutputResult = m_output.extract(filePath.ToString()); + auto extractInputResult = m_input.extract(filePath.ToString()); + } + + bool IsSpecialFile(std::string_view fileName) + { + // Check if the file name is a pipe or the standard input/output streams + return fileName.starts_with("\\\\.\\pipe\\") || + fileName == "CONIN$" || + fileName == "CONOUT$"; + } + + std::set m_input; + std::set m_inputMissing; + std::set m_output; + }; +} diff --git a/Source/Build/Runtime/Recipe.toml b/Source/Build/Runtime/Recipe.toml deleted file mode 100644 index ba331d8d..00000000 --- a/Source/Build/Runtime/Recipe.toml +++ /dev/null @@ -1,16 +0,0 @@ -Name = "Soup.Build.Runtime" -Version = "0.1.0" - -Dependencies = [ - "../Core/", - # "Soup.Build@0.3.0", - "../Extensions/", - # "Soup.Build.Extensions@0.3.0", - "../../../Dependencies/Opal/Source/", - # "Opal@0.1.2", -] - -Public = "Module.cpp" -Source = [ - "Value.cpp", -] diff --git a/Source/Build/Extensions.UnitTests/Recipe.toml b/Source/Build/Utilities.UnitTests/Recipe.toml similarity index 68% rename from Source/Build/Extensions.UnitTests/Recipe.toml rename to Source/Build/Utilities.UnitTests/Recipe.toml index facc6ac8..6bc4a77e 100644 --- a/Source/Build/Extensions.UnitTests/Recipe.toml +++ b/Source/Build/Utilities.UnitTests/Recipe.toml @@ -1,8 +1,8 @@ -Name = "SoupBuildExtensionsUnitTests" +Name = "Soup.Build.Utlities.UnitTests" Version = "1.0.0" Type = "Executable" Dependencies = [ - "../Extensions/", + "../Utilities/", "../../TestUtilities/", "SoupTest@0.1.0", ] diff --git a/Source/Build/Extensions.UnitTests/RecipeLanguageVersionTests.h b/Source/Build/Utilities.UnitTests/RecipeLanguageVersionTests.h similarity index 96% rename from Source/Build/Extensions.UnitTests/RecipeLanguageVersionTests.h rename to Source/Build/Utilities.UnitTests/RecipeLanguageVersionTests.h index 82e17f75..23b98491 100644 --- a/Source/Build/Extensions.UnitTests/RecipeLanguageVersionTests.h +++ b/Source/Build/Utilities.UnitTests/RecipeLanguageVersionTests.h @@ -4,7 +4,7 @@ #pragma once -namespace Soup::Build::Extensions::UnitTests +namespace Soup::Build::Utilities::UnitTests { class RecipeLanguageVersionTests { diff --git a/Source/Build/Extensions.UnitTests/RecipeTypeTests.h b/Source/Build/Utilities.UnitTests/RecipeTypeTests.h similarity index 95% rename from Source/Build/Extensions.UnitTests/RecipeTypeTests.h rename to Source/Build/Utilities.UnitTests/RecipeTypeTests.h index 05d1ed2a..a998beb5 100644 --- a/Source/Build/Extensions.UnitTests/RecipeTypeTests.h +++ b/Source/Build/Utilities.UnitTests/RecipeTypeTests.h @@ -4,7 +4,7 @@ #pragma once -namespace Soup::Build::Extensions::UnitTests +namespace Soup::Build::Utilities::UnitTests { class RecipeTypeTests { diff --git a/Source/Build/Extensions.UnitTests/gen/Main.cpp b/Source/Build/Utilities.UnitTests/gen/Main.cpp similarity index 83% rename from Source/Build/Extensions.UnitTests/gen/Main.cpp rename to Source/Build/Utilities.UnitTests/gen/Main.cpp index 38e158bb..227c224a 100644 --- a/Source/Build/Extensions.UnitTests/gen/Main.cpp +++ b/Source/Build/Utilities.UnitTests/gen/Main.cpp @@ -7,7 +7,7 @@ #include import Opal; -import Soup.Build.Extensions; +import Soup.Build.Utilities; import SoupTest; import SoupTestUtilities; @@ -30,5 +30,8 @@ int main() std::cout << state.PassCount << " PASSED." << std::endl; std::cout << state.FailCount << " FAILED." << std::endl; - return 0; + if (state.FailCount > 0) + return 1; + else + return 0; } diff --git a/Source/Build/Extensions.UnitTests/gen/RecipeLanguageVersionTests.gen.h b/Source/Build/Utilities.UnitTests/gen/RecipeLanguageVersionTests.gen.h similarity index 62% rename from Source/Build/Extensions.UnitTests/gen/RecipeLanguageVersionTests.gen.h rename to Source/Build/Utilities.UnitTests/gen/RecipeLanguageVersionTests.gen.h index d91f4dfc..dd4d34f2 100644 --- a/Source/Build/Extensions.UnitTests/gen/RecipeLanguageVersionTests.gen.h +++ b/Source/Build/Utilities.UnitTests/gen/RecipeLanguageVersionTests.gen.h @@ -4,16 +4,16 @@ TestState RunRecipeLanguageVersionTests() { auto className = "RecipeLanguageVersionTests"; - auto testClass = std::make_shared(); + auto testClass = std::make_shared(); TestState state = { 0, 0 }; - state += SoupTest::RunTest(className, "ToStringValues(Soup::RecipeLanguageVersion::CPP11, \"C++11\")", [&testClass]() { testClass->ToStringValues(Soup::Build::Extensions::RecipeLanguageVersion::CPP11, "C++11"); }); - state += SoupTest::RunTest(className, "ToStringValues(Soup::RecipeLanguageVersion::CPP14, \"C++14\")", [&testClass]() { testClass->ToStringValues(Soup::Build::Extensions::RecipeLanguageVersion::CPP14, "C++14"); }); - state += SoupTest::RunTest(className, "ToStringValues(Soup::RecipeLanguageVersion::CPP17, \"C++17\")", [&testClass]() { testClass->ToStringValues(Soup::Build::Extensions::RecipeLanguageVersion::CPP17, "C++17"); }); - state += SoupTest::RunTest(className, "ToStringValues(Soup::RecipeLanguageVersion::CPP20, \"C++17\")", [&testClass]() { testClass->ToStringValues(Soup::Build::Extensions::RecipeLanguageVersion::CPP20, "C++20"); }); - state += SoupTest::RunTest(className, "ParseValues(\"C++11\", Soup::RecipeLanguageVersion::CPP11)", [&testClass]() { testClass->ParseValues("C++11", Soup::Build::Extensions::RecipeLanguageVersion::CPP11); }); - state += SoupTest::RunTest(className, "ParseValues(\"C++14\", Soup::RecipeLanguageVersion::CPP14)", [&testClass]() { testClass->ParseValues("C++14", Soup::Build::Extensions::RecipeLanguageVersion::CPP14); }); - state += SoupTest::RunTest(className, "ParseValues(\"C++17\", Soup::RecipeLanguageVersion::CPP17)", [&testClass]() { testClass->ParseValues("C++17", Soup::Build::Extensions::RecipeLanguageVersion::CPP17); }); - state += SoupTest::RunTest(className, "ParseValues(\"C++20\", Soup::RecipeLanguageVersion::CPP20)", [&testClass]() { testClass->ParseValues("C++20", Soup::Build::Extensions::RecipeLanguageVersion::CPP20); }); + state += SoupTest::RunTest(className, "ToStringValues(Soup::RecipeLanguageVersion::CPP11, \"C++11\")", [&testClass]() { testClass->ToStringValues(Soup::Build::Utilities::RecipeLanguageVersion::CPP11, "C++11"); }); + state += SoupTest::RunTest(className, "ToStringValues(Soup::RecipeLanguageVersion::CPP14, \"C++14\")", [&testClass]() { testClass->ToStringValues(Soup::Build::Utilities::RecipeLanguageVersion::CPP14, "C++14"); }); + state += SoupTest::RunTest(className, "ToStringValues(Soup::RecipeLanguageVersion::CPP17, \"C++17\")", [&testClass]() { testClass->ToStringValues(Soup::Build::Utilities::RecipeLanguageVersion::CPP17, "C++17"); }); + state += SoupTest::RunTest(className, "ToStringValues(Soup::RecipeLanguageVersion::CPP20, \"C++17\")", [&testClass]() { testClass->ToStringValues(Soup::Build::Utilities::RecipeLanguageVersion::CPP20, "C++20"); }); + state += SoupTest::RunTest(className, "ParseValues(\"C++11\", Soup::RecipeLanguageVersion::CPP11)", [&testClass]() { testClass->ParseValues("C++11", Soup::Build::Utilities::RecipeLanguageVersion::CPP11); }); + state += SoupTest::RunTest(className, "ParseValues(\"C++14\", Soup::RecipeLanguageVersion::CPP14)", [&testClass]() { testClass->ParseValues("C++14", Soup::Build::Utilities::RecipeLanguageVersion::CPP14); }); + state += SoupTest::RunTest(className, "ParseValues(\"C++17\", Soup::RecipeLanguageVersion::CPP17)", [&testClass]() { testClass->ParseValues("C++17", Soup::Build::Utilities::RecipeLanguageVersion::CPP17); }); + state += SoupTest::RunTest(className, "ParseValues(\"C++20\", Soup::RecipeLanguageVersion::CPP20)", [&testClass]() { testClass->ParseValues("C++20", Soup::Build::Utilities::RecipeLanguageVersion::CPP20); }); state += SoupTest::RunTest(className, "ParseGarbageThrows", [&testClass]() { testClass->ParseGarbageThrows(); }); return state; diff --git a/Source/Build/Extensions.UnitTests/gen/RecipeTypeTests.gen.h b/Source/Build/Utilities.UnitTests/gen/RecipeTypeTests.gen.h similarity index 61% rename from Source/Build/Extensions.UnitTests/gen/RecipeTypeTests.gen.h rename to Source/Build/Utilities.UnitTests/gen/RecipeTypeTests.gen.h index cb1c24dd..c793ea7c 100644 --- a/Source/Build/Extensions.UnitTests/gen/RecipeTypeTests.gen.h +++ b/Source/Build/Utilities.UnitTests/gen/RecipeTypeTests.gen.h @@ -4,14 +4,14 @@ TestState RunRecipeTypeTests() { auto className = "RecipeTypeTests"; - auto testClass = std::make_shared(); + auto testClass = std::make_shared(); TestState state = { 0, 0 }; - state += SoupTest::RunTest(className, "ToStringValues(Soup::RecipeType::Executable, \"Executable\")", [&testClass]() { testClass->ToStringValues(Soup::Build::Extensions::RecipeType::Executable, "Executable"); }); - state += SoupTest::RunTest(className, "ToStringValues(Soup::RecipeType::StaticLibrary, \"StaticLibrary\")", [&testClass]() { testClass->ToStringValues(Soup::Build::Extensions::RecipeType::StaticLibrary, "StaticLibrary"); }); - state += SoupTest::RunTest(className, "ToStringValues(Soup::RecipeType::DynamicLibrary, \"DynamicLibrary\")", [&testClass]() { testClass->ToStringValues(Soup::Build::Extensions::RecipeType::DynamicLibrary, "DynamicLibrary"); }); - state += SoupTest::RunTest(className, "ParseValues(\"Executable\", Soup::RecipeType::Executable)", [&testClass]() { testClass->ParseValues("Executable", Soup::Build::Extensions::RecipeType::Executable); }); - state += SoupTest::RunTest(className, "ParseValues(\"StaticLibrary\", Soup::RecipeType::StaticLibrary)", [&testClass]() { testClass->ParseValues("StaticLibrary", Soup::Build::Extensions::RecipeType::StaticLibrary); }); - state += SoupTest::RunTest(className, "ParseValues(\"DynamicLibrary\", Soup::RecipeType::DynamicLibrary)", [&testClass]() { testClass->ParseValues("DynamicLibrary", Soup::Build::Extensions::RecipeType::DynamicLibrary); }); + state += SoupTest::RunTest(className, "ToStringValues(Soup::RecipeType::Executable, \"Executable\")", [&testClass]() { testClass->ToStringValues(Soup::Build::Utilities::RecipeType::Executable, "Executable"); }); + state += SoupTest::RunTest(className, "ToStringValues(Soup::RecipeType::StaticLibrary, \"StaticLibrary\")", [&testClass]() { testClass->ToStringValues(Soup::Build::Utilities::RecipeType::StaticLibrary, "StaticLibrary"); }); + state += SoupTest::RunTest(className, "ToStringValues(Soup::RecipeType::DynamicLibrary, \"DynamicLibrary\")", [&testClass]() { testClass->ToStringValues(Soup::Build::Utilities::RecipeType::DynamicLibrary, "DynamicLibrary"); }); + state += SoupTest::RunTest(className, "ParseValues(\"Executable\", Soup::RecipeType::Executable)", [&testClass]() { testClass->ParseValues("Executable", Soup::Build::Utilities::RecipeType::Executable); }); + state += SoupTest::RunTest(className, "ParseValues(\"StaticLibrary\", Soup::RecipeType::StaticLibrary)", [&testClass]() { testClass->ParseValues("StaticLibrary", Soup::Build::Utilities::RecipeType::StaticLibrary); }); + state += SoupTest::RunTest(className, "ParseValues(\"DynamicLibrary\", Soup::RecipeType::DynamicLibrary)", [&testClass]() { testClass->ParseValues("DynamicLibrary", Soup::Build::Utilities::RecipeType::DynamicLibrary); }); state += SoupTest::RunTest(className, "ParseGarbageThrows", [&testClass]() { testClass->ParseGarbageThrows(); }); return state; diff --git a/Source/Build/Extensions/BuildOperationExtensions.h b/Source/Build/Utilities/BuildOperationExtensions.h similarity index 94% rename from Source/Build/Extensions/BuildOperationExtensions.h rename to Source/Build/Utilities/BuildOperationExtensions.h index b7db27f5..8f3cb7d8 100644 --- a/Source/Build/Extensions/BuildOperationExtensions.h +++ b/Source/Build/Utilities/BuildOperationExtensions.h @@ -4,7 +4,7 @@ #pragma once -namespace Soup::Build::Extensions +namespace Soup::Build::Utilities { /// /// Build operation extension methods diff --git a/Source/Build/Extensions/Module.cpp b/Source/Build/Utilities/Module.cpp similarity index 87% rename from Source/Build/Extensions/Module.cpp rename to Source/Build/Utilities/Module.cpp index f902d79a..91a2b830 100644 --- a/Source/Build/Extensions/Module.cpp +++ b/Source/Build/Utilities/Module.cpp @@ -6,7 +6,7 @@ #include #include -export module Soup.Build.Extensions; +export module Soup.Build.Utilities; import Opal; import Soup.Build; diff --git a/Source/Build/Extensions/Recipe.toml b/Source/Build/Utilities/Recipe.toml similarity index 58% rename from Source/Build/Extensions/Recipe.toml rename to Source/Build/Utilities/Recipe.toml index 783f1811..8974e3d6 100644 --- a/Source/Build/Extensions/Recipe.toml +++ b/Source/Build/Utilities/Recipe.toml @@ -1,9 +1,11 @@ -Name = "Soup.Build.Extensions" +Name = "Soup.Build.Utilities" +Description = """A set of utility classes that are commonly needed to help +make writting a Build Extension easier.""" Version = "0.3.0" Dependencies = [ "../../../Dependencies/Opal/Source/", # "Opal@0.1.2", - "../Core/", + "../Contracts/", # "Soup.Build@0.3.0", ] diff --git a/Source/Build/Extensions/RecipeLanguageVersion.h b/Source/Build/Utilities/RecipeLanguageVersion.h similarity index 97% rename from Source/Build/Extensions/RecipeLanguageVersion.h rename to Source/Build/Utilities/RecipeLanguageVersion.h index f76bbc62..57c06a44 100644 --- a/Source/Build/Extensions/RecipeLanguageVersion.h +++ b/Source/Build/Utilities/RecipeLanguageVersion.h @@ -2,7 +2,7 @@ // Copyright (c) Soup. All rights reserved. // -namespace Soup::Build::Extensions +namespace Soup::Build::Utilities { /// /// The enumeration of recipe language versions diff --git a/Source/Build/Extensions/RecipeType.h b/Source/Build/Utilities/RecipeType.h similarity index 97% rename from Source/Build/Extensions/RecipeType.h rename to Source/Build/Utilities/RecipeType.h index 08c3b1e5..f78f5057 100644 --- a/Source/Build/Extensions/RecipeType.h +++ b/Source/Build/Utilities/RecipeType.h @@ -2,7 +2,7 @@ // Copyright (c) Soup. All rights reserved. // -namespace Soup::Build::Extensions +namespace Soup::Build::Utilities { /// /// The enumeration of recipe types diff --git a/Source/Build/Extensions/Runtime/BuildOperation.h b/Source/Build/Utilities/Runtime/BuildOperation.h similarity index 94% rename from Source/Build/Extensions/Runtime/BuildOperation.h rename to Source/Build/Utilities/Runtime/BuildOperation.h index ae17d93c..3775c164 100644 --- a/Source/Build/Extensions/Runtime/BuildOperation.h +++ b/Source/Build/Utilities/Runtime/BuildOperation.h @@ -6,7 +6,7 @@ #include "BuildOperationList.h" #include "StringList.h" -namespace Soup::Build::Extensions +namespace Soup::Build::Utilities { /// /// A build operation that represents a single operation in the build diff --git a/Source/Build/Extensions/Runtime/BuildOperationList.cpp b/Source/Build/Utilities/Runtime/BuildOperationList.cpp similarity index 93% rename from Source/Build/Extensions/Runtime/BuildOperationList.cpp rename to Source/Build/Utilities/Runtime/BuildOperationList.cpp index 315a1617..fed0ed3d 100644 --- a/Source/Build/Extensions/Runtime/BuildOperationList.cpp +++ b/Source/Build/Utilities/Runtime/BuildOperationList.cpp @@ -11,11 +11,11 @@ module; #include #include -module Soup.Build.Extensions; +module Soup.Build.Utilities; using namespace Opal; -namespace Soup::Build::Extensions +namespace Soup::Build::Utilities { BuildOperationList::BuildOperationList() : _values() diff --git a/Source/Build/Extensions/Runtime/BuildOperationList.h b/Source/Build/Utilities/Runtime/BuildOperationList.h similarity index 94% rename from Source/Build/Extensions/Runtime/BuildOperationList.h rename to Source/Build/Utilities/Runtime/BuildOperationList.h index aecd7cb7..903ddb18 100644 --- a/Source/Build/Extensions/Runtime/BuildOperationList.h +++ b/Source/Build/Utilities/Runtime/BuildOperationList.h @@ -4,7 +4,7 @@ #pragma once -namespace Soup::Build::Extensions +namespace Soup::Build::Utilities { export class BuildOperation; diff --git a/Source/Build/Extensions/Runtime/StringList.h b/Source/Build/Utilities/Runtime/StringList.h similarity index 93% rename from Source/Build/Extensions/Runtime/StringList.h rename to Source/Build/Utilities/Runtime/StringList.h index 57e09ca6..c8656732 100644 --- a/Source/Build/Extensions/Runtime/StringList.h +++ b/Source/Build/Utilities/Runtime/StringList.h @@ -4,7 +4,7 @@ #pragma once -namespace Soup::Build::Extensions +namespace Soup::Build::Utilities { export class StringList : public IList, public IReadOnlyList { diff --git a/Source/Build/Extensions/Wrapper/BuildOperationListWrapper.cpp b/Source/Build/Utilities/Wrapper/BuildOperationListWrapper.cpp similarity index 93% rename from Source/Build/Extensions/Wrapper/BuildOperationListWrapper.cpp rename to Source/Build/Utilities/Wrapper/BuildOperationListWrapper.cpp index 27eedf66..58451d0c 100644 --- a/Source/Build/Extensions/Wrapper/BuildOperationListWrapper.cpp +++ b/Source/Build/Utilities/Wrapper/BuildOperationListWrapper.cpp @@ -9,11 +9,11 @@ module; #include #include -module Soup.Build.Extensions; +module Soup.Build.Utilities; using namespace Opal; -namespace Soup::Build::Extensions +namespace Soup::Build::Utilities { BuildOperationListWrapper::BuildOperationListWrapper(IList& value) : _value(value) diff --git a/Source/Build/Extensions/Wrapper/BuildOperationListWrapper.h b/Source/Build/Utilities/Wrapper/BuildOperationListWrapper.h similarity index 93% rename from Source/Build/Extensions/Wrapper/BuildOperationListWrapper.h rename to Source/Build/Utilities/Wrapper/BuildOperationListWrapper.h index e94bb327..0302008d 100644 --- a/Source/Build/Extensions/Wrapper/BuildOperationListWrapper.h +++ b/Source/Build/Utilities/Wrapper/BuildOperationListWrapper.h @@ -4,7 +4,7 @@ #pragma once -namespace Soup::Build::Extensions +namespace Soup::Build::Utilities { export class BuildOperationWrapper; diff --git a/Source/Build/Extensions/Wrapper/BuildOperationWrapper.h b/Source/Build/Utilities/Wrapper/BuildOperationWrapper.h similarity index 94% rename from Source/Build/Extensions/Wrapper/BuildOperationWrapper.h rename to Source/Build/Utilities/Wrapper/BuildOperationWrapper.h index 9097f37b..56de1ec9 100644 --- a/Source/Build/Extensions/Wrapper/BuildOperationWrapper.h +++ b/Source/Build/Utilities/Wrapper/BuildOperationWrapper.h @@ -8,7 +8,7 @@ #include "BuildOperationListWrapper.h" #include "ValuePrimitiveWrapper.h" -namespace Soup::Build::Extensions +namespace Soup::Build::Utilities { /// /// Build Property Bag Extension used to make the IBuildOperation interface more usable diff --git a/Source/Build/Extensions/Wrapper/BuildStateWrapper.h b/Source/Build/Utilities/Wrapper/BuildStateWrapper.h similarity index 95% rename from Source/Build/Extensions/Wrapper/BuildStateWrapper.h rename to Source/Build/Utilities/Wrapper/BuildStateWrapper.h index dd1f8aff..4a7c59ab 100644 --- a/Source/Build/Extensions/Wrapper/BuildStateWrapper.h +++ b/Source/Build/Utilities/Wrapper/BuildStateWrapper.h @@ -6,7 +6,7 @@ #include "BuildOperationWrapper.h" #include "ValueTableWrapper.h" -namespace Soup::Build::Extensions +namespace Soup::Build::Utilities { /// /// Build Property Bag Extension used to make the IBuildState interface more usable diff --git a/Source/Build/Extensions/Wrapper/ReadOnlyStringListWrapper.h b/Source/Build/Utilities/Wrapper/ReadOnlyStringListWrapper.h similarity index 93% rename from Source/Build/Extensions/Wrapper/ReadOnlyStringListWrapper.h rename to Source/Build/Utilities/Wrapper/ReadOnlyStringListWrapper.h index b26bc7d9..bf54d622 100644 --- a/Source/Build/Extensions/Wrapper/ReadOnlyStringListWrapper.h +++ b/Source/Build/Utilities/Wrapper/ReadOnlyStringListWrapper.h @@ -4,7 +4,7 @@ #pragma once -namespace Soup::Build::Extensions +namespace Soup::Build::Utilities { /// /// Build State property list implementation, string specialization diff --git a/Source/Build/Extensions/Wrapper/StringListWrapper.h b/Source/Build/Utilities/Wrapper/StringListWrapper.h similarity index 94% rename from Source/Build/Extensions/Wrapper/StringListWrapper.h rename to Source/Build/Utilities/Wrapper/StringListWrapper.h index e2618d1d..b643f56a 100644 --- a/Source/Build/Extensions/Wrapper/StringListWrapper.h +++ b/Source/Build/Utilities/Wrapper/StringListWrapper.h @@ -4,7 +4,7 @@ #pragma once -namespace Soup::Build::Extensions +namespace Soup::Build::Utilities { /// /// Build State property list implementation, string specialization diff --git a/Source/Build/Extensions/Wrapper/ValueListWrapper.h b/Source/Build/Utilities/Wrapper/ValueListWrapper.h similarity index 95% rename from Source/Build/Extensions/Wrapper/ValueListWrapper.h rename to Source/Build/Utilities/Wrapper/ValueListWrapper.h index ff7a292a..a284cbef 100644 --- a/Source/Build/Extensions/Wrapper/ValueListWrapper.h +++ b/Source/Build/Utilities/Wrapper/ValueListWrapper.h @@ -5,7 +5,7 @@ #pragma once #include "ValueWrapper.h" -namespace Soup::Build::Extensions +namespace Soup::Build::Utilities { /// /// Build State property list implementation, string specialization diff --git a/Source/Build/Extensions/Wrapper/ValuePrimitiveWrapper.h b/Source/Build/Utilities/Wrapper/ValuePrimitiveWrapper.h similarity index 91% rename from Source/Build/Extensions/Wrapper/ValuePrimitiveWrapper.h rename to Source/Build/Utilities/Wrapper/ValuePrimitiveWrapper.h index 43dc2656..c85948cd 100644 --- a/Source/Build/Extensions/Wrapper/ValuePrimitiveWrapper.h +++ b/Source/Build/Utilities/Wrapper/ValuePrimitiveWrapper.h @@ -4,7 +4,7 @@ #pragma once -namespace Soup::Build::Extensions +namespace Soup::Build::Utilities { /// /// Build State property list implementation, string specialization diff --git a/Source/Build/Extensions/Wrapper/ValueTableWrapper.h b/Source/Build/Utilities/Wrapper/ValueTableWrapper.h similarity index 94% rename from Source/Build/Extensions/Wrapper/ValueTableWrapper.h rename to Source/Build/Utilities/Wrapper/ValueTableWrapper.h index 8605c822..1f79ee46 100644 --- a/Source/Build/Extensions/Wrapper/ValueTableWrapper.h +++ b/Source/Build/Utilities/Wrapper/ValueTableWrapper.h @@ -6,7 +6,7 @@ #include "ValueWrapper.h" #include "ValuePrimitiveWrapper.h" -namespace Soup::Build::Extensions +namespace Soup::Build::Utilities { /// /// Build Property Table Extension used to make the IValueTable interface more usable diff --git a/Source/Build/Extensions/Wrapper/ValueWrapper.cpp b/Source/Build/Utilities/Wrapper/ValueWrapper.cpp similarity index 94% rename from Source/Build/Extensions/Wrapper/ValueWrapper.cpp rename to Source/Build/Utilities/Wrapper/ValueWrapper.cpp index e23ef689..95f32d99 100644 --- a/Source/Build/Extensions/Wrapper/ValueWrapper.cpp +++ b/Source/Build/Utilities/Wrapper/ValueWrapper.cpp @@ -9,11 +9,11 @@ module; #include #include -module Soup.Build.Extensions; +module Soup.Build.Utilities; using namespace Opal; -namespace Soup::Build::Extensions +namespace Soup::Build::Utilities { ValueWrapper::ValueWrapper(IValue& value) : diff --git a/Source/Build/Extensions/Wrapper/ValueWrapper.h b/Source/Build/Utilities/Wrapper/ValueWrapper.h similarity index 94% rename from Source/Build/Extensions/Wrapper/ValueWrapper.h rename to Source/Build/Utilities/Wrapper/ValueWrapper.h index fa42203c..2c84b2ee 100644 --- a/Source/Build/Extensions/Wrapper/ValueWrapper.h +++ b/Source/Build/Utilities/Wrapper/ValueWrapper.h @@ -4,7 +4,7 @@ #pragma once -namespace Soup::Build::Extensions +namespace Soup::Build::Utilities { export class ValueTableWrapper; export class ValueListWrapper; diff --git a/Source/Client/CLI.UnitTests/gen/Main.cpp b/Source/Client/CLI.UnitTests/gen/Main.cpp index fe3173ce..fa4d8a82 100644 --- a/Source/Client/CLI.UnitTests/gen/Main.cpp +++ b/Source/Client/CLI.UnitTests/gen/Main.cpp @@ -29,5 +29,8 @@ int main() std::cout << state.PassCount << " PASSED." << std::endl; std::cout << state.FailCount << " FAILED." << std::endl; - return 0; + if (state.FailCount > 0) + return 1; + else + return 0; } diff --git a/Source/Client/CLI/Commands/BuildCommand.h b/Source/Client/CLI/Commands/BuildCommand.h index 6dcb19f6..037b5889 100644 --- a/Source/Client/CLI/Commands/BuildCommand.h +++ b/Source/Client/CLI/Commands/BuildCommand.h @@ -69,64 +69,15 @@ namespace Soup::Client else arguments.Flavor = "debug"; - if (!_options.Platform.empty()) - arguments.Platform = _options.Platform; + if (!_options.System.empty()) + arguments.System = _options.System; else - arguments.Platform = "Windows"; // TODO: Pull current platform + arguments.System = "win32"; - // TODO: Hard coded to windows MSVC runtime libraries - // And we only trust the config today - arguments.PlatformIncludePaths = std::vector({}); - for (auto& path : config.GetWindowsSDKIncludePaths()) - { - arguments.PlatformIncludePaths.push_back(path); - } - - arguments.PlatformLibraryPaths = std::vector({}); - for (auto& path : config.GetWindowsSDKLibraryPaths()) - { - arguments.PlatformLibraryPaths.push_back(path); - } - - arguments.PlatformPreprocessorDefinitions = std::vector({ - // "_DLL", // Link against the dynamic runtime dll - // "_MT", // Use multithreaded runtime - }); - - // if (_options.Configuration == "debug") - // { - // // arguments.PlatformPreprocessorDefinitions.push_back("_DEBUG"); - // arguments.PlatformLibraries = std::vector({ - // Path("msvcprtd.lib"), - // Path("msvcrtd.lib"), - // Path("ucrtd.lib"), - // Path("vcruntimed.lib"), - // }); - // } - // else - // { - // arguments.PlatformLibraries = std::vector({ - // Path("msvcprt.lib"), - // Path("msvcrt.lib"), - // Path("ucrt.lib"), - // Path("vcruntime.lib"), - // }); - // } - - // arguments.PlatformLibraries.push_back(Path("kernel32.lib")); - arguments.PlatformLibraries.push_back("user32.lib"); - // arguments.PlatformLibraries.push_back(Path("gdi32.lib")); - // arguments.PlatformLibraries.push_back(Path("winspool.lib")); - // arguments.PlatformLibraries.push_back(Path("comdlg32.lib")); - arguments.PlatformLibraries.push_back("advapi32.lib"); - arguments.PlatformLibraries.push_back("shell32.lib"); - // arguments.PlatformLibraries.push_back(Path("ole32.lib")); - arguments.PlatformLibraries.push_back("oleaut32.lib"); - // arguments.PlatformLibraries.push_back(Path("uuid.lib")); - // arguments.PlatformLibraries.push_back(Path("odbc32.lib")); - // arguments.PlatformLibraries.push_back(Path("odbccp32.lib")); - - arguments.PlatformLibraries.push_back("crypt32.lib"); + if (!_options.Architecture.empty()) + arguments.Architecture = _options.Architecture; + else + arguments.Architecture = "x64"; std::string runtimeCompiler = config.GetRuntimeCompiler(); std::string systemCompiler = runtimeCompiler; @@ -135,7 +86,7 @@ namespace Soup::Client Log::Info("Begin Build:"); auto startTime = std::chrono::high_resolution_clock::now(); - auto buildManager = Build::Runtime::RecipeBuildManager(systemCompiler, runtimeCompiler); + auto buildManager = Build::RecipeBuildManager(systemCompiler, runtimeCompiler); buildManager.Execute(workingDirectory, recipe, arguments); auto endTime = std::chrono::high_resolution_clock::now(); diff --git a/Source/Client/CLI/Commands/InitializeCommand.h b/Source/Client/CLI/Commands/InitializeCommand.h index 922caf3b..7105bce1 100644 --- a/Source/Client/CLI/Commands/InitializeCommand.h +++ b/Source/Client/CLI/Commands/InitializeCommand.h @@ -40,7 +40,7 @@ namespace Soup::Client workingDirectory.GetFileName(), SemanticVersion(1, 0, 0)); - recipe.SetType(Build::Extensions::RecipeType::Executable); + recipe.SetType(Build::Utilities::RecipeType::Executable); recipe.SetSource(std::vector({ "Main.cpp", })); diff --git a/Source/Client/CLI/Commands/RunCommand.h b/Source/Client/CLI/Commands/RunCommand.h index b0ab3a08..41d80dd3 100644 --- a/Source/Client/CLI/Commands/RunCommand.h +++ b/Source/Client/CLI/Commands/RunCommand.h @@ -44,16 +44,22 @@ namespace Soup::Client } // Ensure that this is an executable - if (recipe.GetType() != Build::Extensions::RecipeType::Executable) + if (recipe.GetType() != Build::Utilities::RecipeType::Executable) { Log::Error("Cannot run a project not of type executable"); return; } // Ensure the executable exists - auto configuration = "debug"; + auto flavor = "debug"; + auto system = "win32"; + auto architecture = "x64"; auto compilerName = config.GetRuntimeCompiler(); - auto binaryDirectory = RecipeExtensions::GetBinaryDirectory(compilerName, configuration); + auto binaryDirectory = RecipeExtensions::GetBinaryDirectory( + compilerName, + flavor, + system, + architecture); auto executablePath = workingDirectory + binaryDirectory + Path(recipe.GetName() + ".exe"); Log::Info(executablePath.ToString()); if (!System::IFileSystem::Current().Exists(executablePath)) @@ -69,29 +75,30 @@ namespace Soup::Client } // Execute the requested target - auto result = System::IProcessManager::Current().Execute( + auto process = System::IProcessManager::Current().CreateProcess( executablePath, arguments.str(), workingDirectory); + process->Start(); + process->WaitForExit(); - // TODO: Directly pipe to output and make sure there is no extra newline - if (!result.StdOut.empty()) - { - Log::HighPriority(result.StdOut); - } + auto stdOut = process->GetStandardOutput(); + auto stdErr = process->GetStandardError(); + auto exitCode = process->GetExitCode(); - if (!result.StdErr.empty()) + // TODO: Directly pipe to output and make sure there is no extra newline + if (!stdOut.empty()) { - Log::Error(result.StdErr); + Log::HighPriority(stdOut); } - if (result.ExitCode != 0) + if (!stdErr.empty()) { - // TODO: Return error code - Log::Error("FAILED"); + Log::Error(stdErr); } - Log::Info("Done"); + if (exitCode != 0) + throw HandledException(exitCode); } private: diff --git a/Source/Client/CLI/Commands/VersionCommand.h b/Source/Client/CLI/Commands/VersionCommand.h index 57834c86..e45f579d 100644 --- a/Source/Client/CLI/Commands/VersionCommand.h +++ b/Source/Client/CLI/Commands/VersionCommand.h @@ -31,7 +31,7 @@ namespace Soup::Client // TODO var version = Assembly.GetExecutingAssembly().GetName().Version; // Log::Message($"{version.Major}.{version.Minor}.{version.Build}"); - Log::HighPriority("0.7.0"); + Log::HighPriority("0.8.0"); } private: diff --git a/Source/Client/CLI/Main.cpp b/Source/Client/CLI/Main.cpp index 8e522647..9efe1497 100644 --- a/Source/Client/CLI/Main.cpp +++ b/Source/Client/CLI/Main.cpp @@ -11,6 +11,7 @@ #include #include +import Monitor.Shared; import Opal; import Opal.Extensions; import SoupCore; diff --git a/Source/Client/CLI/Options/ArgumentsParser.h b/Source/Client/CLI/Options/ArgumentsParser.h index 61d0bf3b..5aab5db0 100644 --- a/Source/Client/CLI/Options/ArgumentsParser.h +++ b/Source/Client/CLI/Options/ArgumentsParser.h @@ -62,10 +62,16 @@ namespace Soup::Client options->Flavor = std::move(flavorValue); } - auto platformValue = std::string(); - if (TryGetValueArgument("platform", unusedArgs, platformValue)) + auto systemValue = std::string(); + if (TryGetValueArgument("system", unusedArgs, systemValue)) { - options->Platform = std::move(platformValue); + options->System = std::move(systemValue); + } + + auto architectureValue = std::string(); + if (TryGetValueArgument("architecture", unusedArgs, architectureValue)) + { + options->Architecture = std::move(architectureValue); } result = std::move(options); diff --git a/Source/Client/CLI/Options/BuildOptions.h b/Source/Client/CLI/Options/BuildOptions.h index db76226c..64ff9b02 100644 --- a/Source/Client/CLI/Options/BuildOptions.h +++ b/Source/Client/CLI/Options/BuildOptions.h @@ -39,9 +39,15 @@ namespace Soup::Client std::string Flavor; /// - /// Gets or sets a value indicating what target platform + /// Gets or sets a value indicating what target system /// - [[Args::Option('p', "platform", Default = false, HelpText = "Platform.")]] - std::string Platform; + [[Args::Option('s', "system", Default = false, HelpText = "System.")]] + std::string System; + + /// + /// Gets or sets a value indicating what target architecture + /// + [[Args::Option('a', "architecture", Default = false, HelpText = "Architecture.")]] + std::string Architecture; }; } diff --git a/Source/Client/CLI/Program.h b/Source/Client/CLI/Program.h index 5bef3aba..b0b92f4e 100644 --- a/Source/Client/CLI/Program.h +++ b/Source/Client/CLI/Program.h @@ -53,6 +53,7 @@ namespace Soup::Client Network::INetworkManager::Register(std::make_shared()); System::IFileSystem::Register(std::make_shared()); System::IProcessManager::Register(std::make_shared()); + Monitor::IDetourProcessManager::Register(std::make_shared()); IO::IConsoleManager::Register(std::make_shared()); // Attempt to parse the provided arguments @@ -100,10 +101,10 @@ namespace Soup::Client return 0; } - catch (const HandledException&) + catch (const HandledException& ex) { - Log::Info("Exception Handled: Exiting"); - return -1; + Log::Diag("Exception Handled: Exiting"); + return ex.GetExitCode(); } catch (const std::exception& ex) { diff --git a/Source/Client/CLI/Recipe.toml b/Source/Client/CLI/Recipe.toml index 4a580e52..f597d729 100644 --- a/Source/Client/CLI/Recipe.toml +++ b/Source/Client/CLI/Recipe.toml @@ -1,11 +1,12 @@ Name = "Soup" -Version = "0.7.0" +Version = "0.8.0" Type = "Executable" # Ensure the core build extensions are runtime dependencies Dependencies = [ "../Core/", "../../Extensions/RecipeBuild/", + "../../Monitor/Shared/", ] RuntimeDependencies = [ "LocalUserConfig.json", diff --git a/Source/Client/Core.UnitTests/Package/RecipeBuildManagerTests.h b/Source/Client/Core.UnitTests/Package/RecipeBuildManagerTests.h index 7fff6e25..bcf410ef 100644 --- a/Source/Client/Core.UnitTests/Package/RecipeBuildManagerTests.h +++ b/Source/Client/Core.UnitTests/Package/RecipeBuildManagerTests.h @@ -4,7 +4,7 @@ #pragma once -namespace Soup::Build::Runtime::UnitTests +namespace Soup::Build::UnitTests { class RecipeBuildManagerTests { diff --git a/Source/Client/Core.UnitTests/Package/RecipeJsonTests.h b/Source/Client/Core.UnitTests/Package/RecipeJsonTests.h index faa0ac93..43d89bd1 100644 --- a/Source/Client/Core.UnitTests/Package/RecipeJsonTests.h +++ b/Source/Client/Core.UnitTests/Package/RecipeJsonTests.h @@ -82,8 +82,8 @@ namespace Soup::Build::UnitTests auto expected = Recipe( "MyPackage", SemanticVersion(1, 2, 3), - Build::Extensions::RecipeType::Executable, - Build::Extensions::RecipeLanguageVersion::CPP17, + Build::Utilities::RecipeType::Executable, + Build::Utilities::RecipeLanguageVersion::CPP17, std::vector(), std::vector(), "Public.cpp", @@ -119,8 +119,8 @@ namespace Soup::Build::UnitTests auto recipe = Recipe( "MyPackage", SemanticVersion(1, 2, 3), - Build::Extensions::RecipeType::Executable, - Build::Extensions::RecipeLanguageVersion::CPP17, + Build::Utilities::RecipeType::Executable, + Build::Utilities::RecipeLanguageVersion::CPP17, std::vector(), std::vector(), "Public.cpp", diff --git a/Source/Client/Core.UnitTests/Package/RecipeTests.h b/Source/Client/Core.UnitTests/Package/RecipeTests.h index ed78c1aa..45ed006e 100644 --- a/Source/Client/Core.UnitTests/Package/RecipeTests.h +++ b/Source/Client/Core.UnitTests/Package/RecipeTests.h @@ -32,8 +32,8 @@ namespace Soup::Build::UnitTests auto uut = Recipe( "MyPackage", SemanticVersion(1, 2, 3), - Build::Extensions::RecipeType::Executable, - Build::Extensions::RecipeLanguageVersion::CPP20, + Build::Utilities::RecipeType::Executable, + Build::Utilities::RecipeLanguageVersion::CPP20, std::vector({ PackageReference(Path("../OtherPackage")), }), @@ -54,9 +54,9 @@ namespace Soup::Build::UnitTests Assert::AreEqual("MyPackage", uut.GetName(), "Verify name matches expected."); Assert::AreEqual(SemanticVersion(1, 2, 3), uut.GetVersion(), "Verify version is correct."); Assert::IsTrue(uut.HasType(), "Verify has type."); - Assert::AreEqual(Build::Extensions::RecipeType::Executable, uut.GetType(), "Verify type is correct."); + Assert::AreEqual(Build::Utilities::RecipeType::Executable, uut.GetType(), "Verify type is correct."); Assert::IsTrue(uut.HasLanguageVersion(), "Verify has language version."); - Assert::AreEqual(Build::Extensions::RecipeLanguageVersion::CPP20, uut.GetLanguageVersion(), "Verify language version is correct."); + Assert::AreEqual(Build::Utilities::RecipeLanguageVersion::CPP20, uut.GetLanguageVersion(), "Verify language version is correct."); Assert::IsTrue(uut.HasDependencies(), "Verify has dependencies."); Assert::AreEqual( std::vector({ @@ -110,8 +110,8 @@ namespace Soup::Build::UnitTests auto uut = Recipe( "MyPackage", SemanticVersion(1, 2, 3), - Build::Extensions::RecipeType::Executable, - Build::Extensions::RecipeLanguageVersion::CPP17, + Build::Utilities::RecipeType::Executable, + Build::Utilities::RecipeLanguageVersion::CPP17, std::vector({ PackageReference(Path("../OtherPackage")), }), @@ -133,8 +133,8 @@ namespace Soup::Build::UnitTests Recipe( "MyPackage", SemanticVersion(1, 2, 3), - Build::Extensions::RecipeType::Executable, - Build::Extensions::RecipeLanguageVersion::CPP17, + Build::Utilities::RecipeType::Executable, + Build::Utilities::RecipeLanguageVersion::CPP17, std::vector({ PackageReference(Path("../OtherPackage")), }), @@ -161,8 +161,8 @@ namespace Soup::Build::UnitTests auto uut = Recipe( "MyPackage", SemanticVersion(1, 2, 3), - Build::Extensions::RecipeType::Executable, - Build::Extensions::RecipeLanguageVersion::CPP17, + Build::Utilities::RecipeType::Executable, + Build::Utilities::RecipeLanguageVersion::CPP17, std::vector({ PackageReference(Path("../OtherPackage")), }), @@ -184,8 +184,8 @@ namespace Soup::Build::UnitTests Recipe( "MyPackage2", SemanticVersion(1, 2, 3), - Build::Extensions::RecipeType::Executable, - Build::Extensions::RecipeLanguageVersion::CPP17, + Build::Utilities::RecipeType::Executable, + Build::Utilities::RecipeLanguageVersion::CPP17, std::vector({ PackageReference(Path("../OtherPackage")), }), @@ -212,8 +212,8 @@ namespace Soup::Build::UnitTests auto uut = Recipe( "MyPackage", SemanticVersion(1, 2, 3), - Build::Extensions::RecipeType::Executable, - Build::Extensions::RecipeLanguageVersion::CPP17, + Build::Utilities::RecipeType::Executable, + Build::Utilities::RecipeLanguageVersion::CPP17, std::vector({ PackageReference(Path("../OtherPackage")), }), @@ -235,8 +235,8 @@ namespace Soup::Build::UnitTests Recipe( "MyPackage", SemanticVersion(11, 2, 3), - Build::Extensions::RecipeType::Executable, - Build::Extensions::RecipeLanguageVersion::CPP17, + Build::Utilities::RecipeType::Executable, + Build::Utilities::RecipeLanguageVersion::CPP17, std::vector({ PackageReference(Path("../OtherPackage")), }), @@ -263,8 +263,8 @@ namespace Soup::Build::UnitTests auto uut = Recipe( "MyPackage", SemanticVersion(1, 2, 3), - Build::Extensions::RecipeType::Executable, - Build::Extensions::RecipeLanguageVersion::CPP17, + Build::Utilities::RecipeType::Executable, + Build::Utilities::RecipeLanguageVersion::CPP17, std::vector({ PackageReference(Path("../OtherPackage")), }), @@ -286,8 +286,8 @@ namespace Soup::Build::UnitTests Recipe( "MyPackage", SemanticVersion(1, 2, 3), - Build::Extensions::RecipeType::StaticLibrary, - Build::Extensions::RecipeLanguageVersion::CPP17, + Build::Utilities::RecipeType::StaticLibrary, + Build::Utilities::RecipeLanguageVersion::CPP17, std::vector({ PackageReference(Path("../OtherPackage")), }), @@ -314,8 +314,8 @@ namespace Soup::Build::UnitTests auto uut = Recipe( "MyPackage", SemanticVersion(1, 2, 3), - Build::Extensions::RecipeType::Executable, - Build::Extensions::RecipeLanguageVersion::CPP17, + Build::Utilities::RecipeType::Executable, + Build::Utilities::RecipeLanguageVersion::CPP17, std::vector({ PackageReference(Path("../OtherPackage")), }), @@ -338,7 +338,7 @@ namespace Soup::Build::UnitTests "MyPackage", SemanticVersion(1, 2, 3), std::nullopt, - Build::Extensions::RecipeLanguageVersion::CPP17, + Build::Utilities::RecipeLanguageVersion::CPP17, std::vector({ PackageReference(Path("../OtherPackage")), }), @@ -365,8 +365,8 @@ namespace Soup::Build::UnitTests auto uut = Recipe( "MyPackage", SemanticVersion(1, 2, 3), - Build::Extensions::RecipeType::Executable, - Build::Extensions::RecipeLanguageVersion::CPP17, + Build::Utilities::RecipeType::Executable, + Build::Utilities::RecipeLanguageVersion::CPP17, std::vector({ PackageReference(Path("../OtherPackage")), }), @@ -388,8 +388,8 @@ namespace Soup::Build::UnitTests Recipe( "MyPackage", SemanticVersion(1, 2, 3), - Build::Extensions::RecipeType::Executable, - Build::Extensions::RecipeLanguageVersion::CPP20, + Build::Utilities::RecipeType::Executable, + Build::Utilities::RecipeLanguageVersion::CPP20, std::vector({ PackageReference(Path("../OtherPackage")), }), @@ -416,8 +416,8 @@ namespace Soup::Build::UnitTests auto uut = Recipe( "MyPackage", SemanticVersion(1, 2, 3), - Build::Extensions::RecipeType::Executable, - Build::Extensions::RecipeLanguageVersion::CPP17, + Build::Utilities::RecipeType::Executable, + Build::Utilities::RecipeLanguageVersion::CPP17, std::vector({ PackageReference(Path("../OtherPackage")), }), @@ -439,7 +439,7 @@ namespace Soup::Build::UnitTests Recipe( "MyPackage", SemanticVersion(1, 2, 3), - Build::Extensions::RecipeType::Executable, + Build::Utilities::RecipeType::Executable, std::nullopt, std::vector({ PackageReference(Path("../OtherPackage")), @@ -467,8 +467,8 @@ namespace Soup::Build::UnitTests auto uut = Recipe( "MyPackage", SemanticVersion(1, 2, 3), - Build::Extensions::RecipeType::Executable, - Build::Extensions::RecipeLanguageVersion::CPP17, + Build::Utilities::RecipeType::Executable, + Build::Utilities::RecipeLanguageVersion::CPP17, std::vector({ PackageReference(Path("../OtherPackage")), }), @@ -490,8 +490,8 @@ namespace Soup::Build::UnitTests Recipe( "MyPackage", SemanticVersion(1, 2, 3), - Build::Extensions::RecipeType::Executable, - Build::Extensions::RecipeLanguageVersion::CPP17, + Build::Utilities::RecipeType::Executable, + Build::Utilities::RecipeLanguageVersion::CPP17, std::vector({ }), std::vector({ @@ -517,8 +517,8 @@ namespace Soup::Build::UnitTests auto uut = Recipe( "MyPackage", SemanticVersion(1, 2, 3), - Build::Extensions::RecipeType::Executable, - Build::Extensions::RecipeLanguageVersion::CPP17, + Build::Utilities::RecipeType::Executable, + Build::Utilities::RecipeLanguageVersion::CPP17, std::vector({ PackageReference(Path("../OtherPackage")), }), @@ -540,8 +540,8 @@ namespace Soup::Build::UnitTests Recipe( "MyPackage", SemanticVersion(1, 2, 3), - Build::Extensions::RecipeType::Executable, - Build::Extensions::RecipeLanguageVersion::CPP17, + Build::Utilities::RecipeType::Executable, + Build::Utilities::RecipeLanguageVersion::CPP17, std::nullopt, std::vector({ PackageReference(Path("../BuildTask")), @@ -566,8 +566,8 @@ namespace Soup::Build::UnitTests auto uut = Recipe( "MyPackage", SemanticVersion(1, 2, 3), - Build::Extensions::RecipeType::Executable, - Build::Extensions::RecipeLanguageVersion::CPP17, + Build::Utilities::RecipeType::Executable, + Build::Utilities::RecipeLanguageVersion::CPP17, std::vector({ PackageReference(Path("../OtherPackage")), }), @@ -589,8 +589,8 @@ namespace Soup::Build::UnitTests Recipe( "MyPackage", SemanticVersion(1, 2, 3), - Build::Extensions::RecipeType::Executable, - Build::Extensions::RecipeLanguageVersion::CPP17, + Build::Utilities::RecipeType::Executable, + Build::Utilities::RecipeLanguageVersion::CPP17, std::vector({ PackageReference(Path("../OtherPackage")), }), @@ -616,8 +616,8 @@ namespace Soup::Build::UnitTests auto uut = Recipe( "MyPackage", SemanticVersion(1, 2, 3), - Build::Extensions::RecipeType::Executable, - Build::Extensions::RecipeLanguageVersion::CPP17, + Build::Utilities::RecipeType::Executable, + Build::Utilities::RecipeLanguageVersion::CPP17, std::vector({ PackageReference(Path("../OtherPackage")), }), @@ -639,8 +639,8 @@ namespace Soup::Build::UnitTests Recipe( "MyPackage", SemanticVersion(1, 2, 3), - Build::Extensions::RecipeType::Executable, - Build::Extensions::RecipeLanguageVersion::CPP17, + Build::Utilities::RecipeType::Executable, + Build::Utilities::RecipeLanguageVersion::CPP17, std::vector({ PackageReference(Path("../OtherPackage")), }), @@ -665,8 +665,8 @@ namespace Soup::Build::UnitTests auto uut = Recipe( "MyPackage", SemanticVersion(1, 2, 3), - Build::Extensions::RecipeType::Executable, - Build::Extensions::RecipeLanguageVersion::CPP17, + Build::Utilities::RecipeType::Executable, + Build::Utilities::RecipeLanguageVersion::CPP17, std::vector({ PackageReference(Path("../OtherPackage")), }), @@ -688,8 +688,8 @@ namespace Soup::Build::UnitTests Recipe( "MyPackage", SemanticVersion(1, 2, 3), - Build::Extensions::RecipeType::Executable, - Build::Extensions::RecipeLanguageVersion::CPP17, + Build::Utilities::RecipeType::Executable, + Build::Utilities::RecipeLanguageVersion::CPP17, std::vector({ PackageReference(Path("../OtherPackage")), }), @@ -716,8 +716,8 @@ namespace Soup::Build::UnitTests auto uut = Recipe( "MyPackage", SemanticVersion(1, 2, 3), - Build::Extensions::RecipeType::Executable, - Build::Extensions::RecipeLanguageVersion::CPP17, + Build::Utilities::RecipeType::Executable, + Build::Utilities::RecipeLanguageVersion::CPP17, std::vector({ PackageReference(Path("../OtherPackage")), }), @@ -739,8 +739,8 @@ namespace Soup::Build::UnitTests Recipe( "MyPackage", SemanticVersion(1, 2, 3), - Build::Extensions::RecipeType::Executable, - Build::Extensions::RecipeLanguageVersion::CPP17, + Build::Utilities::RecipeType::Executable, + Build::Utilities::RecipeLanguageVersion::CPP17, std::vector({ PackageReference(Path("../OtherPackage")), }), @@ -767,8 +767,8 @@ namespace Soup::Build::UnitTests auto uut = Recipe( "MyPackage", SemanticVersion(1, 2, 3), - Build::Extensions::RecipeType::Executable, - Build::Extensions::RecipeLanguageVersion::CPP17, + Build::Utilities::RecipeType::Executable, + Build::Utilities::RecipeLanguageVersion::CPP17, std::vector({ PackageReference(Path("../OtherPackage")), }), @@ -790,8 +790,8 @@ namespace Soup::Build::UnitTests Recipe( "MyPackage", SemanticVersion(1, 2, 3), - Build::Extensions::RecipeType::Executable, - Build::Extensions::RecipeLanguageVersion::CPP17, + Build::Utilities::RecipeType::Executable, + Build::Utilities::RecipeLanguageVersion::CPP17, std::vector({ PackageReference(Path("../OtherPackage")), }), @@ -817,8 +817,8 @@ namespace Soup::Build::UnitTests auto uut = Recipe( "MyPackage", SemanticVersion(1, 2, 3), - Build::Extensions::RecipeType::Executable, - Build::Extensions::RecipeLanguageVersion::CPP17, + Build::Utilities::RecipeType::Executable, + Build::Utilities::RecipeLanguageVersion::CPP17, std::vector({ PackageReference(Path("../OtherPackage")), }), @@ -840,8 +840,8 @@ namespace Soup::Build::UnitTests Recipe( "MyPackage", SemanticVersion(1, 2, 3), - Build::Extensions::RecipeType::Executable, - Build::Extensions::RecipeLanguageVersion::CPP17, + Build::Utilities::RecipeType::Executable, + Build::Utilities::RecipeLanguageVersion::CPP17, std::vector({ PackageReference(Path("../OtherPackage")), }), @@ -866,8 +866,8 @@ namespace Soup::Build::UnitTests auto uut = Recipe( "MyPackage", SemanticVersion(1, 2, 3), - Build::Extensions::RecipeType::Executable, - Build::Extensions::RecipeLanguageVersion::CPP17, + Build::Utilities::RecipeType::Executable, + Build::Utilities::RecipeLanguageVersion::CPP17, std::vector({ PackageReference(Path("../OtherPackage")), }), @@ -889,8 +889,8 @@ namespace Soup::Build::UnitTests Recipe( "MyPackage", SemanticVersion(1, 2, 3), - Build::Extensions::RecipeType::Executable, - Build::Extensions::RecipeLanguageVersion::CPP17, + Build::Utilities::RecipeType::Executable, + Build::Utilities::RecipeLanguageVersion::CPP17, std::vector({ PackageReference(Path("../OtherPackage")), }), @@ -916,8 +916,8 @@ namespace Soup::Build::UnitTests auto uut = Recipe( "MyPackage", SemanticVersion(1, 2, 3), - Build::Extensions::RecipeType::Executable, - Build::Extensions::RecipeLanguageVersion::CPP17, + Build::Utilities::RecipeType::Executable, + Build::Utilities::RecipeLanguageVersion::CPP17, std::vector({ PackageReference(Path("../OtherPackage")), }), @@ -939,8 +939,8 @@ namespace Soup::Build::UnitTests Recipe( "MyPackage", SemanticVersion(1, 2, 3), - Build::Extensions::RecipeType::Executable, - Build::Extensions::RecipeLanguageVersion::CPP17, + Build::Utilities::RecipeType::Executable, + Build::Utilities::RecipeLanguageVersion::CPP17, std::vector({ PackageReference(Path("../OtherPackage")), }), @@ -965,8 +965,8 @@ namespace Soup::Build::UnitTests auto uut = Recipe( "MyPackage", SemanticVersion(1, 2, 3), - Build::Extensions::RecipeType::Executable, - Build::Extensions::RecipeLanguageVersion::CPP17, + Build::Utilities::RecipeType::Executable, + Build::Utilities::RecipeLanguageVersion::CPP17, std::vector({ PackageReference(Path("../OtherPackage")), }), @@ -988,8 +988,8 @@ namespace Soup::Build::UnitTests Recipe( "MyPackage", SemanticVersion(1, 2, 3), - Build::Extensions::RecipeType::Executable, - Build::Extensions::RecipeLanguageVersion::CPP17, + Build::Utilities::RecipeType::Executable, + Build::Utilities::RecipeLanguageVersion::CPP17, std::vector({ PackageReference(Path("../OtherPackage")), }), @@ -1015,8 +1015,8 @@ namespace Soup::Build::UnitTests auto uut = Recipe( "MyPackage", SemanticVersion(1, 2, 3), - Build::Extensions::RecipeType::Executable, - Build::Extensions::RecipeLanguageVersion::CPP17, + Build::Utilities::RecipeType::Executable, + Build::Utilities::RecipeLanguageVersion::CPP17, std::vector({ PackageReference(Path("../OtherPackage")), }), @@ -1038,8 +1038,8 @@ namespace Soup::Build::UnitTests Recipe( "MyPackage", SemanticVersion(1, 2, 3), - Build::Extensions::RecipeType::Executable, - Build::Extensions::RecipeLanguageVersion::CPP17, + Build::Utilities::RecipeType::Executable, + Build::Utilities::RecipeLanguageVersion::CPP17, std::vector({ PackageReference(Path("../OtherPackage")), }), diff --git a/Source/Client/Core.UnitTests/Package/RecipeTomlTests.h b/Source/Client/Core.UnitTests/Package/RecipeTomlTests.h index f749513e..77334a07 100644 --- a/Source/Client/Core.UnitTests/Package/RecipeTomlTests.h +++ b/Source/Client/Core.UnitTests/Package/RecipeTomlTests.h @@ -108,8 +108,8 @@ namespace Soup::Build::UnitTests auto expected = Recipe( "MyPackage", SemanticVersion(1, 2, 3), - Build::Extensions::RecipeType::Executable, - Build::Extensions::RecipeLanguageVersion::CPP17, + Build::Utilities::RecipeType::Executable, + Build::Utilities::RecipeLanguageVersion::CPP17, std::vector(), std::vector(), "Public.cpp", @@ -168,8 +168,8 @@ Version = "1.2.3" auto recipe = Recipe( "MyPackage", SemanticVersion(1, 2, 3), - Build::Extensions::RecipeType::Executable, - Build::Extensions::RecipeLanguageVersion::CPP17, + Build::Utilities::RecipeType::Executable, + Build::Utilities::RecipeLanguageVersion::CPP17, std::vector(), std::vector(), "Public.cpp", diff --git a/Source/Client/Core.UnitTests/gen/Main.cpp b/Source/Client/Core.UnitTests/gen/Main.cpp index 116e4dc8..49ca00c2 100644 --- a/Source/Client/Core.UnitTests/gen/Main.cpp +++ b/Source/Client/Core.UnitTests/gen/Main.cpp @@ -22,12 +22,6 @@ using namespace SoupTest; #include "Api/SoupApiTests.gen.h" #include "Api/SoupApiJsonModelsTests.gen.h" -#include "Build/Runner/BuildHistoryCheckerTests.gen.h" -#include "Build/Runner/BuildHistoryJsonTests.gen.h" -#include "Build/Runner/BuildHistoryTests.gen.h" -#include "Build/Runner/BuildHistoryManagerTests.gen.h" -#include "Build/Runner/BuildRunnerTests.gen.h" - #include "Config/LocalUserConfigExtensionsTests.gen.h" #include "Config/LocalUserConfigJsonTests.gen.h" #include "Config/LocalUserConfigTests.gen.h" @@ -53,12 +47,6 @@ int main() state += RunSoupApiTests(); state += RunSoupApiJsonModelsTests(); - state += RunBuildHistoryCheckerTests(); - state += RunBuildHistoryJsonTests(); - state += RunBuildHistoryTests(); - state += RunBuildHistoryManagerTests(); - state += RunBuildRunnerTests(); - state += RunLocalUserConfigExtensionsTests(); state += RunLocalUserConfigJsonTests(); state += RunLocalUserConfigTests(); @@ -79,7 +67,7 @@ int main() std::cout << state.FailCount << " FAILED." << std::endl; if (state.FailCount > 0) - return -1; + return 1; else return 0; } diff --git a/Source/Client/Core.UnitTests/gen/Package/RecipeBuildManagerTests.gen.h b/Source/Client/Core.UnitTests/gen/Package/RecipeBuildManagerTests.gen.h index aa3ed1e7..c2703123 100644 --- a/Source/Client/Core.UnitTests/gen/Package/RecipeBuildManagerTests.gen.h +++ b/Source/Client/Core.UnitTests/gen/Package/RecipeBuildManagerTests.gen.h @@ -4,7 +4,7 @@ TestState RunRecipeBuildManagerTests() { auto className = "RecipeBuildManagerTests"; - auto testClass = std::make_shared(); + auto testClass = std::make_shared(); TestState state = { 0, 0 }; state += SoupTest::RunTest(className, "Initialize", [&testClass]() { testClass->Initialize(); }); diff --git a/Source/Client/Core/Build/Runner/BuildHistory.h b/Source/Client/Core/Build/Runner/BuildHistory.h deleted file mode 100644 index 5c604179..00000000 --- a/Source/Client/Core/Build/Runner/BuildHistory.h +++ /dev/null @@ -1,246 +0,0 @@ -// -// Copyright (c) Soup. All rights reserved. -// - -#pragma once -#include "CompileResult.h" - -namespace Soup::Build -{ - export class FileInfo - { - public: - /// - /// Initializes a new instance of the class. - /// - FileInfo() : - File(), - Includes() - { - } - - /// - /// Initializes a new instance of the class. - /// - FileInfo(Path file, std::vector includes) : - File(std::move(file)), - Includes(std::move(includes)) - { - } - - Path File; - std::vector Includes; - - /// - /// Equality operator - /// - bool operator ==(const FileInfo& rhs) const - { - return File == rhs.File && - Includes == rhs.Includes; - } - - bool operator !=(const FileInfo& rhs) const - { - return !(*this == rhs); - } - }; - - struct FileInfo_LessThan - { - bool operator() (const FileInfo& lhs, const FileInfo& rhs) const - { - return lhs.File < rhs.File; - } - }; - - export class BuildHistory - { - public: - /// - /// Initializes a new instance of the class. - /// - BuildHistory() : - _knownFiles(), - _fastLookup() - { - } - - /// - /// Initializes a new instance of the class. - /// - BuildHistory(std::vector knownFiles) : - _knownFiles(std::move(knownFiles)), - _fastLookup() - { - BuildFastLookupDictionary(); - } - - /// - /// Get the known files list - /// - const std::vector& GetKnownFiles() const - { - return _knownFiles; - } - - /// - /// Recursively build up the closure of all included files - /// from the build state - /// - bool TryBuildIncludeClosure( - const Path& sourceFiles, - std::vector& closure) - { - // Convert the input vector into a set of strings - auto closureSet = std::unordered_set(); - for (auto& file : closure) - { - closureSet.insert(file.ToString()); - } - - if (TryBuildIncludeClosure( - std::vector({ sourceFiles }), - closureSet)) - { - // Convert the set to a vector output - closure.clear(); - for (auto& file : closureSet) - { - closure.push_back(Path(file)); - } - - return true; - } - else - { - return false; - } - } - - /// - /// Update the build state for the provided files - /// - void UpdateIncludeTree(const std::vector& includeTree) - { - // Flatten out the tree - auto activeSet = std::set( - std::make_move_iterator(_knownFiles.begin()), - std::make_move_iterator(_knownFiles.end())); - _knownFiles.clear(); - - UpdateIncludes(activeSet, includeTree); - - // Convert the set back to a vector - _knownFiles = std::vector( - std::make_move_iterator(activeSet.begin()), - std::make_move_iterator(activeSet.end())); - - // Ensure the dictionary is up to date - BuildFastLookupDictionary(); - } - - /// - /// Equality operator - /// - bool operator ==(const BuildHistory& rhs) const - { - return _knownFiles == rhs._knownFiles; - } - - /// - /// Inequality operator - /// - bool operator !=(const BuildHistory& rhs) const - { - return !(*this == rhs); - } - - private: - void BuildFastLookupDictionary() - { - _fastLookup.clear(); - for (auto& info : _knownFiles) - { - _fastLookup.emplace(info.File.ToString(), info); - } - } - - /// - /// Internal implentation - /// - bool TryBuildIncludeClosure( - const std::vector& sourceFiles, - std::unordered_set& closure) - { - for (auto& file : sourceFiles) - { - auto fileInfoResult = _fastLookup.find(file.ToString()); - if (fileInfoResult != _fastLookup.end()) - { - // Find all of the files that do not already exist in the closure - auto& includes = fileInfoResult->second.Includes; - auto newIncludes = std::vector(); - for (auto& include : includes) - { - auto insertResult = closure.insert(include.ToString()); - if (insertResult.second) - { - newIncludes.push_back(include); - } - } - - // Build up the child includes - if (!TryBuildIncludeClosure(newIncludes, closure)) - { - // Propagate the failed result - return false; - } - } - else - { - Log::Info("Missing file info: " + file.ToString()); - return false; - } - } - - return true; - } - - /// - /// Update the build state for the provided files - /// - static void UpdateIncludes( - std::set& activeSet, - const std::vector& level) - { - for (auto& current : level) - { - // Create the FileInfo - auto info = FileInfo(); - info.File = current.Filename; - for (auto& include : current.Includes) - { - info.Includes.push_back(include.Filename); - } - - // Remove previous entry if exists - auto existingFileInfo = activeSet.find(info); - if (existingFileInfo != activeSet.end()) - { - activeSet.erase(existingFileInfo); - } - - // Add the file info - activeSet.insert(std::move(info)); - - // Recurse to the children - UpdateIncludes(activeSet, current.Includes); - } - } - - private: - std::unordered_map _fastLookup; - std::vector _knownFiles; - }; -} diff --git a/Source/Client/Core/Build/Runner/BuildHistoryJson.h b/Source/Client/Core/Build/Runner/BuildHistoryJson.h deleted file mode 100644 index ec6a8680..00000000 --- a/Source/Client/Core/Build/Runner/BuildHistoryJson.h +++ /dev/null @@ -1,149 +0,0 @@ -// -// Copyright (c) Soup. All rights reserved. -// - -#pragma once -#include "BuildHistory.h" - -namespace Soup::Build -{ - /// - /// The build state json serializer - /// - export class BuildHistoryJson - { - private: - static constexpr const char* Property_File = "file"; - static constexpr const char* Property_KnownFiles = "knownFiles"; - static constexpr const char* Property_Includes = "includes"; - - public: - /// - /// Load from stream - /// - static BuildHistory Deserialize(std::istream& stream) - { - // Read the entire file into a string - std::string content( - (std::istreambuf_iterator(stream)), - std::istreambuf_iterator()); - - // Read the contents of the build state file - std::string error = ""; - auto jsonRoot = json11::Json::parse(content, error); - if (jsonRoot.is_null()) - { - auto message = "Failed to parse the build state json: " + error; - throw std::runtime_error(std::move(message)); - } - else - { - return LoadJsonBuildHistory(jsonRoot); - } - } - - /// - /// Save the BuildHistory to the root file - /// - static void Serialize(const BuildHistory& state, std::ostream& stream) - { - // Serialize the contents of the build state - json11::Json json = BuildJsonBuildHistory(state); - - stream << json.dump(); - } - - private: - static BuildHistory LoadJsonBuildHistory(const json11::Json& value) - { - std::vector knownFiles; - - if (!value[Property_KnownFiles].is_null()) - { - auto values = std::vector(); - for (auto& value : value[Property_KnownFiles].array_items()) - { - auto fileInfo = LoadJsonFileInfo(value); - values.push_back(std::move(fileInfo)); - } - - knownFiles = std::move(values); - } - else - { - throw std::runtime_error("Missing Required field: knownFiles."); - } - - return BuildHistory( - std::move(knownFiles)); - } - - static FileInfo LoadJsonFileInfo(const json11::Json& value) - { - Path file; - std::vector includes; - - if (!value[Property_File].is_null()) - { - file = Path(value[Property_File].string_value()); - } - else - { - throw std::runtime_error("Missing Required field: file."); - } - - if (!value[Property_Includes].is_null()) - { - auto values = std::vector(); - for (auto& value : value[Property_Includes].array_items()) - { - values.push_back(Path(value.string_value())); - } - - includes = std::move(values); - } - else - { - throw std::runtime_error("Missing Required field: includes."); - } - - return FileInfo( - std::move(file), - std::move(includes)); - } - - static json11::Json BuildJsonBuildHistory(const BuildHistory& state) - { - json11::Json::object result = {}; - - // Add required fields - json11::Json::array knownFiles; - for (auto& value : state.GetKnownFiles()) - { - knownFiles.push_back(BuildJsonFileInfo(value)); - } - - result[Property_KnownFiles] = std::move(knownFiles); - - return result; - } - - static json11::Json BuildJsonFileInfo(const FileInfo& info) - { - json11::Json::object result = {}; - - // Add required fields - result[Property_File] = info.File.ToString(); - - json11::Json::array includes; - for (auto& value : info.Includes) - { - includes.push_back(value.ToString()); - } - - result[Property_Includes] = std::move(includes); - - return result; - } - }; -} diff --git a/Source/Client/Core/Build/Runner/BuildRunner.h b/Source/Client/Core/Build/Runner/BuildRunner.h deleted file mode 100644 index 1d872e1d..00000000 --- a/Source/Client/Core/Build/Runner/BuildRunner.h +++ /dev/null @@ -1,466 +0,0 @@ -// -// Copyright (c) Soup. All rights reserved. -// - -#pragma once -#include "Build/Runner/BuildHistory.h" - -namespace Soup::Build -{ - /// - /// The build task - /// - export class BuildRunner - { - public: - /// - /// Initializes a new instance of the class. - /// - BuildRunner(Path workingDirectory) : - _workingDirectory(std::move(workingDirectory)), - _dependencyCounts(), - _buildHistory(), - _stateChecker() - { - } - - // TODO: Convert vector to const when we have a const version of the operation wrapper. - void Execute( - Extensions::BuildOperationListWrapper& operations, - const Path& objectDirectory, - bool forceBuild) - { - // Load the previous build state if performing an incremental build - auto targetDirectory = _workingDirectory + objectDirectory; - if (!forceBuild) - { - Log::Diag("Loading previous build state"); - if (!BuildHistoryManager::TryLoadState(targetDirectory, _buildHistory)) - { - Log::Info("No previous state found, full rebuild required"); - _buildHistory = BuildHistory(); - forceBuild = true; - } - } - - // Build the initial operation dependency set to - // ensure operations are built in the correct order - // and that there are no cycles - auto emptyParentSet = std::set(); - BuildDependencies(operations, emptyParentSet); - - // Run all build operations in the correct order with incremental build checks - CheckExecuteOperations(operations, forceBuild); - - Log::Info("Saving updated build state"); - BuildHistoryManager::SaveState(targetDirectory, _buildHistory); - - Log::HighPriority("Done"); - } - - private: - /// - /// Build dependencies - /// - void BuildDependencies( - Extensions::BuildOperationListWrapper& operations, - const std::set& parentSet) - { - for (auto i = 0; i < operations.GetSize(); i++) - { - // Make sure there are no cycles using the address as a unique id - auto operation = operations.GetValueAt(i); - auto operationId = reinterpret_cast(operation.GetRaw()); - if (parentSet.contains(operationId)) - throw std::runtime_error("A build operation graph must be acyclic."); - - // Check if the operation was already a child from a different path - auto currentOperationSearch = _dependencyCounts.find(operationId); - if (currentOperationSearch != _dependencyCounts.end()) - { - // Increment the dependency count - currentOperationSearch->second++; - } - else - { - // Insert a new entry with a single count - _dependencyCounts.emplace(operationId, 1); - - // Recurse to children only the first time we see an operation - auto updatedParentSet = parentSet; - updatedParentSet.insert(operationId); - BuildDependencies(operation.GetChildList(), updatedParentSet); - } - } - } - - /// - /// Execute the collection of build operations - /// - void CheckExecuteOperations( - Extensions::BuildOperationListWrapper& operations, - bool forceBuild) - { - for (auto i = 0; i < operations.GetSize(); i++) - { - // Check if the operation was already a child from a different path - // Make sure there are no cycles using the address as a unique id - auto operation = operations.GetValueAt(i); - auto operationId = reinterpret_cast(operation.GetRaw()); - auto currentOperationSearch = _dependencyCounts.find(operationId); - if (currentOperationSearch != _dependencyCounts.end()) - { - auto remainingCount = --currentOperationSearch->second; - if (remainingCount == 0) - { - ExecuteOperation(operation, forceBuild); - } - else - { - // This operation will be executed from a different path - } - } - else - { - throw std::runtime_error("A operation id was missing from the dependency collection."); - } - } - } - - /// - /// Execute a single build operation and all of its children - /// - void ExecuteOperation( - Extensions::BuildOperationWrapper& operation, - bool forceBuild) - { - bool buildRequired = forceBuild; - if (!forceBuild) - { - // Check if each source file is out of date and requires a rebuild - Log::Diag("Check for updated source"); - - // Try to build up the closure of include dependencies - auto inputFiles = operation.GetInputFileList().CopyAsPathVector(); - if (!inputFiles.empty()) - { - auto inputClosure = std::vector(); - - // TODO: Is this how we want to handle no input operations? - // If there are source files to the operation check their build state - for (auto& inputFile : inputFiles) - { - // Build the input closure for all source files - if (inputFile.GetFileExtension() == ".cpp") - { - if (!_buildHistory.TryBuildIncludeClosure(inputFile, inputClosure)) - { - // Could not determine the set of input files, not enough info to perform incremental build - buildRequired = true; - break; - } - } - } - - // If we were able to load all of the build history then perform the timestamp checks - if (!buildRequired) - { - // Include the source files itself - inputClosure.insert(inputClosure.end(), inputFiles.begin(), inputFiles.end()); - - // Load the output files - auto outputFiles = operation.GetOutputFileList().CopyAsPathVector(); - - // Check if any of the input files have changed since last build - if (_stateChecker.IsOutdated( - outputFiles, - inputClosure, - Path(operation.GetWorkingDirectory()))) - { - // The file or a dependency has changed - buildRequired = true; - } - else - { - Log::Info("Up to date"); - } - } - } - else - { - // Since there are no input files, the best we can do for an - // incremental build is check that the output exists - for (auto& file : operation.GetOutputFileList().CopyAsPathVector()) - { - auto relativeOutputFile = file.HasRoot() ? file : Path(operation.GetWorkingDirectory()) + file; - if (!System::IFileSystem::Current().Exists(relativeOutputFile)) - { - Log::Info("Output target does not exist: " + relativeOutputFile.ToString()); - buildRequired = true; - break; - } - } - } - } - - if (buildRequired) - { - Log::HighPriority(operation.GetTitle()); - auto executable = Path(operation.GetExecutable()); - auto arguments = std::string(operation.GetArguments()); - auto workingDirectory = Path(operation.GetWorkingDirectory()); - auto message = "Execute: " + executable.ToString() + " " + arguments; - Log::Diag(message); - auto result = System::IProcessManager::Current().Execute( - executable, - arguments, - workingDirectory); - - // Try parse includes if available - auto cleanOutput = std::stringstream(); - auto headerIncludes = std::vector(); - if (TryParsesHeaderIncludes(operation, result.StdOut, headerIncludes, cleanOutput)) - { - // Save off the build history for future builds - _buildHistory.UpdateIncludeTree(headerIncludes); - - // Replace the output string with the clean version - result.StdOut = cleanOutput.str(); - } - - if (!result.StdOut.empty()) - { - // Upgrade output to a warning if the command fails - if (result.ExitCode != 0) - Log::Warning(result.StdOut); - else - Log::Info(result.StdOut); - } - - // If there was any error output then the build failed - // TODO: Find warnings + errors - if (!result.StdErr.empty()) - { - Log::Error(result.StdErr); - } - - if (result.ExitCode != 0) - { - throw std::runtime_error("Compiler Object Error: " + std::to_string(result.ExitCode)); - } - } - else - { - Log::Info(operation.GetTitle()); - } - - // Recursively build all of the operation children - // Note: Force build if this operation was built - CheckExecuteOperations(operation.GetChildList(), buildRequired); - } - - bool TryParsesHeaderIncludes( - Extensions::BuildOperationWrapper& operation, - const std::string& output, - std::vector& headerIncludes, - std::stringstream& cleanOutput) - { - // Check for any cpp input files - auto executable = Path(operation.GetExecutable()); - for (auto& inputFile : operation.GetInputFileList().CopyAsPathVector()) - { - if (inputFile.GetFileExtension() == ".cpp") - { - // Parse known compiler output - if (executable.GetFileName() == "cl.exe") - { - headerIncludes = ParseMSVCIncludes(inputFile, output, cleanOutput); - return true; - } - else if (executable.GetFileName() == "clang++.exe") - { - headerIncludes = ParseMSVCIncludes(inputFile, output, cleanOutput); - return true; - } - } - } - - headerIncludes = std::vector(); - return false; - } - - std::vector ParseClangIncludes( - const Path& file, - const std::string& output, - std::stringstream& cleanOutput) - { - // Add the root file - std::stack current; - current.push(HeaderInclude(file)); - - std::stringstream content(output); - std::string line; - while (std::getline(content, line)) - { - // TODO: Getline is dumb and uses newline on windows - if (line[line.size() - 1] == '\r') - { - line.resize(line.size() - 1); - } - - auto includeDepth = GetClangIncludeDepth(line); - if (includeDepth > 0) - { - // Parse the file reference - auto includeFile = Path(line.substr(includeDepth + 1)); - - // Ensure we are at the correct depth - while (includeDepth < current.size()) - { - // Remove the top file and push it onto its parent - auto previous = std::move(current.top()); - current.pop(); - current.top().Includes.push_back(std::move(previous)); - } - - // Ensure we do not try to go up more than one level at a time - if (includeDepth > current.size() + 1) - throw std::runtime_error("Missing an include level."); - - current.push(HeaderInclude(includeFile)); - } - else - { - // Not an include, pass along - cleanOutput << line << "\n"; - } - } - - // Ensure we are at the top level - while (1 < current.size()) - { - // Remove the top file and push it onto its parent - auto previous = std::move(current.top()); - current.pop(); - current.top().Includes.push_back(std::move(previous)); - } - - return std::vector({ std::move(current.top()) }); - } - - int GetClangIncludeDepth(const std::string& line) - { - int depth = 0; - for (depth = 0; depth < line.size(); depth++) - { - if (line[depth] != '.') - { - break; - } - } - - // Verify the next character is a space, otherwise reset the depth to zero - if (depth < line.size() && line[depth] != ' ') - { - depth = 0; - } - - return depth; - } - - std::vector ParseMSVCIncludes( - const Path& file, - const std::string& output, - std::stringstream& cleanOutput) - { - // Add the root file - std::stack current; - current.push(HeaderInclude(file)); - - std::stringstream content(output); - std::string line; - while (std::getline(content, line)) - { - // TODO: Getline is dumb and uses newline on windows - if (line[line.size() - 1] == '\r') - { - line.resize(line.size() - 1); - } - - auto includeDepth = GetMSVCIncludeDepth(line); - if (includeDepth > 0) - { - // Parse the file reference - auto includePrefix = GetMSVCIncludePrefix(); - auto offset = includePrefix.size() + includeDepth; - auto includeFile = Path(line.substr(offset)); - - // Ensure we are at the correct depth - while (includeDepth < current.size()) - { - // Remove the top file and push it onto its parent - auto previous = std::move(current.top()); - current.pop(); - current.top().Includes.push_back(std::move(previous)); - } - - // Ensure we do not try to go up more than one level at a time - if (includeDepth > current.size() + 1) - throw std::runtime_error("Missing an include level."); - - current.push(HeaderInclude(includeFile)); - } - else - { - // Not an include, pass along - cleanOutput << line << "\n"; - } - } - - // Ensure we are at the top level - while (1 < current.size()) - { - // Remove the top file and push it onto its parent - auto previous = std::move(current.top()); - current.pop(); - current.top().Includes.push_back(std::move(previous)); - } - - return std::vector({ std::move(current.top()) }); - } - - int GetMSVCIncludeDepth(const std::string& line) - { - int depth = 0; - auto includePrefix = GetMSVCIncludePrefix(); - if (line.rfind(includePrefix, 0) == 0) - { - // Find the end of the whitespace - int offset = includePrefix.size(); - for (; offset < line.size(); offset++) - { - if (line[offset] != ' ') - { - break; - } - } - - // The depth is the number of whitespaces past the prefix - depth = offset - includePrefix.size(); - } - - return depth; - } - - std::string_view GetMSVCIncludePrefix() - { - return std::string_view("Note: including file:"); - } - - private: - Path _workingDirectory; - std::map _dependencyCounts; - BuildHistory _buildHistory; - BuildHistoryChecker _stateChecker; - }; -} diff --git a/Source/Client/Core/Build/Runner/CompileResult.h b/Source/Client/Core/Build/Runner/CompileResult.h deleted file mode 100644 index 4e6a691f..00000000 --- a/Source/Client/Core/Build/Runner/CompileResult.h +++ /dev/null @@ -1,41 +0,0 @@ -// -// Copyright (c) Soup. All rights reserved. -// - -namespace Soup::Build -{ - /// - /// Header includes recursive container - /// - export class HeaderInclude - { - public: - HeaderInclude(Path filename) : - Filename(std::move(filename)), - Includes() - { - } - - /// - /// Gets or sets the filename - /// - Path Filename; - - /// - /// Gets or sets the list of includes - /// - std::vector Includes; - }; - - /// - /// The results of a compilation - /// - export class CompileResult - { - public: - /// - /// Gets or sets the list of include files - /// - std::vector HeaderIncludeFiles; - }; -} diff --git a/Source/Client/Core/Config/LocalUserConfigExtensions.h b/Source/Client/Core/Config/LocalUserConfigExtensions.h index d64d5a72..94f18db5 100644 --- a/Source/Client/Core/Config/LocalUserConfigExtensions.h +++ b/Source/Client/Core/Config/LocalUserConfigExtensions.h @@ -19,7 +19,7 @@ namespace Soup /// static Path GetLocalUserConfigFilePath() { - auto result = System::IProcessManager::Current().GetProcessFileName(); + auto result = System::IProcessManager::Current().GetCurrentProcessFileName(); result.SetFilename(Constants::LocalUserConfigFileName); return result; } diff --git a/Source/Client/Core/Constants.h b/Source/Client/Core/Constants.h index 6f14fd0a..e677af24 100644 --- a/Source/Client/Core/Constants.h +++ b/Source/Client/Core/Constants.h @@ -68,11 +68,6 @@ namespace Soup /// static constexpr std::string_view StoreLibraryFolderName = "Library"; - /// - /// Gets the project generation folder name - /// - static constexpr std::string_view ProjectGenerateFolderName = ".soup"; - /// /// Gets the project generation build folder name /// diff --git a/Source/Client/Core/Module.cpp b/Source/Client/Core/Module.cpp index 5c5c972d..cf202703 100644 --- a/Source/Client/Core/Module.cpp +++ b/Source/Client/Core/Module.cpp @@ -21,8 +21,9 @@ export module SoupCore; import Opal; import Opal.Extensions; import Soup.Build; -import Soup.Build.Extensions; -import Soup.Build.Runtime; +import Soup.Build.Utilities; +import Soup.Build.Evaluate; +import Soup.Build.Execute; import LzmaSdk; import json11; import toml11; @@ -34,12 +35,6 @@ using namespace Opal; #include "Api/SoupApi.h" -#include "Build/Runner/BuildHistory.h" -#include "Build/Runner/BuildHistoryChecker.h" -#include "Build/Runner/BuildHistoryJson.h" -#include "Build/Runner/BuildHistoryManager.h" -#include "Build/Runner/BuildRunner.h" - #include "Config/LocalUserConfigExtensions.h" #include "Package/PackageManager.h" diff --git a/Source/Client/Core/Package/Recipe.h b/Source/Client/Core/Package/Recipe.h index 218577ed..aa628035 100644 --- a/Source/Client/Core/Package/Recipe.h +++ b/Source/Client/Core/Package/Recipe.h @@ -54,8 +54,8 @@ namespace Soup Recipe( std::string_view name, SemanticVersion version, - std::optional type, - std::optional languageVersion, + std::optional type, + std::optional languageVersion, std::optional> dependencies, std::optional> devDependencies, std::optional publicFile, @@ -144,15 +144,15 @@ namespace Soup return HasValue(Property_Type); } - Build::Extensions::RecipeType GetType() + Build::Utilities::RecipeType GetType() { if (!HasType()) throw std::runtime_error("No type."); - return Build::Extensions::ParseRecipeType(GetValue(Property_Type).AsString()); + return Build::Utilities::ParseRecipeType(GetValue(Property_Type).AsString()); } - void SetType(Build::Extensions::RecipeType value) + void SetType(Build::Utilities::RecipeType value) { return EnsureValue(Property_Type).SetValueString(ToString(value)); } @@ -165,16 +165,16 @@ namespace Soup return HasValue(Property_Language); } - Build::Extensions::RecipeLanguageVersion GetLanguageVersion() + Build::Utilities::RecipeLanguageVersion GetLanguageVersion() { if (!HasLanguageVersion()) throw std::runtime_error("No language version."); - return Build::Extensions::ParseRecipeLanguageVersion( + return Build::Utilities::ParseRecipeLanguageVersion( GetValue(Property_Language).AsString()); } - void SetLanguageVersion(Build::Extensions::RecipeLanguageVersion value) + void SetLanguageVersion(Build::Utilities::RecipeLanguageVersion value) { return EnsureValue(Property_Language).SetValueString(ToString(value)); } diff --git a/Source/Client/Core/Package/RecipeBuildArguments.h b/Source/Client/Core/Package/RecipeBuildArguments.h index 4989ad2e..16b9163c 100644 --- a/Source/Client/Core/Package/RecipeBuildArguments.h +++ b/Source/Client/Core/Package/RecipeBuildArguments.h @@ -17,33 +17,14 @@ namespace Soup std::string Flavor; /// - /// Gets or sets the platform name + /// Gets or sets the system name /// - std::string Platform; + std::string System; /// - /// Gets or sets the platform library paths - /// TODO: Pull this from somewhere when we implement platforms + /// Gets or sets the architecture name /// - std::vector PlatformIncludePaths; - - /// - /// Gets or sets the platform library paths - /// TODO: Pull this from somewhere when we implement platforms - /// - std::vector PlatformLibraryPaths; - - /// - /// Gets or sets the platform preprocessor definitions - /// TODO: Pull this from somewhere when we implement platforms - /// - std::vector PlatformPreprocessorDefinitions; - - /// - /// Gets or sets the platform libraries - /// TODO: Pull this from somewhere when we implement platforms - /// - std::vector PlatformLibraries; + std::string Architecture; /// /// Gets or sets a value indicating whether to skip running the build operations @@ -61,11 +42,9 @@ namespace Soup bool operator ==(const RecipeBuildArguments& rhs) const { return Flavor == rhs.Flavor && - Platform == rhs.Platform && - PlatformIncludePaths == rhs.PlatformIncludePaths && - PlatformLibraryPaths == rhs.PlatformLibraryPaths && - PlatformPreprocessorDefinitions == rhs.PlatformPreprocessorDefinitions && - PlatformLibraries == rhs.PlatformLibraries && + System == rhs.System && + Architecture == rhs.Architecture && + SkipRun == rhs.SkipRun && ForceRebuild == rhs.ForceRebuild; } diff --git a/Source/Client/Core/Package/RecipeBuildManager.h b/Source/Client/Core/Package/RecipeBuildManager.h index d2da42b3..77aba300 100644 --- a/Source/Client/Core/Package/RecipeBuildManager.h +++ b/Source/Client/Core/Package/RecipeBuildManager.h @@ -5,9 +5,8 @@ #pragma once #include "RecipeBuildArguments.h" #include "RecipeExtensions.h" -#include "Build/Runner/BuildRunner.h" -namespace Soup::Build::Runtime +namespace Soup::Build { /// /// The recipe build manager that knows how to perform the correct build for a recipe @@ -77,23 +76,23 @@ namespace Soup::Build::Runtime /// /// Convert the root recipe table to a build Value Table entry /// - ValueTable ConvertToRootBuildState(const RecipeTable& table) + Evaluate::ValueTable ConvertToRootBuildState(const RecipeTable& table) { // Convert teh root table auto recipeState = ConvertToBuildState(table); // Initialize the Recipe state - auto state = ValueTable(); - state.SetValue("Recipe", Value(std::move(recipeState))); + auto state = Evaluate::ValueTable(); + state.SetValue("Recipe", Evaluate::Value(std::move(recipeState))); return state; } /// /// Convert the recipe internal representation to initial build state /// - ValueTable ConvertToBuildState(const RecipeTable& table) + Evaluate::ValueTable ConvertToBuildState(const RecipeTable& table) { - auto result = ValueTable(); + auto result = Evaluate::ValueTable(); for (auto& value : table) { auto buildValue = ConvertToBuildState(value.second); @@ -106,9 +105,9 @@ namespace Soup::Build::Runtime /// /// Convert the recipe internal representation to initial build state /// - ValueList ConvertToBuildState(const RecipeList& list) + Evaluate::ValueList ConvertToBuildState(const RecipeList& list) { - auto result = ValueList(); + auto result = Evaluate::ValueList(); for (auto& value : list) { auto buildValue = ConvertToBuildState(value); @@ -121,24 +120,24 @@ namespace Soup::Build::Runtime /// /// Convert the recipe internal representation to initial build state /// - Value ConvertToBuildState(const RecipeValue& value) + Evaluate::Value ConvertToBuildState(const RecipeValue& value) { switch (value.GetType()) { case RecipeValueType::Empty: - return Value(); + return Evaluate::Value(); case RecipeValueType::Table: - return Value(ConvertToBuildState(value.AsTable())); + return Evaluate::Value(ConvertToBuildState(value.AsTable())); case RecipeValueType::List: - return Value(ConvertToBuildState(value.AsList())); + return Evaluate::Value(ConvertToBuildState(value.AsList())); case RecipeValueType::String: - return Value(value.AsString()); + return Evaluate::Value(value.AsString()); case RecipeValueType::Integer: - return Value(value.AsInteger()); + return Evaluate::Value(value.AsInteger()); case RecipeValueType::Float: - return Value(value.AsFloat()); + return Evaluate::Value(value.AsFloat()); case RecipeValueType::Boolean: - return Value(value.AsBoolean()); + return Evaluate::Value(value.AsBoolean()); default: throw std::runtime_error("Unknown value type."); } @@ -155,7 +154,7 @@ namespace Soup::Build::Runtime bool isSystemBuild, bool isDevBuild, const std::set& parentSet, - ValueTable& sharedState) + Evaluate::ValueTable& sharedState) { // Add current package to the parent set when building child dependencies auto activeParentSet = parentSet; @@ -186,7 +185,7 @@ namespace Soup::Build::Runtime } // Nothing we can do, exit - throw HandledException(); + throw HandledException(1234); } // Ensure we do not have any circular dependencies @@ -269,8 +268,8 @@ namespace Soup::Build::Runtime const RecipeBuildArguments& arguments, bool isSystemBuild, bool isDevBuild, - ValueTable& activeState, - ValueTable& sharedState) + Evaluate::ValueTable& activeState, + Evaluate::ValueTable& sharedState) { // TODO: RAII for active id try @@ -317,13 +316,17 @@ namespace Soup::Build::Runtime { // Move the parent state from active into the parents active state auto& devDependenciesTable = sharedState.EnsureValue("DevDependencies").EnsureTable(); - devDependenciesTable.SetValue(recipe.GetName(), Value(findBuildState->second)); + devDependenciesTable.SetValue( + recipe.GetName(), + Evaluate::Value(findBuildState->second)); } else { // Move the parent state from active into the parents active state auto& dependenciesTable = sharedState.EnsureValue("Dependencies").EnsureTable(); - dependenciesTable.SetValue(recipe.GetName(), Value(findBuildState->second)); + dependenciesTable.SetValue( + recipe.GetName(), + Evaluate::Value(findBuildState->second)); } Log::SetActiveId(0); @@ -337,22 +340,22 @@ namespace Soup::Build::Runtime return projectId; } - ValueTable RunInProcessBuild( + Evaluate::ValueTable RunInProcessBuild( int projectId, const Path& packageRoot, Recipe& recipe, const RecipeBuildArguments& arguments, bool isSystemBuild, - ValueTable& activeState) + Evaluate::ValueTable& activeState) { // Ensure the external build extension libraries outlive all usage in the build system auto activeExtensionLibraries = std::vector(); { // Create a new build system for the requested build - auto buildSystem = BuildSystem(); - auto buildState = BuildState(activeState); - auto activeStateWrapper = Extensions::ValueTableWrapper(buildState.GetActiveState()); + auto buildSystem = Evaluate::BuildSystem(); + auto buildState = Evaluate::BuildState(activeState); + auto activeStateWrapper = Utilities::ValueTableWrapper(buildState.GetActiveState()); // Select the correct compiler to use std::string activeCompiler = ""; @@ -367,19 +370,25 @@ namespace Soup::Build::Runtime activeCompiler = _runtimeCompiler; } - auto binaryDirectory = RecipeExtensions::GetBinaryDirectory(_systemCompiler, arguments.Flavor); - auto objectDirectory = RecipeExtensions::GetObjectDirectory(_systemCompiler, arguments.Flavor); + auto binaryDirectory = RecipeExtensions::GetBinaryDirectory( + _systemCompiler, + arguments.Flavor, + arguments.System, + arguments.Architecture); + auto objectDirectory = RecipeExtensions::GetObjectDirectory( + _systemCompiler, + arguments.Flavor, + arguments.System, + arguments.Architecture); // Set the input properties activeStateWrapper.EnsureValue("PackageRoot").SetValueString(packageRoot.ToString()); activeStateWrapper.EnsureValue("BuildFlavor").SetValueString(arguments.Flavor); + activeStateWrapper.EnsureValue("BuildSystem").SetValueString(arguments.System); + activeStateWrapper.EnsureValue("BuildArchitecture").SetValueString(arguments.Architecture); activeStateWrapper.EnsureValue("CompilerName").SetValueString(activeCompiler); activeStateWrapper.EnsureValue("BinaryDirectory").SetValueString(binaryDirectory.ToString()); activeStateWrapper.EnsureValue("ObjectDirectory").SetValueString(objectDirectory.ToString()); - activeStateWrapper.EnsureValue("PlatformLibraries").SetValueStringList(arguments.PlatformLibraries); - activeStateWrapper.EnsureValue("PlatformIncludePaths").SetValueStringList(arguments.PlatformIncludePaths); - activeStateWrapper.EnsureValue("PlatformLibraryPaths").SetValueStringList(arguments.PlatformLibraryPaths); - activeStateWrapper.EnsureValue("PlatformPreprocessorDefinitions").SetValueStringList(arguments.PlatformPreprocessorDefinitions); // Run all build extensions // Note: Keep the extension libraries open while running the build system @@ -418,8 +427,8 @@ namespace Soup::Build::Runtime if (!arguments.SkipRun) { // Execute the build operations - auto runner = BuildRunner(packageRoot); - auto buildOperations = Extensions::BuildOperationListWrapper(buildState.GetBuildOperations()); + auto runner = Execute::BuildRunner(packageRoot); + auto buildOperations = Utilities::BuildOperationListWrapper(buildState.GetBuildOperations()); runner.Execute( buildOperations, objectDirectory, @@ -521,7 +530,7 @@ namespace Soup::Build::Runtime std::string _systemCompiler; std::string _runtimeCompiler; std::map _knownRecipes; - std::map _buildSet; - std::map _systemBuildSet; + std::map _buildSet; + std::map _systemBuildSet; }; } diff --git a/Source/Client/Core/Package/RecipeExtensions.h b/Source/Client/Core/Package/RecipeExtensions.h index 54d6e1dd..c543e220 100644 --- a/Source/Client/Core/Package/RecipeExtensions.h +++ b/Source/Client/Core/Package/RecipeExtensions.h @@ -116,20 +116,36 @@ namespace Soup return packagePath; } - static Path GetObjectDirectory(const std::string& compiler, const std::string& configuration) + static Path GetObjectDirectory( + const std::string& compiler, + const std::string& flavor, + const std::string& system, + const std::string& architecture) { // Setup the output directories auto outputDirectory = Path("out"); auto objectDirectory = outputDirectory + Path("obj"); - return objectDirectory + Path(compiler) + Path(configuration); + return objectDirectory + + Path(compiler) + + Path(flavor) + + Path(system) + + Path(architecture); } - static Path GetBinaryDirectory(const std::string& compiler, const std::string& configuration) + static Path GetBinaryDirectory( + const std::string& compiler, + const std::string& flavor, + const std::string& system, + const std::string& architecture) { // Setup the output directories auto outputDirectory = Path("out"); auto binaryDirectory = outputDirectory + Path("bin"); - return binaryDirectory + Path(compiler) + Path(configuration); + return binaryDirectory + + Path(compiler) + + Path(flavor) + + Path(system) + + Path(architecture); } }; } diff --git a/Source/Client/Core/Recipe.toml b/Source/Client/Core/Recipe.toml index a3012b14..fc996dfd 100644 --- a/Source/Client/Core/Recipe.toml +++ b/Source/Client/Core/Recipe.toml @@ -8,11 +8,12 @@ Dependencies = [ # "../../../Dependencies/toml11/", "toml11@1.0.0", "../OpalExtensions/", - "../../Build/Core/", + "../../Build/Contracts/", # "Soup.Build@0.3.0", - "../../Build/Extensions/", - # "Soup.Build.Extensions@0.3.0", - "../../Build/Runtime/", + "../../Build/Utilities/", + # "Soup.Build.Utilities@0.3.0", + "../../Build/Execute/", + "../../Build/Evaluate/", ] Defines = [ # "LOCAL_DEBUG", @@ -25,7 +26,7 @@ IncludePaths = [ ] DevDependencies = [ - "../../Extensions/TestBuild/", + # "../../Extensions/TestBuild/", # "../../../Dependencies/SoupTest/Assert/", "SoupTest@0.1.0", "../../TestUtilities/", diff --git a/Source/Client/Core/Utils/HandledException.h b/Source/Client/Core/Utils/HandledException.h index 5b195312..41c59c80 100644 --- a/Source/Client/Core/Utils/HandledException.h +++ b/Source/Client/Core/Utils/HandledException.h @@ -15,9 +15,18 @@ namespace Soup /// /// Initialize a new instance of the HandledException class /// - HandledException() : - std::exception() + HandledException(int exitCode) : + std::exception(), + m_exitCode(exitCode) { } + + int GetExitCode() const + { + return m_exitCode; + } + + private: + int m_exitCode; }; } diff --git a/Source/Client/Core/Utils/Helpers.h b/Source/Client/Core/Utils/Helpers.h index 153091a8..dc9a6b62 100644 --- a/Source/Client/Core/Utils/Helpers.h +++ b/Source/Client/Core/Utils/Helpers.h @@ -74,19 +74,4 @@ namespace Soup { return value ? "true" : "false"; } - - export std::time_t CreateDateTime(int year, int month, int day, int hour, int minutes) - { - std::tm timeInfo = std::tm(); - - // Year is offset from 1900 - timeInfo.tm_year = year - 1900; - timeInfo.tm_mon = month; - timeInfo.tm_mday = day; - timeInfo.tm_hour = hour; - timeInfo.tm_min = minutes; - - std::time_t time = std::mktime(&timeInfo); - return time; - } } \ No newline at end of file diff --git a/Source/Extensions/Compiler/Clang.UnitTests/CompilerArgumentBuilderTests.h b/Source/Extensions/Compiler/Clang.UnitTests/CompilerArgumentBuilderTests.h index e1597ed7..7b432521 100644 --- a/Source/Extensions/Compiler/Clang.UnitTests/CompilerArgumentBuilderTests.h +++ b/Source/Extensions/Compiler/Clang.UnitTests/CompilerArgumentBuilderTests.h @@ -80,45 +80,6 @@ namespace Soup::Compiler::Clang::UnitTests Assert::AreEqual(expectedOutput, actualOutput, "Verify generated output match expected."); } - [[Fact]] - void SingleArgument_GenerateIncludeTree() - { - CompileArguments arguments = {}; - arguments.SourceFile = Path("File.cpp"); - arguments.TargetFile = Path("File.o"); - arguments.GenerateIncludeTree = true; - - auto actualInput = std::vector(); - auto actualOutput = std::vector(); - auto actualArguments = ArgumentBuilder::BuildCompilerArguments( - arguments, - actualInput, - actualOutput); - - auto expectedArguments = std::vector({ - "-nostdinc", - "-Wno-unknown-attributes", - "-Xclang", - "-flto-visibility-public-std", - "-H", - "-std=c++11", - "-c", - "File.cpp", - "-o", - "File.o", - }); - auto expectedInput = std::vector({ - Path("File.cpp"), - }); - auto expectedOutput = std::vector({ - Path("File.o"), - }); - - Assert::AreEqual(expectedArguments, actualArguments, "Verify generated arguments match expected."); - Assert::AreEqual(expectedInput, actualInput, "Verify generated input match expected."); - Assert::AreEqual(expectedOutput, actualOutput, "Verify generated output match expected."); - } - [[Theory]] [[InlineData(Soup::LanguageStandard::CPP11, "-std=c++11")]] [[InlineData(Soup::LanguageStandard::CPP14, "-std=c++14")]] diff --git a/Source/Extensions/Compiler/Clang.UnitTests/CompilerTests.h b/Source/Extensions/Compiler/Clang.UnitTests/CompilerTests.h index 948c4d53..58da1c09 100644 --- a/Source/Extensions/Compiler/Clang.UnitTests/CompilerTests.h +++ b/Source/Extensions/Compiler/Clang.UnitTests/CompilerTests.h @@ -30,12 +30,12 @@ namespace Soup::Compiler::Clang::UnitTests arguments.TargetFile = Path("obj/File.o"); arguments.RootDirectory = Path("Source"); - auto buildState = Build::Runtime::BuildState(Build::Runtime::ValueTable()); - auto result = uut.CreateCompileOperation(Build::Extensions::BuildStateWrapper(buildState), arguments); + auto buildState = Build::Evaluate::BuildState(Build::Evaluate::ValueTable()); + auto result = uut.CreateCompileOperation(Build::Utilities::BuildStateWrapper(buildState), arguments); // Verify result - auto expected = Memory::Reference( - new Build::Extensions::BuildOperation( + auto expected = Memory::Reference( + new Build::Utilities::BuildOperation( "File.cpp", Path("C:/Clang/bin/clang++.exe"), "-nostdinc -Wno-unknown-attributes -Xclang -flto-visibility-public-std -std=c++11 -c File.cpp -o obj/File.o", @@ -70,12 +70,12 @@ namespace Soup::Compiler::Clang::UnitTests }); arguments.ExportModule = true; - auto buildState = Build::Runtime::BuildState(Build::Runtime::ValueTable()); - auto result = uut.CreateCompileOperation(Build::Extensions::BuildStateWrapper(buildState), arguments); + auto buildState = Build::Evaluate::BuildState(Build::Evaluate::ValueTable()); + auto result = uut.CreateCompileOperation(Build::Utilities::BuildStateWrapper(buildState), arguments); // Verify result - auto expected = Memory::Reference( - new Build::Extensions::BuildOperation( + auto expected = Memory::Reference( + new Build::Utilities::BuildOperation( "File.cpp", Path("C:/Clang/bin/clang++.exe"), "-nostdinc -Wno-unknown-attributes -Xclang -flto-visibility-public-std -std=c++11 -I\"Includes\" -DDEBUG -fmodule-file=\"Module.pcm\" --precompile File.cpp -o obj/File.pcm", @@ -87,8 +87,8 @@ namespace Soup::Compiler::Clang::UnitTests std::vector({ Path("obj/File.pcm"), }), - std::vector>({ - new Build::Extensions::BuildOperation( + std::vector>({ + new Build::Utilities::BuildOperation( "obj/File.pcm", Path("C:/Clang/bin/clang++.exe"), "-nostdinc -Wno-unknown-attributes -Xclang -flto-visibility-public-std -std=c++11 -c obj/File.pcm -o obj/File.obj", @@ -117,12 +117,12 @@ namespace Soup::Compiler::Clang::UnitTests Path("File.mock.o"), }); - auto buildState = Build::Runtime::BuildState(Build::Runtime::ValueTable()); - auto result = uut.CreateLinkOperation(Build::Extensions::BuildStateWrapper(buildState), arguments); + auto buildState = Build::Evaluate::BuildState(Build::Evaluate::ValueTable()); + auto result = uut.CreateLinkOperation(Build::Utilities::BuildStateWrapper(buildState), arguments); // Verify result - auto expected = Memory::Reference( - new Build::Extensions::BuildOperation( + auto expected = Memory::Reference( + new Build::Utilities::BuildOperation( "Library.mock.a", Path("C:/Clang/bin/llvm-ar.exe"), "rc Library.mock.a File.mock.o", @@ -144,6 +144,7 @@ namespace Soup::Compiler::Clang::UnitTests LinkArguments arguments = {}; arguments.TargetType = LinkTarget::Executable; + arguments.TargetArchitecture = "x64"; arguments.TargetFile = Path("Something.exe"); arguments.RootDirectory = Path("Source"); arguments.ObjectFiles = std::vector({ @@ -153,12 +154,12 @@ namespace Soup::Compiler::Clang::UnitTests Path("Library.mock.a"), }); - auto buildState = Build::Runtime::BuildState(Build::Runtime::ValueTable()); - auto result = uut.CreateLinkOperation(Build::Extensions::BuildStateWrapper(buildState), arguments); + auto buildState = Build::Evaluate::BuildState(Build::Evaluate::ValueTable()); + auto result = uut.CreateLinkOperation(Build::Utilities::BuildStateWrapper(buildState), arguments); // Verify result - auto expected = Memory::Reference( - new Build::Extensions::BuildOperation( + auto expected = Memory::Reference( + new Build::Utilities::BuildOperation( "Something.exe", Path("C:/Clang/bin/lld-link.exe"), "/nologo /subsystem:console /machine:X64 /out:\"Something.exe\" Library.mock.a File.mock.o", diff --git a/Source/Extensions/Compiler/Clang.UnitTests/LinkerArgumentBuilderTests.h b/Source/Extensions/Compiler/Clang.UnitTests/LinkerArgumentBuilderTests.h index b06d753b..b7c3b3ba 100644 --- a/Source/Extensions/Compiler/Clang.UnitTests/LinkerArgumentBuilderTests.h +++ b/Source/Extensions/Compiler/Clang.UnitTests/LinkerArgumentBuilderTests.h @@ -89,6 +89,7 @@ namespace Soup::Compiler::Clang::UnitTests { LinkArguments arguments = {}; arguments.TargetType = LinkTarget::DynamicLibrary; + arguments.TargetArchitecture = "x64"; arguments.TargetFile = Path("Library.mock.so"); arguments.ImplementationFile = Path("Library.mock.lib"); arguments.ObjectFiles = std::vector({ @@ -126,6 +127,7 @@ namespace Soup::Compiler::Clang::UnitTests { LinkArguments arguments = {}; arguments.TargetType = LinkTarget::Executable; + arguments.TargetArchitecture = "x64"; arguments.TargetFile = Path("out/Something.exe"); arguments.ObjectFiles = std::vector({ Path("File.mock.o"), diff --git a/Source/Extensions/Compiler/Clang.UnitTests/Recipe.toml b/Source/Extensions/Compiler/Clang.UnitTests/Recipe.toml index 063df56b..c1043987 100644 --- a/Source/Extensions/Compiler/Clang.UnitTests/Recipe.toml +++ b/Source/Extensions/Compiler/Clang.UnitTests/Recipe.toml @@ -4,7 +4,7 @@ Type = "Executable" Dependencies = [ # "../../../Dependencies/SoupTest/Assert/", "../Clang/", - "../../../Build/Runtime/", + "../../../Build/Evaluate/", "../../../TestUtilities/", "SoupTest@0.1.0", ] diff --git a/Source/Extensions/Compiler/Clang.UnitTests/gen/CompilerArgumentBuilderTests.gen.h b/Source/Extensions/Compiler/Clang.UnitTests/gen/CompilerArgumentBuilderTests.gen.h index c1007177..865be68c 100644 --- a/Source/Extensions/Compiler/Clang.UnitTests/gen/CompilerArgumentBuilderTests.gen.h +++ b/Source/Extensions/Compiler/Clang.UnitTests/gen/CompilerArgumentBuilderTests.gen.h @@ -9,7 +9,6 @@ TestState RunCompilerArgumentBuilderTests() state += SoupTest::RunTest(className, "EmptySourceFile_Throws", [&testClass]() { testClass->EmptySourceFile_Throws(); }); state += SoupTest::RunTest(className, "EmptyTargetFile_Throws", [&testClass]() { testClass->EmptyTargetFile_Throws(); }); state += SoupTest::RunTest(className, "DefaultParameters", [&testClass]() { testClass->DefaultParameters(); }); - state += SoupTest::RunTest(className, "SingleArgument_GenerateIncludeTree", [&testClass]() { testClass->SingleArgument_GenerateIncludeTree(); }); state += SoupTest::RunTest(className, "SingleArgument_LanguageStandard(Soup::LanguageStandard::CPP11, \"-std=c++11\")", [&testClass]() { testClass->SingleArgument_LanguageStandard(Soup::Compiler::LanguageStandard::CPP11, "-std=c++11"); }); state += SoupTest::RunTest(className, "SingleArgument_LanguageStandard(Soup::LanguageStandard::CPP14, \"-std=c++14\")", [&testClass]() { testClass->SingleArgument_LanguageStandard(Soup::Compiler::LanguageStandard::CPP14, "-std=c++14"); }); state += SoupTest::RunTest(className, "SingleArgument_LanguageStandard(Soup::LanguageStandard::CPP17, \"-std=c++17\")", [&testClass]() { testClass->SingleArgument_LanguageStandard(Soup::Compiler::LanguageStandard::CPP17, "-std=c++17"); }); diff --git a/Source/Extensions/Compiler/Clang.UnitTests/gen/Main.cpp b/Source/Extensions/Compiler/Clang.UnitTests/gen/Main.cpp index c7323111..c40a5e46 100644 --- a/Source/Extensions/Compiler/Clang.UnitTests/gen/Main.cpp +++ b/Source/Extensions/Compiler/Clang.UnitTests/gen/Main.cpp @@ -11,8 +11,8 @@ import SoupCompilerClang; import SoupTest; import SoupTestUtilities; import Soup.Build; -import Soup.Build.Extensions; -import Soup.Build.Runtime; +import Soup.Build.Utilities; +import Soup.Build.Evaluate; using namespace Opal; using namespace Opal::System; @@ -35,5 +35,8 @@ int main() std::cout << state.PassCount << " PASSED." << std::endl; std::cout << state.FailCount << " FAILED." << std::endl; - return 0; + if (state.FailCount > 0) + return 1; + else + return 0; } diff --git a/Source/Extensions/Compiler/Clang/ArgumentBuilder.h b/Source/Extensions/Compiler/Clang/ArgumentBuilder.h index edc7b7d6..39f2004f 100644 --- a/Source/Extensions/Compiler/Clang/ArgumentBuilder.h +++ b/Source/Extensions/Compiler/Clang/ArgumentBuilder.h @@ -44,12 +44,6 @@ namespace Soup::Compiler::Clang commandArgs.push_back("-Xclang"); commandArgs.push_back("-flto-visibility-public-std"); - // Enable Header includes if needed - if (args.GenerateIncludeTree) - { - commandArgs.push_back("-H"); - } - // Generate source debug information if (args.GenerateSourceDebugInfo) { diff --git a/Source/Extensions/Compiler/Clang/Compiler.h b/Source/Extensions/Compiler/Clang/Compiler.h index 794e236f..727a32eb 100644 --- a/Source/Extensions/Compiler/Clang/Compiler.h +++ b/Source/Extensions/Compiler/Clang/Compiler.h @@ -68,8 +68,8 @@ namespace Soup::Compiler::Clang /// /// Compile /// - Build::Extensions::BuildOperationWrapper CreateCompileOperation( - Build::Extensions::BuildStateWrapper& state, + Build::Utilities::BuildOperationWrapper CreateCompileOperation( + Build::Utilities::BuildStateWrapper& state, const CompileArguments& args) const override final { // Clang decided to do their module compilation in two stages @@ -87,8 +87,8 @@ namespace Soup::Compiler::Clang /// /// Link /// - Build::Extensions::BuildOperationWrapper CreateLinkOperation( - Build::Extensions::BuildStateWrapper& state, + Build::Utilities::BuildOperationWrapper CreateLinkOperation( + Build::Utilities::BuildStateWrapper& state, const LinkArguments& args) const override final { // Select the correct executable for linking libraries or executables @@ -111,8 +111,8 @@ namespace Soup::Compiler::Clang auto outputFiles = std::vector(); auto commandArgs = ArgumentBuilder::BuildLinkerArguments(args, inputFiles, outputFiles); - auto buildOperation = Build::Extensions::BuildOperationWrapper( - new Build::Extensions::BuildOperation( + auto buildOperation = Build::Utilities::BuildOperationWrapper( + new Build::Utilities::BuildOperation( args.TargetFile.ToString(), executablePath, CombineArguments(commandArgs), @@ -124,8 +124,8 @@ namespace Soup::Compiler::Clang } private: - Build::Extensions::BuildOperationWrapper CompileStandard( - Build::Extensions::BuildStateWrapper& state, + Build::Utilities::BuildOperationWrapper CompileStandard( + Build::Utilities::BuildStateWrapper& state, const CompileArguments& args) const { auto executablePath = _toolPath + Path(CompilerExecutable); @@ -135,8 +135,8 @@ namespace Soup::Compiler::Clang auto outputFiles = std::vector(); auto commandArgs = ArgumentBuilder::BuildCompilerArguments(args, inputFiles, outputFiles); - auto buildOperation = Build::Extensions::BuildOperationWrapper( - new Build::Extensions::BuildOperation( + auto buildOperation = Build::Utilities::BuildOperationWrapper( + new Build::Utilities::BuildOperation( args.SourceFile.ToString(), executablePath, CombineArguments(commandArgs), @@ -147,8 +147,8 @@ namespace Soup::Compiler::Clang return buildOperation; } - Build::Extensions::BuildOperationWrapper CompileModuleInterfaceUnit( - Build::Extensions::BuildStateWrapper& state, + Build::Utilities::BuildOperationWrapper CompileModuleInterfaceUnit( + Build::Utilities::BuildStateWrapper& state, const CompileArguments& args) const { auto executablePath = _toolPath + Path(CompilerExecutable); @@ -162,7 +162,6 @@ namespace Soup::Compiler::Clang generatePrecompiledModuleArgs.IncludeModules = args.IncludeModules; generatePrecompiledModuleArgs.ExportModule = true; generatePrecompiledModuleArgs.PreprocessorDefinitions = args.PreprocessorDefinitions; - generatePrecompiledModuleArgs.GenerateIncludeTree = args.GenerateIncludeTree; generatePrecompiledModuleArgs.GenerateSourceDebugInfo = args.GenerateSourceDebugInfo; // Use the target file as input to the build and generate an object with the same name @@ -179,8 +178,8 @@ namespace Soup::Compiler::Clang generatePrecompiledModuleInputFiles, generatePrecompiledModuleOutputFiles); - auto precompiledModuleBuildOperation = Build::Extensions::BuildOperationWrapper( - new Build::Extensions::BuildOperation( + auto precompiledModuleBuildOperation = Build::Utilities::BuildOperationWrapper( + new Build::Utilities::BuildOperation( generatePrecompiledModuleArgs.SourceFile.ToString(), executablePath, CombineArguments(generatePrecompiledModuleCommandArgs), @@ -205,8 +204,8 @@ namespace Soup::Compiler::Clang compileObjectInputFiles, compileObjectOutputFiles); - auto compileBuildOperation = Build::Extensions::BuildOperationWrapper( - new Build::Extensions::BuildOperation( + auto compileBuildOperation = Build::Utilities::BuildOperationWrapper( + new Build::Utilities::BuildOperation( compileObjectArgs.SourceFile.ToString(), executablePath, CombineArguments(compileObjectCommandArgs), @@ -215,7 +214,7 @@ namespace Soup::Compiler::Clang compileObjectOutputFiles)); // Ensure the compile operation runs after the precompile - Build::Extensions::BuildOperationExtensions::AddLeafChild( + Build::Utilities::BuildOperationExtensions::AddLeafChild( precompiledModuleBuildOperation, compileBuildOperation); diff --git a/Source/Extensions/Compiler/Core.UnitTests/BuildEngineTests.h b/Source/Extensions/Compiler/Core.UnitTests/BuildEngineTests.h index df5f493d..b17be022 100644 --- a/Source/Extensions/Compiler/Core.UnitTests/BuildEngineTests.h +++ b/Source/Extensions/Compiler/Core.UnitTests/BuildEngineTests.h @@ -44,8 +44,8 @@ namespace Soup::Compiler::UnitTests }); auto uut = BuildEngine(compiler); - auto buildState = Build::Runtime::BuildState(Build::Runtime::ValueTable()); - auto result = uut.Execute(Build::Extensions::BuildStateWrapper(buildState), arguments); + auto buildState = Build::Evaluate::BuildState(Build::Evaluate::ValueTable()); + auto result = uut.Execute(Build::Utilities::BuildStateWrapper(buildState), arguments); // Verify expected logs Assert::AreEqual( @@ -65,7 +65,6 @@ namespace Soup::Compiler::UnitTests expectedCompileArguments.RootDirectory = Path("C:/root/"); expectedCompileArguments.SourceFile = Path("TestFile.cpp"); expectedCompileArguments.TargetFile = Path("obj/TestFile.mock.obj"); - expectedCompileArguments.GenerateIncludeTree = true; auto expectedLinkArguments = LinkArguments(); expectedLinkArguments.TargetType = LinkTarget::Executable; @@ -95,8 +94,8 @@ namespace Soup::Compiler::UnitTests // Verify build state auto expectedLinkOperation = - Memory::Reference( - new Build::Extensions::BuildOperation( + Memory::Reference( + new Build::Utilities::BuildOperation( "MockLink: 1", Path("MockLinker.exe"), "Arguments", @@ -109,8 +108,8 @@ namespace Soup::Compiler::UnitTests }))); auto expectedCompileOperation = - Memory::Reference( - new Build::Extensions::BuildOperation( + Memory::Reference( + new Build::Utilities::BuildOperation( "MockCompile: 1", Path("MockCompiler.exe"), "Arguments", @@ -121,12 +120,12 @@ namespace Soup::Compiler::UnitTests std::vector({ Path("OutputFile.out"), }), - std::vector>({ + std::vector>({ expectedLinkOperation, }))); - auto expectedBuildOperations = std::vector>({ - new Build::Extensions::BuildOperation( + auto expectedBuildOperations = std::vector>({ + new Build::Utilities::BuildOperation( "MakeDir [C:/root/obj]", Path("C:/Windows/System32/cmd.exe"), "/C if not exist \"C:/root/obj\" mkdir \"C:/root/obj\"", @@ -135,10 +134,10 @@ namespace Soup::Compiler::UnitTests std::vector({ Path("C:/root/obj"), }), - std::vector>({ + std::vector>({ expectedCompileOperation, })), - new Build::Extensions::BuildOperation( + new Build::Utilities::BuildOperation( "MakeDir [C:/root/bin]", Path("C:/Windows/System32/cmd.exe"), "/C if not exist \"C:/root/bin\" mkdir \"C:/root/bin\"", @@ -147,7 +146,7 @@ namespace Soup::Compiler::UnitTests std::vector({ Path("C:/root/bin"), }), - std::vector>({ + std::vector>({ expectedCompileOperation, })), }); @@ -210,8 +209,8 @@ namespace Soup::Compiler::UnitTests }); auto uut = BuildEngine(compiler); - auto buildState = Build::Runtime::BuildState(Build::Runtime::ValueTable()); - auto result = uut.Execute(Build::Extensions::BuildStateWrapper(buildState), arguments); + auto buildState = Build::Evaluate::BuildState(Build::Evaluate::ValueTable()); + auto result = uut.Execute(Build::Utilities::BuildStateWrapper(buildState), arguments); // Verify expected logs Assert::AreEqual( @@ -240,7 +239,6 @@ namespace Soup::Compiler::UnitTests Path("../Other/bin/OtherModule1.mock.bmi"), Path("../OtherModule2.mock.bmi"), }); - expectedCompileArguments.GenerateIncludeTree = true; auto expectedCompile1Arguments = expectedCompileArguments; expectedCompile1Arguments.SourceFile = Path("TestFile1.cpp"); @@ -283,8 +281,8 @@ namespace Soup::Compiler::UnitTests // Verify build state auto expectedLinkOperation = - Memory::Reference( - new Build::Extensions::BuildOperation( + Memory::Reference( + new Build::Utilities::BuildOperation( "MockLink: 1", Path("MockLinker.exe"), "Arguments", @@ -296,8 +294,8 @@ namespace Soup::Compiler::UnitTests Path("OutputFile.out"), }))); - auto expectedCompileOperations = std::vector>({ - new Build::Extensions::BuildOperation( + auto expectedCompileOperations = std::vector>({ + new Build::Utilities::BuildOperation( "MockCompile: 1", Path("MockCompiler.exe"), "Arguments", @@ -308,10 +306,10 @@ namespace Soup::Compiler::UnitTests std::vector({ Path("OutputFile.out"), }), - std::vector>({ + std::vector>({ expectedLinkOperation, })), - new Build::Extensions::BuildOperation( + new Build::Utilities::BuildOperation( "MockCompile: 2", Path("MockCompiler.exe"), "Arguments", @@ -322,10 +320,10 @@ namespace Soup::Compiler::UnitTests std::vector({ Path("OutputFile.out"), }), - std::vector>({ + std::vector>({ expectedLinkOperation, })), - new Build::Extensions::BuildOperation( + new Build::Utilities::BuildOperation( "MockCompile: 3", Path("MockCompiler.exe"), "Arguments", @@ -336,13 +334,13 @@ namespace Soup::Compiler::UnitTests std::vector({ Path("OutputFile.out"), }), - std::vector>({ + std::vector>({ expectedLinkOperation, })), }); - auto expectedBuildOperations = std::vector>({ - new Build::Extensions::BuildOperation( + auto expectedBuildOperations = std::vector>({ + new Build::Utilities::BuildOperation( "MakeDir [C:/root/obj]", Path("C:/Windows/System32/cmd.exe"), "/C if not exist \"C:/root/obj\" mkdir \"C:/root/obj\"", @@ -352,7 +350,7 @@ namespace Soup::Compiler::UnitTests Path("C:/root/obj"), }), expectedCompileOperations), - new Build::Extensions::BuildOperation( + new Build::Utilities::BuildOperation( "MakeDir [C:/root/bin]", Path("C:/Windows/System32/cmd.exe"), "/C if not exist \"C:/root/bin\" mkdir \"C:/root/bin\"", @@ -431,8 +429,8 @@ namespace Soup::Compiler::UnitTests }); auto uut = BuildEngine(compiler); - auto buildState = Build::Runtime::BuildState(Build::Runtime::ValueTable()); - auto result = uut.Execute(Build::Extensions::BuildStateWrapper(buildState), arguments); + auto buildState = Build::Evaluate::BuildState(Build::Evaluate::ValueTable()); + auto result = uut.Execute(Build::Utilities::BuildStateWrapper(buildState), arguments); // Verify expected logs Assert::AreEqual( @@ -463,7 +461,6 @@ namespace Soup::Compiler::UnitTests Path("../Other/bin/OtherModule1.mock.bmi"), Path("../OtherModule2.mock.bmi"), }); - expectedCompileArguments.GenerateIncludeTree = true; expectedCompileArguments.PreprocessorDefinitions = std::vector({ "DEBUG", "AWESOME", @@ -518,8 +515,8 @@ namespace Soup::Compiler::UnitTests // Verify build state auto expectedLinkOperation = - Memory::Reference( - new Build::Extensions::BuildOperation( + Memory::Reference( + new Build::Utilities::BuildOperation( "MockLink: 1", Path("MockLinker.exe"), "Arguments", @@ -531,8 +528,8 @@ namespace Soup::Compiler::UnitTests Path("OutputFile.out"), }))); - auto expectedCompileSourceOperations = std::vector>({ - new Build::Extensions::BuildOperation( + auto expectedCompileSourceOperations = std::vector>({ + new Build::Utilities::BuildOperation( "MockCompile: 2", Path("MockCompiler.exe"), "Arguments", @@ -543,10 +540,10 @@ namespace Soup::Compiler::UnitTests std::vector({ Path("OutputFile.out"), }), - std::vector>({ + std::vector>({ expectedLinkOperation, })), - new Build::Extensions::BuildOperation( + new Build::Utilities::BuildOperation( "MockCompile: 3", Path("MockCompiler.exe"), "Arguments", @@ -557,10 +554,10 @@ namespace Soup::Compiler::UnitTests std::vector({ Path("OutputFile.out"), }), - std::vector>({ + std::vector>({ expectedLinkOperation, })), - new Build::Extensions::BuildOperation( + new Build::Utilities::BuildOperation( "MockCompile: 4", Path("MockCompiler.exe"), "Arguments", @@ -571,14 +568,14 @@ namespace Soup::Compiler::UnitTests std::vector({ Path("OutputFile.out"), }), - std::vector>({ + std::vector>({ expectedLinkOperation, })), }); auto expectedCopyModuleInterfaceOperation = - Memory::Reference( - new Build::Extensions::BuildOperation( + Memory::Reference( + new Build::Utilities::BuildOperation( "Copy [C:/root/obj/Public.mock.bmi] -> [C:/root/bin/Library.mock.bmi]", Path("C:/Windows/System32/cmd.exe"), "/C copy /Y \"C:\\root\\obj\\Public.mock.bmi\" \"C:\\root\\bin\\Library.mock.bmi\"", @@ -592,8 +589,8 @@ namespace Soup::Compiler::UnitTests expectedCompileSourceOperations)); auto expectedCompileModuleOperation = - Memory::Reference( - new Build::Extensions::BuildOperation( + Memory::Reference( + new Build::Utilities::BuildOperation( "MockCompile: 1", Path("MockCompiler.exe"), "Arguments", @@ -604,12 +601,12 @@ namespace Soup::Compiler::UnitTests std::vector({ Path("OutputFile.out"), }), - std::vector>({ + std::vector>({ expectedCopyModuleInterfaceOperation, }))); - auto expectedBuildOperations = std::vector>({ - new Build::Extensions::BuildOperation( + auto expectedBuildOperations = std::vector>({ + new Build::Utilities::BuildOperation( "MakeDir [C:/root/obj]", Path("C:/Windows/System32/cmd.exe"), "/C if not exist \"C:/root/obj\" mkdir \"C:/root/obj\"", @@ -618,10 +615,10 @@ namespace Soup::Compiler::UnitTests std::vector({ Path("C:/root/obj"), }), - std::vector>({ + std::vector>({ expectedCompileModuleOperation, })), - new Build::Extensions::BuildOperation( + new Build::Utilities::BuildOperation( "MakeDir [C:/root/bin]", Path("C:/Windows/System32/cmd.exe"), "/C if not exist \"C:/root/bin\" mkdir \"C:/root/bin\"", @@ -630,7 +627,7 @@ namespace Soup::Compiler::UnitTests std::vector({ Path("C:/root/bin"), }), - std::vector>({ + std::vector>({ expectedCompileModuleOperation, })), }); @@ -696,8 +693,8 @@ namespace Soup::Compiler::UnitTests }); auto uut = BuildEngine(compiler); - auto buildState = Build::Runtime::BuildState(Build::Runtime::ValueTable()); - auto result = uut.Execute(Build::Extensions::BuildStateWrapper(buildState), arguments); + auto buildState = Build::Evaluate::BuildState(Build::Evaluate::ValueTable()); + auto result = uut.Execute(Build::Utilities::BuildStateWrapper(buildState), arguments); // Verify expected logs Assert::AreEqual( @@ -724,7 +721,6 @@ namespace Soup::Compiler::UnitTests Path("../Other/bin/OtherModule1.mock.bmi"), Path("../OtherModule2.mock.bmi"), }); - expectedCompileArguments.GenerateIncludeTree = true; auto expectedCompileModuleArguments = expectedCompileArguments; expectedCompileModuleArguments.SourceFile = Path("Public.cpp"); @@ -756,8 +752,8 @@ namespace Soup::Compiler::UnitTests // Verify build state auto expectedLinkOperation = - Memory::Reference( - new Build::Extensions::BuildOperation( + Memory::Reference( + new Build::Utilities::BuildOperation( "MockLink: 1", Path("MockLinker.exe"), "Arguments", @@ -770,8 +766,8 @@ namespace Soup::Compiler::UnitTests }))); auto expectedCopyModuleInterfaceOperation = - Memory::Reference( - new Build::Extensions::BuildOperation( + Memory::Reference( + new Build::Utilities::BuildOperation( "Copy [C:/root/obj/Public.mock.bmi] -> [C:/root/bin/Library.mock.bmi]", Path("C:/Windows/System32/cmd.exe"), "/C copy /Y \"C:\\root\\obj\\Public.mock.bmi\" \"C:\\root\\bin\\Library.mock.bmi\"", @@ -782,13 +778,13 @@ namespace Soup::Compiler::UnitTests std::vector({ Path("C:/root/bin/Library.mock.bmi"), }), - std::vector>({ + std::vector>({ expectedLinkOperation, }))); auto expectedCompileModuleOperation = - Memory::Reference( - new Build::Extensions::BuildOperation( + Memory::Reference( + new Build::Utilities::BuildOperation( "MockCompile: 1", Path("MockCompiler.exe"), "Arguments", @@ -799,12 +795,12 @@ namespace Soup::Compiler::UnitTests std::vector({ Path("OutputFile.out"), }), - std::vector>({ + std::vector>({ expectedCopyModuleInterfaceOperation, }))); - auto expectedBuildOperations = std::vector>({ - new Build::Extensions::BuildOperation( + auto expectedBuildOperations = std::vector>({ + new Build::Utilities::BuildOperation( "MakeDir [C:/root/obj]", Path("C:/Windows/System32/cmd.exe"), "/C if not exist \"C:/root/obj\" mkdir \"C:/root/obj\"", @@ -813,10 +809,10 @@ namespace Soup::Compiler::UnitTests std::vector({ Path("C:/root/obj"), }), - std::vector>({ + std::vector>({ expectedCompileModuleOperation, })), - new Build::Extensions::BuildOperation( + new Build::Utilities::BuildOperation( "MakeDir [C:/root/bin]", Path("C:/Windows/System32/cmd.exe"), "/C if not exist \"C:/root/bin\" mkdir \"C:/root/bin\"", @@ -825,7 +821,7 @@ namespace Soup::Compiler::UnitTests std::vector({ Path("C:/root/bin"), }), - std::vector>({ + std::vector>({ expectedCompileModuleOperation, })), }); diff --git a/Source/Extensions/Compiler/Core.UnitTests/Recipe.toml b/Source/Extensions/Compiler/Core.UnitTests/Recipe.toml index ef0cf09a..83bfb3d6 100644 --- a/Source/Extensions/Compiler/Core.UnitTests/Recipe.toml +++ b/Source/Extensions/Compiler/Core.UnitTests/Recipe.toml @@ -3,7 +3,7 @@ Version = "1.0.0" Type = "Executable" Dependencies = [ "../Core/", - "../../../Build/Runtime/", + "../../../Build/Evaluate/", "../../../TestUtilities/", "SoupTest@0.1.0", ] diff --git a/Source/Extensions/Compiler/Core.UnitTests/gen/Main.cpp b/Source/Extensions/Compiler/Core.UnitTests/gen/Main.cpp index 16455312..68496f76 100644 --- a/Source/Extensions/Compiler/Core.UnitTests/gen/Main.cpp +++ b/Source/Extensions/Compiler/Core.UnitTests/gen/Main.cpp @@ -7,7 +7,7 @@ #include import Opal; -import Soup.Build.Runtime; +import Soup.Build.Evaluate; import SoupCompiler; import SoupTest; import SoupTestUtilities; @@ -29,5 +29,8 @@ int main() std::cout << state.PassCount << " PASSED." << std::endl; std::cout << state.FailCount << " FAILED." << std::endl; - return 0; + if (state.FailCount > 0) + return 1; + else + return 0; } diff --git a/Source/Extensions/Compiler/Core/BuildArguments.h b/Source/Extensions/Compiler/Core/BuildArguments.h index d9edfe1a..ea4cfe8a 100644 --- a/Source/Extensions/Compiler/Core/BuildArguments.h +++ b/Source/Extensions/Compiler/Core/BuildArguments.h @@ -99,6 +99,11 @@ namespace Soup::Compiler /// std::string TargetName; + /// + /// Gets or sets the target architecture + /// + std::string TargetArchitecture; + /// /// Gets or sets the target type /// @@ -189,6 +194,7 @@ namespace Soup::Compiler bool operator ==(const BuildArguments& rhs) const { return TargetName == rhs.TargetName && + TargetArchitecture == rhs.TargetArchitecture && TargetType == rhs.TargetType && LanguageStandard == rhs.LanguageStandard && WorkingDirectory == rhs.WorkingDirectory && diff --git a/Source/Extensions/Compiler/Core/BuildEngine.h b/Source/Extensions/Compiler/Core/BuildEngine.h index b3d28ba8..fbb35373 100644 --- a/Source/Extensions/Compiler/Core/BuildEngine.h +++ b/Source/Extensions/Compiler/Core/BuildEngine.h @@ -25,7 +25,7 @@ namespace Soup::Compiler /// Generate the required build operations for the requested build /// BuildResult Execute( - Soup::Build::Extensions::BuildStateWrapper& buildState, + Soup::Build::Utilities::BuildStateWrapper& buildState, const BuildArguments& arguments) { auto result = BuildResult(); @@ -63,14 +63,14 @@ namespace Soup::Compiler /// Compile the module and source files /// void CoreCompile( - Soup::Build::Extensions::BuildStateWrapper& buildState, + Soup::Build::Utilities::BuildStateWrapper& buildState, const BuildArguments& arguments, BuildResult& result) { - auto rootCompileOperations = std::vector(); + auto rootCompileOperations = std::vector(); // Compile the module interface unit if present - auto moduleCompileOperation = Soup::Build::Extensions::BuildOperationWrapper(); + auto moduleCompileOperation = Soup::Build::Utilities::BuildOperationWrapper(); if (!arguments.ModuleInterfaceSourceFile.IsEmpty()) { CompileModuleInterfaceUnit( @@ -92,7 +92,7 @@ namespace Soup::Compiler buildState, objectModuleInterfaceFile, binaryOutputModuleInterfaceFile); - Soup::Build::Extensions::BuildOperationExtensions::AddLeafChild(result.BuildOperations, copyInterfaceOperation); + Soup::Build::Utilities::BuildOperationExtensions::AddLeafChild(result.BuildOperations, copyInterfaceOperation); // Add output module interface to the parent set of modules // This will allow the module implementation units access as well as downstream @@ -114,7 +114,7 @@ namespace Soup::Compiler /// Returns true if the file was compiled /// void CompileModuleInterfaceUnit( - Soup::Build::Extensions::BuildStateWrapper& buildState, + Soup::Build::Utilities::BuildStateWrapper& buildState, const BuildArguments& arguments, BuildResult& result) { @@ -132,7 +132,6 @@ namespace Soup::Compiler compileArguments.PreprocessorDefinitions = {}; compileArguments.IncludeDirectories = arguments.IncludeDirectories; compileArguments.IncludeModules = arguments.ModuleDependencies; - compileArguments.GenerateIncludeTree = true; compileArguments.ExportModule = true; compileArguments.PreprocessorDefinitions = arguments.PreprocessorDefinitions; compileArguments.GenerateSourceDebugInfo = arguments.GenerateSourceDebugInfo; @@ -146,14 +145,14 @@ namespace Soup::Compiler auto compileOperation = _compiler->CreateCompileOperation(buildState, compileArguments); // Run after the module interface unit compile - Soup::Build::Extensions::BuildOperationExtensions::AddLeafChild(result.BuildOperations, compileOperation); + Soup::Build::Utilities::BuildOperationExtensions::AddLeafChild(result.BuildOperations, compileOperation); } /// /// Compile the supporting source files /// void CompileSourceFiles( - Soup::Build::Extensions::BuildStateWrapper& buildState, + Soup::Build::Utilities::BuildStateWrapper& buildState, const BuildArguments& arguments, BuildResult& result) { @@ -168,7 +167,6 @@ namespace Soup::Compiler compileArguments.PreprocessorDefinitions = {}; compileArguments.IncludeDirectories = arguments.IncludeDirectories; compileArguments.IncludeModules = arguments.ModuleDependencies; - compileArguments.GenerateIncludeTree = true; compileArguments.ExportModule = false; compileArguments.PreprocessorDefinitions = arguments.PreprocessorDefinitions; compileArguments.GenerateSourceDebugInfo = arguments.GenerateSourceDebugInfo; @@ -180,7 +178,7 @@ namespace Soup::Compiler std::back_inserter(compileArguments.IncludeModules)); // Compile the individual translation units - auto buildOperations = std::vector(); + auto buildOperations = std::vector(); for (auto& file : arguments.SourceFiles) { buildState.LogInfo("Generate Compile Operation: " + file.ToString()); @@ -194,14 +192,14 @@ namespace Soup::Compiler } // Run the core compile next - Soup::Build::Extensions::BuildOperationExtensions::AddLeafChildren(result.BuildOperations, buildOperations); + Soup::Build::Utilities::BuildOperationExtensions::AddLeafChildren(result.BuildOperations, buildOperations); } /// /// Link the library /// void CoreLink( - Soup::Build::Extensions::BuildStateWrapper& buildState, + Soup::Build::Utilities::BuildStateWrapper& buildState, const BuildArguments& arguments, BuildResult& result) { @@ -238,6 +236,7 @@ namespace Soup::Compiler auto linkArguments = LinkArguments(); linkArguments.TargetFile = std::move(targetFile); + linkArguments.TargetArchitecture = arguments.TargetArchitecture; linkArguments.ImplementationFile = std::move(implementationFile); linkArguments.RootDirectory = arguments.WorkingDirectory; linkArguments.LibraryPaths = arguments.LibraryPaths; @@ -316,21 +315,21 @@ namespace Soup::Compiler auto linkOperation = _compiler->CreateLinkOperation(buildState, linkArguments); // Run the link operation - Soup::Build::Extensions::BuildOperationExtensions::AddLeafChild(result.BuildOperations, linkOperation); + Soup::Build::Utilities::BuildOperationExtensions::AddLeafChild(result.BuildOperations, linkOperation); } /// /// Copy runtime dependencies /// void CopyRuntimeDependencies( - Soup::Build::Extensions::BuildStateWrapper& buildState, + Soup::Build::Utilities::BuildStateWrapper& buildState, const BuildArguments& arguments, BuildResult& result) { if (arguments.TargetType == BuildTargetType::Executable || arguments.TargetType == BuildTargetType::DynamicLibrary) { - auto copyOperations = std::vector(); + auto copyOperations = std::vector(); for (auto source : arguments.RuntimeDependencies) { auto target = arguments.WorkingDirectory + arguments.BinaryDirectory + Path(source.GetFileName()); @@ -340,7 +339,7 @@ namespace Soup::Compiler if (!copyOperations.empty()) { - Soup::Build::Extensions::BuildOperationExtensions::AddLeafChildren(result.BuildOperations, copyOperations); + Soup::Build::Utilities::BuildOperationExtensions::AddLeafChildren(result.BuildOperations, copyOperations); } } } diff --git a/Source/Extensions/Compiler/Core/BuildResult.h b/Source/Extensions/Compiler/Core/BuildResult.h index 56f897a1..4067339e 100644 --- a/Source/Extensions/Compiler/Core/BuildResult.h +++ b/Source/Extensions/Compiler/Core/BuildResult.h @@ -14,7 +14,7 @@ namespace Soup::Compiler /// /// Gets or sets the resulting root build operations /// - std::vector BuildOperations; + std::vector BuildOperations; /// /// Gets or sets the list of module dependencies diff --git a/Source/Extensions/Compiler/Core/BuildUtilities.h b/Source/Extensions/Compiler/Core/BuildUtilities.h index 5e16c4be..3c9bafd2 100644 --- a/Source/Extensions/Compiler/Core/BuildUtilities.h +++ b/Source/Extensions/Compiler/Core/BuildUtilities.h @@ -15,16 +15,18 @@ namespace Soup::Compiler /// /// Create a build operation that will copy a file /// - static Soup::Build::Extensions::BuildOperationWrapper CreateCopyFileOperation( - Soup::Build::Extensions::BuildStateWrapper& state, + static Soup::Build::Utilities::BuildOperationWrapper CreateCopyFileOperation( + Soup::Build::Utilities::BuildStateWrapper& state, const Path& source, const Path& destination) { auto titleStream = std::stringstream(); titleStream << "Copy [" << source.ToString() << "] -> [" << destination.ToString() << "]"; - // TODO: Replace with platform specific implementation - auto program = Path("C:/Windows/System32/cmd.exe"); + auto moduleName = System::IProcessManager::Current().GetCurrentProcessFileName(); + auto moduleFolder = moduleName.GetParent(); + + auto program = moduleFolder + Path("copy.exe"); auto workingDirectory = Path(""); auto inputFiles = std::vector({ source, @@ -35,10 +37,10 @@ namespace Soup::Compiler // Build the arguments std::stringstream arguments; - arguments << "/C copy /Y \"" << source.ToAlternateString() << "\" \"" << destination.ToAlternateString() << "\""; + arguments << "\"" << source.ToAlternateString() << "\" \"" << destination.ToAlternateString() << "\""; - return Build::Extensions::BuildOperationWrapper( - new Build::Extensions::BuildOperation( + return Build::Utilities::BuildOperationWrapper( + new Build::Utilities::BuildOperation( titleStream.str(), program, arguments.str(), @@ -50,15 +52,17 @@ namespace Soup::Compiler /// /// Create a build operation that will create a directory /// - static Soup::Build::Extensions::BuildOperationWrapper CreateCreateDirectoryOperation( - Soup::Build::Extensions::BuildStateWrapper& state, + static Soup::Build::Utilities::BuildOperationWrapper CreateCreateDirectoryOperation( + Soup::Build::Utilities::BuildStateWrapper& state, const Path& directory) { auto titleStream = std::stringstream(); titleStream << "MakeDir [" << directory.ToString() << "]"; - // TODO: Replace with platform specific implementation - auto program = Path("C:/Windows/System32/cmd.exe"); + auto moduleName = System::IProcessManager::Current().GetCurrentProcessFileName(); + auto moduleFolder = moduleName.GetParent(); + + auto program = moduleFolder + Path("mkdir.exe"); auto workingDirectory = Path(""); auto inputFiles = std::vector({}); auto outputFiles = std::vector({ @@ -67,10 +71,10 @@ namespace Soup::Compiler // Build the arguments std::stringstream arguments; - arguments << "/C if not exist \"" << directory.ToString() << "\" mkdir \"" << directory.ToString() << "\""; + arguments << "\"" << directory.ToString() << "\""; - return Build::Extensions::BuildOperationWrapper( - new Build::Extensions::BuildOperation( + return Build::Utilities::BuildOperationWrapper( + new Build::Utilities::BuildOperation( titleStream.str(), program, arguments.str(), diff --git a/Source/Extensions/Compiler/Core/CompileArguments.h b/Source/Extensions/Compiler/Core/CompileArguments.h index e5d68061..f1e0363d 100644 --- a/Source/Extensions/Compiler/Core/CompileArguments.h +++ b/Source/Extensions/Compiler/Core/CompileArguments.h @@ -135,11 +135,6 @@ namespace Soup::Compiler /// bool ExportModule; - /// - /// Gets or sets a value indicating whether to generate the include set for each file - /// - bool GenerateIncludeTree; - /// /// Gets or sets a value indicating whether to generate source debug information /// @@ -159,7 +154,6 @@ namespace Soup::Compiler IncludeDirectories == rhs.IncludeDirectories && IncludeModules == rhs.IncludeModules && ExportModule == rhs.ExportModule && - GenerateIncludeTree == rhs.GenerateIncludeTree && GenerateSourceDebugInfo == rhs.GenerateSourceDebugInfo; } @@ -192,8 +186,7 @@ namespace Soup::Compiler stringBuilder << value.ToString() << ", "; stringBuilder << "], " << - std::to_string(ExportModule) << ", " << - std::to_string(GenerateIncludeTree) << "]"; + std::to_string(ExportModule) << "]"; return stringBuilder.str(); } diff --git a/Source/Extensions/Compiler/Core/ICompiler.h b/Source/Extensions/Compiler/Core/ICompiler.h index f78fb4e2..7073c609 100644 --- a/Source/Extensions/Compiler/Core/ICompiler.h +++ b/Source/Extensions/Compiler/Core/ICompiler.h @@ -45,15 +45,15 @@ namespace Soup::Compiler /// Compile /// // TODO: Should this state be replaced with a factory to limit access? - virtual Build::Extensions::BuildOperationWrapper CreateCompileOperation( - Build::Extensions::BuildStateWrapper& state, + virtual Build::Utilities::BuildOperationWrapper CreateCompileOperation( + Build::Utilities::BuildStateWrapper& state, const CompileArguments& args) const = 0; /// /// Link /// - virtual Build::Extensions::BuildOperationWrapper CreateLinkOperation( - Build::Extensions::BuildStateWrapper& state, + virtual Build::Utilities::BuildOperationWrapper CreateLinkOperation( + Build::Utilities::BuildStateWrapper& state, const LinkArguments& args) const = 0; }; } diff --git a/Source/Extensions/Compiler/Core/LinkArguments.h b/Source/Extensions/Compiler/Core/LinkArguments.h index 9efdf022..6e7c4ab1 100644 --- a/Source/Extensions/Compiler/Core/LinkArguments.h +++ b/Source/Extensions/Compiler/Core/LinkArguments.h @@ -66,6 +66,11 @@ namespace Soup::Compiler /// Path RootDirectory; + /// + /// Gets or sets the target architecture + /// + std::string TargetArchitecture; + /// /// Gets or sets the list of object files /// @@ -101,6 +106,7 @@ namespace Soup::Compiler ImplementationFile == rhs.ImplementationFile && RootDirectory == rhs.RootDirectory && ObjectFiles == rhs.ObjectFiles && + TargetArchitecture == rhs.TargetArchitecture && LibraryFiles == rhs.LibraryFiles && ExternalLibraryFiles == rhs.ExternalLibraryFiles && LibraryPaths == rhs.LibraryPaths && diff --git a/Source/Extensions/Compiler/Core/MockCompiler.h b/Source/Extensions/Compiler/Core/MockCompiler.h index e62b058c..593234a5 100644 --- a/Source/Extensions/Compiler/Core/MockCompiler.h +++ b/Source/Extensions/Compiler/Core/MockCompiler.h @@ -83,13 +83,13 @@ namespace Soup::Compiler::Mock /// /// Compile /// - Build::Extensions::BuildOperationWrapper CreateCompileOperation( - Build::Extensions::BuildStateWrapper& state, + Build::Utilities::BuildOperationWrapper CreateCompileOperation( + Build::Utilities::BuildStateWrapper& state, const CompileArguments& args) const override final { _compileRequests.push_back(args); - return Build::Extensions::BuildOperationWrapper( - new Build::Extensions::BuildOperation( + return Build::Utilities::BuildOperationWrapper( + new Build::Utilities::BuildOperation( "MockCompile: " + std::to_string(_compileRequests.size()), Path("MockCompiler.exe"), "Arguments", @@ -105,13 +105,13 @@ namespace Soup::Compiler::Mock /// /// Link /// - Build::Extensions::BuildOperationWrapper CreateLinkOperation( - Build::Extensions::BuildStateWrapper& state, + Build::Utilities::BuildOperationWrapper CreateLinkOperation( + Build::Utilities::BuildStateWrapper& state, const LinkArguments& args) const override final { _linkRequests.push_back(args); - return Build::Extensions::BuildOperationWrapper( - new Build::Extensions::BuildOperation( + return Build::Utilities::BuildOperationWrapper( + new Build::Utilities::BuildOperation( "MockLink: " + std::to_string(_linkRequests.size()), Path("MockLinker.exe"), "Arguments", diff --git a/Source/Extensions/Compiler/Core/Module.cpp b/Source/Extensions/Compiler/Core/Module.cpp index 3bb1b063..f0eede8c 100644 --- a/Source/Extensions/Compiler/Core/Module.cpp +++ b/Source/Extensions/Compiler/Core/Module.cpp @@ -10,7 +10,7 @@ export module SoupCompiler; import Opal; -import Soup.Build.Extensions; +import Soup.Build.Utilities; using namespace Opal; diff --git a/Source/Extensions/Compiler/Core/Recipe.toml b/Source/Extensions/Compiler/Core/Recipe.toml index 79737fbb..1ec633f6 100644 --- a/Source/Extensions/Compiler/Core/Recipe.toml +++ b/Source/Extensions/Compiler/Core/Recipe.toml @@ -1,10 +1,12 @@ Name = "SoupCompilerCore" Version = "0.1.0" Dependencies = [ + "../../../Tools/Copy/", + "../../../Tools/Mkdir/", "../../../../Dependencies/Opal/Source/", # "Opal@0.1.2", - "../../../Build/Extensions/", - # "Soup.Build.Extensions@0.3.0", + "../../../Build/Utilities/", + # "Soup.Build.Utilities@0.3.0", ] Public = "Module.cpp" diff --git a/Source/Extensions/Compiler/MSVC.UnitTests/CompilerArgumentBuilderTests.h b/Source/Extensions/Compiler/MSVC.UnitTests/CompilerArgumentBuilderTests.h index e4d91921..95a459fe 100644 --- a/Source/Extensions/Compiler/MSVC.UnitTests/CompilerArgumentBuilderTests.h +++ b/Source/Extensions/Compiler/MSVC.UnitTests/CompilerArgumentBuilderTests.h @@ -89,50 +89,6 @@ namespace Soup::Compiler::MSVC::UnitTests Assert::AreEqual(expectedOutput, actualOutput, "Verify generated output match expected."); } - [[Fact]] - void SingleArgument_GenerateIncludeTree() - { - CompileArguments arguments = {}; - arguments.SourceFile = Path("File.cpp"); - arguments.TargetFile = Path("File.obj"); - arguments.GenerateIncludeTree = true; - auto toolsPath = Path("tools/"); - - auto actualInput = std::vector(); - auto actualOutput = std::vector(); - auto actualArguments = ArgumentBuilder::BuildCompilerArguments( - arguments, - toolsPath, - actualInput, - actualOutput); - - auto expectedArguments = std::vector({ - "/nologo", - "/Zc:__cplusplus", - "/showIncludes", - "/std:c++11", - "/Od", - "/X", - "/RTC1", - "/EHsc", - "/MT", - "/bigobj", - "/c", - "File.cpp", - "/Fo\"File.obj\"", - }); - auto expectedInput = std::vector({ - Path("File.cpp"), - }); - auto expectedOutput = std::vector({ - Path("File.obj"), - }); - - Assert::AreEqual(expectedArguments, actualArguments, "Verify generated arguments match expected."); - Assert::AreEqual(expectedInput, actualInput, "Verify generated input match expected."); - Assert::AreEqual(expectedOutput, actualOutput, "Verify generated output match expected."); - } - [[Theory]] [[InlineData(Soup::Compiler::LanguageStandard::CPP11, "/std:c++11")]] [[InlineData(Soup::Compiler::LanguageStandard::CPP14, "/std:c++14")]] diff --git a/Source/Extensions/Compiler/MSVC.UnitTests/CompilerTests.h b/Source/Extensions/Compiler/MSVC.UnitTests/CompilerTests.h index 068a7a47..1d01b3a7 100644 --- a/Source/Extensions/Compiler/MSVC.UnitTests/CompilerTests.h +++ b/Source/Extensions/Compiler/MSVC.UnitTests/CompilerTests.h @@ -38,12 +38,12 @@ namespace Soup::Compiler::MSVC::UnitTests arguments.TargetFile = Path("obj/File.obj"); arguments.RootDirectory = Path("Source"); - auto buildState = Build::Runtime::BuildState(Build::Runtime::ValueTable()); - auto result = uut.CreateCompileOperation(Build::Extensions::BuildStateWrapper(buildState), arguments); + auto buildState = Build::Evaluate::BuildState(Build::Evaluate::ValueTable()); + auto result = uut.CreateCompileOperation(Build::Utilities::BuildStateWrapper(buildState), arguments); // Verify result - auto expected = Memory::Reference( - new Build::Extensions::BuildOperation( + auto expected = Memory::Reference( + new Build::Utilities::BuildOperation( "File.cpp", Path("bin/mock.cl.exe"), "/nologo /Zc:__cplusplus /std:c++11 /Od /X /RTC1 /EHsc /MT /bigobj /c File.cpp /Fo\"obj/File.obj\"", @@ -82,12 +82,12 @@ namespace Soup::Compiler::MSVC::UnitTests }); arguments.ExportModule = true; - auto buildState = Build::Runtime::BuildState(Build::Runtime::ValueTable()); - auto result = uut.CreateCompileOperation(Build::Extensions::BuildStateWrapper(buildState), arguments); + auto buildState = Build::Evaluate::BuildState(Build::Evaluate::ValueTable()); + auto result = uut.CreateCompileOperation(Build::Utilities::BuildStateWrapper(buildState), arguments); // Verify result - auto expected = Memory::Reference( - new Build::Extensions::BuildOperation( + auto expected = Memory::Reference( + new Build::Utilities::BuildOperation( "File.cpp", Path("bin/mock.cl.exe"), "/nologo /Zc:__cplusplus /std:c++11 /Od /I\"Includes\" /DDEBUG /X /RTC1 /EHsc /MT /module:reference \"Module.pcm\" /module:interface /module:output \"obj/File.ifc\" /bigobj /c File.cpp /Fo\"obj/File.obj\"", @@ -115,18 +115,19 @@ namespace Soup::Compiler::MSVC::UnitTests LinkArguments arguments = {}; arguments.TargetType = LinkTarget::StaticLibrary; + arguments.TargetArchitecture = "x64"; arguments.TargetFile = Path("Library.mock.a"); arguments.RootDirectory = Path("Source"); arguments.ObjectFiles = std::vector({ Path("File.mock.obj"), }); - auto buildState = Build::Runtime::BuildState(Build::Runtime::ValueTable()); - auto result = uut.CreateLinkOperation(Build::Extensions::BuildStateWrapper(buildState), arguments); + auto buildState = Build::Evaluate::BuildState(Build::Evaluate::ValueTable()); + auto result = uut.CreateLinkOperation(Build::Utilities::BuildStateWrapper(buildState), arguments); // Verify result - auto expected = Memory::Reference( - new Build::Extensions::BuildOperation( + auto expected = Memory::Reference( + new Build::Utilities::BuildOperation( "Library.mock.a", Path("bin/mock.lib.exe"), "/nologo /machine:X64 /out:\"Library.mock.a\" File.mock.obj", @@ -152,6 +153,7 @@ namespace Soup::Compiler::MSVC::UnitTests LinkArguments arguments = {}; arguments.TargetType = LinkTarget::Executable; + arguments.TargetArchitecture = "x64"; arguments.TargetFile = Path("Something.exe"); arguments.RootDirectory = Path("Source"); arguments.ObjectFiles = std::vector({ @@ -161,12 +163,12 @@ namespace Soup::Compiler::MSVC::UnitTests Path("Library.mock.a"), }); - auto buildState = Build::Runtime::BuildState(Build::Runtime::ValueTable()); - auto result = uut.CreateLinkOperation(Build::Extensions::BuildStateWrapper(buildState), arguments); + auto buildState = Build::Evaluate::BuildState(Build::Evaluate::ValueTable()); + auto result = uut.CreateLinkOperation(Build::Utilities::BuildStateWrapper(buildState), arguments); // Verify result - auto expected = Memory::Reference( - new Build::Extensions::BuildOperation( + auto expected = Memory::Reference( + new Build::Utilities::BuildOperation( "Something.exe", Path("bin/mock.link.exe"), "/nologo /subsystem:console /machine:X64 /out:\"Something.exe\" Library.mock.a File.mock.obj", diff --git a/Source/Extensions/Compiler/MSVC.UnitTests/LinkerArgumentBuilderTests.h b/Source/Extensions/Compiler/MSVC.UnitTests/LinkerArgumentBuilderTests.h index 58c62115..8e7a7cb0 100644 --- a/Source/Extensions/Compiler/MSVC.UnitTests/LinkerArgumentBuilderTests.h +++ b/Source/Extensions/Compiler/MSVC.UnitTests/LinkerArgumentBuilderTests.h @@ -14,6 +14,7 @@ namespace Soup::Compiler::MSVC::UnitTests { LinkArguments arguments = {}; arguments.TargetType = LinkTarget::StaticLibrary; + arguments.TargetArchitecture = "x64"; arguments.TargetFile = Path("Library.mock.lib"); arguments.ObjectFiles = std::vector({}); @@ -58,6 +59,7 @@ namespace Soup::Compiler::MSVC::UnitTests { LinkArguments arguments = {}; arguments.TargetType = LinkTarget::StaticLibrary; + arguments.TargetArchitecture = "x64"; arguments.TargetFile = Path("Library.mock.lib"); arguments.ObjectFiles = std::vector({ Path("File.mock.o"), @@ -90,6 +92,7 @@ namespace Soup::Compiler::MSVC::UnitTests { LinkArguments arguments = {}; arguments.TargetType = LinkTarget::StaticLibrary; + arguments.TargetArchitecture = "x64"; arguments.TargetFile = Path("Library.mock.lib"); arguments.ObjectFiles = std::vector({ Path("File.mock.o"), @@ -126,6 +129,7 @@ namespace Soup::Compiler::MSVC::UnitTests { LinkArguments arguments = {}; arguments.TargetType = LinkTarget::DynamicLibrary; + arguments.TargetArchitecture = "x64"; arguments.TargetFile = Path("Library.mock.dll"); arguments.ImplementationFile = Path("Library.mock.lib"); arguments.ObjectFiles = std::vector({ @@ -163,6 +167,7 @@ namespace Soup::Compiler::MSVC::UnitTests { LinkArguments arguments = {}; arguments.TargetType = LinkTarget::Executable; + arguments.TargetArchitecture = "x64"; arguments.TargetFile = Path("out/Something.exe"); arguments.ObjectFiles = std::vector({ Path("File.mock.obj"), diff --git a/Source/Extensions/Compiler/MSVC.UnitTests/Recipe.toml b/Source/Extensions/Compiler/MSVC.UnitTests/Recipe.toml index 4e20f976..eaefcfc5 100644 --- a/Source/Extensions/Compiler/MSVC.UnitTests/Recipe.toml +++ b/Source/Extensions/Compiler/MSVC.UnitTests/Recipe.toml @@ -5,7 +5,7 @@ Dependencies = [ # "../../../Dependencies/SoupTest/Assert/", "../MSVC/", "../../../TestUtilities/", - "../../../Build/Runtime/", + "../../../Build/Evaluate/", "SoupTest@0.1.0", ] Source = [ diff --git a/Source/Extensions/Compiler/MSVC.UnitTests/gen/CompilerArgumentBuilderTests.gen.h b/Source/Extensions/Compiler/MSVC.UnitTests/gen/CompilerArgumentBuilderTests.gen.h index 46e4570b..34515839 100644 --- a/Source/Extensions/Compiler/MSVC.UnitTests/gen/CompilerArgumentBuilderTests.gen.h +++ b/Source/Extensions/Compiler/MSVC.UnitTests/gen/CompilerArgumentBuilderTests.gen.h @@ -9,7 +9,6 @@ TestState RunCompilerArgumentBuilderTests() state += SoupTest::RunTest(className, "EmptySourceFile_Throws", [&testClass]() { testClass->EmptySourceFile_Throws(); }); state += SoupTest::RunTest(className, "EmptyTargetFile_Throws", [&testClass]() { testClass->EmptyTargetFile_Throws(); }); state += SoupTest::RunTest(className, "DefaultParameters", [&testClass]() { testClass->DefaultParameters(); }); - state += SoupTest::RunTest(className, "SingleArgument_GenerateIncludeTree", [&testClass]() { testClass->SingleArgument_GenerateIncludeTree(); }); state += SoupTest::RunTest(className, "SingleArgument_LanguageStandard(Soup::LanguageStandard::CPP11, \"/std:c++11\")", [&testClass]() { testClass->SingleArgument_LanguageStandard(Soup::Compiler::LanguageStandard::CPP11, "/std:c++11"); }); state += SoupTest::RunTest(className, "SingleArgument_LanguageStandard(Soup::LanguageStandard::CPP14, \"/std:c++14\")", [&testClass]() { testClass->SingleArgument_LanguageStandard(Soup::Compiler::LanguageStandard::CPP14, "/std:c++14"); }); state += SoupTest::RunTest(className, "SingleArgument_LanguageStandard(Soup::LanguageStandard::CPP17, \"/std:c++17\")", [&testClass]() { testClass->SingleArgument_LanguageStandard(Soup::Compiler::LanguageStandard::CPP17, "/std:c++17"); }); diff --git a/Source/Extensions/Compiler/MSVC.UnitTests/gen/Main.cpp b/Source/Extensions/Compiler/MSVC.UnitTests/gen/Main.cpp index 9b30f3de..043e4e84 100644 --- a/Source/Extensions/Compiler/MSVC.UnitTests/gen/Main.cpp +++ b/Source/Extensions/Compiler/MSVC.UnitTests/gen/Main.cpp @@ -9,8 +9,8 @@ import Opal; import SoupCompiler; import SoupCompilerMSVC; import Soup.Build; -import Soup.Build.Extensions; -import Soup.Build.Runtime; +import Soup.Build.Utilities; +import Soup.Build.Evaluate; import SoupTest; import SoupTestUtilities; @@ -35,5 +35,8 @@ int main() std::cout << state.PassCount << " PASSED." << std::endl; std::cout << state.FailCount << " FAILED." << std::endl; - return 0; + if (state.FailCount > 0) + return 1; + else + return 0; } diff --git a/Source/Extensions/Compiler/MSVC/ArgumentBuilder.h b/Source/Extensions/Compiler/MSVC/ArgumentBuilder.h index 841fa226..a629c22a 100644 --- a/Source/Extensions/Compiler/MSVC/ArgumentBuilder.h +++ b/Source/Extensions/Compiler/MSVC/ArgumentBuilder.h @@ -17,7 +17,6 @@ namespace Soup::Compiler::MSVC static constexpr std::string_view Compiler_ArgumentFlag_GenerateDebugInformation = "Z7"; static constexpr std::string_view Compiler_ArgumentFlag_GenerateDebugInformationExternal = "Zi"; - static constexpr std::string_view Compiler_ArgumentFlag_ShowIncludes = "showIncludes"; static constexpr std::string_view Compiler_ArgumentFlag_CompileOnly = "c"; static constexpr std::string_view Compiler_ArgumentFlag_IgnoreStandardIncludePaths = "X"; static constexpr std::string_view Compiler_ArgumentFlag_Optimization_Disable = "Od"; @@ -44,6 +43,7 @@ namespace Soup::Compiler::MSVC static constexpr std::string_view Linker_ArgumentParameter_Machine = "machine"; static constexpr std::string_view Linker_ArgumentParameter_DefaultLibrary = "defaultlib"; static constexpr std::string_view Linker_ArgumentValue_X64 = "X64"; + static constexpr std::string_view Linker_ArgumentValue_X86 = "X86"; public: static std::vector BuildCompilerArguments( @@ -67,12 +67,6 @@ namespace Soup::Compiler::MSVC // Get better support for _cplusplus macro version AddParameter(commandArgs, "Zc", "__cplusplus"); - // Enable Header includes if needed - if (args.GenerateIncludeTree) - { - AddFlag(commandArgs, Compiler_ArgumentFlag_ShowIncludes); - } - // Generate source debug information if (args.GenerateSourceDebugInfo) { @@ -258,7 +252,12 @@ namespace Soup::Compiler::MSVC } // Add the machine target - AddParameter(commandArgs, Linker_ArgumentParameter_Machine, Linker_ArgumentValue_X64); + if (args.TargetArchitecture == "x64") + AddParameter(commandArgs, Linker_ArgumentParameter_Machine, Linker_ArgumentValue_X64); + else if (args.TargetArchitecture == "x86") + AddParameter(commandArgs, Linker_ArgumentParameter_Machine, Linker_ArgumentValue_X86); + else + throw std::runtime_error("Unknown target architecture."); // Set the library paths for (auto directory : args.LibraryPaths) diff --git a/Source/Extensions/Compiler/MSVC/Compiler.h b/Source/Extensions/Compiler/MSVC/Compiler.h index ab062191..93a3cd19 100644 --- a/Source/Extensions/Compiler/MSVC/Compiler.h +++ b/Source/Extensions/Compiler/MSVC/Compiler.h @@ -66,8 +66,8 @@ namespace Soup::Compiler::MSVC /// /// Compile /// - Build::Extensions::BuildOperationWrapper CreateCompileOperation( - Build::Extensions::BuildStateWrapper& state, + Build::Utilities::BuildOperationWrapper CreateCompileOperation( + Build::Utilities::BuildStateWrapper& state, const CompileArguments& args) const override final { // Clang decided to do their module compilation in two stages @@ -85,8 +85,8 @@ namespace Soup::Compiler::MSVC /// /// Link /// - Build::Extensions::BuildOperationWrapper CreateLinkOperation( - Build::Extensions::BuildStateWrapper& state, + Build::Utilities::BuildOperationWrapper CreateLinkOperation( + Build::Utilities::BuildStateWrapper& state, const LinkArguments& args) const override final { // Select the correct executable for linking libraries or executables @@ -109,8 +109,8 @@ namespace Soup::Compiler::MSVC auto outputFiles = std::vector(); auto commandArgs = ArgumentBuilder::BuildLinkerArguments(args, inputFiles, outputFiles); - auto buildOperation = Build::Extensions::BuildOperationWrapper( - new Build::Extensions::BuildOperation( + auto buildOperation = Build::Utilities::BuildOperationWrapper( + new Build::Utilities::BuildOperation( args.TargetFile.ToString(), executablePath, CombineArguments(commandArgs), @@ -122,8 +122,8 @@ namespace Soup::Compiler::MSVC } private: - Build::Extensions::BuildOperationWrapper CompileStandard( - Build::Extensions::BuildStateWrapper& state, + Build::Utilities::BuildOperationWrapper CompileStandard( + Build::Utilities::BuildStateWrapper& state, const CompileArguments& args) const { auto executablePath = _toolsPath + _compilerExecutable; @@ -137,8 +137,8 @@ namespace Soup::Compiler::MSVC inputFiles, outputFiles); - auto buildOperation = Build::Extensions::BuildOperationWrapper( - new Build::Extensions::BuildOperation( + auto buildOperation = Build::Utilities::BuildOperationWrapper( + new Build::Utilities::BuildOperation( args.SourceFile.ToString(), executablePath, CombineArguments(commandArgs), @@ -149,8 +149,8 @@ namespace Soup::Compiler::MSVC return buildOperation; } - Build::Extensions::BuildOperationWrapper CompileModuleInterfaceUnit( - Build::Extensions::BuildStateWrapper& state, + Build::Utilities::BuildOperationWrapper CompileModuleInterfaceUnit( + Build::Utilities::BuildStateWrapper& state, const CompileArguments& args) const { auto executablePath = _toolsPath + _compilerExecutable; @@ -164,7 +164,6 @@ namespace Soup::Compiler::MSVC compiledModuleArgs.IncludeModules = args.IncludeModules; compiledModuleArgs.ExportModule = true; compiledModuleArgs.PreprocessorDefinitions = args.PreprocessorDefinitions; - compiledModuleArgs.GenerateIncludeTree = args.GenerateIncludeTree; compiledModuleArgs.GenerateSourceDebugInfo = args.GenerateSourceDebugInfo; // Use the target file as input to the build and generate an object with the same name @@ -180,8 +179,8 @@ namespace Soup::Compiler::MSVC inputFiles, outputFiles); - auto buildOperation = Build::Extensions::BuildOperationWrapper( - new Build::Extensions::BuildOperation( + auto buildOperation = Build::Utilities::BuildOperationWrapper( + new Build::Utilities::BuildOperation( args.SourceFile.ToString(), executablePath, CombineArguments(compiledModuleCommandArgs), diff --git a/Source/Extensions/RecipeBuild.UnitTests/Tasks/BuildTaskTests.h b/Source/Extensions/RecipeBuild.UnitTests/Tasks/BuildTaskTests.h index 793043dd..5afbb7a4 100644 --- a/Source/Extensions/RecipeBuild.UnitTests/Tasks/BuildTaskTests.h +++ b/Source/Extensions/RecipeBuild.UnitTests/Tasks/BuildTaskTests.h @@ -89,7 +89,6 @@ namespace RecipeBuild::UnitTests expectedCompileArguments.RootDirectory = Path("C:/root/"); expectedCompileArguments.SourceFile = Path("TestFile.cpp"); expectedCompileArguments.TargetFile = Path("obj/TestFile.mock.obj"); - expectedCompileArguments.GenerateIncludeTree = true; auto expectedLinkArguments = Soup::LinkArguments(); expectedLinkArguments.TargetType = Soup::LinkTarget::Executable; @@ -243,7 +242,6 @@ namespace RecipeBuild::UnitTests expectedCompileArguments.RootDirectory = Path("C:/root/"); expectedCompileArguments.SourceFile = Path("TestFile.cpp"); expectedCompileArguments.TargetFile = Path("obj/TestFile.mock.obj"); - expectedCompileArguments.GenerateIncludeTree = true; auto expectedLinkArguments = Soup::LinkArguments(); expectedLinkArguments.TargetType = Soup::LinkTarget::Executable; @@ -397,7 +395,6 @@ namespace RecipeBuild::UnitTests expectedCompileArguments.RootDirectory = Path("C:/root/"); expectedCompileArguments.SourceFile = Path("TestFile.cpp"); expectedCompileArguments.TargetFile = Path("obj/TestFile.mock.obj"); - expectedCompileArguments.GenerateIncludeTree = true; auto expectedLinkArguments = Soup::LinkArguments(); expectedLinkArguments.TargetType = Soup::LinkTarget::Executable; @@ -579,7 +576,6 @@ namespace RecipeBuild::UnitTests Path("../Other/bin/OtherModule1.mock.bmi"), Path("../OtherModule2.mock.bmi"), }); - expectedCompileArguments.GenerateIncludeTree = true; auto expectedCompile1Arguments = expectedCompileArguments; expectedCompile1Arguments.SourceFile = Path("TestFile1.cpp"); @@ -812,7 +808,6 @@ namespace RecipeBuild::UnitTests Path("../Other/bin/OtherModule1.mock.bmi"), Path("../OtherModule2.mock.bmi"), }); - expectedCompileArguments.GenerateIncludeTree = true; expectedCompileArguments.PreprocessorDefinitions = std::vector({ "DEBUG", "AWESOME", @@ -1079,7 +1074,6 @@ namespace RecipeBuild::UnitTests Path("../Other/bin/OtherModule1.mock.bmi"), Path("../OtherModule2.mock.bmi"), }); - expectedCompileArguments.GenerateIncludeTree = true; auto expectedCompileModuleArguments = expectedCompileArguments; expectedCompileModuleArguments.SourceFile = Path("Public.cpp"); diff --git a/Source/Extensions/RecipeBuild.UnitTests/Tasks/StandardLibraryIncludeTaskTests.h b/Source/Extensions/RecipeBuild.UnitTests/Tasks/StandardLibraryIncludeTaskTests.h index 3f2fb282..c742e1c5 100644 --- a/Source/Extensions/RecipeBuild.UnitTests/Tasks/StandardLibraryIncludeTaskTests.h +++ b/Source/Extensions/RecipeBuild.UnitTests/Tasks/StandardLibraryIncludeTaskTests.h @@ -49,7 +49,7 @@ namespace RecipeBuild::UnitTests // Verify build state auto expectedBuildOperations = std::vector>(); - Soup::AssertExtensions::AreEqual( + Soup::AssertUtilities::AreEqual( expectedBuildOperations, buildState.GetBuildOperations()); diff --git a/Source/Extensions/RecipeBuild.UnitTests/gen/Main.cpp b/Source/Extensions/RecipeBuild.UnitTests/gen/Main.cpp index 626aade4..27b0cbfc 100644 --- a/Source/Extensions/RecipeBuild.UnitTests/gen/Main.cpp +++ b/Source/Extensions/RecipeBuild.UnitTests/gen/Main.cpp @@ -38,5 +38,8 @@ int main() std::cout << state.PassCount << " PASSED." << std::endl; std::cout << state.FailCount << " FAILED." << std::endl; - return 0; + if (state.FailCount > 0) + return 1; + else + return 0; } diff --git a/Source/Extensions/RecipeBuild/Module.cpp b/Source/Extensions/RecipeBuild/Module.cpp index 96149d67..ac4114c6 100644 --- a/Source/Extensions/RecipeBuild/Module.cpp +++ b/Source/Extensions/RecipeBuild/Module.cpp @@ -23,8 +23,8 @@ export module RecipeBuild; import Opal; import Soup.Build; -import Soup.Build.Extensions; -import Soup.Build.Runtime; +import Soup.Build.Utilities; +import Soup.Build.Evaluate; import SoupCompiler; import SoupCompilerClang; import SoupCompilerMSVC; diff --git a/Source/Extensions/RecipeBuild/Recipe.toml b/Source/Extensions/RecipeBuild/Recipe.toml index a28dc5ec..0e5b9447 100644 --- a/Source/Extensions/RecipeBuild/Recipe.toml +++ b/Source/Extensions/RecipeBuild/Recipe.toml @@ -4,7 +4,7 @@ Version = "1.0.0" Dependencies = [ "../../../Dependencies/Opal/Source/", # "Opal@0.1.2", - "../../Build/Runtime/", + "../../Build/Evaluate/", "../Compiler/Core/", "../Compiler/Clang/", "../Compiler/MSVC/", diff --git a/Source/Extensions/RecipeBuild/RegisterBuildExtension.cpp b/Source/Extensions/RecipeBuild/RegisterBuildExtension.cpp index 82bbdb01..08776217 100644 --- a/Source/Extensions/RecipeBuild/RegisterBuildExtension.cpp +++ b/Source/Extensions/RecipeBuild/RegisterBuildExtension.cpp @@ -25,11 +25,11 @@ module RecipeBuild; using namespace Opal; -std::shared_ptr CreateMSVCCompiler(Soup::Build::Extensions::ValueTableWrapper& activeState) +std::shared_ptr CreateMSVCCompiler(Soup::Build::Utilities::ValueTableWrapper& activeState) { - auto visualCompilerToolsRoot = activeState.GetValue("MSVC.VCToolsRoot").AsString().GetValue(); + auto visualCompilerToolsRoot = activeState.GetValue("MSVC.VCToolsBinaryRoot").AsString().GetValue(); std::shared_ptr compiler = std::make_shared( - Path(visualCompilerToolsRoot) + Path("bin/Hostx64/x64/"), + Path(visualCompilerToolsRoot), Path("cl.exe"), Path("link.exe"), Path("lib.exe")); diff --git a/Source/Extensions/RecipeBuild/Tasks/BuildTask.h b/Source/Extensions/RecipeBuild/Tasks/BuildTask.h index 2bfafd93..9fda7f1f 100644 --- a/Source/Extensions/RecipeBuild/Tasks/BuildTask.h +++ b/Source/Extensions/RecipeBuild/Tasks/BuildTask.h @@ -6,7 +6,7 @@ namespace RecipeBuild { - export using CreateCompiler = std::function(Soup::Build::Extensions::ValueTableWrapper&)>; + export using CreateCompiler = std::function(Soup::Build::Utilities::ValueTableWrapper&)>; export using CompilerFactory = std::map; /// @@ -50,7 +50,7 @@ namespace RecipeBuild Soup::Build::ApiCallResult TryExecute( Soup::Build::IBuildState& buildState) noexcept override final { - auto buildStateWrapper = Soup::Build::Extensions::BuildStateWrapper(buildState); + auto buildStateWrapper = Soup::Build::Utilities::BuildStateWrapper(buildState); try { @@ -73,7 +73,7 @@ namespace RecipeBuild /// The Core build task /// Soup::Build::ApiCallResult Execute( - Soup::Build::Extensions::BuildStateWrapper& buildState) + Soup::Build::Utilities::BuildStateWrapper& buildState) { auto activeState = buildState.GetActiveState(); auto sharedState = buildState.GetSharedState(); @@ -81,6 +81,7 @@ namespace RecipeBuild auto buildTable = activeState.GetValue("Build").AsTable(); auto arguments = Soup::Compiler::BuildArguments(); + arguments.TargetArchitecture = activeState.GetValue("BuildArchitecture").AsString().GetValue(); arguments.TargetName = buildTable.GetValue("TargetName").AsString().GetValue(); arguments.TargetType = static_cast( buildTable.GetValue("TargetType").AsInteger().GetValue()); @@ -216,7 +217,7 @@ namespace RecipeBuild private: CompilerFactory _compilerFactory; - Soup::Build::Extensions::StringList _runBeforeList; - Soup::Build::Extensions::StringList _runAfterList; + Soup::Build::Utilities::StringList _runBeforeList; + Soup::Build::Utilities::StringList _runAfterList; }; } diff --git a/Source/Extensions/RecipeBuild/Tasks/RecipeBuildTask.h b/Source/Extensions/RecipeBuild/Tasks/RecipeBuildTask.h index 943eb3f2..9f80a841 100644 --- a/Source/Extensions/RecipeBuild/Tasks/RecipeBuildTask.h +++ b/Source/Extensions/RecipeBuild/Tasks/RecipeBuildTask.h @@ -48,7 +48,7 @@ namespace RecipeBuild Soup::Build::ApiCallResult TryExecute( Soup::Build::IBuildState& buildState) noexcept override final { - auto buildStateWrapper = Soup::Build::Extensions::BuildStateWrapper(buildState); + auto buildStateWrapper = Soup::Build::Utilities::BuildStateWrapper(buildState); try { @@ -71,7 +71,7 @@ namespace RecipeBuild /// /// Internal implementation that can throw /// - void Execute(Soup::Build::Extensions::BuildStateWrapper& buildState) + void Execute(Soup::Build::Utilities::BuildStateWrapper& buildState) { auto rootTable = buildState.GetActiveState(); auto recipeTable = rootTable.GetValue("Recipe").AsTable(); @@ -93,7 +93,18 @@ namespace RecipeBuild std::vector linkLibraries = std::vector(); if (recipeTable.HasValue("LinkLibraries")) { - linkLibraries = recipeTable.GetValue("LinkLibraries").AsList().CopyAsPathVector(); + for (auto value : recipeTable.GetValue("LinkLibraries").AsList().CopyAsPathVector()) + { + // If relative then resolve to working directory + if (value.HasRoot()) + { + linkLibraries.push_back(std::move(value)); + } + else + { + linkLibraries.push_back(packageRoot + value); + } + } } // Add the dependency runtime dependencies closure if present @@ -105,11 +116,18 @@ namespace RecipeBuild runtimeDependencies = buildTable.GetValue("RuntimeDependencies").AsList().CopyAsPathVector(); } - auto recipeRuntimeDependencies = recipeTable.GetValue("RuntimeDependencies").AsList().CopyAsPathVector(); - std::copy( - recipeRuntimeDependencies.begin(), - recipeRuntimeDependencies.end(), - std::back_inserter(runtimeDependencies)); + for (auto value : recipeTable.GetValue("RuntimeDependencies").AsList().CopyAsPathVector()) + { + // If relative then resolve to working directory + if (value.HasRoot()) + { + runtimeDependencies.push_back(std::move(value)); + } + else + { + runtimeDependencies.push_back(packageRoot + value); + } + } buildTable.EnsureValue("RuntimeDependencies").SetValuePathList(runtimeDependencies); } @@ -210,21 +228,21 @@ namespace RecipeBuild // Convert the recipe type to the required build type Soup::Compiler::BuildTargetType targetType; - auto recipeType = Soup::Build::Extensions::RecipeType::StaticLibrary; + auto recipeType = Soup::Build::Utilities::RecipeType::StaticLibrary; if (recipeTable.HasValue("Type")) { - recipeType = Soup::Build::Extensions::ParseRecipeType(recipeTable.GetValue("Type").AsString().GetValue()); + recipeType = Soup::Build::Utilities::ParseRecipeType(recipeTable.GetValue("Type").AsString().GetValue()); } switch (recipeType) { - case Soup::Build::Extensions::RecipeType::StaticLibrary: + case Soup::Build::Utilities::RecipeType::StaticLibrary: targetType = Soup::Compiler::BuildTargetType::StaticLibrary; break; - case Soup::Build::Extensions::RecipeType::DynamicLibrary: + case Soup::Build::Utilities::RecipeType::DynamicLibrary: targetType = Soup::Compiler::BuildTargetType::DynamicLibrary; break; - case Soup::Build::Extensions::RecipeType::Executable: + case Soup::Build::Utilities::RecipeType::Executable: targetType = Soup::Compiler::BuildTargetType::Executable; break; default: @@ -234,26 +252,26 @@ namespace RecipeBuild buildTable.EnsureValue("TargetType").SetValueInteger(static_cast(targetType)); // Convert the recipe language version to the required build language - auto recipeLanguageVersion = Soup::Build::Extensions::RecipeLanguageVersion::CPP20; + auto recipeLanguageVersion = Soup::Build::Utilities::RecipeLanguageVersion::CPP20; if (recipeTable.HasValue("Language")) { - recipeLanguageVersion = Soup::Build::Extensions::ParseRecipeLanguageVersion( + recipeLanguageVersion = Soup::Build::Utilities::ParseRecipeLanguageVersion( recipeTable.GetValue("Language").AsString().GetValue()); } Soup::Compiler::LanguageStandard languageStandard; switch (recipeLanguageVersion) { - case Soup::Build::Extensions::RecipeLanguageVersion::CPP11: + case Soup::Build::Utilities::RecipeLanguageVersion::CPP11: languageStandard = Soup::Compiler::LanguageStandard::CPP11; break; - case Soup::Build::Extensions::RecipeLanguageVersion::CPP14: + case Soup::Build::Utilities::RecipeLanguageVersion::CPP14: languageStandard = Soup::Compiler::LanguageStandard::CPP14; break; - case Soup::Build::Extensions::RecipeLanguageVersion::CPP17: + case Soup::Build::Utilities::RecipeLanguageVersion::CPP17: languageStandard = Soup::Compiler::LanguageStandard::CPP17; break; - case Soup::Build::Extensions::RecipeLanguageVersion::CPP20: + case Soup::Build::Utilities::RecipeLanguageVersion::CPP20: languageStandard = Soup::Compiler::LanguageStandard::CPP20; break; default: @@ -264,7 +282,7 @@ namespace RecipeBuild } private: - Soup::Build::Extensions::StringList _runBeforeList; - Soup::Build::Extensions::StringList _runAfterList; + Soup::Build::Utilities::StringList _runBeforeList; + Soup::Build::Utilities::StringList _runAfterList; }; } diff --git a/Source/Extensions/RecipeBuild/Tasks/ResolveDependenciesTask.h b/Source/Extensions/RecipeBuild/Tasks/ResolveDependenciesTask.h index 1fa6b822..54cf0ff6 100644 --- a/Source/Extensions/RecipeBuild/Tasks/ResolveDependenciesTask.h +++ b/Source/Extensions/RecipeBuild/Tasks/ResolveDependenciesTask.h @@ -7,7 +7,8 @@ namespace RecipeBuild { /// - /// The resolve dependencies build task that knows how to combine all previous state into the active state. + /// The resolve dependencies build task that knows how to combine all previous state + /// into the active state. /// export class ResolveDependenciesTask : public Memory::ReferenceCounted { @@ -48,7 +49,7 @@ namespace RecipeBuild Soup::Build::ApiCallResult TryExecute( Soup::Build::IBuildState& buildState) noexcept override final { - auto buildStateWrapper = Soup::Build::Extensions::BuildStateWrapper(buildState); + auto buildStateWrapper = Soup::Build::Utilities::BuildStateWrapper(buildState); try { @@ -71,7 +72,7 @@ namespace RecipeBuild /// /// The Core Execute task /// - void Execute(Soup::Build::Extensions::BuildStateWrapper& buildState) + void Execute(Soup::Build::Utilities::BuildStateWrapper& buildState) { auto activeState = buildState.GetActiveState(); @@ -122,7 +123,7 @@ namespace RecipeBuild } private: - Soup::Build::Extensions::StringList _runBeforeList; - Soup::Build::Extensions::StringList _runAfterList; + Soup::Build::Utilities::StringList _runBeforeList; + Soup::Build::Utilities::StringList _runAfterList; }; } diff --git a/Source/Extensions/RecipeBuild/Tasks/ResolveToolsTask.h b/Source/Extensions/RecipeBuild/Tasks/ResolveToolsTask.h index 1c1307d6..20248c8a 100644 --- a/Source/Extensions/RecipeBuild/Tasks/ResolveToolsTask.h +++ b/Source/Extensions/RecipeBuild/Tasks/ResolveToolsTask.h @@ -42,7 +42,7 @@ namespace RecipeBuild Soup::Build::ApiCallResult TryExecute( Soup::Build::IBuildState& buildState) noexcept override final { - auto buildStateWrapper = Soup::Build::Extensions::BuildStateWrapper(buildState); + auto buildStateWrapper = Soup::Build::Utilities::BuildStateWrapper(buildState); try { @@ -65,10 +65,16 @@ namespace RecipeBuild /// /// The Core Execute task /// - void Execute(Soup::Build::Extensions::BuildStateWrapper& buildState) + void Execute(Soup::Build::Utilities::BuildStateWrapper& buildState) { auto state = buildState.GetActiveState(); + auto systemName = std::string(state.GetValue("BuildSystem").AsString().GetValue()); + auto architectureName = std::string(state.GetValue("BuildArchitecture").AsString().GetValue()); + + if (systemName != "win32") + throw std::runtime_error("Win32 is the only supported system... so far."); + // Find the location of the Windows SDK auto visualStudioInstallRoot = FindVSInstallRoot(buildState); buildState.LogInfo("Using VS Installation: " + visualStudioInstallRoot.ToString()); @@ -81,17 +87,27 @@ namespace RecipeBuild auto visualCompilerVersionFolder = visualStudioInstallRoot + Path("/VC/Tools/MSVC/") + Path(visualCompilerVersion); + // Sey the VC tools binary folder + Path vcToolsBinaryFolder; + if (architectureName == "x64") + vcToolsBinaryFolder = visualCompilerVersionFolder + Path("/bin/Hostx64/x64/"); + else if (architectureName == "x86") + vcToolsBinaryFolder = visualCompilerVersionFolder + Path("/bin/Hostx64/x86/"); + else + throw std::runtime_error("Unknown architecture."); + // Save the build properties state.EnsureValue("MSVS.InstallRoot").SetValueString(visualStudioInstallRoot.ToString()); state.EnsureValue("MSVC.Version").SetValueString(visualCompilerVersion); state.EnsureValue("MSVC.VCToolsRoot").SetValueString(visualCompilerVersionFolder.ToString()); + state.EnsureValue("MSVC.VCToolsBinaryRoot").SetValueString(vcToolsBinaryFolder.ToString()); // Calculate the windows kits directory auto windows10KitPath = Path("C:/Program Files (x86)/Windows Kits/10/"); auto windows10KitIncludePath = windows10KitPath + Path("/include/"); auto windows10KitLibPath = windows10KitPath + Path("/Lib/"); - auto windowsKitVersion = FindNewestWindows10KitVersion(buildState, windows10KitIncludePath); + auto windowsKitVersion = FindNewestWindows10KitVersion(windows10KitIncludePath); buildState.LogInfo("Using Windows Kit Version: " + windowsKitVersion); auto windows10KitVersionIncludePath = windows10KitIncludePath + Path(windowsKitVersion); @@ -106,24 +122,81 @@ namespace RecipeBuild }); // Set the include paths - auto platformLibraryPaths = std::vector({ - windows10KitVersionLibPath + Path("/ucrt/x64/"), - windows10KitVersionLibPath + Path("/um/x64/"), - visualCompilerVersionFolder + Path("/atlmfc/lib/x64/"), - visualCompilerVersionFolder + Path("/lib/x64/"), + auto platformLibraryPaths = std::vector(); + if (architectureName == "x64") + { + platformLibraryPaths.push_back(windows10KitVersionLibPath + Path("/ucrt/x64/")); + platformLibraryPaths.push_back(windows10KitVersionLibPath + Path("/um/x64/")); + platformLibraryPaths.push_back(visualCompilerVersionFolder + Path("/atlmfc/lib/x64/")); + platformLibraryPaths.push_back(visualCompilerVersionFolder + Path("/lib/x64/")); + } + else if (architectureName == "x86") + { + platformLibraryPaths.push_back(windows10KitVersionLibPath + Path("/ucrt/x86/")); + platformLibraryPaths.push_back(windows10KitVersionLibPath + Path("/um/x86/")); + platformLibraryPaths.push_back(visualCompilerVersionFolder + Path("/atlmfc/lib/x86/")); + platformLibraryPaths.push_back(visualCompilerVersionFolder + Path("/lib/x86/")); + } + + // Set the platform definitions + auto platformPreprocessorDefinitions = std::vector({ + // "_DLL", // Link against the dynamic runtime dll + // "_MT", // Use multithreaded runtime }); + if (architectureName == "x86") + platformPreprocessorDefinitions.push_back("WIN32"); + + // Set the platform libraries + auto platformLibraries = std::vector({ + // Path("kernel32.lib"), + Path("user32.lib"), + // Path("gdi32.lib"), + // Path("winspool.lib"), + // Path("comdlg32.lib"), + Path("advapi32.lib"), + Path("shell32.lib"), + // Path("ole32.lib"), + Path("oleaut32.lib"), + // Path("uuid.lib"), + // Path("odbc32.lib"), + // Path("odbccp32.lib"), + Path("crypt32.lib"), + }); + + // if (_options.Configuration == "debug") + // { + // // arguments.PlatformPreprocessorDefinitions.push_back("_DEBUG"); + // arguments.PlatformLibraries = std::vector({ + // Path("msvcprtd.lib"), + // Path("msvcrtd.lib"), + // Path("ucrtd.lib"), + // Path("vcruntimed.lib"), + // }); + // } + // else + // { + // arguments.PlatformLibraries = std::vector({ + // Path("msvcprt.lib"), + // Path("msvcrt.lib"), + // Path("ucrt.lib"), + // Path("vcruntime.lib"), + // }); + // } + state.EnsureValue("PlatformIncludePaths").SetValuePathList(platformIncludePaths); state.EnsureValue("PlatformLibraryPaths").SetValuePathList(platformLibraryPaths); + state.EnsureValue("PlatformLibraries").SetValuePathList(platformLibraries); + state.EnsureValue("PlatformPreprocessorDefinitions").SetValueStringList(platformPreprocessorDefinitions); } private: - Path FindVSInstallRoot(Soup::Build::Extensions::BuildStateWrapper& buildState) + Path FindVSInstallRoot(Soup::Build::Utilities::BuildStateWrapper& buildState) { // Find a copy of visual studio that has the required VisualCompiler auto executablePath = Path("C:/Program Files (x86)/Microsoft Visual Studio/Installer/vswhere.exe"); auto workingDirectory = Path(""); - auto arguments = std::vector({ + auto argumentList = std::vector({ "-latest", "-products", "*", @@ -137,29 +210,37 @@ namespace RecipeBuild bool includePrerelease = true; if (includePrerelease) { - arguments.push_back("-prerelease"); + argumentList.push_back("-prerelease"); } // Execute the requested target - auto result = System::IProcessManager::Current().Execute( + auto arguments = CombineArguments(argumentList); + buildState.LogDebug(executablePath.ToString() + " " + arguments); + auto process = System::IProcessManager::Current().CreateProcess( executablePath, - CombineArguments(arguments), + arguments, workingDirectory); + process->Start(); + process->WaitForExit(); + + auto stdOut = process->GetStandardOutput(); + auto stdErr = process->GetStandardError(); + auto exitCode = process->GetExitCode(); - if (!result.StdErr.empty()) + if (!stdErr.empty()) { - buildState.LogError(result.StdErr); + buildState.LogError(stdErr); throw std::runtime_error("VSWhere failed."); } - if (result.ExitCode != 0) + if (exitCode != 0) { // TODO: Return error code buildState.LogError("FAILED"); throw std::runtime_error("VSWhere failed."); } - auto stream = std::istringstream(result.StdOut); + auto stream = std::istringstream(stdOut); // The first line is the path auto path = std::string(); @@ -173,7 +254,7 @@ namespace RecipeBuild } std::string FindDefaultVCToolsVersion( - Soup::Build::Extensions::BuildStateWrapper& buildState, + Soup::Build::Utilities::BuildStateWrapper& buildState, const Path& visualStudioInstallRoot) { // Check the default tools version @@ -200,7 +281,6 @@ namespace RecipeBuild } std::string FindNewestWindows10KitVersion( - Soup::Build::Extensions::BuildStateWrapper& buildState, const Path& windows10KitIncludePath) { // Check the default tools version @@ -240,7 +320,7 @@ namespace RecipeBuild } private: - Soup::Build::Extensions::StringList _runBeforeList; - Soup::Build::Extensions::StringList _runAfterList; + Soup::Build::Utilities::StringList _runBeforeList; + Soup::Build::Utilities::StringList _runAfterList; }; } diff --git a/Source/Extensions/RecipeBuild/Tasks/StandardLibraryIncludeTask.h b/Source/Extensions/RecipeBuild/Tasks/StandardLibraryIncludeTask.h index 32240c8c..74eff715 100644 --- a/Source/Extensions/RecipeBuild/Tasks/StandardLibraryIncludeTask.h +++ b/Source/Extensions/RecipeBuild/Tasks/StandardLibraryIncludeTask.h @@ -44,7 +44,7 @@ namespace RecipeBuild { try { - auto state = Soup::Build::Extensions::BuildStateWrapper(buildState); + auto state = Soup::Build::Utilities::BuildStateWrapper(buildState); return Soup::Build::ApiCallResult::Success; } @@ -56,7 +56,7 @@ namespace RecipeBuild } private: - Soup::Build::Extensions::StringList _runBeforeList; - Soup::Build::Extensions::StringList _runAfterList; + Soup::Build::Utilities::StringList _runBeforeList; + Soup::Build::Utilities::StringList _runAfterList; }; } diff --git a/Source/Extensions/TestBuild/Recipe.toml b/Source/Extensions/TestBuild/Recipe.toml index bc86dc9a..75bf8cbe 100644 --- a/Source/Extensions/TestBuild/Recipe.toml +++ b/Source/Extensions/TestBuild/Recipe.toml @@ -5,7 +5,7 @@ Version = "1.0.0" Dependencies = [ "../../../Dependencies/Opal/Source/", # "Opal@0.1.2", - "../../Build/Runtime/", + "../../Build/Evaluate/", "../Compiler/Core/", "../Compiler/Clang/", "../Compiler/MSVC/", diff --git a/Source/Extensions/TestBuild/RegisterBuildExtension.cpp b/Source/Extensions/TestBuild/RegisterBuildExtension.cpp index 8a553608..c8798f80 100644 --- a/Source/Extensions/TestBuild/RegisterBuildExtension.cpp +++ b/Source/Extensions/TestBuild/RegisterBuildExtension.cpp @@ -10,7 +10,7 @@ import Opal; import Soup.Build; -import Soup.Build.Extensions; +import Soup.Build.Utilities; import SoupCompiler; import SoupCompilerClang; import SoupCompilerMSVC; @@ -21,11 +21,11 @@ using namespace Opal; #define DllExport __declspec(dllexport) -std::shared_ptr CreateMSVCCompiler(Soup::Build::Extensions::ValueTableWrapper& activeState) +std::shared_ptr CreateMSVCCompiler(Soup::Build::Utilities::ValueTableWrapper& activeState) { - auto visualCompilerToolsRoot = activeState.GetValue("MSVC.VCToolsRoot").AsString().GetValue(); + auto visualCompilerToolsRoot = activeState.GetValue("MSVC.VCToolsBinRoot").AsString().GetValue(); std::shared_ptr compiler = std::make_shared( - Path(visualCompilerToolsRoot) + Path("bin/Hostx64/x64/"), + Path(visualCompilerToolsRoot), Path("cl.exe"), Path("link.exe"), Path("lib.exe")); diff --git a/Source/Extensions/TestBuild/Tasks/TestBuildTask.h b/Source/Extensions/TestBuild/Tasks/TestBuildTask.h index 6760dc7b..84b77fca 100644 --- a/Source/Extensions/TestBuild/Tasks/TestBuildTask.h +++ b/Source/Extensions/TestBuild/Tasks/TestBuildTask.h @@ -2,7 +2,7 @@ namespace Soup::Test { - using CreateCompiler = std::function(Soup::Build::Extensions::ValueTableWrapper&)>; + using CreateCompiler = std::function(Soup::Build::Utilities::ValueTableWrapper&)>; using CompilerFactory = std::map; /// @@ -46,7 +46,7 @@ namespace Soup::Test Soup::Build::ApiCallResult TryExecute( Soup::Build::IBuildState& buildState) noexcept override final { - auto buildStateWrapper = Soup::Build::Extensions::BuildStateWrapper(buildState); + auto buildStateWrapper = Soup::Build::Utilities::BuildStateWrapper(buildState); try { @@ -66,7 +66,7 @@ namespace Soup::Test /// /// The Core Execute task /// - void Execute(Soup::Build::Extensions::BuildStateWrapper& buildState) + void Execute(Soup::Build::Utilities::BuildStateWrapper& buildState) { auto activeState = buildState.GetActiveState(); auto sharedState = buildState.GetSharedState(); @@ -122,8 +122,8 @@ namespace Soup::Test auto runArguments = ""; auto inputFiles = std::vector({}); auto outputFiles = std::vector({}); - auto runTestsOperation = Build::Extensions::BuildOperationWrapper( - new Build::Extensions::BuildOperation( + auto runTestsOperation = Build::Utilities::BuildOperationWrapper( + new Build::Utilities::BuildOperation( title, program, runArguments, @@ -132,7 +132,7 @@ namespace Soup::Test outputFiles)); // Run the test harness - Soup::Build::Extensions::BuildOperationExtensions::AddLeafChild( + Soup::Build::Utilities::BuildOperationExtensions::AddLeafChild( buildResult.BuildOperations, runTestsOperation); @@ -141,7 +141,7 @@ namespace Soup::Test } void LoadBuildProperties( - Soup::Build::Extensions::ValueTableWrapper& buildTable, + Soup::Build::Utilities::ValueTableWrapper& buildTable, Soup::Compiler::BuildArguments& arguments) { arguments.LanguageStandard = static_cast( @@ -202,8 +202,8 @@ namespace Soup::Test } void LoadTestBuildProperties( - Soup::Build::Extensions::BuildStateWrapper& buildState, - Soup::Build::Extensions::ValueTableWrapper& testTable, + Soup::Build::Utilities::BuildStateWrapper& buildState, + Soup::Build::Utilities::ValueTableWrapper& testTable, Soup::Compiler::BuildArguments& arguments) { if (!testTable.HasValue("Source")) @@ -228,7 +228,7 @@ namespace Soup::Test } void LoadDependencyBuildInput( - Soup::Build::Extensions::ValueTableWrapper& buildTable, + Soup::Build::Utilities::ValueTableWrapper& buildTable, Soup::Compiler::BuildArguments& arguments) { // Load the runtime dependencies @@ -254,8 +254,8 @@ namespace Soup::Test } static void LoadDevDependencyBuildInput( - Soup::Build::Extensions::BuildStateWrapper& buildState, - Soup::Build::Extensions::ValueTableWrapper& activeState, + Soup::Build::Utilities::BuildStateWrapper& buildState, + Soup::Build::Utilities::ValueTableWrapper& activeState, Soup::Compiler::BuildArguments& arguments) { if (activeState.HasValue("DevDependencies")) @@ -344,14 +344,14 @@ namespace Soup::Test private: CompilerFactory _compilerFactory; - static Soup::Build::Extensions::StringList _runBeforeList; - static Soup::Build::Extensions::StringList _runAfterList; + static Soup::Build::Utilities::StringList _runBeforeList; + static Soup::Build::Utilities::StringList _runAfterList; }; - Soup::Build::Extensions::StringList TestBuildTask::_runBeforeList = - Soup::Build::Extensions::StringList(); - Soup::Build::Extensions::StringList TestBuildTask::_runAfterList = - Soup::Build::Extensions::StringList({ + Soup::Build::Utilities::StringList TestBuildTask::_runBeforeList = + Soup::Build::Utilities::StringList(); + Soup::Build::Utilities::StringList TestBuildTask::_runAfterList = + Soup::Build::Utilities::StringList({ "Build", }); } diff --git a/Source/Monitor/Detours/EventLogger.h b/Source/Monitor/Detours/EventLogger.h new file mode 100644 index 00000000..5f7f7f23 --- /dev/null +++ b/Source/Monitor/Detours/EventLogger.h @@ -0,0 +1,196 @@ + +#pragma once +#include "Helpers.h" +#include "Functions/FileApiCache.h" + +class EventLogger +{ +public: + static void Initialize() + { + std::stringstream pipeNameBuilder; + pipeNameBuilder << TBLOG_PIPE_NAMEA << "." << s_nTraceProcessId; + auto pipeName = pipeNameBuilder.str(); + + auto lock = std::lock_guard(s_pipeMutex); + for (int retries = 0; retries < 10; retries++) + { + // Wait up to 1 seconds for a pipe to appear. + auto timoutMilliseconds = 1000; + if (WaitNamedPipeA(pipeName.c_str(), timoutMilliseconds) != 0) + { + // Attempt to open the pipe + s_pipeHandle = Functions::FileApi::Cache::CreateFileA( + pipeName.c_str(), + GENERIC_WRITE, + 0, + nullptr, + OPEN_EXISTING, + 0, + nullptr); + if (s_pipeHandle != INVALID_HANDLE_VALUE) + { + DWORD pipeMode = PIPE_READMODE_MESSAGE; + if (SetNamedPipeHandleState(s_pipeHandle, &pipeMode, nullptr, nullptr)) + { + // All good! + return; + } + } + } + } + + // Couldn't open pipe. + throw std::runtime_error("Failed to open pipe for event logger."); + } + + static void Shutdown() + { + auto lock = std::lock_guard(s_pipeMutex); + if (s_pipeHandle != INVALID_HANDLE_VALUE) + { + Monitor::DetourMessage message; + message.Type = Monitor::DetourMessageType::Info_Shutdown; + message.ContentSize = 0; + UnsafeWriteMessage(message); + FlushFileBuffers(s_pipeHandle); + CloseHandle(s_pipeHandle); + s_pipeHandle = INVALID_HANDLE_VALUE; + } + } + + static void AppendValue(Monitor::DetourMessage& message, const char* value) + { + if (value != nullptr) + { + auto stringValue = std::string_view(value); + auto startIndex = message.ContentSize; + auto size = stringValue.size() + 1; + message.ContentSize += size; + if (message.ContentSize > sizeof(Monitor::DetourMessage::Content)) + throw std::runtime_error("Message content too long for string value"); + + stringValue.copy(reinterpret_cast(message.Content + startIndex), size); + } + else + { + AppendValue(message, ""); + } + } + + static void AppendValue(Monitor::DetourMessage& message, const wchar_t* value) + { + if (value != nullptr) + { + auto stringValue = std::wstring_view(value); + auto startIndex = message.ContentSize; + auto size = 2 * (stringValue.size() + 1); + message.ContentSize += size; + if (message.ContentSize > sizeof(Monitor::DetourMessage::Content)) + throw std::runtime_error("Message content too long for string value"); + + stringValue.copy(reinterpret_cast(message.Content + startIndex), size); + } + else + { + AppendValue(message, L""); + } + } + + static void AppendValue(Monitor::DetourMessage& message, void* value) + { + auto startIndex = message.ContentSize; + message.ContentSize += sizeof(void*); + if (message.ContentSize > sizeof(Monitor::DetourMessage::Content)) + throw std::runtime_error("Message content too long for int value"); + + *reinterpret_cast(message.Content + startIndex) = value; + } + + static void AppendValue(Monitor::DetourMessage& message, int value) + { + auto startIndex = message.ContentSize; + message.ContentSize += sizeof(int); + if (message.ContentSize > sizeof(Monitor::DetourMessage::Content)) + throw std::runtime_error("Message content too long for int value"); + + *reinterpret_cast(message.Content + startIndex) = value; + } + + static void AppendValue(Monitor::DetourMessage& message, unsigned int value) + { + auto startIndex = message.ContentSize; + message.ContentSize += sizeof(unsigned int); + if (message.ContentSize > sizeof(Monitor::DetourMessage::Content)) + throw std::runtime_error("Message content too long for unsigned int value"); + + *reinterpret_cast(message.Content + startIndex) = value; + } + + static void AppendValue(Monitor::DetourMessage& message, unsigned long value) + { + auto startIndex = message.ContentSize; + message.ContentSize += sizeof(unsigned long); + if (message.ContentSize > sizeof(Monitor::DetourMessage::Content)) + throw std::runtime_error("Message content too long for unsigned long value"); + + *reinterpret_cast(message.Content + startIndex) = value; + } + + static void AppendValue(Monitor::DetourMessage& message, unsigned long long value) + { + auto startIndex = message.ContentSize; + message.ContentSize += sizeof(unsigned long long); + if (message.ContentSize > sizeof(Monitor::DetourMessage::Content)) + throw std::runtime_error("Message content too long for unsigned long long value"); + + *reinterpret_cast(message.Content + startIndex) = value; + } + + static void WriteError(std::string_view value) + { + Monitor::DetourMessage message; + message.Type = Monitor::DetourMessageType::Info_Error; + message.ContentSize = 0; + AppendValue(message, value.data()); + UnsafeWriteMessage(message); + } + + static void WriteMessage(const Monitor::DetourMessage& message) + { + auto lock = std::lock_guard(s_pipeMutex); + UnsafeWriteMessage(message); + } + +private: + static void UnsafeWriteMessage(const Monitor::DetourMessage& message) + { + if (s_pipeHandle == INVALID_HANDLE_VALUE) + return; // TODO: A static dll init may do bad things before the main entry initialize + + // Write the message + DWORD countBytesToWrite = message.ContentSize + + sizeof(Monitor::DetourMessage::Type) + + sizeof(Monitor::DetourMessage::ContentSize); + DWORD countBytesWritten = 0; + if (!Functions::FileApi::Cache::WriteFile( + s_pipeHandle, + &message, + countBytesToWrite, + &countBytesWritten, + nullptr)) + { + throw std::runtime_error("Failed write event logger"); + } + + if (countBytesWritten != countBytesToWrite) + throw std::runtime_error("Did not write the expected number of bytes"); + } + +private: + static std::mutex s_pipeMutex; + static HANDLE s_pipeHandle; +}; + +/*static*/ std::mutex EventLogger::s_pipeMutex = std::mutex(); +/*static*/ HANDLE EventLogger::s_pipeHandle = INVALID_HANDLE_VALUE; \ No newline at end of file diff --git a/Source/Monitor/Detours/FileAccessReporter.h b/Source/Monitor/Detours/FileAccessReporter.h new file mode 100644 index 00000000..be6ebea0 --- /dev/null +++ b/Source/Monitor/Detours/FileAccessReporter.h @@ -0,0 +1,147 @@ + +typedef HANDLE (WINAPI *CreateFileW_t)( + __in LPCWSTR lpFileName, + __in DWORD dwDesiredAccess, + __in DWORD dwShareMode, + __in_opt LPSECURITY_ATTRIBUTES lpSecurityAttributes, + __in DWORD dwCreationDisposition, + __in DWORD dwFlagsAndAttributes, + __in_opt HANDLE hTemplateFile + ); + +typedef HANDLE (WINAPI *CreateFileA_t)( + __in LPCSTR lpFileName, + __in DWORD dwDesiredAccess, + __in DWORD dwShareMode, + __in_opt LPSECURITY_ATTRIBUTES lpSecurityAttributes, + __in DWORD dwCreationDisposition, + __in DWORD dwFlagsAndAttributes, + __in_opt HANDLE hTemplateFile + ); + +CreateFileW_t Real_CreateFileW; +CreateFileA_t Real_CreateFileA; + +HANDLE WINAPI Detoured_CreateFileW( + _In_ LPCWSTR lpFileName, + _In_ DWORD dwDesiredAccess, + _In_ DWORD dwShareMode, + _In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes, + _In_ DWORD dwCreationDisposition, + _In_ DWORD dwFlagsAndAttributes, + _In_opt_ HANDLE hTemplateFile) +{ + std::cout << "CreateFileW" << std::endl; + return Real_CreateFileW( + lpFileName, + dwDesiredAccess, + dwShareMode, + lpSecurityAttributes, + dwCreationDisposition, + dwFlagsAndAttributes, + hTemplateFile); +} + +HANDLE WINAPI Detoured_CreateFileA( + _In_ LPCSTR lpFileName, + _In_ DWORD dwDesiredAccess, + _In_ DWORD dwShareMode, + _In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes, + _In_ DWORD dwCreationDisposition, + _In_ DWORD dwFlagsAndAttributes, + _In_opt_ HANDLE hTemplateFile) +{ + std::cout << "CreateFileA" << std::endl; + return Real_CreateFileA( + lpFileName, + dwDesiredAccess, + dwShareMode, + lpSecurityAttributes, + dwCreationDisposition, + dwFlagsAndAttributes, + hTemplateFile); +} + +DllExport bool AttachDetours() +{ + LONG hr; + + if (!DetourRestoreAfterWith()) + return false; + + hr = DetourTransactionBegin(); + if (hr != NO_ERROR) + return false; + + hr = DetourUpdateThread(GetCurrentThread()); + if (hr != NO_ERROR) + return false; + + Real_CreateFileA = ::CreateFileA; + hr = DetourAttach((PVOID*)&Real_CreateFileA, Detoured_CreateFileA); + if (hr != ERROR_SUCCESS) + return false; + + Real_CreateFileW = ::CreateFileW; + hr = DetourAttach((PVOID*)&Real_CreateFileW, Detoured_CreateFileW); + if (hr != ERROR_SUCCESS) + return false; + + hr = DetourTransactionCommit(); + if (hr != NO_ERROR) + return false; + + return true; +} + +DllExport bool DetachDetours() +{ + LONG hr; + + hr = DetourTransactionBegin(); + if (hr != NO_ERROR) + return false; + + hr = DetourUpdateThread(GetCurrentThread()); + if (hr != NO_ERROR) + return false; + + hr = DetourDetach(&(PVOID&)Real_CreateFileA, Detoured_CreateFileA); + if (hr != NO_ERROR) + return false; + + hr = DetourDetach(&(PVOID&)Real_CreateFileW, Detoured_CreateFileW); + if (hr != NO_ERROR) + return false; + + hr = DetourTransactionCommit(); + if (hr != NO_ERROR) + return false; + + return true; +} + +BOOL WINAPI DllMain(HINSTANCE hinst, DWORD dwReason, LPVOID reserved) +{ + (void)hinst; + (void)reserved; + + if (DetourIsHelperProcess()) + { + return true; + } + + if (dwReason == DLL_PROCESS_ATTACH) + { + if (!AttachDetours()) + return false; + } + else if (dwReason == DLL_PROCESS_DETACH) + { + if (!DetachDetours()) + return false; + } + + return true; +} + diff --git a/Source/Monitor/Detours/Functions/FileApiCache.h b/Source/Monitor/Detours/Functions/FileApiCache.h new file mode 100644 index 00000000..f4d520e7 --- /dev/null +++ b/Source/Monitor/Detours/Functions/FileApiCache.h @@ -0,0 +1,678 @@ +#pragma once + +namespace Functions::FileApi::Cache +{ + /// + /// Determines whether the file I/O functions are using the ANSI or OEM character set code page. + /// + BOOL (WINAPI* AreFileApisANSI)() = ::AreFileApisANSI; + + /// + /// Compares two file times. + /// + LONG (WINAPI* CompareFileTime)( + const FILETIME *lpFileTime1, + const FILETIME *lpFileTime2) = ::CompareFileTime; + + /// + /// Creates a new directory. + /// + BOOL (WINAPI* CreateDirectoryA)( + LPCSTR lpPathName, + LPSECURITY_ATTRIBUTES lpSecurityAttributes) = ::CreateDirectoryA; + BOOL (WINAPI* CreateDirectoryW)( + LPCWSTR lpPathName, + LPSECURITY_ATTRIBUTES lpSecurityAttributes) = ::CreateDirectoryW; + + /// + /// Creates or opens a file or I/O device. + /// + HANDLE (WINAPI* CreateFile2)( + LPCWSTR lpFileName, + DWORD dwDesiredAccess, + DWORD dwShareMode, + DWORD dwCreationDisposition, + LPCREATEFILE2_EXTENDED_PARAMETERS pCreateExParams) = ::CreateFile2; + + /// + /// Creates or opens a file or I/O device. The most commonly used I/O devices are as follows: + /// file, file stream, directory, physical disk, volume, console buffer, tape drive, + /// communications resource, mailslot, and pipe. + /// + HANDLE (WINAPI* CreateFileA)( + LPCSTR lpFileName, + DWORD dwDesiredAccess, + DWORD dwShareMode, + LPSECURITY_ATTRIBUTES lpSecurityAttributes, + DWORD dwCreationDisposition, + DWORD dwFlagsAndAttributes, + HANDLE hTemplateFile) = ::CreateFileA; + HANDLE (WINAPI* CreateFileW)( + LPCWSTR lpFileName, + DWORD dwDesiredAccess, + DWORD dwShareMode, + LPSECURITY_ATTRIBUTES lpSecurityAttributes, + DWORD dwCreationDisposition, + DWORD dwFlagsAndAttributes, + HANDLE hTemplateFile) = ::CreateFileW; + + /// + /// Defines, redefines, or deletes MS-DOS device names. + /// + BOOL (WINAPI* DefineDosDeviceW)( + DWORD dwFlags, + LPCWSTR lpDeviceName, + LPCWSTR lpTargetPath) = ::DefineDosDeviceW; + + /// + /// Deletes an existing file. + /// + BOOL (WINAPI* DeleteFileA)( + LPCSTR lpFileName) = ::DeleteFileA; + BOOL (WINAPI* DeleteFileW)( + LPCWSTR lpFileName) = ::DeleteFileW; + + /// + /// Deletes a drive letter or mounted folder. + /// + BOOL (WINAPI* DeleteVolumeMountPointW)( + LPCWSTR lpszVolumeMountPoint) = ::DeleteVolumeMountPointW; + + /// + /// Converts a file time to a local file time. + /// + BOOL (WINAPI* FileTimeToLocalFileTime)( + const FILETIME *lpFileTime, + LPFILETIME lpLocalFileTime) = ::FileTimeToLocalFileTime; + + /// + /// Closes a file search handle opened by the FindFirstFile, FindFirstFileEx, FindFirstFileNameW, + /// FindFirstFileNameTransactedW, FindFirstFileTransacted, FindFirstStreamTransactedW, or FindFirstStreamW functions. + /// + BOOL (WINAPI* FindClose)( + HANDLE hFindFile) = ::FindClose; + + /// + /// Stops change notification handle monitoring. + /// + BOOL (WINAPI* FindCloseChangeNotification)( + HANDLE hChangeHandle) = ::FindCloseChangeNotification; + + /// + /// Creates a change notification handle and sets up initial change notification filter conditions. + /// + HANDLE (WINAPI* FindFirstChangeNotificationA)( + LPCSTR lpPathName, + BOOL bWatchSubtree, + DWORD dwNotifyFilter) = ::FindFirstChangeNotificationA; + HANDLE (WINAPI* FindFirstChangeNotificationW)( + LPCWSTR lpPathName, + BOOL bWatchSubtree, + DWORD ) = ::FindFirstChangeNotificationW; + + /// + /// Searches a directory for a file or subdirectory with a name that matches a specific name (or partial name if wildcards are used). + /// + HANDLE (WINAPI* FindFirstFileA)( + LPCSTR lpFileName, + LPWIN32_FIND_DATAA lpFindFileData) = ::FindFirstFileA; + HANDLE (WINAPI* FindFirstFileW)( + LPCWSTR lpFileName, + LPWIN32_FIND_DATAW lpFindFileData) = ::FindFirstFileW; + + /// + /// Searches a directory for a file or subdirectory with a name and attributes that match those specified. + /// + HANDLE (WINAPI* FindFirstFileExA)( + LPCSTR lpFileName, + FINDEX_INFO_LEVELS fInfoLevelId, + LPVOID lpFindFileData, + FINDEX_SEARCH_OPS fSearchOp, + LPVOID lpSearchFilter, + DWORD dwAdditionalFlags) = ::FindFirstFileExA; + HANDLE (WINAPI* FindFirstFileExW)( + LPCWSTR lpFileName, + FINDEX_INFO_LEVELS fInfoLevelId, + LPVOID lpFindFileData, + FINDEX_SEARCH_OPS fSearchOp, + LPVOID lpSearchFilter, + DWORD dwAdditionalFlags) = ::FindFirstFileExW; + + /// + /// Creates an enumeration of all the hard links to the specified file. The FindFirstFileNameW function returns + /// a handle to the enumeration that can be used on subsequent calls to the FindNextFileNameW function. + /// + HANDLE (WINAPI* FindFirstFileNameW)( + LPCWSTR lpFileName, + DWORD dwFlags, + LPDWORD StringLength, + PWSTR LinkName) = ::FindFirstFileNameW; + + /// + /// Enumerates the first stream with a ::$DATA stream type in the specified file or directory. + /// + HANDLE (WINAPI* FindFirstStreamW)( + LPCWSTR lpFileName, + STREAM_INFO_LEVELS InfoLevel, + LPVOID lpFindStreamData, + DWORD dwFlags) = ::FindFirstStreamW; + + /// + /// Retrieves the name of a volume on a computer. + /// + HANDLE (WINAPI* FindFirstVolumeW)( + LPWSTR lpszVolumeName, + DWORD cchBufferLength) = ::FindFirstVolumeW; + + /// + /// Requests that the operating system signal a change notification handle the next time it detects an appropriate change. + /// + BOOL (WINAPI* FindNextChangeNotification)( + HANDLE hChangeHandle) = ::FindNextChangeNotification; + + /// + /// Continues a file search from a previous call to the FindFirstFile, FindFirstFileEx, or FindFirstFileTransacted functions. + /// + BOOL (WINAPI* FindNextFileA)( + HANDLE hFindFile, + LPWIN32_FIND_DATAA lpFindFileData) = ::FindNextFileA; + BOOL (WINAPI* FindNextFileW)( + HANDLE hFindFile, + LPWIN32_FIND_DATAW lpFindFileData) = ::FindNextFileW; + + /// + /// Continues enumerating the hard links to a file using the handle returned by a successful call to the + /// FindFirstFileNameW function. + /// + BOOL (WINAPI* FindNextFileNameW)( + HANDLE hFindStream, + LPDWORD StringLength, + PWSTR LinkName) = ::FindNextFileNameW; + + /// + /// Continues a stream search started by a previous call to the FindFirstStreamW function. + /// + BOOL (WINAPI* FindNextStreamW)( + HANDLE hFindStream, + LPVOID lpFindStreamData) = ::FindNextStreamW; + + /// + /// Continues a volume search started by a call to the FindFirstVolume function. + /// + BOOL (WINAPI* FindNextVolumeW)( + HANDLE hFindVolume, + LPWSTR lpszVolumeName, + DWORD cchBufferLength) = ::FindNextVolumeW; + + /// + /// Closes the specified volume search handle. + /// + BOOL (WINAPI* FindVolumeClose)( + HANDLE hFindVolume) = ::FindVolumeClose; + + /// + /// Flushes the buffers of a specified file and causes all buffered data to be written to a file. + /// + BOOL (WINAPI* FlushFileBuffers)( + HANDLE hFile) = ::FlushFileBuffers; + + /// + /// Retrieves the actual number of bytes of disk storage used to store a specified file. + /// + DWORD (WINAPI* GetCompressedFileSizeA)( + LPCSTR lpFileName, + LPDWORD lpFileSizeHigh) = ::GetCompressedFileSizeA; + DWORD (WINAPI* GetCompressedFileSizeW)( + LPCWSTR lpFileName, + LPDWORD lpFileSizeHigh) = ::GetCompressedFileSizeW; + + /// + /// Retrieves information about the specified disk, including the amount of free space on the disk. + /// + BOOL (WINAPI* GetDiskFreeSpaceA)( + LPCSTR lpRootPathName, + LPDWORD lpSectorsPerCluster, + LPDWORD lpBytesPerSector, + LPDWORD lpNumberOfFreeClusters, + LPDWORD lpTotalNumberOfClusters) = ::GetDiskFreeSpaceA; + BOOL (WINAPI* GetDiskFreeSpaceW)( + LPCWSTR lpRootPathName, + LPDWORD lpSectorsPerCluster, + LPDWORD lpBytesPerSector, + LPDWORD lpNumberOfFreeClusters, + LPDWORD lpTotalNumberOfClusters) = ::GetDiskFreeSpaceW; + + /// + /// Retrieves information about the amount of space that is available on a disk volume, which is the + /// total amount of space, the total amount of free space, and the total amount of free space available + /// to the user that is associated with the calling thread. + /// + BOOL (WINAPI* GetDiskFreeSpaceExA)( + LPCSTR lpDirectoryName, + PULARGE_INTEGER lpFreeBytesAvailableToCaller, + PULARGE_INTEGER lpTotalNumberOfBytes, + PULARGE_INTEGER lpTotalNumberOfFreeBytes) = ::GetDiskFreeSpaceExA; + BOOL (WINAPI* GetDiskFreeSpaceExW)( + LPCWSTR lpDirectoryName, + PULARGE_INTEGER lpFreeBytesAvailableToCaller, + PULARGE_INTEGER lpTotalNumberOfBytes, + PULARGE_INTEGER lpTotalNumberOfFreeBytes) = ::GetDiskFreeSpaceExW; + + /// + /// Determines whether a disk drive is a removable, fixed, CD-ROM, RAM disk, or network drive. + /// + UINT (WINAPI* GetDriveTypeA)( + LPCSTR lpRootPathName) = ::GetDriveTypeA; + UINT (WINAPI* GetDriveTypeW)( + LPCWSTR lpRootPathName) = ::GetDriveTypeW; + + /// + /// Retrieves file system attributes for a specified file or directory. + /// + DWORD (WINAPI* GetFileAttributesA)( + LPCSTR lpFileName) = ::GetFileAttributesA; + DWORD (WINAPI* GetFileAttributesW)( + LPCWSTR lpFileName) = ::GetFileAttributesW; + + /// + /// Retrieves attributes for a specified file or directory. + /// + BOOL (WINAPI* GetFileAttributesExA)( + LPCSTR lpFileName, + GET_FILEEX_INFO_LEVELS fInfoLevelId, + LPVOID lpFileInformation) = ::GetFileAttributesExA; + BOOL (WINAPI* GetFileAttributesExW)( + LPCWSTR lpFileName, + GET_FILEEX_INFO_LEVELS fInfoLevelId, + LPVOID lpFileInformation) = ::GetFileAttributesExW; + + /// + /// Retrieves file information for the specified file. + /// + BOOL (WINAPI* GetFileInformationByHandle)( + HANDLE hFile, + LPBY_HANDLE_FILE_INFORMATION lpFileInformation) = ::GetFileInformationByHandle; + + /// + /// Retrieves the size of the specified file, in bytes. + /// + DWORD (WINAPI* GetFileSize)( + HANDLE hFile, + LPDWORD lpFileSizeHigh) = ::GetFileSize; + + /// + /// Retrieves the size of the specified file. + /// + BOOL (WINAPI* GetFileSizeEx)( + HANDLE hFile, + PLARGE_INTEGER lpFileSize) = ::GetFileSizeEx; + + /// + /// Retrieves the date and time that a file or directory was created, last accessed, and last modified. + /// + BOOL (WINAPI* GetFileTime)( + HANDLE hFile, + LPFILETIME lpCreationTime, + LPFILETIME lpLastAccessTime, + LPFILETIME lpLastWriteTime) = ::GetFileTime; + + /// + /// Retrieves the file type of the specified file. + /// + DWORD (WINAPI* GetFileType)( + HANDLE hFile) = ::GetFileType; + + /// + /// Retrieves the final path for the specified file. + /// + DWORD (WINAPI* GetFinalPathNameByHandleA)( + HANDLE hFile, + LPSTR lpszFilePath, + DWORD cchFilePath, + DWORD dwFlags) = ::GetFinalPathNameByHandleA; + DWORD (WINAPI* GetFinalPathNameByHandleW)( + HANDLE hFile, + LPWSTR lpszFilePath, + DWORD cchFilePath, + DWORD dwFlags) = ::GetFinalPathNameByHandleW; + + /// + /// Retrieves the full path and file name of the specified file. + /// + DWORD (WINAPI* GetFullPathNameA)( + LPCSTR lpFileName, + DWORD nBufferLength, + LPSTR lpBuffer, + LPSTR *lpFilePart) = ::GetFullPathNameA; + DWORD (WINAPI* GetFullPathNameW)( + LPCWSTR lpFileName, + DWORD nBufferLength, + LPWSTR lpBuffer, + LPWSTR *lpFilePart) = ::GetFullPathNameW; + + /// + /// Retrieves a bitmask representing the currently available disk drives. + /// + DWORD (WINAPI* GetLogicalDrives)() = ::GetLogicalDrives; + + /// + /// Fills a buffer with strings that specify valid drives in the system. + /// + DWORD (WINAPI* GetLogicalDriveStringsW)( + DWORD nBufferLength, + LPWSTR lpBuffer) = ::GetLogicalDriveStringsW; + + /// + /// Converts the specified path to its long form. + /// + DWORD (WINAPI* GetLongPathNameA)( + LPCSTR lpszShortPath, + LPSTR lpszLongPath, + DWORD cchBuffer) = ::GetLongPathNameA; + DWORD (WINAPI* GetLongPathNameW)( + LPCWSTR lpszShortPath, + LPWSTR lpszLongPath, + DWORD cchBuffer) = ::GetLongPathNameW; + + /// + /// Retrieves the short path form of the specified path. + /// + DWORD (WINAPI* GetShortPathNameW)( + LPCWSTR lpszLongPath, + LPWSTR lpszShortPath, + DWORD cchBuffer) = ::GetShortPathNameW; + + /// + /// Creates a name for a temporary file. If a unique file name is generated, an empty + /// file is created and the handle to it is released; otherwise, only a file name is generated. + /// + UINT (WINAPI* GetTempFileNameA)( + LPCSTR lpPathName, + LPCSTR lpPrefixString, + UINT uUnique, + LPSTR lpTempFileName) = ::GetTempFileNameA; + UINT (WINAPI* GetTempFileNameW)( + LPCWSTR lpPathName, + LPCWSTR lpPrefixString, + UINT uUnique, + LPWSTR lpTempFileName) = ::GetTempFileNameW; + + /// + /// Retrieves the path of the directory designated for temporary files. + /// + DWORD (WINAPI* GetTempPathA)( + DWORD nBufferLength, + LPSTR lpBuffer) = ::GetTempPathA; + DWORD (WINAPI* GetTempPathW)( + DWORD nBufferLength, + LPWSTR lpBuffer) = ::GetTempPathW; + + /// + /// Retrieves information about the file system and volume associated with the specified root directory. + /// + BOOL (WINAPI* GetVolumeInformationA)( + LPCSTR lpRootPathName, + LPSTR lpVolumeNameBuffer, + DWORD nVolumeNameSize, + LPDWORD lpVolumeSerialNumber, + LPDWORD lpMaximumComponentLength, + LPDWORD lpFileSystemFlags, + LPSTR lpFileSystemNameBuffer, + DWORD nFileSystemNameSize) = ::GetVolumeInformationA; + BOOL (WINAPI* GetVolumeInformationW)( + LPCWSTR lpRootPathName, + LPWSTR lpVolumeNameBuffer, + DWORD nVolumeNameSize, + LPDWORD lpVolumeSerialNumber, + LPDWORD lpMaximumComponentLength, + LPDWORD lpFileSystemFlags, + LPWSTR lpFileSystemNameBuffer, + DWORD nFileSystemNameSize) = ::GetVolumeInformationW; + + /// + /// Retrieves information about the file system and volume associated with the specified file. + /// + BOOL (WINAPI* GetVolumeInformationByHandleW)( + HANDLE hFile, + LPWSTR lpVolumeNameBuffer, + DWORD nVolumeNameSize, + LPDWORD lpVolumeSerialNumber, + LPDWORD lpMaximumComponentLength, + LPDWORD lpFileSystemFlags, + LPWSTR lpFileSystemNameBuffer, + DWORD nFileSystemNameSize) = ::GetVolumeInformationByHandleW; + + /// + /// Retrieves a volume GUID path for the volume that is associated with the specified volume mount point + /// (drive letter, volume GUID path, or mounted folder). + /// + BOOL (WINAPI* GetVolumeNameForVolumeMountPointW)( + LPCWSTR lpszVolumeMountPoint, + LPWSTR lpszVolumeName, + DWORD cchBufferLength) = ::GetVolumeNameForVolumeMountPointW; + + /// + /// Retrieves a list of drive letters and mounted folder paths for the specified volume. + /// + BOOL (WINAPI* GetVolumePathNamesForVolumeNameW)( + LPCWSTR lpszVolumeName, + LPWCH lpszVolumePathNames, + DWORD cchBufferLength, + PDWORD lpcchReturnLength) = ::GetVolumePathNamesForVolumeNameW; + + /// + /// Retrieves the volume mount point where the specified path is mounted. + /// + BOOL (WINAPI* GetVolumePathNameW)( + LPCWSTR lpszFileName, + LPWSTR lpszVolumePathName, + DWORD cchBufferLength) = ::GetVolumePathNameW; + + /// + /// Converts a local file time to a file time based on the Coordinated Universal Time (UTC). + /// + BOOL (WINAPI* LocalFileTimeToFileTime)( + const FILETIME *lpLocalFileTime, + LPFILETIME lpFileTime) = ::LocalFileTimeToFileTime; + + /// + /// Locks the specified file for exclusive access by the calling process. + /// + BOOL (WINAPI* LockFile)( + HANDLE hFile, + DWORD dwFileOffsetLow, + DWORD dwFileOffsetHigh, + DWORD nNumberOfBytesToLockLow, + DWORD nNumberOfBytesToLockHigh) = ::LockFile; + + /// + /// Locks the specified file for exclusive access by the calling process. This function can operate + /// either synchronously or asynchronously and can request either an exclusive or a shared lock. + /// + BOOL (WINAPI* LockFileEx)( + HANDLE hFile, + DWORD dwFlags, + DWORD dwReserved, + DWORD nNumberOfBytesToLockLow, + DWORD nNumberOfBytesToLockHigh, + LPOVERLAPPED lpOverlapped) = ::LockFileEx; + + /// + /// Retrieves information about MS-DOS device names. + /// + DWORD (WINAPI* QueryDosDeviceW)( + LPCWSTR lpDeviceName, + LPWSTR lpTargetPath, + DWORD ucchMax) = ::QueryDosDeviceW; + + /// + /// Reads data from the specified file or input/output (I/O) device. Reads occur at the position + /// specified by the file pointer if supported by the device. + /// + BOOL (WINAPI* ReadFile)( + HANDLE hFile, + LPVOID lpBuffer, + DWORD nNumberOfBytesToRead, + LPDWORD lpNumberOfBytesRead, + LPOVERLAPPED lpOverlapped) = ::ReadFile; + + /// + /// Reads data from the specified file or input/output (I/O) device. It reports its completion + /// status asynchronously, calling the specified completion routine when reading is completed + /// or canceled and the calling thread is in an alertable wait state. + /// + BOOL (WINAPI* ReadFileEx)( + HANDLE hFile, + LPVOID lpBuffer, + DWORD nNumberOfBytesToRead, + LPOVERLAPPED lpOverlapped, + LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine) = ::ReadFileEx; + + /// + /// Reads data from a file and stores it in an array of buffers. + /// + BOOL (WINAPI* ReadFileScatter)( + HANDLE hFile, + FILE_SEGMENT_ELEMENT aSegmentArray[], + DWORD nNumberOfBytesToRead, + LPDWORD lpReserved, + LPOVERLAPPED lpOverlapped) = ::ReadFileScatter; + + /// + /// Deletes an existing empty directory. + /// + BOOL (WINAPI* RemoveDirectoryA)( + LPCSTR lpPathName) = ::RemoveDirectoryA; + BOOL (WINAPI* RemoveDirectoryW)( + LPCWSTR lpPathName) = ::RemoveDirectoryW; + + /// + /// Sets the physical file size for the specified file to the current position of the file pointer. + /// + BOOL (WINAPI* SetEndOfFile)( + HANDLE hFile) = ::SetEndOfFile; + + /// + /// Causes the file I/O functions to use the ANSI character set code page for the current process. + /// + void (WINAPI* SetFileApisToANSI)() = ::SetFileApisToANSI; + + /// + /// Causes the file I/O functions for the process to use the OEM character set code page. + /// + void (WINAPI* SetFileApisToOEM)() = ::SetFileApisToOEM; + + /// + /// Sets the attributes for a file or directory. + /// + BOOL (WINAPI* SetFileAttributesA)( + LPCSTR lpFileName, + DWORD dwFileAttributes) = ::SetFileAttributesA; + BOOL (WINAPI* SetFileAttributesW)( + LPCWSTR lpFileName, + DWORD dwFileAttributes) = ::SetFileAttributesW; + + /// + /// Sets the file information for the specified file. + /// + BOOL (WINAPI* SetFileInformationByHandle)( + HANDLE hFile, + FILE_INFO_BY_HANDLE_CLASS FileInformationClass, + LPVOID lpFileInformation, + DWORD dwBufferSize) = ::SetFileInformationByHandle; + + /// + /// Associates a virtual address range with the specified file handle. + /// + BOOL (WINAPI* SetFileIoOverlappedRange)( + HANDLE FileHandle, + PUCHAR OverlappedRangeStart, + ULONG Length) = ::SetFileIoOverlappedRange; + + /// + /// Moves the file pointer of the specified file. + /// + DWORD (WINAPI* SetFilePointer)( + HANDLE hFile, + LONG lDistanceToMove, + PLONG lpDistanceToMoveHigh, + DWORD dwMoveMethod) = ::SetFilePointer; + + /// + /// Moves the file pointer of the specified file. + /// + BOOL (WINAPI* SetFilePointerEx)( + HANDLE hFile, + LARGE_INTEGER liDistanceToMove, + PLARGE_INTEGER lpNewFilePointer, + DWORD dwMoveMethod) = ::SetFilePointerEx; + + /// + /// Sets the date and time that the specified file or directory was created, last accessed, or last modified. + /// + BOOL (WINAPI* SetFileTime)( + HANDLE hFile, + const FILETIME *lpCreationTime, + const FILETIME *lpLastAccessTime, + const FILETIME *lpLastWriteTime) = ::SetFileTime; + + /// + /// Sets the valid data length of the specified file. This function is useful in very limited scenarios. + /// For more information, see the Remarks section. + /// + BOOL (WINAPI* SetFileValidData)( + HANDLE hFile, + LONGLONG ValidDataLength) = ::SetFileValidData; + + /// + /// Unlocks a region in an open file. + /// + BOOL (WINAPI* UnlockFile)( + HANDLE hFile, + DWORD dwFileOffsetLow, + DWORD dwFileOffsetHigh, + DWORD nNumberOfBytesToUnlockLow, + DWORD nNumberOfBytesToUnlockHigh) = ::UnlockFile; + + /// + /// Unlocks a region in the specified file. This function can operate either synchronously or asynchronously. + /// + BOOL (WINAPI* UnlockFileEx)( + HANDLE hFile, + DWORD dwReserved, + DWORD nNumberOfBytesToUnlockLow, + DWORD nNumberOfBytesToUnlockHigh, + LPOVERLAPPED lpOverlapped) = ::UnlockFileEx; + + /// + /// Writes data to the specified file or input/output (I/O) device. + /// + BOOL (WINAPI* WriteFile)( + HANDLE hFile, + LPCVOID lpBuffer, + DWORD nNumberOfBytesToWrite, + LPDWORD lpNumberOfBytesWritten, + LPOVERLAPPED lpOverlapped) = ::WriteFile; + + /// + /// Writes data to the specified file or input/output (I/O) device. It reports its completion + /// status asynchronously, calling the specified completion routine when writing is completed + /// or canceled and the calling thread is in an alertable wait state. + /// + BOOL (WINAPI* WriteFileEx)( + HANDLE hFile, + LPCVOID lpBuffer, + DWORD nNumberOfBytesToWrite, + LPOVERLAPPED lpOverlapped, + LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine) = ::WriteFileEx; + + /// + /// Retrieves data from an array of buffers and writes the data to a file. + /// + BOOL (WINAPI* WriteFileGather)( + HANDLE hFile, + FILE_SEGMENT_ELEMENT aSegmentArray[], + DWORD nNumberOfBytesToWrite, + LPDWORD lpReserved, + LPOVERLAPPED lpOverlapped) = ::WriteFileGather; +} \ No newline at end of file diff --git a/Source/Monitor/Detours/Functions/FileApiOverrides.h b/Source/Monitor/Detours/Functions/FileApiOverrides.h new file mode 100644 index 00000000..f8fb37ef --- /dev/null +++ b/Source/Monitor/Detours/Functions/FileApiOverrides.h @@ -0,0 +1,2285 @@ +#pragma once +#include "FileApiCache.h" +#include "EventLogger.h" + +namespace Functions::FileApi::Overrides +{ + BOOL WINAPI AreFileApisANSI() + { + BOOL result = 0; + __try + { + result = Cache::AreFileApisANSI(); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::AreFileApisANSI; + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + LONG WINAPI CompareFileTime( + const FILETIME *lpFileTime1, + const FILETIME *lpFileTime2) + { + LONG result = 0; + __try + { + result = Cache::CompareFileTime( + lpFileTime1, + lpFileTime2 + ); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::CompareFileTime; + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + BOOL WINAPI CreateDirectoryA( + LPCSTR lpPathName, + LPSECURITY_ATTRIBUTES lpSecurityAttributes) + { + BOOL result = 0; + __try + { + result = Cache::CreateDirectoryA( + lpPathName, + lpSecurityAttributes); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::CreateDirectoryA; + EventLogger::AppendValue(message, lpPathName); + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + BOOL WINAPI CreateDirectoryW( + LPCWSTR lpPathName, + LPSECURITY_ATTRIBUTES lpSecurityAttributes) + { + BOOL result = 0; + __try + { + result = Cache::CreateDirectoryW( + lpPathName, + lpSecurityAttributes); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::CreateDirectoryW; + EventLogger::AppendValue(message, lpPathName); + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + HANDLE WINAPI CreateFile2( + LPCWSTR lpFileName, + DWORD dwDesiredAccess, + DWORD dwShareMode, + DWORD dwCreationDisposition, + LPCREATEFILE2_EXTENDED_PARAMETERS pCreateExParams) + { + HANDLE result = 0; + __try + { + result = Cache::CreateFile2( + lpFileName, + dwDesiredAccess, + dwShareMode, + dwCreationDisposition, + pCreateExParams); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::CreateFile2; + EventLogger::AppendValue(message, lpFileName); + EventLogger::AppendValue(message, dwDesiredAccess); + EventLogger::AppendValue(message, dwShareMode); + EventLogger::AppendValue(message, dwCreationDisposition); + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + HANDLE WINAPI CreateFileA( + LPCSTR lpFileName, + DWORD dwDesiredAccess, + DWORD dwShareMode, + LPSECURITY_ATTRIBUTES lpSecurityAttributes, + DWORD dwCreationDisposition, + DWORD dwFlagsAndAttributes, + HANDLE hTemplateFile) + { + HANDLE result = 0; + __try + { + result = Cache::CreateFileA( + lpFileName, + dwDesiredAccess, + dwShareMode, + lpSecurityAttributes, + dwCreationDisposition, + dwFlagsAndAttributes, + hTemplateFile); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::CreateFileA; + EventLogger::AppendValue(message, lpFileName); + EventLogger::AppendValue(message, dwDesiredAccess); + EventLogger::AppendValue(message, dwShareMode); + EventLogger::AppendValue(message, dwCreationDisposition); + EventLogger::AppendValue(message, dwFlagsAndAttributes); + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + HANDLE WINAPI CreateFileW( + LPCWSTR lpFileName, + DWORD dwDesiredAccess, + DWORD dwShareMode, + LPSECURITY_ATTRIBUTES lpSecurityAttributes, + DWORD dwCreationDisposition, + DWORD dwFlagsAndAttributes, + HANDLE hTemplateFile) + { + HANDLE result = 0; + __try + { + result = Cache::CreateFileW( + lpFileName, + dwDesiredAccess, + dwShareMode, + lpSecurityAttributes, + dwCreationDisposition, + dwFlagsAndAttributes, + hTemplateFile); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::CreateFileW; + EventLogger::AppendValue(message, lpFileName); + EventLogger::AppendValue(message, dwDesiredAccess); + EventLogger::AppendValue(message, dwShareMode); + EventLogger::AppendValue(message, dwCreationDisposition); + EventLogger::AppendValue(message, dwFlagsAndAttributes); + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + BOOL WINAPI DefineDosDeviceW( + DWORD dwFlags, + LPCWSTR lpDeviceName, + LPCWSTR lpTargetPath) + { + BOOL result = 0; + __try + { + result = Cache::DefineDosDeviceW( + dwFlags, + lpDeviceName, + lpTargetPath); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::DefineDosDeviceW; + EventLogger::AppendValue(message, dwFlags); + EventLogger::AppendValue(message, lpDeviceName); + EventLogger::AppendValue(message, lpTargetPath); + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + BOOL WINAPI DeleteFileA( + LPCSTR lpFileName) + { + BOOL result = 0; + __try + { + result = Cache::DeleteFileA( + lpFileName); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::DeleteFileA; + EventLogger::AppendValue(message, lpFileName); + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + BOOL WINAPI DeleteFileW( + LPCWSTR lpFileName) + { + BOOL result = 0; + __try + { + result = Cache::DeleteFileW( + lpFileName); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::DeleteFileW; + EventLogger::AppendValue(message, lpFileName); + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + BOOL WINAPI DeleteVolumeMountPointW( + LPCWSTR lpszVolumeMountPoint) + { + BOOL result = 0; + __try + { + result = Cache::DeleteVolumeMountPointW( + lpszVolumeMountPoint); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::DeleteVolumeMountPointW; + EventLogger::AppendValue(message, lpszVolumeMountPoint); + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + BOOL WINAPI FileTimeToLocalFileTime( + const FILETIME *lpFileTime, + LPFILETIME lpLocalFileTime) + { + BOOL result = 0; + __try + { + result = Cache::FileTimeToLocalFileTime( + lpFileTime, + lpLocalFileTime + ); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::FileTimeToLocalFileTime; + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + BOOL WINAPI FindClose( + HANDLE hFindFile) + { + BOOL result = 0; + __try + { + result = Cache::FindClose( + hFindFile); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::FindClose; + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + BOOL WINAPI FindCloseChangeNotification( + HANDLE hChangeHandle) + { + BOOL result = 0; + __try + { + result = Cache::FindCloseChangeNotification( + hChangeHandle); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::FindCloseChangeNotification; + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + HANDLE WINAPI FindFirstChangeNotificationA( + LPCSTR lpPathName, + BOOL bWatchSubtree, + DWORD dwNotifyFilter) + { + HANDLE result = 0; + __try + { + result = Cache::FindFirstChangeNotificationA( + lpPathName, + bWatchSubtree, + dwNotifyFilter); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::FindFirstChangeNotificationA; + EventLogger::AppendValue(message, lpPathName); + EventLogger::AppendValue(message, bWatchSubtree); + EventLogger::AppendValue(message, dwNotifyFilter); + EventLogger::WriteMessage(message); + } + + return result; + } + + HANDLE WINAPI FindFirstChangeNotificationW( + LPCWSTR lpPathName, + BOOL bWatchSubtree, + DWORD dwNotifyFilter) + { + HANDLE result = 0; + __try + { + result = Cache::FindFirstChangeNotificationW( + lpPathName, + bWatchSubtree, + dwNotifyFilter); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::FindFirstChangeNotificationW; + EventLogger::AppendValue(message, lpPathName); + EventLogger::AppendValue(message, bWatchSubtree); + EventLogger::AppendValue(message, dwNotifyFilter); + EventLogger::WriteMessage(message); + } + + return result; + } + + HANDLE WINAPI FindFirstFileA( + LPCSTR lpFileName, + LPWIN32_FIND_DATAA lpFindFileData) + { + HANDLE result = 0; + __try + { + result = Cache::FindFirstFileA( + lpFileName, + lpFindFileData); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::FindFirstFileA; + EventLogger::AppendValue(message, lpFileName); + EventLogger::WriteMessage(message); + } + + return result; + } + + HANDLE WINAPI FindFirstFileW( + LPCWSTR lpFileName, + LPWIN32_FIND_DATAW lpFindFileData) + { + HANDLE result = 0; + __try + { + result = Cache::FindFirstFileW( + lpFileName, + lpFindFileData); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::FindFirstFileW; + EventLogger::AppendValue(message, lpFileName); + EventLogger::WriteMessage(message); + } + + return result; + } + + HANDLE WINAPI FindFirstFileExA( + LPCSTR lpFileName, + FINDEX_INFO_LEVELS fInfoLevelId, + LPVOID lpFindFileData, + FINDEX_SEARCH_OPS fSearchOp, + LPVOID lpSearchFilter, + DWORD dwAdditionalFlags) + { + HANDLE result = 0; + __try + { + result = Cache::FindFirstFileExA( + lpFileName, + fInfoLevelId, + lpFindFileData, + fSearchOp, + lpSearchFilter, + dwAdditionalFlags); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::FindFirstFileExA; + EventLogger::AppendValue(message, lpFileName); + EventLogger::WriteMessage(message); + } + + return result; + } + + HANDLE WINAPI FindFirstFileExW( + LPCWSTR lpFileName, + FINDEX_INFO_LEVELS fInfoLevelId, + LPVOID lpFindFileData, + FINDEX_SEARCH_OPS fSearchOp, + LPVOID lpSearchFilter, + DWORD dwAdditionalFlags) + { + HANDLE result = 0; + __try + { + result = Cache::FindFirstFileExW( + lpFileName, + fInfoLevelId, + lpFindFileData, + fSearchOp, + lpSearchFilter, + dwAdditionalFlags); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::FindFirstFileExW; + EventLogger::AppendValue(message, lpFileName); + EventLogger::WriteMessage(message); + } + + return result; + } + + HANDLE WINAPI FindFirstFileNameW( + LPCWSTR lpFileName, + DWORD dwFlags, + LPDWORD StringLength, + PWSTR LinkName) + { + HANDLE result = 0; + __try + { + result = Cache::FindFirstFileNameW( + lpFileName, + dwFlags, + StringLength, + LinkName); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::FindFirstFileNameW; + EventLogger::AppendValue(message, lpFileName); + EventLogger::AppendValue(message, dwFlags); + EventLogger::WriteMessage(message); + } + + return result; + } + + HANDLE WINAPI FindFirstStreamW( + LPCWSTR lpFileName, + STREAM_INFO_LEVELS InfoLevel, + LPVOID lpFindStreamData, + DWORD dwFlags) + { + HANDLE result = 0; + __try + { + result = Cache::FindFirstStreamW( + lpFileName, + InfoLevel, + lpFindStreamData, + dwFlags); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::FindFirstStreamW; + EventLogger::AppendValue(message, lpFileName); + EventLogger::WriteMessage(message); + } + + return result; + } + + HANDLE WINAPI FindFirstVolumeW( + LPWSTR lpszVolumeName, + DWORD cchBufferLength) + { + HANDLE result = 0; + __try + { + result = Cache::FindFirstVolumeW( + lpszVolumeName, + cchBufferLength); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::FindFirstVolumeW; + EventLogger::AppendValue(message, lpszVolumeName); + EventLogger::WriteMessage(message); + } + + return result; + } + + BOOL WINAPI FindNextChangeNotification( + HANDLE hChangeHandle) + { + BOOL result = 0; + __try + { + result = Cache::FindNextChangeNotification( + hChangeHandle); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::FindNextChangeNotification; + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + BOOL WINAPI FindNextFileA( + HANDLE hFindFile, + LPWIN32_FIND_DATAA lpFindFileData) + { + BOOL result = 0; + __try + { + result = Cache::FindNextFileA( + hFindFile, + lpFindFileData); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::FindNextFileA; + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + BOOL WINAPI FindNextFileW( + HANDLE hFindFile, + LPWIN32_FIND_DATAW lpFindFileData) + { + BOOL result = 0; + __try + { + result = Cache::FindNextFileW( + hFindFile, + lpFindFileData); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::FindNextFileW; + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + BOOL WINAPI FindNextFileNameW( + HANDLE hFindStream, + LPDWORD StringLength, + PWSTR LinkName) + { + BOOL result = 0; + __try + { + result = Cache::FindNextFileNameW( + hFindStream, + StringLength, + LinkName); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::FindNextFileNameW; + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + BOOL WINAPI FindNextStreamW( + HANDLE hFindStream, + LPVOID lpFindStreamData) + { + BOOL result = 0; + __try + { + result = Cache::FindNextStreamW( + hFindStream, + lpFindStreamData); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::FindNextStreamW; + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + BOOL WINAPI FindNextVolumeW( + HANDLE hFindVolume, + LPWSTR lpszVolumeName, + DWORD cchBufferLength) + { + BOOL result = 0; + __try + { + result = Cache::FindNextVolumeW( + hFindVolume, + lpszVolumeName, + cchBufferLength); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::FindNextVolumeW; + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + BOOL WINAPI FindVolumeClose( + HANDLE hFindVolume) + { + BOOL result = 0; + __try + { + result = Cache::FindVolumeClose( + hFindVolume); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::FindVolumeClose; + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + BOOL WINAPI FlushFileBuffers( + HANDLE hFile) + { + BOOL result = 0; + __try + { + result = Cache::FlushFileBuffers( + hFile); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::FlushFileBuffers; + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + DWORD WINAPI GetCompressedFileSizeA( + LPCSTR lpFileName, + LPDWORD lpFileSizeHigh) + { + DWORD result = 0; + __try + { + result = Cache::GetCompressedFileSizeA( + lpFileName, + lpFileSizeHigh); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::GetCompressedFileSizeA; + EventLogger::AppendValue(message, lpFileName); + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + DWORD WINAPI GetCompressedFileSizeW( + LPCWSTR lpFileName, + LPDWORD lpFileSizeHigh) + { + DWORD result = 0; + __try + { + result = Cache::GetCompressedFileSizeW( + lpFileName, + lpFileSizeHigh); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::GetCompressedFileSizeW; + EventLogger::AppendValue(message, lpFileName); + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + BOOL WINAPI GetDiskFreeSpaceA( + LPCSTR lpRootPathName, + LPDWORD lpSectorsPerCluster, + LPDWORD lpBytesPerSector, + LPDWORD lpNumberOfFreeClusters, + LPDWORD lpTotalNumberOfClusters) + { + BOOL result = 0; + __try + { + result = Cache::GetDiskFreeSpaceA( + lpRootPathName, + lpSectorsPerCluster, + lpBytesPerSector, + lpNumberOfFreeClusters, + lpTotalNumberOfClusters); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::GetDiskFreeSpaceA; + EventLogger::AppendValue(message, lpRootPathName); + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + BOOL WINAPI GetDiskFreeSpaceW( + LPCWSTR lpRootPathName, + LPDWORD lpSectorsPerCluster, + LPDWORD lpBytesPerSector, + LPDWORD lpNumberOfFreeClusters, + LPDWORD lpTotalNumberOfClusters) + { + BOOL result = 0; + __try + { + result = Cache::GetDiskFreeSpaceW( + lpRootPathName, + lpSectorsPerCluster, + lpBytesPerSector, + lpNumberOfFreeClusters, + lpTotalNumberOfClusters); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::GetDiskFreeSpaceW; + EventLogger::AppendValue(message, lpRootPathName); + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + BOOL WINAPI GetDiskFreeSpaceExA( + LPCSTR lpDirectoryName, + PULARGE_INTEGER lpFreeBytesAvailableToCaller, + PULARGE_INTEGER lpTotalNumberOfBytes, + PULARGE_INTEGER lpTotalNumberOfFreeBytes) + { + BOOL result = 0; + __try + { + result = Cache::GetDiskFreeSpaceExA( + lpDirectoryName, + lpFreeBytesAvailableToCaller, + lpTotalNumberOfBytes, + lpTotalNumberOfFreeBytes); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::GetDiskFreeSpaceExA; + EventLogger::AppendValue(message, lpDirectoryName); + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + BOOL WINAPI GetDiskFreeSpaceExW( + LPCWSTR lpDirectoryName, + PULARGE_INTEGER lpFreeBytesAvailableToCaller, + PULARGE_INTEGER lpTotalNumberOfBytes, + PULARGE_INTEGER lpTotalNumberOfFreeBytes) + { + BOOL result = 0; + __try + { + result = Cache::GetDiskFreeSpaceExW( + lpDirectoryName, + lpFreeBytesAvailableToCaller, + lpTotalNumberOfBytes, + lpTotalNumberOfFreeBytes); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::GetDiskFreeSpaceExW; + EventLogger::AppendValue(message, lpDirectoryName); + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + UINT WINAPI GetDriveTypeA( + LPCSTR lpRootPathName) + { + UINT result = 0; + __try + { + result = Cache::GetDriveTypeA( + lpRootPathName); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::GetDriveTypeA; + EventLogger::AppendValue(message, lpRootPathName); + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + UINT WINAPI GetDriveTypeW( + LPCWSTR lpRootPathName) + { + UINT result = 0; + __try + { + result = Cache::GetDriveTypeW( + lpRootPathName); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::GetDriveTypeW; + EventLogger::AppendValue(message, lpRootPathName); + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + DWORD WINAPI GetFileAttributesA( + LPCSTR lpFileName) + { + bool result = 0; + __try + { + result = Cache::GetFileAttributesA( + lpFileName); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::GetFileAttributesA; + EventLogger::AppendValue(message, lpFileName); + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + DWORD WINAPI GetFileAttributesW( + LPCWSTR lpFileName) + { + DWORD result = 0; + __try + { + result = Cache::GetFileAttributesW( + lpFileName); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::GetFileAttributesW; + EventLogger::AppendValue(message, lpFileName); + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + BOOL WINAPI GetFileAttributesExA( + LPCSTR lpFileName, + GET_FILEEX_INFO_LEVELS fInfoLevelId, + LPVOID lpFileInformation) + { + BOOL result = 0; + __try + { + result = Cache::GetFileAttributesExA( + lpFileName, + fInfoLevelId, + lpFileInformation); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::GetFileAttributesExA; + EventLogger::AppendValue(message, lpFileName); + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + BOOL WINAPI GetFileAttributesExW( + LPCWSTR lpFileName, + GET_FILEEX_INFO_LEVELS fInfoLevelId, + LPVOID lpFileInformation) + { + BOOL result = 0; + __try + { + result = Cache::GetFileAttributesExW( + lpFileName, + fInfoLevelId, + lpFileInformation); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::GetFileAttributesExW; + EventLogger::AppendValue(message, lpFileName); + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + BOOL WINAPI GetFileInformationByHandle( + HANDLE hFile, + LPBY_HANDLE_FILE_INFORMATION lpFileInformation) + { + BOOL result = 0; + __try + { + result = Cache::GetFileInformationByHandle( + hFile, + lpFileInformation); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::GetFileInformationByHandle; + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + DWORD WINAPI GetFileSize( + HANDLE hFile, + LPDWORD lpFileSizeHigh) + { + DWORD result = 0; + __try + { + result = Cache::GetFileSize( + hFile, + lpFileSizeHigh); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::GetFileSize; + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + BOOL WINAPI GetFileSizeEx( + HANDLE hFile, + PLARGE_INTEGER lpFileSize) + { + BOOL result = 0; + __try + { + result = Cache::GetFileSizeEx( + hFile, + lpFileSize); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::GetFileSizeEx; + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + BOOL WINAPI GetFileTime( + HANDLE hFile, + LPFILETIME lpCreationTime, + LPFILETIME lpLastAccessTime, + LPFILETIME lpLastWriteTime) + { + BOOL result = 0; + __try + { + result = Cache::GetFileTime( + hFile, + lpCreationTime, + lpLastAccessTime, + lpLastWriteTime); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::GetFileTime; + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + DWORD WINAPI GetFileType( + HANDLE hFile) + { + DWORD result = 0; + __try + { + result = Cache::GetFileType( + hFile); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::GetFileType; + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + DWORD WINAPI GetFinalPathNameByHandleA( + HANDLE hFile, + LPSTR lpszFilePath, + DWORD cchFilePath, + DWORD dwFlags) + { + DWORD result = 0; + __try + { + result = Cache::GetFinalPathNameByHandleA( + hFile, + lpszFilePath, + cchFilePath, + dwFlags); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::GetFinalPathNameByHandleA; + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + DWORD WINAPI GetFinalPathNameByHandleW( + HANDLE hFile, + LPWSTR lpszFilePath, + DWORD cchFilePath, + DWORD dwFlags) + { + DWORD result = 0; + __try + { + result = Cache::GetFinalPathNameByHandleW( + hFile, + lpszFilePath, + cchFilePath, + dwFlags); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::GetFinalPathNameByHandleW; + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + DWORD WINAPI GetFullPathNameA( + LPCSTR lpFileName, + DWORD nBufferLength, + LPSTR lpBuffer, + LPSTR *lpFilePart) + { + DWORD result = 0; + __try + { + result = Cache::GetFullPathNameA( + lpFileName, + nBufferLength, + lpBuffer, + lpFilePart); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::GetFullPathNameA; + EventLogger::AppendValue(message, lpFileName); + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + DWORD WINAPI GetFullPathNameW( + LPCWSTR lpFileName, + DWORD nBufferLength, + LPWSTR lpBuffer, + LPWSTR *lpFilePart) + { + DWORD result = 0; + __try + { + result = Cache::GetFullPathNameW( + lpFileName, + nBufferLength, + lpBuffer, + lpFilePart); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::GetFullPathNameW; + EventLogger::AppendValue(message, lpFileName); + EventLogger::AppendValue(message, lpBuffer); + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + DWORD WINAPI GetLogicalDrives() + { + DWORD result = 0; + __try + { + result = Cache::GetLogicalDrives(); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::GetLogicalDrives; + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + DWORD WINAPI GetLogicalDriveStringsW( + DWORD nBufferLength, + LPWSTR lpBuffer) + { + DWORD result = 0; + __try + { + result = Cache::GetLogicalDriveStringsW( + nBufferLength, + lpBuffer); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::GetLogicalDriveStringsW; + EventLogger::AppendValue(message, lpBuffer); + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + DWORD WINAPI GetLongPathNameA( + LPCSTR lpszShortPath, + LPSTR lpszLongPath, + DWORD cchBuffer) + { + DWORD result = 0; + __try + { + result = Cache::GetLongPathNameA( + lpszShortPath, + lpszLongPath, + cchBuffer); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::GetLongPathNameA; + EventLogger::AppendValue(message, lpszShortPath); + EventLogger::AppendValue(message, lpszLongPath); + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + DWORD WINAPI GetLongPathNameW( + LPCWSTR lpszShortPath, + LPWSTR lpszLongPath, + DWORD cchBuffer) + { + DWORD result = 0; + __try + { + result = Cache::GetLongPathNameW( + lpszShortPath, + lpszLongPath, + cchBuffer); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::GetLongPathNameW; + EventLogger::AppendValue(message, lpszShortPath); + EventLogger::AppendValue(message, lpszLongPath); + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + DWORD WINAPI GetShortPathNameW( + LPCWSTR lpszLongPath, + LPWSTR lpszShortPath, + DWORD cchBuffer) + { + DWORD result = 0; + __try + { + result = Cache::GetShortPathNameW( + lpszLongPath, + lpszShortPath, + cchBuffer); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::GetShortPathNameW; + EventLogger::AppendValue(message, lpszLongPath); + EventLogger::AppendValue(message, lpszShortPath); + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + UINT WINAPI GetTempFileNameA( + LPCSTR lpPathName, + LPCSTR lpPrefixString, + UINT uUnique, + LPSTR lpTempFileName) + { + UINT result = 0; + __try + { + result = Cache::GetTempFileNameA( + lpPathName, + lpPrefixString, + uUnique, + lpTempFileName); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::GetTempFileNameA; + EventLogger::AppendValue(message, lpPathName); + EventLogger::AppendValue(message, lpPrefixString); + EventLogger::AppendValue(message, uUnique); + EventLogger::AppendValue(message, lpTempFileName); + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + UINT WINAPI GetTempFileNameW( + LPCWSTR lpPathName, + LPCWSTR lpPrefixString, + UINT uUnique, + LPWSTR lpTempFileName) + { + UINT result = 0; + __try + { + result = Cache::GetTempFileNameW( + lpPathName, + lpPrefixString, + uUnique, + lpTempFileName); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::GetTempFileNameW; + EventLogger::AppendValue(message, lpPathName); + EventLogger::AppendValue(message, lpPrefixString); + EventLogger::AppendValue(message, uUnique); + EventLogger::AppendValue(message, lpTempFileName); + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + DWORD WINAPI GetTempPathA( + DWORD nBufferLength, + LPSTR lpBuffer) + { + DWORD result = 0; + __try + { + result = Cache::GetTempPathA( + nBufferLength, + lpBuffer); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::GetTempPathA; + EventLogger::AppendValue(message, lpBuffer); + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + DWORD WINAPI GetTempPathW( + DWORD nBufferLength, + LPWSTR lpBuffer) + { + DWORD result = 0; + __try + { + result = Cache::GetTempPathW( + nBufferLength, + lpBuffer); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::GetTempPathW; + EventLogger::AppendValue(message, lpBuffer); + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + BOOL WINAPI GetVolumeInformationA( + LPCSTR lpRootPathName, + LPSTR lpVolumeNameBuffer, + DWORD nVolumeNameSize, + LPDWORD lpVolumeSerialNumber, + LPDWORD lpMaximumComponentLength, + LPDWORD lpFileSystemFlags, + LPSTR lpFileSystemNameBuffer, + DWORD nFileSystemNameSize) + { + BOOL result = 0; + __try + { + result = Cache::GetVolumeInformationA( + lpRootPathName, + lpVolumeNameBuffer, + nVolumeNameSize, + lpVolumeSerialNumber, + lpMaximumComponentLength, + lpFileSystemFlags, + lpFileSystemNameBuffer, + nFileSystemNameSize); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::GetVolumeInformationA; + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + BOOL WINAPI GetVolumeInformationW( + LPCWSTR lpRootPathName, + LPWSTR lpVolumeNameBuffer, + DWORD nVolumeNameSize, + LPDWORD lpVolumeSerialNumber, + LPDWORD lpMaximumComponentLength, + LPDWORD lpFileSystemFlags, + LPWSTR lpFileSystemNameBuffer, + DWORD nFileSystemNameSize) + { + BOOL result = 0; + __try + { + result = Cache::GetVolumeInformationW( + lpRootPathName, + lpVolumeNameBuffer, + nVolumeNameSize, + lpVolumeSerialNumber, + lpMaximumComponentLength, + lpFileSystemFlags, + lpFileSystemNameBuffer, + nFileSystemNameSize); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::GetVolumeInformationW; + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + BOOL WINAPI GetVolumeInformationByHandleW( + HANDLE hFile, + LPWSTR lpVolumeNameBuffer, + DWORD nVolumeNameSize, + LPDWORD lpVolumeSerialNumber, + LPDWORD lpMaximumComponentLength, + LPDWORD lpFileSystemFlags, + LPWSTR lpFileSystemNameBuffer, + DWORD nFileSystemNameSize) + { + BOOL result = 0; + __try + { + result = Cache::GetVolumeInformationByHandleW( + hFile, + lpVolumeNameBuffer, + nVolumeNameSize, + lpVolumeSerialNumber, + lpMaximumComponentLength, + lpFileSystemFlags, + lpFileSystemNameBuffer, + nFileSystemNameSize); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::GetVolumeInformationByHandleW; + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + BOOL WINAPI GetVolumeNameForVolumeMountPointW( + LPCWSTR lpszVolumeMountPoint, + LPWSTR lpszVolumeName, + DWORD cchBufferLength) + { + BOOL result = 0; + __try + { + result = Cache::GetVolumeNameForVolumeMountPointW( + lpszVolumeMountPoint, + lpszVolumeName, + cchBufferLength); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::GetVolumeNameForVolumeMountPointW; + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + BOOL WINAPI GetVolumePathNamesForVolumeNameW( + LPCWSTR lpszVolumeName, + LPWCH lpszVolumePathNames, + DWORD cchBufferLength, + PDWORD lpcchReturnLength) + { + BOOL result = 0; + __try + { + result = Cache::GetVolumePathNamesForVolumeNameW( + lpszVolumeName, + lpszVolumePathNames, + cchBufferLength, + lpcchReturnLength); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::GetVolumePathNamesForVolumeNameW; + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + BOOL WINAPI GetVolumePathNameW( + LPCWSTR lpszFileName, + LPWSTR lpszVolumePathName, + DWORD cchBufferLength) + { + BOOL result = 0; + __try + { + result = Cache::GetVolumePathNameW( + lpszFileName, + lpszVolumePathName, + cchBufferLength); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::GetVolumePathNameW; + EventLogger::AppendValue(message, lpszFileName); + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + BOOL WINAPI LocalFileTimeToFileTime( + const FILETIME *lpLocalFileTime, + LPFILETIME lpFileTime) + { + BOOL result = 0; + __try + { + result = Cache::LocalFileTimeToFileTime( + lpLocalFileTime, + lpFileTime); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::LocalFileTimeToFileTime; + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + BOOL WINAPI LockFile( + HANDLE hFile, + DWORD dwFileOffsetLow, + DWORD dwFileOffsetHigh, + DWORD nNumberOfBytesToLockLow, + DWORD nNumberOfBytesToLockHigh) + { + BOOL result = 0; + __try + { + result = Cache::LockFile( + hFile, + dwFileOffsetLow, + dwFileOffsetHigh, + nNumberOfBytesToLockLow, + nNumberOfBytesToLockHigh); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::LockFile; + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + BOOL WINAPI LockFileEx( + HANDLE hFile, + DWORD dwFlags, + DWORD dwReserved, + DWORD nNumberOfBytesToLockLow, + DWORD nNumberOfBytesToLockHigh, + LPOVERLAPPED lpOverlapped) + { + BOOL result = 0; + __try + { + result = Cache::LockFileEx( + hFile, + dwFlags, + dwReserved, + nNumberOfBytesToLockLow, + nNumberOfBytesToLockHigh, + lpOverlapped); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::LockFileEx; + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + DWORD WINAPI QueryDosDeviceW( + LPCWSTR lpDeviceName, + LPWSTR lpTargetPath, + DWORD ucchMax) + { + DWORD result = 0; + __try + { + result = Cache::QueryDosDeviceW( + lpDeviceName, + lpTargetPath, + ucchMax); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::QueryDosDeviceW; + EventLogger::AppendValue(message, lpDeviceName); + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + BOOL WINAPI ReadFile( + HANDLE hFile, + LPVOID lpBuffer, + DWORD nNumberOfBytesToRead, + LPDWORD lpNumberOfBytesRead, + LPOVERLAPPED lpOverlapped) + { + BOOL result = 0; + __try + { + result = Cache::ReadFile( + hFile, + lpBuffer, + nNumberOfBytesToRead, + lpNumberOfBytesRead, + lpOverlapped); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::ReadFile; + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + BOOL WINAPI ReadFileEx( + HANDLE hFile, + LPVOID lpBuffer, + DWORD nNumberOfBytesToRead, + LPOVERLAPPED lpOverlapped, + LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine) + { + BOOL result = 0; + __try + { + result = Cache::ReadFileEx( + hFile, + lpBuffer, + nNumberOfBytesToRead, + lpOverlapped, + lpCompletionRoutine); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::ReadFileEx; + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + BOOL WINAPI ReadFileScatter( + HANDLE hFile, + FILE_SEGMENT_ELEMENT aSegmentArray[], + DWORD nNumberOfBytesToRead, + LPDWORD lpReserved, + LPOVERLAPPED lpOverlapped) + { + BOOL result = 0; + __try + { + result = Cache::ReadFileScatter( + hFile, + aSegmentArray, + nNumberOfBytesToRead, + lpReserved, + lpOverlapped); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::ReadFileScatter; + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + BOOL WINAPI RemoveDirectoryA( + LPCSTR lpPathName) + { + BOOL result = 0; + __try + { + result = Cache::RemoveDirectoryA( + lpPathName); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::RemoveDirectoryA; + EventLogger::AppendValue(message, lpPathName); + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + BOOL WINAPI RemoveDirectoryW( + LPCWSTR lpPathName) + { + BOOL result = 0; + __try + { + result = Cache::RemoveDirectoryW( + lpPathName); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::RemoveDirectoryW; + EventLogger::AppendValue(message, lpPathName); + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + BOOL WINAPI SetEndOfFile( + HANDLE hFile) + { + BOOL result = 0; + __try + { + result = Cache::SetEndOfFile( + hFile); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::SetEndOfFile; + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + void WINAPI SetFileApisToANSI() + { + __try + { + Cache::SetFileApisToANSI(); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::SetFileApisToANSI; + EventLogger::WriteMessage(message); + } + } + + void WINAPI SetFileApisToOEM() + { + __try + { + Cache::SetFileApisToOEM(); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::SetFileApisToOEM; + EventLogger::WriteMessage(message); + } + } + + BOOL WINAPI SetFileAttributesA( + LPCSTR lpFileName, + DWORD dwFileAttributes) + { + BOOL result = 0; + __try + { + result = Cache::SetFileAttributesA( + lpFileName, + dwFileAttributes); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::SetFileAttributesA; + EventLogger::AppendValue(message, lpFileName); + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + BOOL WINAPI SetFileAttributesW( + LPCWSTR lpFileName, + DWORD dwFileAttributes) + { + BOOL result = 0; + __try + { + result = Cache::SetFileAttributesW( + lpFileName, + dwFileAttributes); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::SetFileAttributesW; + EventLogger::AppendValue(message, lpFileName); + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + BOOL WINAPI SetFileInformationByHandle( + HANDLE hFile, + FILE_INFO_BY_HANDLE_CLASS FileInformationClass, + LPVOID lpFileInformation, + DWORD dwBufferSize) + { + BOOL result = 0; + __try + { + result = Cache::SetFileInformationByHandle( + hFile, + FileInformationClass, + lpFileInformation, + dwBufferSize); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::SetFileInformationByHandle; + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + BOOL WINAPI SetFileIoOverlappedRange( + HANDLE FileHandle, + PUCHAR OverlappedRangeStart, + ULONG Length) + { + BOOL result = 0; + __try + { + result = Cache::SetFileIoOverlappedRange( + FileHandle, + OverlappedRangeStart, + Length); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::SetFileIoOverlappedRange; + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + DWORD WINAPI SetFilePointer( + HANDLE hFile, + LONG lDistanceToMove, + PLONG lpDistanceToMoveHigh, + DWORD dwMoveMethod) + { + DWORD result = 0; + __try + { + result = Cache::SetFilePointer( + hFile, + lDistanceToMove, + lpDistanceToMoveHigh, + dwMoveMethod); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::SetFilePointer; + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + BOOL WINAPI SetFilePointerEx( + HANDLE hFile, + LARGE_INTEGER liDistanceToMove, + PLARGE_INTEGER lpNewFilePointer, + DWORD dwMoveMethod) + { + BOOL result = 0; + __try + { + result = Cache::SetFilePointerEx( + hFile, + liDistanceToMove, + lpNewFilePointer, + dwMoveMethod); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::SetFilePointerEx; + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + BOOL WINAPI SetFileTime( + HANDLE hFile, + const FILETIME *lpCreationTime, + const FILETIME *lpLastAccessTime, + const FILETIME *lpLastWriteTime) + { + BOOL result = 0; + __try + { + result = Cache::SetFileTime( + hFile, + lpCreationTime, + lpLastAccessTime, + lpLastWriteTime); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::SetFileTime; + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + BOOL WINAPI SetFileValidData( + HANDLE hFile, + LONGLONG ValidDataLength) + { + BOOL result = 0; + __try + { + result = Cache::SetFileValidData( + hFile, + ValidDataLength); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::SetFileValidData; + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + BOOL WINAPI UnlockFile( + HANDLE hFile, + DWORD dwFileOffsetLow, + DWORD dwFileOffsetHigh, + DWORD nNumberOfBytesToUnlockLow, + DWORD nNumberOfBytesToUnlockHigh) + { + BOOL result = 0; + __try + { + result = Cache::UnlockFile( + hFile, + dwFileOffsetLow, + dwFileOffsetHigh, + nNumberOfBytesToUnlockLow, + nNumberOfBytesToUnlockHigh); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::UnlockFile; + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + BOOL WINAPI UnlockFileEx( + HANDLE hFile, + DWORD dwReserved, + DWORD nNumberOfBytesToUnlockLow, + DWORD nNumberOfBytesToUnlockHigh, + LPOVERLAPPED lpOverlapped) + { + BOOL result = 0; + __try + { + result = Cache::UnlockFileEx( + hFile, + dwReserved, + nNumberOfBytesToUnlockLow, + nNumberOfBytesToUnlockHigh, + lpOverlapped); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::UnlockFileEx; + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + BOOL WINAPI WriteFile( + HANDLE hFile, + LPCVOID lpBuffer, + DWORD nNumberOfBytesToWrite, + LPDWORD lpNumberOfBytesWritten, + LPOVERLAPPED lpOverlapped) + { + BOOL result = 0; + __try + { + result = Cache::WriteFile( + hFile, + lpBuffer, + nNumberOfBytesToWrite, + lpNumberOfBytesWritten, + lpOverlapped); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::WriteFile; + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + BOOL WINAPI WriteFileEx( + HANDLE hFile, + LPCVOID lpBuffer, + DWORD nNumberOfBytesToWrite, + LPOVERLAPPED lpOverlapped, + LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine) + { + BOOL result = 0; + __try + { + result = Cache::WriteFileEx( + hFile, + lpBuffer, + nNumberOfBytesToWrite, + lpOverlapped, + lpCompletionRoutine); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::WriteFileEx; + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + BOOL WINAPI WriteFileGather( + HANDLE hFile, + FILE_SEGMENT_ELEMENT aSegmentArray[], + DWORD nNumberOfBytesToWrite, + LPDWORD lpReserved, + LPOVERLAPPED lpOverlapped) + { + BOOL result = 0; + __try + { + result = Cache::WriteFileGather( + hFile, + aSegmentArray, + nNumberOfBytesToWrite, + lpReserved, + lpOverlapped); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::WriteFileGather; + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } +} \ No newline at end of file diff --git a/Source/Monitor/Detours/Functions/LibLoaderApiCache.h b/Source/Monitor/Detours/Functions/LibLoaderApiCache.h new file mode 100644 index 00000000..13e3a1dc --- /dev/null +++ b/Source/Monitor/Detours/Functions/LibLoaderApiCache.h @@ -0,0 +1,24 @@ +#pragma once + +namespace Functions::LibLoaderApi::Cache +{ + /// + /// Loads the specified module into the address space of the calling process. + /// + HMODULE (WINAPI* LoadLibraryA)( + LPCSTR lpLibFileName) = ::LoadLibraryA; + HMODULE (WINAPI* LoadLibraryW)( + LPCWSTR lpLibFileName) = ::LoadLibraryW; + + /// + /// Loads the specified module into the address space of the calling process. + /// + HMODULE (WINAPI* LoadLibraryExA)( + LPCSTR lpLibFileName, + HANDLE hFile, + DWORD dwFlags) = ::LoadLibraryExA; + HMODULE (WINAPI* LoadLibraryExW)( + LPCWSTR lpLibFileName, + HANDLE hFile, + DWORD dwFlags) = ::LoadLibraryExW; +} \ No newline at end of file diff --git a/Source/Monitor/Detours/Functions/LibLoaderApiOverrides.h b/Source/Monitor/Detours/Functions/LibLoaderApiOverrides.h new file mode 100644 index 00000000..7553e1da --- /dev/null +++ b/Source/Monitor/Detours/Functions/LibLoaderApiOverrides.h @@ -0,0 +1,93 @@ +#pragma once +#include "LibLoaderApiCache.h" + +namespace Functions::LibLoaderApi::Overrides +{ + HMODULE WINAPI LoadLibraryA( + LPCSTR lpLibFileName) + { + HMODULE result = 0; + __try + { + result = Cache::LoadLibraryA( + lpLibFileName); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::LoadLibraryA; + EventLogger::AppendValue(message, lpLibFileName); + EventLogger::WriteMessage(message); + } + + return result; + } + + HMODULE WINAPI LoadLibraryW( + LPCWSTR lpLibFileName) + { + HMODULE result = 0; + __try + { + result = Cache::LoadLibraryW( + lpLibFileName); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::LoadLibraryW; + EventLogger::AppendValue(message, lpLibFileName); + EventLogger::WriteMessage(message); + } + + return result; + } + + HMODULE WINAPI LoadLibraryExA( + LPCSTR lpLibFileName, + HANDLE hFile, + DWORD dwFlags) + { + HMODULE result = 0; + __try + { + result = Cache::LoadLibraryExA( + lpLibFileName, + hFile, + dwFlags); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::LoadLibraryExA; + EventLogger::AppendValue(message, lpLibFileName); + EventLogger::WriteMessage(message); + } + + return result; + } + + HMODULE WINAPI LoadLibraryExW( + LPCWSTR lpLibFileName, + HANDLE hFile, + DWORD dwFlags) + { + HMODULE result = 0; + __try + { + result = Cache::LoadLibraryExW( + lpLibFileName, + hFile, + dwFlags); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::LoadLibraryExW; + EventLogger::AppendValue(message, lpLibFileName); + EventLogger::WriteMessage(message); + } + + return result; + } +} \ No newline at end of file diff --git a/Source/Monitor/Detours/Functions/ProcessEnvCache.h b/Source/Monitor/Detours/Functions/ProcessEnvCache.h new file mode 100644 index 00000000..b7f3f693 --- /dev/null +++ b/Source/Monitor/Detours/Functions/ProcessEnvCache.h @@ -0,0 +1,22 @@ +#pragma once + +namespace Functions::ProcessEnv::Cache +{ + /// + /// Searches for a specified file in a specified path. + /// + DWORD (WINAPI* SearchPathA)( + LPCSTR lpPath, + LPCSTR lpFileName, + LPCSTR lpExtension, + DWORD nBufferLength, + LPSTR lpBuffer, + LPSTR *lpFilePart) = ::SearchPathA; + DWORD (WINAPI* SearchPathW)( + LPCWSTR lpPath, + LPCWSTR lpFileName, + LPCWSTR lpExtension, + DWORD nBufferLength, + LPWSTR lpBuffer, + LPWSTR *lpFilePart) = ::SearchPathW; +} \ No newline at end of file diff --git a/Source/Monitor/Detours/Functions/ProcessEnvOverrides.h b/Source/Monitor/Detours/Functions/ProcessEnvOverrides.h new file mode 100644 index 00000000..a68a76c2 --- /dev/null +++ b/Source/Monitor/Detours/Functions/ProcessEnvOverrides.h @@ -0,0 +1,71 @@ +#pragma once +#include "ProcessEnvCache.h" + +namespace Functions::ProcessEnv::Overrides +{ + DWORD WINAPI SearchPathA( + LPCSTR lpPath, + LPCSTR lpFileName, + LPCSTR lpExtension, + DWORD nBufferLength, + LPSTR lpBuffer, + LPSTR *lpFilePart) + { + DWORD result = 0; + __try + { + result = Cache::SearchPathA( + lpPath, + lpFileName, + lpExtension, + nBufferLength, + lpBuffer, + lpFilePart); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::SearchPathA; + EventLogger::AppendValue(message, lpPath); + EventLogger::AppendValue(message, lpFileName); + EventLogger::AppendValue(message, lpExtension); + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + DWORD WINAPI SearchPathW( + LPCWSTR lpPath, + LPCWSTR lpFileName, + LPCWSTR lpExtension, + DWORD nBufferLength, + LPWSTR lpBuffer, + LPWSTR *lpFilePart) + { + DWORD result = 0; + __try + { + result = Cache::SearchPathW( + lpPath, + lpFileName, + lpExtension, + nBufferLength, + lpBuffer, + lpFilePart); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::SearchPathW; + EventLogger::AppendValue(message, lpPath); + EventLogger::AppendValue(message, lpFileName); + EventLogger::AppendValue(message, lpExtension); + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } +} \ No newline at end of file diff --git a/Source/Monitor/Detours/Functions/ProcessThreadsApiCache.h b/Source/Monitor/Detours/Functions/ProcessThreadsApiCache.h new file mode 100644 index 00000000..d3ed2ec3 --- /dev/null +++ b/Source/Monitor/Detours/Functions/ProcessThreadsApiCache.h @@ -0,0 +1,66 @@ +#pragma once + +namespace Functions::ProcessThreadsApi::Cache +{ + /// + /// Creates a new process and its primary thread. The new process runs + /// in the security context of the calling process. + /// + BOOL (WINAPI* CreateProcessA)( + LPCSTR lpApplicationName, + LPSTR lpCommandLine, + LPSECURITY_ATTRIBUTES lpProcessAttributes, + LPSECURITY_ATTRIBUTES lpThreadAttributes, + BOOL bInheritHandles, + DWORD dwCreationFlags, + LPVOID lpEnvironment, + LPCSTR lpCurrentDirectory, + LPSTARTUPINFOA lpStartupInfo, + LPPROCESS_INFORMATION lpProcessInformation) = ::CreateProcessA; + BOOL (WINAPI* CreateProcessW)( + LPCWSTR lpApplicationName, + LPWSTR lpCommandLine, + LPSECURITY_ATTRIBUTES lpProcessAttributes, + LPSECURITY_ATTRIBUTES lpThreadAttributes, + BOOL bInheritHandles, + DWORD dwCreationFlags, + LPVOID lpEnvironment, + LPCWSTR lpCurrentDirectory, + LPSTARTUPINFOW lpStartupInfo, + LPPROCESS_INFORMATION lpProcessInformation) = ::CreateProcessW; + + /// + /// Creates a new process and its primary thread. The new process runs + /// in the security context of the user represented by the specified token. + /// + BOOL (WINAPI* CreateProcessAsUserA)( + HANDLE hToken, + LPCSTR lpApplicationName, + LPSTR lpCommandLine, + LPSECURITY_ATTRIBUTES lpProcessAttributes, + LPSECURITY_ATTRIBUTES lpThreadAttributes, + BOOL bInheritHandles, + DWORD dwCreationFlags, + LPVOID lpEnvironment, + LPCSTR lpCurrentDirectory, + LPSTARTUPINFOA lpStartupInfo, + LPPROCESS_INFORMATION lpProcessInformation) = ::CreateProcessAsUserA; + BOOL (WINAPI* CreateProcessAsUserW)( + HANDLE hToken, + LPCWSTR lpApplicationName, + LPWSTR lpCommandLine, + LPSECURITY_ATTRIBUTES lpProcessAttributes, + LPSECURITY_ATTRIBUTES lpThreadAttributes, + BOOL bInheritHandles, + DWORD dwCreationFlags, + LPVOID lpEnvironment, + LPCWSTR lpCurrentDirectory, + LPSTARTUPINFOW lpStartupInfo, + LPPROCESS_INFORMATION lpProcessInformation) = ::CreateProcessAsUserW; + + /// + /// Ends the calling process and all its threads. + /// + void (WINAPI* ExitProcess)( + UINT uExitCode) = ::ExitProcess; +} \ No newline at end of file diff --git a/Source/Monitor/Detours/Functions/ProcessThreadsApiOverrides.h b/Source/Monitor/Detours/Functions/ProcessThreadsApiOverrides.h new file mode 100644 index 00000000..43ad89c3 --- /dev/null +++ b/Source/Monitor/Detours/Functions/ProcessThreadsApiOverrides.h @@ -0,0 +1,248 @@ +#pragma once +#include "ProcessThreadsApiCache.h" + +namespace Functions::ProcessThreadsApi::Overrides +{ + BOOL WINAPI CreateProcessA( + LPCSTR lpApplicationName, + LPSTR lpCommandLine, + LPSECURITY_ATTRIBUTES lpProcessAttributes, + LPSECURITY_ATTRIBUTES lpThreadAttributes, + BOOL bInheritHandles, + DWORD dwCreationFlags, + LPVOID lpEnvironment, + LPCSTR lpCurrentDirectory, + LPSTARTUPINFOA lpStartupInfo, + LPPROCESS_INFORMATION lpProcessInformation) + { + BOOL result = 0; + __try + { + // If the caller did not request the process information then create a temporary + // one for ourselves + LPPROCESS_INFORMATION lpInternalProcessInformation = lpProcessInformation; + PROCESS_INFORMATION privateProcessInformation; + if (lpInternalProcessInformation == nullptr) + { + lpInternalProcessInformation = &privateProcessInformation; + } + + // Pass along the request with an initially suspended process + result = DetourCreateProcessWithDllExA( + lpApplicationName, + lpCommandLine, + lpProcessAttributes, + lpThreadAttributes, + bInheritHandles, + dwCreationFlags | CREATE_SUSPENDED, + lpEnvironment, + lpCurrentDirectory, + lpStartupInfo, + lpInternalProcessInformation, + s_szDllPath, + Cache::CreateProcessA); + + if (result) + { + // Perform the detour setup + CreateProcessInternals(lpInternalProcessInformation->hProcess); + + // If the caller did not create the process suspended then undo our override + if (!(dwCreationFlags & CREATE_SUSPENDED)) + { + ResumeThread(lpInternalProcessInformation->hThread); + } + + // Cleanup if we used the private information store + if (lpInternalProcessInformation == &privateProcessInformation) + { + CloseHandle(privateProcessInformation.hThread); + CloseHandle(privateProcessInformation.hProcess); + } + } + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::CreateProcessA; + EventLogger::AppendValue(message, lpApplicationName); + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + BOOL WINAPI CreateProcessW( + LPCWSTR lpApplicationName, + LPWSTR lpCommandLine, + LPSECURITY_ATTRIBUTES lpProcessAttributes, + LPSECURITY_ATTRIBUTES lpThreadAttributes, + BOOL bInheritHandles, + DWORD dwCreationFlags, + LPVOID lpEnvironment, + LPCWSTR lpCurrentDirectory, + LPSTARTUPINFOW lpStartupInfo, + LPPROCESS_INFORMATION lpProcessInformation) + { + BOOL result = 0; + __try + { + // If the caller did not request the process information then create a temporary + // one for ourselves + LPPROCESS_INFORMATION lpInternalProcessInformation = lpProcessInformation; + PROCESS_INFORMATION privateProcessInformation; + if (lpInternalProcessInformation == nullptr) + { + lpInternalProcessInformation = &privateProcessInformation; + } + + // Pass along the request with an initially suspended process + result = DetourCreateProcessWithDllExW( + lpApplicationName, + lpCommandLine, + lpProcessAttributes, + lpThreadAttributes, + bInheritHandles, + dwCreationFlags | CREATE_SUSPENDED, + lpEnvironment, + lpCurrentDirectory, + lpStartupInfo, + lpInternalProcessInformation, + s_szDllPath, + Cache::CreateProcessW); + + if (result) + { + // Perform the detour setup + CreateProcessInternals(lpInternalProcessInformation->hProcess); + + // If the caller did not create the process suspended then undo our override + if (!(dwCreationFlags & CREATE_SUSPENDED)) + { + ResumeThread(lpInternalProcessInformation->hThread); + } + + // Cleanup if we used the private information store + if (lpInternalProcessInformation == &privateProcessInformation) + { + CloseHandle(privateProcessInformation.hThread); + CloseHandle(privateProcessInformation.hProcess); + } + } + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::CreateProcessW; + EventLogger::AppendValue(message, lpApplicationName); + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + BOOL WINAPI CreateProcessAsUserA( + HANDLE hToken, + LPCSTR lpApplicationName, + LPSTR lpCommandLine, + LPSECURITY_ATTRIBUTES lpProcessAttributes, + LPSECURITY_ATTRIBUTES lpThreadAttributes, + BOOL bInheritHandles, + DWORD dwCreationFlags, + LPVOID lpEnvironment, + LPCSTR lpCurrentDirectory, + LPSTARTUPINFOA lpStartupInfo, + LPPROCESS_INFORMATION lpProcessInformation) + { + BOOL result = 0; + __try + { + result = Cache::CreateProcessAsUserA( + hToken, + lpApplicationName, + lpCommandLine, + lpProcessAttributes, + lpThreadAttributes, + bInheritHandles, + dwCreationFlags, + lpEnvironment, + lpCurrentDirectory, + lpStartupInfo, + lpProcessInformation); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::CreateProcessAsUserA; + EventLogger::AppendValue(message, lpApplicationName); + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + + // TODO + EventLogger::WriteError("Cannot detour process from CreateProcessAsUserA"); + } + + return result; + } + + BOOL WINAPI CreateProcessAsUserW( + HANDLE hToken, + LPCWSTR lpApplicationName, + LPWSTR lpCommandLine, + LPSECURITY_ATTRIBUTES lpProcessAttributes, + LPSECURITY_ATTRIBUTES lpThreadAttributes, + BOOL bInheritHandles, + DWORD dwCreationFlags, + LPVOID lpEnvironment, + LPCWSTR lpCurrentDirectory, + LPSTARTUPINFOW lpStartupInfo, + LPPROCESS_INFORMATION lpProcessInformation) + { + BOOL result = 0; + __try + { + result = Cache::CreateProcessAsUserW( + hToken, + lpApplicationName, + lpCommandLine, + lpProcessAttributes, + lpThreadAttributes, + bInheritHandles, + dwCreationFlags, + lpEnvironment, + lpCurrentDirectory, + lpStartupInfo, + lpProcessInformation); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::CreateProcessAsUserW; + EventLogger::AppendValue(message, lpApplicationName); + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + + // TODO + EventLogger::WriteError("Cannot detour process from CreateProcessAsUserW"); + } + + return result; + } + + void WINAPI ExitProcess(UINT uExitCode) + { + __try + { + Cache::ExitProcess(uExitCode); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::ExitProcess; + EventLogger::AppendValue(message, uExitCode); + EventLogger::WriteMessage(message); + } + } +} \ No newline at end of file diff --git a/Source/Monitor/Detours/Functions/UndocumentedApiCache.h b/Source/Monitor/Detours/Functions/UndocumentedApiCache.h new file mode 100644 index 00000000..1271c2e3 --- /dev/null +++ b/Source/Monitor/Detours/Functions/UndocumentedApiCache.h @@ -0,0 +1,28 @@ +#pragma once + +namespace Functions::UndocumentedApi::Cache +{ + /// + /// Entry Point + /// + int (WINAPI* EntryPoint)() = nullptr; + + /// + /// Undocumented api for copy + /// Note: Used in xcopy + /// + BOOL (WINAPI* PrivCopyFileExA)( + LPCSTR lpExistingFileName, + LPCSTR lpNewFileName, + LPPROGRESS_ROUTINE lpProgressRoutine, + LPVOID lpData, + LPBOOL pbCancel, + DWORD dwCopyFlags) = nullptr; + BOOL (WINAPI* PrivCopyFileExW)( + LPCWSTR lpExistingFileName, + LPCWSTR lpNewFileName, + LPPROGRESS_ROUTINE lpProgressRoutine, + LPVOID lpData, + LPBOOL pbCancel, + DWORD dwCopyFlags) = nullptr; +} \ No newline at end of file diff --git a/Source/Monitor/Detours/Functions/UndocumentedApiOverrides.h b/Source/Monitor/Detours/Functions/UndocumentedApiOverrides.h new file mode 100644 index 00000000..47e35fff --- /dev/null +++ b/Source/Monitor/Detours/Functions/UndocumentedApiOverrides.h @@ -0,0 +1,76 @@ +#pragma once +#include "UndocumentedApiCache.h" + +namespace Functions::UndocumentedApi::Overrides +{ + int WINAPI EntryPoint(void) + { + EventLogger::Initialize(); + + return Cache::EntryPoint(); + } + + BOOL WINAPI PrivCopyFileExA( + LPCSTR lpExistingFileName, + LPCSTR lpNewFileName, + LPPROGRESS_ROUTINE lpProgressRoutine, + LPVOID lpData, + LPBOOL pbCancel, + DWORD dwCopyFlags) + { + bool result = 0; + __try + { + result = Cache::PrivCopyFileExA( + lpExistingFileName, + lpNewFileName, + lpProgressRoutine, + lpData, + pbCancel, + dwCopyFlags); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::PrivCopyFileExA; + EventLogger::AppendValue(message, lpExistingFileName); + EventLogger::AppendValue(message, lpNewFileName); + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + BOOL WINAPI PrivCopyFileExW( + LPCWSTR lpExistingFileName, + LPCWSTR lpNewFileName, + LPPROGRESS_ROUTINE lpProgressRoutine, + LPVOID lpData, + LPBOOL pbCancel, + DWORD dwCopyFlags) + { + bool result = 0; + __try + { + result = Cache::PrivCopyFileExW( + lpExistingFileName, + lpNewFileName, + lpProgressRoutine, + lpData, + pbCancel, + dwCopyFlags); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::PrivCopyFileExW; + EventLogger::AppendValue(message, lpExistingFileName); + EventLogger::AppendValue(message, lpNewFileName); + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } +} \ No newline at end of file diff --git a/Source/Monitor/Detours/Functions/WinBaseCache.h b/Source/Monitor/Detours/Functions/WinBaseCache.h new file mode 100644 index 00000000..679f710d --- /dev/null +++ b/Source/Monitor/Detours/Functions/WinBaseCache.h @@ -0,0 +1,657 @@ +#pragma once + +namespace Functions::WinBase::Cache +{ + /// + /// Copies an existing file to a new file. + /// + BOOL (WINAPI* CopyFileA)( + LPCSTR lpExistingFileName, + LPCSTR lpNewFileName, + BOOL bFailIfExists) = ::CopyFileA; + BOOL (WINAPI* CopyFileW)( + LPCWSTR lpExistingFileName, + LPCWSTR lpNewFileName, + BOOL bFailIfExists) = ::CopyFileW; + + /// + /// Copies an existing file to a new file, notifying the application of its progress through a callback function. + /// + HRESULT (WINAPI* CopyFile2)( + PCWSTR pwszExistingFileName, + PCWSTR pwszNewFileName, + COPYFILE2_EXTENDED_PARAMETERS *pExtendedParameters) = ::CopyFile2; + + /// + /// Copies an existing file to a new file, notifying the application of its progress + /// through a callback function. + /// + BOOL (WINAPI* CopyFileExA)( + LPCSTR lpExistingFileName, + LPCSTR lpNewFileName, + LPPROGRESS_ROUTINE lpProgressRoutine, + LPVOID lpData, + LPBOOL pbCancel, + DWORD dwCopyFlags) = ::CopyFileExA; + BOOL (WINAPI* CopyFileExW)( + LPCWSTR lpExistingFileName, + LPCWSTR lpNewFileName, + LPPROGRESS_ROUTINE lpProgressRoutine, + LPVOID lpData, + LPBOOL pbCancel, + DWORD dwCopyFlags) = ::CopyFileExW; + + /// + /// Copies an existing file to a new file as a transacted operation, notifying the + /// application of its progress through a callback function. + /// + BOOL (WINAPI* CopyFileTransactedA)( + LPCSTR lpExistingFileName, + LPCSTR lpNewFileName, + LPPROGRESS_ROUTINE lpProgressRoutine, + LPVOID lpData, + LPBOOL pbCancel, + DWORD dwCopyFlags, + HANDLE hTransaction) = ::CopyFileTransactedA; + BOOL (WINAPI* CopyFileTransactedW)( + LPCWSTR lpExistingFileName, + LPCWSTR lpNewFileName, + LPPROGRESS_ROUTINE lpProgressRoutine, + LPVOID lpData, + LPBOOL pbCancel, + DWORD dwCopyFlags, + HANDLE hTransaction) = ::CopyFileTransactedW; + + /// + /// Creates a new directory. + /// + BOOL (WINAPI* CreateDirectoryExA)( + LPCSTR lpTemplateDirectory, + LPCSTR lpNewDirectory, + LPSECURITY_ATTRIBUTES lpSecurityAttributes) = ::CreateDirectoryExA; + BOOL (WINAPI* CreateDirectoryExW)( + LPCWSTR lpTemplateDirectory, + LPCWSTR lpNewDirectory, + LPSECURITY_ATTRIBUTES lpSecurityAttributes) = ::CreateDirectoryExW; + + /// + /// Creates a new directory as a transacted operation, with the + /// attributes of a specified template directory. + /// + BOOL (WINAPI* CreateDirectoryTransactedA)( + LPCSTR lpTemplateDirectory, + LPCSTR lpNewDirectory, + LPSECURITY_ATTRIBUTES lpSecurityAttributes, + HANDLE hTransaction) = ::CreateDirectoryTransactedA; + BOOL (WINAPI* CreateDirectoryTransactedW)( + LPCWSTR lpTemplateDirectory, + LPCWSTR lpNewDirectory, + LPSECURITY_ATTRIBUTES lpSecurityAttributes, + HANDLE hTransaction) = ::CreateDirectoryTransactedW; + + /// + /// Creates or opens a file, file stream, or directory as a transacted operation. + /// + HANDLE (WINAPI* CreateFileTransactedA)( + LPCSTR lpFileName, + DWORD dwDesiredAccess, + DWORD dwShareMode, + LPSECURITY_ATTRIBUTES lpSecurityAttributes, + DWORD dwCreationDisposition, + DWORD dwFlagsAndAttributes, + HANDLE hTemplateFile, + HANDLE hTransaction, + PUSHORT pusMiniVersion, + PVOID lpExtendedParameter) = ::CreateFileTransactedA; + HANDLE (WINAPI* CreateFileTransactedW)( + LPCWSTR lpFileName, + DWORD dwDesiredAccess, + DWORD dwShareMode, + LPSECURITY_ATTRIBUTES lpSecurityAttributes, + DWORD dwCreationDisposition, + DWORD dwFlagsAndAttributes, + HANDLE hTemplateFile, + HANDLE hTransaction, + PUSHORT pusMiniVersion, + PVOID lpExtendedParameter) = ::CreateFileTransactedW; + + /// + /// Establishes a hard link between an existing file and a new file. + /// + BOOL (WINAPI* CreateHardLinkA)( + LPCSTR lpFileName, + LPCSTR lpExistingFileName, + LPSECURITY_ATTRIBUTES lpSecurityAttributes) = ::CreateHardLinkA; + BOOL (WINAPI* CreateHardLinkW)( + LPCWSTR lpFileName, + LPCWSTR lpExistingFileName, + LPSECURITY_ATTRIBUTES lpSecurityAttributes) = ::CreateHardLinkW; + + /// + /// Establishes a hard link between an existing file and a new file as a transacted operation. + /// + BOOL (WINAPI* CreateHardLinkTransactedA)( + LPCSTR lpFileName, + LPCSTR lpExistingFileName, + LPSECURITY_ATTRIBUTES lpSecurityAttributes, + HANDLE hTransaction) = ::CreateHardLinkTransactedA; + BOOL (WINAPI* CreateHardLinkTransactedW)( + LPCWSTR lpFileName, + LPCWSTR lpExistingFileName, + LPSECURITY_ATTRIBUTES lpSecurityAttributes, + HANDLE hTransaction) = ::CreateHardLinkTransactedW; + + /// + /// Creates a new process and its primary thread. Then the new process runs the specified + /// executable file in the security context of the specified credentials (user, domain, and password). + /// It can optionally load the user profile for a specified user. + /// + BOOL (WINAPI* CreateProcessWithLogonW)( + LPCWSTR lpUsername, + LPCWSTR lpDomain, + LPCWSTR lpPassword, + DWORD dwLogonFlags, + LPCWSTR lpApplicationName, + LPWSTR lpCommandLine, + DWORD dwCreationFlags, + LPVOID lpEnvironment, + LPCWSTR lpCurrentDirectory, + LPSTARTUPINFOW lpStartupInfo, + LPPROCESS_INFORMATION lpProcessInformation) = ::CreateProcessWithLogonW; + + /// + /// Creates a new process and its primary thread. The new process runs in the security context of + /// the specified token. It can optionally load the user profile for the specified user. + /// + BOOL (WINAPI* CreateProcessWithTokenW)( + HANDLE hToken, + DWORD dwLogonFlags, + LPCWSTR lpApplicationName, + LPWSTR lpCommandLine, + DWORD dwCreationFlags, + LPVOID lpEnvironment, + LPCWSTR lpCurrentDirectory, + LPSTARTUPINFOW lpStartupInfo, + LPPROCESS_INFORMATION lpProcessInformation) = ::CreateProcessWithTokenW; + + /// + /// Creates a symbolic link. + /// + BOOLEAN (WINAPI* CreateSymbolicLinkA)( + LPCSTR lpSymlinkFileName, + LPCSTR lpTargetFileName, + DWORD dwFlags) = ::CreateSymbolicLinkA; + BOOLEAN (WINAPI* CreateSymbolicLinkW)( + LPCWSTR lpSymlinkFileName, + LPCWSTR lpTargetFileName, + DWORD dwFlags) = ::CreateSymbolicLinkW; + + /// + /// Creates a symbolic link as a transacted operation. + /// + BOOLEAN (WINAPI* CreateSymbolicLinkTransactedA)( + LPCSTR lpSymlinkFileName, + LPCSTR lpTargetFileName, + DWORD dwFlags, + HANDLE hTransaction) = ::CreateSymbolicLinkTransactedA; + BOOLEAN (WINAPI* CreateSymbolicLinkTransactedW)( + LPCWSTR lpSymlinkFileName, + LPCWSTR lpTargetFileName, + DWORD dwFlags, + HANDLE hTransaction) = ::CreateSymbolicLinkTransactedW; + + /// + /// Decrypts an encrypted file or directory. + /// + BOOL (WINAPI* DecryptFileA)( + LPCSTR lpFileName, + DWORD dwReserved) = ::DecryptFileA; + BOOL (WINAPI* DecryptFileW)( + LPCWSTR lpFileName, + DWORD dwReserved) = ::DecryptFileW; + + /// + /// Deletes an existing file. + /// + BOOL (WINAPI* DeleteFile)( + LPCSTR lpFileName) = ::DeleteFile; + + /// + /// Deletes an existing file as a transacted operation. + /// + BOOL (WINAPI* DeleteFileTransactedA)( + LPCSTR lpFileName, + HANDLE hTransaction) = ::DeleteFileTransactedA; + BOOL (WINAPI* DeleteFileTransactedW)( + LPCWSTR lpFileName, + HANDLE hTransaction) = ::DeleteFileTransactedW; + + /// + /// Encrypts a file or directory. + /// + BOOL (WINAPI* EncryptFileA)( + LPCSTR lpFileName) = ::EncryptFileA; + BOOL (WINAPI* EncryptFileW)( + LPCWSTR lpFileName) = ::EncryptFileW; + + /// + /// Retrieves the encryption status of the specified file. + /// + BOOL (WINAPI* FileEncryptionStatusA)( + LPCSTR lpFileName, + LPDWORD lpStatus) = ::FileEncryptionStatusA; + BOOL (WINAPI* FileEncryptionStatusW)( + LPCWSTR lpFileName, + LPDWORD lpStatus) = ::FileEncryptionStatusW; + + /// + /// Creates an enumeration of all the hard links to the specified file as a transacted operation. + /// The function returns a handle to the enumeration that can be used on subsequent calls to the FindNextFileNameW function. + /// + HANDLE (WINAPI* FindFirstFileNameTransactedW)( + LPCWSTR lpFileName, + DWORD dwFlags, + LPDWORD StringLength, + PWSTR LinkName, + HANDLE hTransaction) = ::FindFirstFileNameTransactedW; + + /// + /// Searches a directory for a file or subdirectory with a name that matches a specific name as a transacted operation. + /// + HANDLE (WINAPI* FindFirstFileTransactedA)( + LPCSTR lpFileName, + FINDEX_INFO_LEVELS fInfoLevelId, + LPVOID lpFindFileData, + FINDEX_SEARCH_OPS fSearchOp, + LPVOID lpSearchFilter, + DWORD dwAdditionalFlags, + HANDLE hTransaction) = ::FindFirstFileTransactedA; + HANDLE (WINAPI* FindFirstFileTransactedW)( + LPCWSTR lpFileName, + FINDEX_INFO_LEVELS fInfoLevelId, + LPVOID lpFindFileData, + FINDEX_SEARCH_OPS fSearchOp, + LPVOID lpSearchFilter, + DWORD dwAdditionalFlags, + HANDLE hTransaction) = ::FindFirstFileTransactedW; + + /// + /// Enumerates the first stream in the specified file or directory as a transacted operation. + /// + HANDLE (WINAPI* FindFirstStreamTransactedW)( + LPCWSTR lpFileName, + STREAM_INFO_LEVELS InfoLevel, + LPVOID lpFindStreamData, + DWORD dwFlags, + HANDLE hTransaction) = ::FindFirstStreamTransactedW; + + /// + /// Determines whether a file is an executable (.exe) file, and if so, which subsystem runs the executable file. + /// + BOOL (WINAPI* GetBinaryTypeA)( + LPCSTR lpApplicationName, + LPDWORD lpBinaryType) = ::GetBinaryTypeA; + BOOL (WINAPI* GetBinaryTypeW)( + LPCWSTR lpApplicationName, + LPDWORD lpBinaryType) = ::GetBinaryTypeW; + + /// + /// Retrieves the actual number of bytes of disk storage used to store a specified file as a transacted operation. + /// + DWORD (WINAPI* GetCompressedFileSizeTransactedA)( + LPCSTR lpFileName, + LPDWORD lpFileSizeHigh, + HANDLE hTransaction) = ::GetCompressedFileSizeTransactedA; + DWORD (WINAPI* GetCompressedFileSizeTransactedW)( + LPCWSTR lpFileName, + LPDWORD lpFileSizeHigh, + HANDLE hTransaction) = ::GetCompressedFileSizeTransactedW; + + /// + /// Retrieves the application-specific portion of the search path used to locate DLLs for the application. + /// + DWORD (WINAPI* GetDllDirectoryA)( + DWORD nBufferLength, + LPSTR lpBuffer) = ::GetDllDirectoryA; + DWORD (WINAPI* GetDllDirectoryW)( + DWORD nBufferLength, + LPWSTR lpBuffer) = ::GetDllDirectoryW; + + /// + /// Retrieves file system attributes for a specified file or directory as a transacted operation. + /// + BOOL (WINAPI* GetFileAttributesTransactedA)( + LPCSTR lpFileName, + GET_FILEEX_INFO_LEVELS fInfoLevelId, + LPVOID lpFileInformation, + HANDLE hTransaction) = ::GetFileAttributesTransactedA; + BOOL (WINAPI* GetFileAttributesTransactedW)( + LPCWSTR lpFileName, + GET_FILEEX_INFO_LEVELS fInfoLevelId, + LPVOID lpFileInformation, + HANDLE hTransaction) = ::GetFileAttributesTransactedW; + + /// + /// Retrieves the bandwidth reservation properties of the volume on which the specified file resides. + /// + BOOL (WINAPI* GetFileBandwidthReservation)( + HANDLE hFile, + LPDWORD lpPeriodMilliseconds, + LPDWORD lpBytesPerPeriod, + LPBOOL pDiscardable, + LPDWORD lpTransferSize, + LPDWORD lpNumOutstandingRequests) = ::GetFileBandwidthReservation; + + /// + /// Retrieves file information for the specified file. + /// + BOOL (WINAPI* GetFileInformationByHandleEx)( + HANDLE hFile, + FILE_INFO_BY_HANDLE_CLASS FileInformationClass, + LPVOID lpFileInformation, + DWORD dwBufferSize) = ::GetFileInformationByHandleEx; + + /// + /// Obtains specified information about the security of a file or directory. The information obtained is constrained by the caller's access rights and privileges. + /// + BOOL (WINAPI* GetFileSecurityA)( + LPCSTR lpFileName, + SECURITY_INFORMATION RequestedInformation, + PSECURITY_DESCRIPTOR pSecurityDescriptor, + DWORD nLength, + LPDWORD lpnLengthNeeded) = ::GetFileSecurityA; + + /// + /// Retrieves the full path and file name of the specified file as a transacted operation. + /// + DWORD (WINAPI* GetFullPathNameTransactedA)( + LPCSTR lpFileName, + DWORD nBufferLength, + LPSTR lpBuffer, + LPSTR *lpFilePart, + HANDLE hTransaction) = ::GetFullPathNameTransactedA; + DWORD (WINAPI* GetFullPathNameTransactedW)( + LPCWSTR lpFileName, + DWORD nBufferLength, + LPWSTR lpBuffer, + LPWSTR *lpFilePart, + HANDLE hTransaction) = ::GetFullPathNameTransactedW; + + /// + /// Converts the specified path to its long form as a transacted operation. + /// + DWORD (WINAPI* GetLongPathNameTransactedA)( + LPCSTR lpszShortPath, + LPSTR lpszLongPath, + DWORD cchBuffer, + HANDLE hTransaction) = ::GetLongPathNameTransactedA; + DWORD (WINAPI* GetLongPathNameTransactedW)( + LPCWSTR lpszShortPath, + LPWSTR lpszLongPath, + DWORD cchBuffer, + HANDLE hTransaction) = ::GetLongPathNameTransactedW; + + /// + /// Attempts to dequeue an I/O completion packet from the specified I/O completion port. + /// + BOOL (WINAPI* GetQueuedCompletionStatus)( + HANDLE CompletionPort, + LPDWORD lpNumberOfBytesTransferred, + PULONG_PTR lpCompletionKey, + LPOVERLAPPED *lpOverlapped, + DWORD dwMilliseconds) = ::GetQueuedCompletionStatus; + + /// + /// Retrieves multiple completion port entries simultaneously. + /// + BOOL (WINAPI* GetQueuedCompletionStatusEx)( + HANDLE CompletionPort, + LPOVERLAPPED_ENTRY lpCompletionPortEntries, + ULONG ulCount, + PULONG ulNumEntriesRemoved, + DWORD dwMilliseconds, + BOOL fAlertable) = ::GetQueuedCompletionStatusEx; + + /// + /// Retrieves the short path form of the specified path. + /// + DWORD (WINAPI* GetShortPathNameA)( + LPCSTR lpszLongPath, + LPSTR lpszShortPath, + DWORD cchBuffer) = ::GetShortPathNameA; + + /// + /// Creates a name for a temporary file. If a unique file name is generated, an empty + /// file is created and the handle to it is released; otherwise, only a file name is generated. + /// + UINT (WINAPI* GetTempFileName)( + LPCSTR lpPathName, + LPCSTR lpPrefixString, + UINT uUnique, + LPSTR lpTempFileName) = ::GetTempFileName; + + /// + /// Loads and executes an application or creates a new instance of an existing application. + /// + DWORD (WINAPI* LoadModule)( + LPCSTR lpModuleName, + LPVOID lpParameterBlock) = ::LoadModule; + + /// + /// Loads the specified packaged module and its dependencies into the address space of the calling process. + /// + HMODULE (WINAPI* LoadPackagedLibrary)( + LPCWSTR lpwLibFileName, + DWORD Reserved) = ::LoadPackagedLibrary; + + /// + /// Moves an existing file or a directory, including its children. + /// + BOOL (WINAPI* MoveFileA)( + LPCSTR lpExistingFileName, + LPCSTR lpNewFileName) = ::MoveFileA; + BOOL (WINAPI* MoveFileW)( + LPCWSTR lpExistingFileName, + LPCWSTR lpNewFileName) = ::MoveFileW; + + /// + /// Moves an existing file or directory, including its children, with various move options. + /// + BOOL (WINAPI* MoveFileExA)( + LPCSTR lpExistingFileName, + LPCSTR lpNewFileName, + DWORD dwFlags) = ::MoveFileExA; + BOOL (WINAPI* MoveFileExW)( + LPCWSTR lpExistingFileName, + LPCWSTR lpNewFileName, + DWORD dwFlags) = ::MoveFileExW; + + /// + /// Moves an existing file or a directory, including its children, as a transacted operation. + /// + BOOL (WINAPI* MoveFileTransactedA)( + LPCSTR lpExistingFileName, + LPCSTR lpNewFileName, + LPPROGRESS_ROUTINE lpProgressRoutine, + LPVOID lpData, + DWORD dwFlags, + HANDLE hTransaction) = ::MoveFileTransactedA; + BOOL (WINAPI* MoveFileTransactedW)( + LPCWSTR lpExistingFileName, + LPCWSTR lpNewFileName, + LPPROGRESS_ROUTINE lpProgressRoutine, + LPVOID lpData, + DWORD dwFlags, + HANDLE hTransaction) = ::MoveFileTransactedW; + + /// + /// Moves a file or directory, including its children. You can provide a callback function that receives progress notifications. + /// + BOOL (WINAPI* MoveFileWithProgressA)( + LPCSTR lpExistingFileName, + LPCSTR lpNewFileName, + LPPROGRESS_ROUTINE lpProgressRoutine, + LPVOID lpData, + DWORD dwFlags) = ::MoveFileWithProgressA; + BOOL (WINAPI* MoveFileWithProgressW)( + LPCWSTR lpExistingFileName, + LPCWSTR lpNewFileName, + LPPROGRESS_ROUTINE lpProgressRoutine, + LPVOID lpData, + DWORD dwFlags) = ::MoveFileWithProgressW; + + /// + /// Opens an encrypted file in order to backup (export) or restore (import) the file. + /// + DWORD (WINAPI* OpenEncryptedFileRawA)( + LPCSTR lpFileName, + ULONG ulFlags, + PVOID *pvContext) = ::OpenEncryptedFileRawA; + DWORD (WINAPI* OpenEncryptedFileRawW)( + LPCWSTR lpFileName, + ULONG ulFlags, + PVOID *pvContext) = ::OpenEncryptedFileRawW; + + /// + /// Creates, opens, reopens, or deletes a file. + /// + HFILE (WINAPI* OpenFile)( + LPCSTR lpFileName, + LPOFSTRUCT lpReOpenBuff, + UINT uStyle) = ::OpenFile; + + /// + /// Opens the file that matches the specified identifier. + /// + HANDLE (WINAPI* OpenFileById)( + HANDLE hVolumeHint, + LPFILE_ID_DESCRIPTOR lpFileId, + DWORD dwDesiredAccess, + DWORD dwShareMode, + LPSECURITY_ATTRIBUTES lpSecurityAttributes, + DWORD dwFlagsAndAttributes) = ::OpenFileById; + + /// + /// Backs up (export) encrypted files. + /// + DWORD (WINAPI* ReadEncryptedFileRaw)( + PFE_EXPORT_FUNC pfExportCallback, + PVOID pvCallbackContext, + PVOID pvContext) = ::ReadEncryptedFileRaw; + + /// + /// Deletes an existing empty directory as a transacted operation. + /// + BOOL (WINAPI* RemoveDirectoryTransactedA)( + LPCSTR lpPathName, + HANDLE hTransaction) = ::RemoveDirectoryTransactedA; + BOOL (WINAPI* RemoveDirectoryTransactedW)( + LPCWSTR lpPathName, + HANDLE hTransaction) = ::RemoveDirectoryTransactedW; + + /// + /// Reopens the specified file system object with different access rights, sharing mode, and flags. + /// + HANDLE (WINAPI* ReOpenFile)( + HANDLE hOriginalFile, + DWORD dwDesiredAccess, + DWORD dwShareMode, + DWORD dwFlagsAndAttributes) = ::ReOpenFile; + + /// + /// Replaces one file with another file, with the option of creating a backup copy of the original file. + /// + BOOL (WINAPI* ReplaceFileA)( + LPCSTR lpReplacedFileName, + LPCSTR lpReplacementFileName, + LPCSTR lpBackupFileName, + DWORD dwReplaceFlags, + LPVOID lpExclude, + LPVOID lpReserved) = ::ReplaceFileA; + BOOL (WINAPI* ReplaceFileW)( + LPCWSTR lpReplacedFileName, + LPCWSTR lpReplacementFileName, + LPCWSTR lpBackupFileName, + DWORD dwReplaceFlags, + LPVOID lpExclude, + LPVOID lpReserved) = ::ReplaceFileW; + + /// + /// Changes the current directory for the current process. + /// + BOOL (WINAPI* SetCurrentDirectoryA)( + LPCSTR lpPathName) = ::SetCurrentDirectoryA; + BOOL (WINAPI* SetCurrentDirectoryW)( + LPCWSTR lpPathName) = ::SetCurrentDirectoryW; + + /// + /// Adds a directory to the search path used to locate DLLs for the application. + /// + BOOL (WINAPI* SetDllDirectoryA)( + LPCSTR lpPathName) = ::SetDllDirectoryA; + BOOL (WINAPI* SetDllDirectoryW)( + LPCWSTR lpPathName) = ::SetDllDirectoryW; + + /// + /// Sets the attributes for a file or directory as a transacted operation. + /// + BOOL (WINAPI* SetFileAttributesTransactedA)( + LPCSTR lpFileName, + DWORD dwFileAttributes, + HANDLE hTransaction) = ::SetFileAttributesTransactedA; + BOOL (WINAPI* SetFileAttributesTransactedW)( + LPCWSTR lpFileName, + DWORD dwFileAttributes, + HANDLE hTransaction) = ::SetFileAttributesTransactedW; + + /// + /// Requests that bandwidth for the specified file stream be reserved. The reservation + /// is specified as a number of bytes in a period of milliseconds for I/O requests on the specified file handle. + /// + BOOL (WINAPI* SetFileBandwidthReservation)( + HANDLE hFile, + DWORD nPeriodMilliseconds, + DWORD nBytesPerPeriod, + BOOL bDiscardable, + LPDWORD lpTransferSize, + LPDWORD lpNumOutstandingRequests) = ::SetFileBandwidthReservation; + + /// + /// Sets the notification modes for a file handle, allowing you to specify how completion notifications work for the specified file. + /// + BOOL (WINAPI* SetFileCompletionNotificationModes)( + HANDLE FileHandle, + UCHAR Flags) = ::SetFileCompletionNotificationModes; + + /// + /// Sets the security of a file or directory object. + /// + BOOL (WINAPI* SetFileSecurityA)( + LPCSTR lpFileName, + SECURITY_INFORMATION SecurityInformation, + PSECURITY_DESCRIPTOR pSecurityDescriptor) = ::SetFileSecurityA; + + /// + /// Sets the short name for the specified file. + /// + BOOL (WINAPI* SetFileShortNameA)( + HANDLE hFile, + LPCSTR lpShortName) = ::SetFileShortNameA; + BOOL (WINAPI* SetFileShortNameW)( + HANDLE hFile, + LPCWSTR lpShortName) = ::SetFileShortNameW; + + /// + /// Sets the per-process mode that the SearchPath function uses when locating files. + /// + BOOL (WINAPI* SetSearchPathMode)( + DWORD Flags) = ::SetSearchPathMode; + + /// + /// Restores (import) encrypted files. + /// + DWORD (WINAPI* WriteEncryptedFileRaw)( + PFE_IMPORT_FUNC pfImportCallback, + PVOID pvCallbackContext, + PVOID pvContext) = ::WriteEncryptedFileRaw; +} \ No newline at end of file diff --git a/Source/Monitor/Detours/Functions/WinBaseOverrides.h b/Source/Monitor/Detours/Functions/WinBaseOverrides.h new file mode 100644 index 00000000..f1deab29 --- /dev/null +++ b/Source/Monitor/Detours/Functions/WinBaseOverrides.h @@ -0,0 +1,2356 @@ +#pragma once +#include "WinBaseCache.h" + +namespace Functions::WinBase::Overrides +{ + BOOL WINAPI CopyFileA( + LPCSTR lpExistingFileName, + LPCSTR lpNewFileName, + BOOL bFailIfExists) + { + BOOL result = 0; + __try + { + result = Cache::CopyFileA( + lpExistingFileName, + lpNewFileName, + bFailIfExists); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::CopyFileA; + EventLogger::AppendValue(message, lpExistingFileName); + EventLogger::AppendValue(message, lpNewFileName); + EventLogger::AppendValue(message, bFailIfExists); + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + BOOL WINAPI CopyFileW( + LPCWSTR lpExistingFileName, + LPCWSTR lpNewFileName, + BOOL bFailIfExists) + { + BOOL result = 0; + __try + { + result = Cache::CopyFileW( + lpExistingFileName, + lpNewFileName, + bFailIfExists); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::CopyFileW; + EventLogger::AppendValue(message, lpExistingFileName); + EventLogger::AppendValue(message, lpNewFileName); + EventLogger::AppendValue(message, bFailIfExists); + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + HRESULT WINAPI CopyFile2( + PCWSTR pwszExistingFileName, + PCWSTR pwszNewFileName, + COPYFILE2_EXTENDED_PARAMETERS *pExtendedParameters) + { + HRESULT result = 0; + __try + { + result = Cache::CopyFile2( + pwszExistingFileName, + pwszNewFileName, + pExtendedParameters); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::CopyFile2; + EventLogger::AppendValue(message, pwszExistingFileName); + EventLogger::AppendValue(message, pwszNewFileName); + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + BOOL WINAPI CopyFileExA( + LPCSTR lpExistingFileName, + LPCSTR lpNewFileName, + LPPROGRESS_ROUTINE lpProgressRoutine, + LPVOID lpData, + LPBOOL pbCancel, + DWORD dwCopyFlags) + { + BOOL result = 0; + __try + { + result = Cache::CopyFileExA( + lpExistingFileName, + lpNewFileName, + lpProgressRoutine, + lpData, + pbCancel, + dwCopyFlags); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::CopyFileExA; + EventLogger::AppendValue(message, lpExistingFileName); + EventLogger::AppendValue(message, lpNewFileName); + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + BOOL WINAPI CopyFileExW( + LPCWSTR lpExistingFileName, + LPCWSTR lpNewFileName, + LPPROGRESS_ROUTINE lpProgressRoutine, + LPVOID lpData, + LPBOOL pbCancel, + DWORD dwCopyFlags) + { + BOOL result = 0; + __try + { + result = Cache::CopyFileExW( + lpExistingFileName, + lpNewFileName, + lpProgressRoutine, + lpData, + pbCancel, + dwCopyFlags); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::CopyFileExW; + EventLogger::AppendValue(message, lpExistingFileName); + EventLogger::AppendValue(message, lpNewFileName); + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + BOOL WINAPI CopyFileTransactedA( + LPCSTR lpExistingFileName, + LPCSTR lpNewFileName, + LPPROGRESS_ROUTINE lpProgressRoutine, + LPVOID lpData, + LPBOOL pbCancel, + DWORD dwCopyFlags, + HANDLE hTransaction) + { + BOOL result = 0; + __try + { + result = Cache::CopyFileTransactedA( + lpExistingFileName, + lpNewFileName, + lpProgressRoutine, + lpData, + pbCancel, + dwCopyFlags, + hTransaction); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::CopyFileTransactedA; + EventLogger::AppendValue(message, lpExistingFileName); + EventLogger::AppendValue(message, lpNewFileName); + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + BOOL WINAPI CopyFileTransactedW( + LPCWSTR lpExistingFileName, + LPCWSTR lpNewFileName, + LPPROGRESS_ROUTINE lpProgressRoutine, + LPVOID lpData, + LPBOOL pbCancel, + DWORD dwCopyFlags, + HANDLE hTransaction) + { + BOOL result = 0; + __try + { + result = Cache::CopyFileTransactedW( + lpExistingFileName, + lpNewFileName, + lpProgressRoutine, + lpData, + pbCancel, + dwCopyFlags, + hTransaction); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::CopyFileTransactedW; + EventLogger::AppendValue(message, lpExistingFileName); + EventLogger::AppendValue(message, lpNewFileName); + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + BOOL WINAPI CreateDirectoryExA( + LPCSTR lpTemplateDirectory, + LPCSTR lpNewDirectory, + LPSECURITY_ATTRIBUTES lpSecurityAttributes) + { + BOOL result = 0; + __try + { + result = Cache::CreateDirectoryExA( + lpTemplateDirectory, + lpNewDirectory, + lpSecurityAttributes); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::CreateDirectoryExA; + EventLogger::AppendValue(message, lpTemplateDirectory); + EventLogger::AppendValue(message, lpNewDirectory); + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + BOOL WINAPI CreateDirectoryExW( + LPCWSTR lpTemplateDirectory, + LPCWSTR lpNewDirectory, + LPSECURITY_ATTRIBUTES lpSecurityAttributes) + { + BOOL result = 0; + __try + { + result = Cache::CreateDirectoryExW( + lpTemplateDirectory, + lpNewDirectory, + lpSecurityAttributes); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::CreateDirectoryExW; + EventLogger::AppendValue(message, lpTemplateDirectory); + EventLogger::AppendValue(message, lpNewDirectory); + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + BOOL WINAPI CreateDirectoryTransactedA( + LPCSTR lpTemplateDirectory, + LPCSTR lpNewDirectory, + LPSECURITY_ATTRIBUTES lpSecurityAttributes, + HANDLE hTransaction) + { + BOOL result = 0; + __try + { + result = Cache::CreateDirectoryTransactedA( + lpTemplateDirectory, + lpNewDirectory, + lpSecurityAttributes, + hTransaction); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::CreateDirectoryTransactedA; + EventLogger::AppendValue(message, lpTemplateDirectory); + EventLogger::AppendValue(message, lpNewDirectory); + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + BOOL WINAPI CreateDirectoryTransactedW( + LPCWSTR lpTemplateDirectory, + LPCWSTR lpNewDirectory, + LPSECURITY_ATTRIBUTES lpSecurityAttributes, + HANDLE hTransaction) + { + BOOL result = 0; + __try + { + result = Cache::CreateDirectoryTransactedW( + lpTemplateDirectory, + lpNewDirectory, + lpSecurityAttributes, + hTransaction); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::CreateDirectoryTransactedW; + EventLogger::AppendValue(message, lpTemplateDirectory); + EventLogger::AppendValue(message, lpNewDirectory); + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + HANDLE WINAPI CreateFileTransactedA( + LPCSTR lpFileName, + DWORD dwDesiredAccess, + DWORD dwShareMode, + LPSECURITY_ATTRIBUTES lpSecurityAttributes, + DWORD dwCreationDisposition, + DWORD dwFlagsAndAttributes, + HANDLE hTemplateFile, + HANDLE hTransaction, + PUSHORT pusMiniVersion, + PVOID lpExtendedParameter) + { + HANDLE result = 0; + __try + { + result = Cache::CreateFileTransactedA( + lpFileName, + dwDesiredAccess, + dwShareMode, + lpSecurityAttributes, + dwCreationDisposition, + dwFlagsAndAttributes, + hTemplateFile, + hTransaction, + pusMiniVersion, + lpExtendedParameter); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::CreateFileTransactedA; + EventLogger::AppendValue(message, lpFileName); + EventLogger::AppendValue(message, dwDesiredAccess); + EventLogger::AppendValue(message, dwShareMode); + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + HANDLE WINAPI CreateFileTransactedW( + LPCWSTR lpFileName, + DWORD dwDesiredAccess, + DWORD dwShareMode, + LPSECURITY_ATTRIBUTES lpSecurityAttributes, + DWORD dwCreationDisposition, + DWORD dwFlagsAndAttributes, + HANDLE hTemplateFile, + HANDLE hTransaction, + PUSHORT pusMiniVersion, + PVOID lpExtendedParameter) + { + HANDLE result = 0; + __try + { + result = Cache::CreateFileTransactedW( + lpFileName, + dwDesiredAccess, + dwShareMode, + lpSecurityAttributes, + dwCreationDisposition, + dwFlagsAndAttributes, + hTemplateFile, + hTransaction, + pusMiniVersion, + lpExtendedParameter); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::CreateFileTransactedW; + EventLogger::AppendValue(message, lpFileName); + EventLogger::AppendValue(message, dwDesiredAccess); + EventLogger::AppendValue(message, dwShareMode); + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + BOOL WINAPI CreateHardLinkA( + LPCSTR lpFileName, + LPCSTR lpExistingFileName, + LPSECURITY_ATTRIBUTES lpSecurityAttributes) + { + BOOL result = 0; + __try + { + result = Cache::CreateHardLinkA( + lpFileName, + lpExistingFileName, + lpSecurityAttributes); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::CreateHardLinkA; + EventLogger::AppendValue(message, lpFileName); + EventLogger::AppendValue(message, lpExistingFileName); + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + BOOL WINAPI CreateHardLinkW( + LPCWSTR lpFileName, + LPCWSTR lpExistingFileName, + LPSECURITY_ATTRIBUTES lpSecurityAttributes) + { + BOOL result = 0; + __try + { + result = Cache::CreateHardLinkW( + lpFileName, + lpExistingFileName, + lpSecurityAttributes);; + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::CreateHardLinkW; + EventLogger::AppendValue(message, lpFileName); + EventLogger::AppendValue(message, lpExistingFileName); + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + BOOL WINAPI CreateHardLinkTransactedA( + LPCSTR lpFileName, + LPCSTR lpExistingFileName, + LPSECURITY_ATTRIBUTES lpSecurityAttributes, + HANDLE hTransaction) + { + BOOL result = 0; + __try + { + result = Cache::CreateHardLinkTransactedA( + lpFileName, + lpExistingFileName, + lpSecurityAttributes, + hTransaction); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::CreateHardLinkTransactedA; + EventLogger::AppendValue(message, lpFileName); + EventLogger::AppendValue(message, lpExistingFileName); + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + BOOL WINAPI CreateHardLinkTransactedW( + LPCWSTR lpFileName, + LPCWSTR lpExistingFileName, + LPSECURITY_ATTRIBUTES lpSecurityAttributes, + HANDLE hTransaction) + { + BOOL result = 0; + __try + { + result = Cache::CreateHardLinkTransactedW( + lpFileName, + lpExistingFileName, + lpSecurityAttributes, + hTransaction); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::CreateHardLinkTransactedW; + EventLogger::AppendValue(message, lpFileName); + EventLogger::AppendValue(message, lpExistingFileName); + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + BOOL WINAPI CreateProcessWithLogonW( + LPCWSTR lpUsername, + LPCWSTR lpDomain, + LPCWSTR lpPassword, + DWORD dwLogonFlags, + LPCWSTR lpApplicationName, + LPWSTR lpCommandLine, + DWORD dwCreationFlags, + LPVOID lpEnvironment, + LPCWSTR lpCurrentDirectory, + LPSTARTUPINFOW lpStartupInfo, + LPPROCESS_INFORMATION lpProcessInformation) + { + BOOL result = 0; + __try + { + result = Cache::CreateProcessWithLogonW( + lpUsername, + lpDomain, + lpPassword, + dwLogonFlags, + lpApplicationName, + lpCommandLine, + dwCreationFlags, + lpEnvironment, + lpCurrentDirectory, + lpStartupInfo, + lpProcessInformation); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::CreateProcessWithLogonW; + EventLogger::AppendValue(message, lpApplicationName); + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + + // TODO + EventLogger::WriteError("Cannot detour process from CreateProcessWithLogonW"); + } + + return result; + } + + BOOL WINAPI CreateProcessWithTokenW( + HANDLE hToken, + DWORD dwLogonFlags, + LPCWSTR lpApplicationName, + LPWSTR lpCommandLine, + DWORD dwCreationFlags, + LPVOID lpEnvironment, + LPCWSTR lpCurrentDirectory, + LPSTARTUPINFOW lpStartupInfo, + LPPROCESS_INFORMATION lpProcessInformation) + { + BOOL result = 0; + __try + { + result = Cache::CreateProcessWithTokenW( + hToken, + dwLogonFlags, + lpApplicationName, + lpCommandLine, + dwCreationFlags, + lpEnvironment, + lpCurrentDirectory, + lpStartupInfo, + lpProcessInformation); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::CreateProcessWithTokenW; + EventLogger::AppendValue(message, lpApplicationName); + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + + // TODO + EventLogger::WriteError("Cannot detour process from CreateProcessWithTokenW"); + } + + return result; + } + + BOOLEAN WINAPI CreateSymbolicLinkA( + LPCSTR lpSymlinkFileName, + LPCSTR lpTargetFileName, + DWORD dwFlags) + { + BOOLEAN result = 0; + __try + { + result = Cache::CreateSymbolicLinkA( + lpSymlinkFileName, + lpTargetFileName, + dwFlags); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::CreateSymbolicLinkA; + EventLogger::AppendValue(message, lpSymlinkFileName); + EventLogger::AppendValue(message, lpTargetFileName); + EventLogger::AppendValue(message, dwFlags); + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + BOOLEAN WINAPI CreateSymbolicLinkW( + LPCWSTR lpSymlinkFileName, + LPCWSTR lpTargetFileName, + DWORD dwFlags) + { + BOOLEAN result = 0; + __try + { + result = Cache::CreateSymbolicLinkW( + lpSymlinkFileName, + lpTargetFileName, + dwFlags); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::CreateSymbolicLinkW; + EventLogger::AppendValue(message, lpSymlinkFileName); + EventLogger::AppendValue(message, lpTargetFileName); + EventLogger::AppendValue(message, dwFlags); + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + BOOLEAN WINAPI CreateSymbolicLinkTransactedA( + LPCSTR lpSymlinkFileName, + LPCSTR lpTargetFileName, + DWORD dwFlags, + HANDLE hTransaction) + { + BOOLEAN result = 0; + __try + { + result = Cache::CreateSymbolicLinkTransactedA( + lpSymlinkFileName, + lpTargetFileName, + dwFlags, + hTransaction); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::CreateSymbolicLinkTransactedA; + EventLogger::AppendValue(message, lpSymlinkFileName); + EventLogger::AppendValue(message, lpTargetFileName); + EventLogger::AppendValue(message, dwFlags); + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + BOOLEAN WINAPI CreateSymbolicLinkTransactedW( + LPCWSTR lpSymlinkFileName, + LPCWSTR lpTargetFileName, + DWORD dwFlags, + HANDLE hTransaction) + { + BOOL result = 0; + __try + { + result = Cache::CreateSymbolicLinkTransactedW( + lpSymlinkFileName, + lpTargetFileName, + dwFlags, + hTransaction); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::CreateSymbolicLinkTransactedW; + EventLogger::AppendValue(message, lpSymlinkFileName); + EventLogger::AppendValue(message, lpTargetFileName); + EventLogger::AppendValue(message, dwFlags); + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + BOOL WINAPI DecryptFileA( + LPCSTR lpFileName, + DWORD dwReserved) + { + BOOL result = 0; + __try + { + result = Cache::DecryptFileA( + lpFileName, + dwReserved); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::DecryptFileA; + EventLogger::AppendValue(message, lpFileName); + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + BOOL WINAPI DecryptFileW( + LPCWSTR lpFileName, + DWORD dwReserved) + { + BOOL result = 0; + __try + { + result = Cache::DecryptFileW( + lpFileName, + dwReserved); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::DecryptFileW; + EventLogger::AppendValue(message, lpFileName); + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + BOOL WINAPI DeleteFile( + LPCSTR lpFileName) + { + BOOL result = 0; + __try + { + result = Cache::DeleteFile( + lpFileName); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::DeleteFile; + EventLogger::AppendValue(message, lpFileName); + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + BOOL WINAPI DeleteFileTransactedA( + LPCSTR lpFileName, + HANDLE hTransaction) + { + BOOL result = 0; + __try + { + result = Cache::DeleteFileTransactedA( + lpFileName, + hTransaction); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::DeleteFileTransactedA; + EventLogger::AppendValue(message, lpFileName); + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + BOOL WINAPI DeleteFileTransactedW( + LPCWSTR lpFileName, + HANDLE hTransaction) + { + BOOL result = 0; + __try + { + result = Cache::DeleteFileTransactedW( + lpFileName, + hTransaction); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::DeleteFileTransactedW; + EventLogger::AppendValue(message, lpFileName); + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + BOOL WINAPI EncryptFileA( + LPCSTR lpFileName) + { + BOOL result = 0; + __try + { + result = Cache::EncryptFileA( + lpFileName); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::EncryptFileA; + EventLogger::AppendValue(message, lpFileName); + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + BOOL WINAPI EncryptFileW( + LPCWSTR lpFileName) + { + BOOL result = 0; + __try + { + result = Cache::EncryptFileW( + lpFileName); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::EncryptFileW; + EventLogger::AppendValue(message, lpFileName); + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + BOOL WINAPI FileEncryptionStatusA( + LPCSTR lpFileName, + LPDWORD lpStatus) + { + BOOL result = 0; + __try + { + result = Cache::FileEncryptionStatusA( + lpFileName, + lpStatus); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::FileEncryptionStatusA; + EventLogger::AppendValue(message, lpFileName); + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + BOOL WINAPI FileEncryptionStatusW( + LPCWSTR lpFileName, + LPDWORD lpStatus) + { + BOOL result = 0; + __try + { + result = Cache::FileEncryptionStatusW( + lpFileName, + lpStatus); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::FileEncryptionStatusW; + EventLogger::AppendValue(message, lpFileName); + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + HANDLE WINAPI FindFirstFileNameTransactedW( + LPCWSTR lpFileName, + DWORD dwFlags, + LPDWORD StringLength, + PWSTR LinkName, + HANDLE hTransaction) + { + HANDLE result = 0; + __try + { + result = Cache::FindFirstFileNameTransactedW( + lpFileName, + dwFlags, + StringLength, + LinkName, + hTransaction); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::FindFirstFileNameTransactedW; + EventLogger::AppendValue(message, lpFileName); + EventLogger::AppendValue(message, dwFlags); + EventLogger::WriteMessage(message); + } + + return result; + } + + HANDLE WINAPI FindFirstFileTransactedA( + LPCSTR lpFileName, + FINDEX_INFO_LEVELS fInfoLevelId, + LPVOID lpFindFileData, + FINDEX_SEARCH_OPS fSearchOp, + LPVOID lpSearchFilter, + DWORD dwAdditionalFlags, + HANDLE hTransaction) + { + HANDLE result = 0; + __try + { + result = Cache::FindFirstFileTransactedA( + lpFileName, + fInfoLevelId, + lpFindFileData, + fSearchOp, + lpSearchFilter, + dwAdditionalFlags, + hTransaction); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::FindFirstFileTransactedA; + EventLogger::AppendValue(message, lpFileName); + EventLogger::WriteMessage(message); + } + + return result; + } + + HANDLE WINAPI FindFirstFileTransactedW( + LPCWSTR lpFileName, + FINDEX_INFO_LEVELS fInfoLevelId, + LPVOID lpFindFileData, + FINDEX_SEARCH_OPS fSearchOp, + LPVOID lpSearchFilter, + DWORD dwAdditionalFlags, + HANDLE hTransaction) + { + HANDLE result = 0; + __try + { + result = Cache::FindFirstFileTransactedW( + lpFileName, + fInfoLevelId, + lpFindFileData, + fSearchOp, + lpSearchFilter, + dwAdditionalFlags, + hTransaction); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::FindFirstFileTransactedW; + EventLogger::AppendValue(message, lpFileName); + EventLogger::WriteMessage(message); + } + + return result; + } + + HANDLE WINAPI FindFirstStreamTransactedW( + LPCWSTR lpFileName, + STREAM_INFO_LEVELS InfoLevel, + LPVOID lpFindStreamData, + DWORD dwFlags, + HANDLE hTransaction) + { + HANDLE result = 0; + __try + { + result = Cache::FindFirstStreamTransactedW( + lpFileName, + InfoLevel, + lpFindStreamData, + dwFlags, + hTransaction); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::FindFirstStreamTransactedW; + EventLogger::AppendValue(message, lpFileName); + EventLogger::WriteMessage(message); + } + + return result; + } + + BOOL WINAPI GetBinaryTypeA( + LPCSTR lpApplicationName, + LPDWORD lpBinaryType) + { + BOOL result = 0; + __try + { + result = Cache::GetBinaryTypeA( + lpApplicationName, + lpBinaryType); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::GetBinaryTypeA; + EventLogger::AppendValue(message, lpApplicationName); + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + BOOL WINAPI GetBinaryTypeW( + LPCWSTR lpApplicationName, + LPDWORD lpBinaryType) + { + BOOL result = 0; + __try + { + result = Cache::GetBinaryTypeW( + lpApplicationName, + lpBinaryType); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::GetBinaryTypeW; + EventLogger::AppendValue(message, lpApplicationName); + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + DWORD WINAPI GetCompressedFileSizeTransactedA( + LPCSTR lpFileName, + LPDWORD lpFileSizeHigh, + HANDLE hTransaction) + { + DWORD result = 0; + __try + { + result = Cache::GetCompressedFileSizeTransactedA( + lpFileName, + lpFileSizeHigh, + hTransaction); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::GetCompressedFileSizeTransactedA; + EventLogger::AppendValue(message, lpFileName); + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + DWORD WINAPI GetCompressedFileSizeTransactedW( + LPCWSTR lpFileName, + LPDWORD lpFileSizeHigh, + HANDLE hTransaction) + { + DWORD result = 0; + __try + { + result = Cache::GetCompressedFileSizeTransactedW( + lpFileName, + lpFileSizeHigh, + hTransaction); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::GetCompressedFileSizeTransactedW; + EventLogger::AppendValue(message, lpFileName); + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + DWORD WINAPI GetDllDirectoryA( + DWORD nBufferLength, + LPSTR lpBuffer) + { + DWORD result = 0; + __try + { + result = Cache::GetDllDirectoryA( + nBufferLength, + lpBuffer); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::GetDllDirectoryA; + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + DWORD WINAPI GetDllDirectoryW( + DWORD nBufferLength, + LPWSTR lpBuffer) + { + BOOL result = 0; + __try + { + result = Cache::GetDllDirectoryW( + nBufferLength, + lpBuffer); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::GetDllDirectoryW; + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + BOOL WINAPI GetFileAttributesTransactedA( + LPCSTR lpFileName, + GET_FILEEX_INFO_LEVELS fInfoLevelId, + LPVOID lpFileInformation, + HANDLE hTransaction) + { + BOOL result = 0; + __try + { + result = Cache::GetFileAttributesTransactedA( + lpFileName, + fInfoLevelId, + lpFileInformation, + hTransaction); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::GetFileAttributesTransactedA; + EventLogger::AppendValue(message, lpFileName); + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + BOOL WINAPI GetFileAttributesTransactedW( + LPCWSTR lpFileName, + GET_FILEEX_INFO_LEVELS fInfoLevelId, + LPVOID lpFileInformation, + HANDLE hTransaction) + { + BOOL result = 0; + __try + { + result = Cache::GetFileAttributesTransactedW( + lpFileName, + fInfoLevelId, + lpFileInformation, + hTransaction); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::GetFileAttributesTransactedW; + EventLogger::AppendValue(message, lpFileName); + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + BOOL WINAPI GetFileBandwidthReservation( + HANDLE hFile, + LPDWORD lpPeriodMilliseconds, + LPDWORD lpBytesPerPeriod, + LPBOOL pDiscardable, + LPDWORD lpTransferSize, + LPDWORD lpNumOutstandingRequests) + { + BOOL result = 0; + __try + { + result = Cache::GetFileBandwidthReservation( + hFile, + lpPeriodMilliseconds, + lpBytesPerPeriod, + pDiscardable, + lpTransferSize, + lpNumOutstandingRequests); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::GetFileBandwidthReservation; + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + BOOL WINAPI GetFileInformationByHandleEx( + HANDLE hFile, + FILE_INFO_BY_HANDLE_CLASS FileInformationClass, + LPVOID lpFileInformation, + DWORD dwBufferSize) + { + BOOL result = 0; + __try + { + result = Cache::GetFileInformationByHandleEx( + hFile, + FileInformationClass, + lpFileInformation, + dwBufferSize); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::GetFileInformationByHandleEx; + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + BOOL WINAPI GetFileSecurityA( + LPCSTR lpFileName, + SECURITY_INFORMATION RequestedInformation, + PSECURITY_DESCRIPTOR pSecurityDescriptor, + DWORD nLength, + LPDWORD lpnLengthNeeded) + { + BOOL result = 0; + __try + { + result = Cache::GetFileSecurityA( + lpFileName, + RequestedInformation, + pSecurityDescriptor, + nLength, + lpnLengthNeeded); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::GetFileSecurityA; + EventLogger::AppendValue(message, lpFileName); + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + DWORD WINAPI GetFullPathNameTransactedA( + LPCSTR lpFileName, + DWORD nBufferLength, + LPSTR lpBuffer, + LPSTR *lpFilePart, + HANDLE hTransaction) + { + DWORD result = 0; + __try + { + result = Cache::GetFullPathNameTransactedA( + lpFileName, + nBufferLength, + lpBuffer, + lpFilePart, + hTransaction); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::GetFullPathNameTransactedA; + EventLogger::AppendValue(message, lpFileName); + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + DWORD WINAPI GetFullPathNameTransactedW( + LPCWSTR lpFileName, + DWORD nBufferLength, + LPWSTR lpBuffer, + LPWSTR *lpFilePart, + HANDLE hTransaction) + { + DWORD result = 0; + __try + { + result = Cache::GetFullPathNameTransactedW( + lpFileName, + nBufferLength, + lpBuffer, + lpFilePart, + hTransaction); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::GetFullPathNameTransactedW; + EventLogger::AppendValue(message, lpFileName); + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + DWORD WINAPI GetLongPathNameTransactedA( + LPCSTR lpszShortPath, + LPSTR lpszLongPath, + DWORD cchBuffer, + HANDLE hTransaction) + { + DWORD result = 0; + __try + { + result = Cache::GetLongPathNameTransactedA( + lpszShortPath, + lpszLongPath, + cchBuffer, + hTransaction); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::GetLongPathNameTransactedA; + EventLogger::AppendValue(message, lpszShortPath); + EventLogger::AppendValue(message, lpszLongPath); + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + DWORD WINAPI GetLongPathNameTransactedW( + LPCWSTR lpszShortPath, + LPWSTR lpszLongPath, + DWORD cchBuffer, + HANDLE hTransaction) + { + DWORD result = 0; + __try + { + result = Cache::GetLongPathNameTransactedW( + lpszShortPath, + lpszLongPath, + cchBuffer, + hTransaction); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::GetLongPathNameTransactedW; + EventLogger::AppendValue(message, lpszShortPath); + EventLogger::AppendValue(message, lpszLongPath); + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + BOOL WINAPI GetQueuedCompletionStatus( + HANDLE CompletionPort, + LPDWORD lpNumberOfBytesTransferred, + PULONG_PTR lpCompletionKey, + LPOVERLAPPED *lpOverlapped, + DWORD dwMilliseconds) + { + BOOL result = 0; + __try + { + result = Cache::GetQueuedCompletionStatus( + CompletionPort, + lpNumberOfBytesTransferred, + lpCompletionKey, + lpOverlapped, + dwMilliseconds); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::GetQueuedCompletionStatus; + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + BOOL WINAPI GetQueuedCompletionStatusEx( + HANDLE CompletionPort, + LPOVERLAPPED_ENTRY lpCompletionPortEntries, + ULONG ulCount, + PULONG ulNumEntriesRemoved, + DWORD dwMilliseconds, + BOOL fAlertable) + { + BOOL result = 0; + __try + { + result = Cache::GetQueuedCompletionStatusEx( + CompletionPort, + lpCompletionPortEntries, + ulCount, + ulNumEntriesRemoved, + dwMilliseconds, + fAlertable); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::GetQueuedCompletionStatusEx; + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + DWORD WINAPI GetShortPathNameA( + LPCSTR lpszLongPath, + LPSTR lpszShortPath, + DWORD cchBuffer) + { + BOOL result = 0; + __try + { + result = Cache::GetShortPathNameA( + lpszLongPath, + lpszShortPath, + cchBuffer); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::GetShortPathNameA; + EventLogger::AppendValue(message, lpszLongPath); + EventLogger::AppendValue(message, lpszShortPath); + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + DWORD WINAPI LoadModule( + LPCSTR lpModuleName, + LPVOID lpParameterBlock) + { + DWORD result = 0; + __try + { + result = Cache::LoadModule( + lpModuleName, + lpParameterBlock); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::LoadModule; + EventLogger::AppendValue(message, lpModuleName); + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + HMODULE WINAPI LoadPackagedLibrary( + LPCWSTR lpwLibFileName, + DWORD Reserved) + { + HMODULE result = 0; + __try + { + result = Cache::LoadPackagedLibrary( + lpwLibFileName, + Reserved); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::LoadPackagedLibrary; + EventLogger::AppendValue(message, lpwLibFileName); + EventLogger::WriteMessage(message); + } + + return result; + } + + BOOL WINAPI MoveFileA( + LPCTSTR lpExistingFileName, + LPCTSTR lpNewFileName) + { + BOOL result = 0; + __try + { + result = Cache::MoveFileA( + lpExistingFileName, + lpNewFileName); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::MoveFileA; + EventLogger::AppendValue(message, lpExistingFileName); + EventLogger::AppendValue(message, lpNewFileName); + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + BOOL WINAPI MoveFileW( + LPCWSTR lpExistingFileName, + LPCWSTR lpNewFileName) + { + BOOL result = 0; + __try + { + result = Cache::MoveFileW( + lpExistingFileName, + lpNewFileName); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::MoveFileW; + EventLogger::AppendValue(message, lpExistingFileName); + EventLogger::AppendValue(message, lpNewFileName); + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + BOOL WINAPI MoveFileExA( + LPCSTR lpExistingFileName, + LPCSTR lpNewFileName, + DWORD dwFlags) + { + BOOL result = 0; + __try + { + result = Cache::MoveFileExA( + lpExistingFileName, + lpNewFileName, + dwFlags); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::MoveFileExA; + EventLogger::AppendValue(message, lpExistingFileName); + EventLogger::AppendValue(message, lpNewFileName); + EventLogger::AppendValue(message, dwFlags); + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + BOOL WINAPI MoveFileExW( + LPCWSTR lpExistingFileName, + LPCWSTR lpNewFileName, + DWORD dwFlags) + { + BOOL result = 0; + __try + { + result = Cache::MoveFileExW( + lpExistingFileName, + lpNewFileName, + dwFlags); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::MoveFileExW; + EventLogger::AppendValue(message, lpExistingFileName); + EventLogger::AppendValue(message, lpNewFileName); + EventLogger::AppendValue(message, dwFlags); + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + BOOL WINAPI MoveFileTransactedA( + LPCSTR lpExistingFileName, + LPCSTR lpNewFileName, + LPPROGRESS_ROUTINE lpProgressRoutine, + LPVOID lpData, + DWORD dwFlags, + HANDLE hTransaction) + { + BOOL result = 0; + __try + { + result = Cache::MoveFileTransactedA( + lpExistingFileName, + lpNewFileName, + lpProgressRoutine, + lpData, + dwFlags, + hTransaction); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::MoveFileTransactedA; + EventLogger::AppendValue(message, lpExistingFileName); + EventLogger::AppendValue(message, lpNewFileName); + EventLogger::AppendValue(message, dwFlags); + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + BOOL WINAPI MoveFileTransactedW( + LPCWSTR lpExistingFileName, + LPCWSTR lpNewFileName, + LPPROGRESS_ROUTINE lpProgressRoutine, + LPVOID lpData, + DWORD dwFlags, + HANDLE hTransaction) + { + BOOL result = 0; + __try + { + result = Cache::MoveFileTransactedW( + lpExistingFileName, + lpNewFileName, + lpProgressRoutine, + lpData, + dwFlags, + hTransaction); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::MoveFileTransactedW; + EventLogger::AppendValue(message, lpExistingFileName); + EventLogger::AppendValue(message, lpNewFileName); + EventLogger::AppendValue(message, dwFlags); + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + BOOL WINAPI MoveFileWithProgressA( + LPCSTR lpExistingFileName, + LPCSTR lpNewFileName, + LPPROGRESS_ROUTINE lpProgressRoutine, + LPVOID lpData, + DWORD dwFlags) + { + BOOL result = 0; + __try + { + result = Cache::MoveFileWithProgressA( + lpExistingFileName, + lpNewFileName, + lpProgressRoutine, + lpData, + dwFlags); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::MoveFileWithProgressA; + EventLogger::AppendValue(message, lpExistingFileName); + EventLogger::AppendValue(message, lpNewFileName); + EventLogger::AppendValue(message, dwFlags); + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + BOOL WINAPI MoveFileWithProgressW( + LPCWSTR lpExistingFileName, + LPCWSTR lpNewFileName, + LPPROGRESS_ROUTINE lpProgressRoutine, + LPVOID lpData, + DWORD dwFlags) + { + BOOL result = 0; + __try + { + result = Cache::MoveFileWithProgressW( + lpExistingFileName, + lpNewFileName, + lpProgressRoutine, + lpData, + dwFlags); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::MoveFileWithProgressW; + EventLogger::AppendValue(message, lpExistingFileName); + EventLogger::AppendValue(message, lpNewFileName); + EventLogger::AppendValue(message, dwFlags); + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + DWORD WINAPI OpenEncryptedFileRawA( + LPCSTR lpFileName, + ULONG ulFlags, + PVOID *pvContext) + { + DWORD result = 0; + __try + { + result = Cache::OpenEncryptedFileRawA( + lpFileName, + ulFlags, + pvContext); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::OpenEncryptedFileRawA; + EventLogger::AppendValue(message, lpFileName); + EventLogger::AppendValue(message, ulFlags); + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + DWORD WINAPI OpenEncryptedFileRawW( + LPCWSTR lpFileName, + ULONG ulFlags, + PVOID *pvContext) + { + DWORD result = 0; + __try + { + result = Cache::OpenEncryptedFileRawW( + lpFileName, + ulFlags, + pvContext); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::OpenEncryptedFileRawW; + EventLogger::AppendValue(message, lpFileName); + EventLogger::AppendValue(message, ulFlags); + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + HFILE WINAPI OpenFile( + LPCSTR lpFileName, + LPOFSTRUCT lpReOpenBuff, + UINT uStyle) + { + HFILE result = 0; + __try + { + result = Cache::OpenFile( + lpFileName, + lpReOpenBuff, + uStyle); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::OpenFile; + EventLogger::AppendValue(message, lpFileName); + EventLogger::WriteMessage(message); + } + + return result; + } + + HANDLE WINAPI OpenFileById( + HANDLE hVolumeHint, + LPFILE_ID_DESCRIPTOR lpFileId, + DWORD dwDesiredAccess, + DWORD dwShareMode, + LPSECURITY_ATTRIBUTES lpSecurityAttributes, + DWORD dwFlagsAndAttributes) + { + HANDLE result = 0; + __try + { + result = Cache::OpenFileById( + hVolumeHint, + lpFileId, + dwDesiredAccess, + dwShareMode, + lpSecurityAttributes, + dwFlagsAndAttributes); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::OpenFileById; + EventLogger::WriteMessage(message); + } + + return result; + } + + DWORD WINAPI ReadEncryptedFileRaw( + PFE_EXPORT_FUNC pfExportCallback, + PVOID pvCallbackContext, + PVOID pvContext) + { + DWORD result = 0; + __try + { + result = Cache::ReadEncryptedFileRaw( + pfExportCallback, + pvCallbackContext, + pvContext); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::ReadEncryptedFileRaw; + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + BOOL WINAPI RemoveDirectoryTransactedA( + LPCSTR lpPathName, + HANDLE hTransaction) + { + BOOL result = 0; + __try + { + result = Cache::RemoveDirectoryTransactedA( + lpPathName, + hTransaction); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::RemoveDirectoryTransactedA; + EventLogger::AppendValue(message, lpPathName); + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + BOOL WINAPI RemoveDirectoryTransactedW( + LPCWSTR lpPathName, + HANDLE hTransaction) + { + BOOL result = 0; + __try + { + result = Cache::RemoveDirectoryTransactedW( + lpPathName, + hTransaction); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::RemoveDirectoryTransactedW; + EventLogger::AppendValue(message, lpPathName); + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + HANDLE WINAPI ReOpenFile( + HANDLE hOriginalFile, + DWORD dwDesiredAccess, + DWORD dwShareMode, + DWORD dwFlagsAndAttributes) + { + HANDLE result = 0; + __try + { + result = Cache::ReOpenFile( + hOriginalFile, + dwDesiredAccess, + dwShareMode, + dwFlagsAndAttributes); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::ReOpenFile; + EventLogger::WriteMessage(message); + } + + return result; + } + + BOOL WINAPI ReplaceFileA( + LPCSTR lpReplacedFileName, + LPCSTR lpReplacementFileName, + LPCSTR lpBackupFileName, + DWORD dwReplaceFlags, + LPVOID lpExclude, + LPVOID lpReserved) + { + BOOL result = 0; + __try + { + result = Cache::ReplaceFileA( + lpReplacedFileName, + lpReplacementFileName, + lpBackupFileName, + dwReplaceFlags, + lpExclude, + lpReserved); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::ReplaceFileA; + EventLogger::AppendValue(message, lpReplacedFileName); + EventLogger::AppendValue(message, lpReplacementFileName); + EventLogger::AppendValue(message, lpBackupFileName); + EventLogger::AppendValue(message, dwReplaceFlags); + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + BOOL WINAPI ReplaceFileW( + LPCWSTR lpReplacedFileName, + LPCWSTR lpReplacementFileName, + LPCWSTR lpBackupFileName, + DWORD dwReplaceFlags, + LPVOID lpExclude, + LPVOID lpReserved) + { + BOOL result = 0; + __try + { + result = Cache::ReplaceFileW( + lpReplacedFileName, + lpReplacementFileName, + lpBackupFileName, + dwReplaceFlags, + lpExclude, + lpReserved); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::ReplaceFileW; + EventLogger::AppendValue(message, lpReplacedFileName); + EventLogger::AppendValue(message, lpReplacementFileName); + EventLogger::AppendValue(message, lpBackupFileName); + EventLogger::AppendValue(message, dwReplaceFlags); + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + BOOL WINAPI SetCurrentDirectoryA( + LPCTSTR lpPathName) + { + BOOL result = 0; + __try + { + result = Cache::SetCurrentDirectoryA( + lpPathName); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::SetCurrentDirectoryA; + EventLogger::AppendValue(message, lpPathName); + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + BOOL WINAPI SetCurrentDirectoryW( + LPCWSTR lpPathName) + { + BOOL result = 0; + __try + { + result = Cache::SetCurrentDirectoryW( + lpPathName); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::SetCurrentDirectoryW; + EventLogger::AppendValue(message, lpPathName); + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + BOOL WINAPI SetDllDirectoryA( + LPCSTR lpPathName) + { + BOOL result = 0; + __try + { + result = Cache::SetDllDirectoryA( + lpPathName); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::SetDllDirectoryA; + EventLogger::AppendValue(message, lpPathName); + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + BOOL WINAPI SetDllDirectoryW( + LPCWSTR lpPathName) + { + BOOL result = 0; + __try + { + result = Cache::SetDllDirectoryW( + lpPathName); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::SetDllDirectoryW; + EventLogger::AppendValue(message, lpPathName); + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + BOOL WINAPI SetFileAttributesTransactedA( + LPCSTR lpFileName, + DWORD dwFileAttributes, + HANDLE hTransaction) + { + BOOL result = 0; + __try + { + result = Cache::SetFileAttributesTransactedA( + lpFileName, + dwFileAttributes, + hTransaction); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::SetFileAttributesTransactedA; + EventLogger::AppendValue(message, lpFileName); + EventLogger::AppendValue(message, dwFileAttributes); + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + BOOL WINAPI SetFileAttributesTransactedW( + LPCWSTR lpFileName, + DWORD dwFileAttributes, + HANDLE hTransaction) + { + BOOL result = 0; + __try + { + result = Cache::SetFileAttributesTransactedW( + lpFileName, + dwFileAttributes, + hTransaction); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::SetFileAttributesTransactedW; + EventLogger::AppendValue(message, lpFileName); + EventLogger::AppendValue(message, dwFileAttributes); + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + BOOL WINAPI SetFileBandwidthReservation( + HANDLE hFile, + DWORD nPeriodMilliseconds, + DWORD nBytesPerPeriod, + BOOL bDiscardable, + LPDWORD lpTransferSize, + LPDWORD lpNumOutstandingRequests) + { + BOOL result = 0; + __try + { + result = Cache::SetFileBandwidthReservation( + hFile, + nPeriodMilliseconds, + nBytesPerPeriod, + bDiscardable, + lpTransferSize, + lpNumOutstandingRequests); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::SetFileBandwidthReservation; + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + BOOL WINAPI SetFileCompletionNotificationModes( + HANDLE FileHandle, + UCHAR Flags) + { + BOOL result = 0; + __try + { + result = Cache::SetFileCompletionNotificationModes( + FileHandle, + Flags); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::SetFileCompletionNotificationModes; + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + BOOL WINAPI SetFileSecurityA( + LPCSTR lpFileName, + SECURITY_INFORMATION SecurityInformation, + PSECURITY_DESCRIPTOR pSecurityDescriptor) + { + BOOL result = 0; + __try + { + result = Cache::SetFileSecurityA( + lpFileName, + SecurityInformation, + pSecurityDescriptor); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::SetFileSecurityA; + EventLogger::AppendValue(message, lpFileName); + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + BOOL WINAPI SetFileShortNameA( + HANDLE hFile, + LPCSTR lpShortName) + { + BOOL result = 0; + __try + { + result = Cache::SetFileShortNameA( + hFile, + lpShortName); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::SetFileShortNameA; + EventLogger::AppendValue(message, lpShortName); + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + BOOL WINAPI SetFileShortNameW( + HANDLE hFile, + LPCWSTR lpShortName) + { + BOOL result = 0; + __try + { + result = Cache::SetFileShortNameW( + hFile, + lpShortName); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::SetFileShortNameW; + EventLogger::AppendValue(message, lpShortName); + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + BOOL WINAPI SetSearchPathMode( + DWORD Flags) + { + BOOL result = 0; + __try + { + result = Cache::SetSearchPathMode( + Flags); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::SetSearchPathMode; + EventLogger::AppendValue(message, Flags); + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } + + DWORD WINAPI WriteEncryptedFileRaw( + PFE_IMPORT_FUNC pfImportCallback, + PVOID pvCallbackContext, + PVOID pvContext) + { + BOOL result = 0; + __try + { + result = Cache::WriteEncryptedFileRaw( + pfImportCallback, + pvCallbackContext, + pvContext); + } + __finally + { + auto message = Monitor::DetourMessage(); + message.Type = Monitor::DetourMessageType::WriteEncryptedFileRaw; + EventLogger::AppendValue(message, result); + EventLogger::WriteMessage(message); + } + + return result; + } +} \ No newline at end of file diff --git a/Source/Monitor/Detours/Helpers.h b/Source/Monitor/Detours/Helpers.h new file mode 100644 index 00000000..9cc41c56 --- /dev/null +++ b/Source/Monitor/Detours/Helpers.h @@ -0,0 +1,30 @@ +#pragma once + +static HMODULE s_hInst = nullptr; +static HMODULE s_hKernel32 = nullptr; +static CHAR s_szDllPath[MAX_PATH]; +static Monitor::DetourPayload s_Payload; +static Monitor::DetourPayload s_ChildPayload; +static CRITICAL_SECTION s_csChildPayload; +static DWORD s_nTraceProcessId = 0; +static LONG s_nChildCnt = 0; + +bool CreateProcessInternals( + HANDLE hProcess) +{ + EnterCriticalSection(&s_csChildPayload); + + ZeroMemory(&s_ChildPayload, sizeof(s_ChildPayload)); + CopyMemory(&s_ChildPayload, &s_Payload, sizeof(s_ChildPayload)); + + s_ChildPayload.nParentProcessId = GetCurrentProcessId(); + s_ChildPayload.rGeneology[s_ChildPayload.nGeneology] = + (DWORD)InterlockedIncrement(&s_nChildCnt); + s_ChildPayload.nGeneology++; + + DetourCopyPayloadToProcess(hProcess, Monitor::GuidTrace, &s_ChildPayload, sizeof(s_ChildPayload)); + + LeaveCriticalSection(&s_csChildPayload); + + return true; +} diff --git a/Source/Monitor/Detours/Module.cpp b/Source/Monitor/Detours/Module.cpp new file mode 100644 index 00000000..56d5ef24 --- /dev/null +++ b/Source/Monitor/Detours/Module.cpp @@ -0,0 +1,614 @@ +module; + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#ifdef CreateProcess +#undef CreateProcess +#endif + +#include +#include + +#define DllExport __declspec(dllexport) + +export module Monitor.Detours; +import Detours; +import Monitor.Shared; + +#include "Helpers.h" + +#include "Functions/FileApiOverrides.h" +#include "Functions/LibLoaderApiOverrides.h" +#include "Functions/ProcessEnvOverrides.h" +#include "Functions/ProcessThreadsApiOverrides.h" +#include "Functions/UndocumentedApiOverrides.h" +#include "Functions/WinBaseOverrides.h" + +// TODO: This exported method forces a lib to be generated to allow for linking... +// Soup should allow runtime references to dlls that have no external symbols +DllExport void Noop() +{ +} + +void AttachDetours() +{ + ThrowIfFailed(DetourTransactionBegin(), "AttachDetours DetourTransactionBegin Failed"); + ThrowIfFailed(DetourUpdateThread(GetCurrentThread()), "AttachDetours DetourUpdateThread Failed"); + + // FileApi + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::FileApi::Cache::AreFileApisANSI, Functions::FileApi::Overrides::AreFileApisANSI), "AttachDetours DetourAttach AreFileApisANSI Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::FileApi::Cache::CompareFileTime, Functions::FileApi::Overrides::CompareFileTime), "AttachDetours DetourAttach CompareFileTime Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::FileApi::Cache::CreateDirectoryA, Functions::FileApi::Overrides::CreateDirectoryA), "AttachDetours DetourAttach CreateDirectoryA Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::FileApi::Cache::CreateDirectoryW, Functions::FileApi::Overrides::CreateDirectoryW), "AttachDetours DetourAttach CreateDirectoryW Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::FileApi::Cache::CreateFile2, Functions::FileApi::Overrides::CreateFile2), "AttachDetours DetourAttach CreateFile2 Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::FileApi::Cache::CreateFileA, Functions::FileApi::Overrides::CreateFileA), "AttachDetours DetourAttach CreateFileA Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::FileApi::Cache::CreateFileW, Functions::FileApi::Overrides::CreateFileW), "AttachDetours DetourAttach CreateFileW Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::FileApi::Cache::DefineDosDeviceW, Functions::FileApi::Overrides::DefineDosDeviceW), "AttachDetours DetourAttach DefineDosDeviceW Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::FileApi::Cache::DeleteFileA, Functions::FileApi::Overrides::DeleteFileA), "AttachDetours DetourAttach DeleteFileA Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::FileApi::Cache::DeleteFileW, Functions::FileApi::Overrides::DeleteFileW), "AttachDetours DetourAttach DeleteFileW Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::FileApi::Cache::DeleteVolumeMountPointW, Functions::FileApi::Overrides::DeleteVolumeMountPointW), "AttachDetours DetourAttach DeleteVolumeMountPointW Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::FileApi::Cache::FileTimeToLocalFileTime, Functions::FileApi::Overrides::FileTimeToLocalFileTime), "AttachDetours DetourAttach FileTimeToLocalFileTime Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::FileApi::Cache::FindClose, Functions::FileApi::Overrides::FindClose), "AttachDetours DetourAttach FindClose Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::FileApi::Cache::FindCloseChangeNotification, Functions::FileApi::Overrides::FindCloseChangeNotification), "AttachDetours DetourAttach FindCloseChangeNotification Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::FileApi::Cache::FindFirstChangeNotificationA, Functions::FileApi::Overrides::FindFirstChangeNotificationA), "AttachDetours DetourAttach FindFirstChangeNotificationA Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::FileApi::Cache::FindFirstChangeNotificationW, Functions::FileApi::Overrides::FindFirstChangeNotificationW), "AttachDetours DetourAttach FindFirstChangeNotificationW Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::FileApi::Cache::FindFirstFileA, Functions::FileApi::Overrides::FindFirstFileA), "AttachDetours DetourAttach FindFirstFileA Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::FileApi::Cache::FindFirstFileW, Functions::FileApi::Overrides::FindFirstFileW), "AttachDetours DetourAttach FindFirstFileW Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::FileApi::Cache::FindFirstFileExA, Functions::FileApi::Overrides::FindFirstFileExA), "AttachDetours DetourAttach FindFirstFileExA Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::FileApi::Cache::FindFirstFileExW, Functions::FileApi::Overrides::FindFirstFileExW), "AttachDetours DetourAttach FindFirstFileExW Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::FileApi::Cache::FindFirstFileNameW, Functions::FileApi::Overrides::FindFirstFileNameW), "AttachDetours DetourAttach FindFirstFileNameW Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::FileApi::Cache::FindFirstStreamW, Functions::FileApi::Overrides::FindFirstStreamW), "AttachDetours DetourAttach FindFirstStreamW Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::FileApi::Cache::FindFirstVolumeW, Functions::FileApi::Overrides::FindFirstVolumeW), "AttachDetours DetourAttach FindFirstVolumeW Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::FileApi::Cache::FindNextChangeNotification, Functions::FileApi::Overrides::FindNextChangeNotification), "AttachDetours DetourAttach FindNextChangeNotification Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::FileApi::Cache::FindNextFileA, Functions::FileApi::Overrides::FindNextFileA), "AttachDetours DetourAttach FindNextFileA Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::FileApi::Cache::FindNextFileW, Functions::FileApi::Overrides::FindNextFileW), "AttachDetours DetourAttach FindNextFileW Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::FileApi::Cache::FindNextFileNameW, Functions::FileApi::Overrides::FindNextFileNameW), "AttachDetours DetourAttach FindNextFileNameW Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::FileApi::Cache::FindNextStreamW, Functions::FileApi::Overrides::FindNextStreamW), "AttachDetours DetourAttach FindNextStreamW Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::FileApi::Cache::FindNextVolumeW, Functions::FileApi::Overrides::FindNextVolumeW), "AttachDetours DetourAttach FindNextVolumeW Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::FileApi::Cache::FindVolumeClose, Functions::FileApi::Overrides::FindVolumeClose), "AttachDetours DetourAttach FindVolumeClose Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::FileApi::Cache::FlushFileBuffers, Functions::FileApi::Overrides::FlushFileBuffers), "AttachDetours DetourAttach FlushFileBuffers Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::FileApi::Cache::GetCompressedFileSizeA, Functions::FileApi::Overrides::GetCompressedFileSizeA), "AttachDetours DetourAttach GetCompressedFileSizeA Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::FileApi::Cache::GetCompressedFileSizeW, Functions::FileApi::Overrides::GetCompressedFileSizeW), "AttachDetours DetourAttach GetCompressedFileSizeW Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::FileApi::Cache::GetDiskFreeSpaceA, Functions::FileApi::Overrides::GetDiskFreeSpaceA), "AttachDetours DetourAttach GetDiskFreeSpaceA Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::FileApi::Cache::GetDiskFreeSpaceW, Functions::FileApi::Overrides::GetDiskFreeSpaceW), "AttachDetours DetourAttach GetDiskFreeSpaceW Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::FileApi::Cache::GetDiskFreeSpaceExA, Functions::FileApi::Overrides::GetDiskFreeSpaceExA), "AttachDetours DetourAttach GetDiskFreeSpaceExA Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::FileApi::Cache::GetDiskFreeSpaceExW, Functions::FileApi::Overrides::GetDiskFreeSpaceExW), "AttachDetours DetourAttach GetDiskFreeSpaceExW Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::FileApi::Cache::GetDriveTypeA, Functions::FileApi::Overrides::GetDriveTypeA), "AttachDetours DetourAttach GetDriveTypeA Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::FileApi::Cache::GetDriveTypeW, Functions::FileApi::Overrides::GetDriveTypeW), "AttachDetours DetourAttach GetDriveTypeW Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::FileApi::Cache::GetFileAttributesA, Functions::FileApi::Overrides::GetFileAttributesA), "AttachDetours DetourAttach GetFileAttributesA Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::FileApi::Cache::GetFileAttributesW, Functions::FileApi::Overrides::GetFileAttributesW), "AttachDetours DetourAttach GetFileAttributesW Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::FileApi::Cache::GetFileAttributesExA, Functions::FileApi::Overrides::GetFileAttributesExA), "AttachDetours DetourAttach GetFileAttributesExA Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::FileApi::Cache::GetFileAttributesExW, Functions::FileApi::Overrides::GetFileAttributesExW), "AttachDetours DetourAttach GetFileAttributesExW Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::FileApi::Cache::GetFileInformationByHandle, Functions::FileApi::Overrides::GetFileInformationByHandle), "AttachDetours DetourAttach GetFileInformationByHandle Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::FileApi::Cache::GetFileSize, Functions::FileApi::Overrides::GetFileSize), "AttachDetours DetourAttach GetFileSize Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::FileApi::Cache::GetFileSizeEx, Functions::FileApi::Overrides::GetFileSizeEx), "AttachDetours DetourAttach GetFileSizeEx Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::FileApi::Cache::GetFileTime, Functions::FileApi::Overrides::GetFileTime), "AttachDetours DetourAttach GetFileTime Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::FileApi::Cache::GetFileType, Functions::FileApi::Overrides::GetFileType), "AttachDetours DetourAttach GetFileType Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::FileApi::Cache::GetFinalPathNameByHandleA, Functions::FileApi::Overrides::GetFinalPathNameByHandleA), "AttachDetours DetourAttach GetFinalPathNameByHandleA Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::FileApi::Cache::GetFinalPathNameByHandleW, Functions::FileApi::Overrides::GetFinalPathNameByHandleW), "AttachDetours DetourAttach GetFinalPathNameByHandleW Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::FileApi::Cache::GetFullPathNameA, Functions::FileApi::Overrides::GetFullPathNameA), "AttachDetours DetourAttach GetFullPathNameA Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::FileApi::Cache::GetFullPathNameW, Functions::FileApi::Overrides::GetFullPathNameW), "AttachDetours DetourAttach GetFullPathNameW Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::FileApi::Cache::GetLogicalDrives, Functions::FileApi::Overrides::GetLogicalDrives), "AttachDetours DetourAttach GetLogicalDrives Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::FileApi::Cache::GetLogicalDriveStringsW, Functions::FileApi::Overrides::GetLogicalDriveStringsW), "AttachDetours DetourAttach GetLogicalDriveStringsW Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::FileApi::Cache::GetLongPathNameA, Functions::FileApi::Overrides::GetLongPathNameA), "AttachDetours DetourAttach GetLongPathNameA Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::FileApi::Cache::GetLongPathNameW, Functions::FileApi::Overrides::GetLongPathNameW), "AttachDetours DetourAttach GetLongPathNameW Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::FileApi::Cache::GetShortPathNameW, Functions::FileApi::Overrides::GetShortPathNameW), "AttachDetours DetourAttach GetShortPathNameW Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::FileApi::Cache::GetTempFileNameA, Functions::FileApi::Overrides::GetTempFileNameA), "AttachDetours DetourAttach GetTempFileNameA Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::FileApi::Cache::GetTempFileNameW, Functions::FileApi::Overrides::GetTempFileNameW), "AttachDetours DetourAttach GetTempFileNameW Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::FileApi::Cache::GetTempPathA, Functions::FileApi::Overrides::GetTempPathA), "AttachDetours DetourAttach GetTempPathA Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::FileApi::Cache::GetTempPathW, Functions::FileApi::Overrides::GetTempPathW), "AttachDetours DetourAttach GetTempPathW Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::FileApi::Cache::GetVolumeInformationA, Functions::FileApi::Overrides::GetVolumeInformationA), "AttachDetours DetourAttach GetVolumeInformationA Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::FileApi::Cache::GetVolumeInformationW, Functions::FileApi::Overrides::GetVolumeInformationW), "AttachDetours DetourAttach GetVolumeInformationW Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::FileApi::Cache::GetVolumeInformationByHandleW, Functions::FileApi::Overrides::GetVolumeInformationByHandleW), "AttachDetours DetourAttach GetVolumeInformationByHandleW Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::FileApi::Cache::GetVolumeNameForVolumeMountPointW, Functions::FileApi::Overrides::GetVolumeNameForVolumeMountPointW), "AttachDetours DetourAttach GetVolumeNameForVolumeMountPointW Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::FileApi::Cache::GetVolumePathNamesForVolumeNameW, Functions::FileApi::Overrides::GetVolumePathNamesForVolumeNameW), "AttachDetours DetourAttach GetVolumePathNamesForVolumeNameW Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::FileApi::Cache::GetVolumePathNameW, Functions::FileApi::Overrides::GetVolumePathNameW), "AttachDetours DetourAttach GetVolumePathNameW Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::FileApi::Cache::LocalFileTimeToFileTime, Functions::FileApi::Overrides::LocalFileTimeToFileTime), "AttachDetours DetourAttach LocalFileTimeToFileTime Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::FileApi::Cache::LockFile, Functions::FileApi::Overrides::LockFile), "AttachDetours DetourAttach LockFile Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::FileApi::Cache::LockFileEx, Functions::FileApi::Overrides::LockFileEx), "AttachDetours DetourAttach LockFileEx Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::FileApi::Cache::QueryDosDeviceW, Functions::FileApi::Overrides::QueryDosDeviceW), "AttachDetours DetourAttach QueryDosDeviceW Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::FileApi::Cache::ReadFile, Functions::FileApi::Overrides::ReadFile), "AttachDetours DetourAttach ReadFile Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::FileApi::Cache::ReadFileEx, Functions::FileApi::Overrides::ReadFileEx), "AttachDetours DetourAttach ReadFileEx Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::FileApi::Cache::ReadFileScatter, Functions::FileApi::Overrides::ReadFileScatter), "AttachDetours DetourAttach ReadFileScatter Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::FileApi::Cache::RemoveDirectoryA, Functions::FileApi::Overrides::RemoveDirectoryA), "AttachDetours DetourAttach RemoveDirectoryA Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::FileApi::Cache::RemoveDirectoryW, Functions::FileApi::Overrides::RemoveDirectoryW), "AttachDetours DetourAttach RemoveDirectoryW Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::FileApi::Cache::SetEndOfFile, Functions::FileApi::Overrides::SetEndOfFile), "AttachDetours DetourAttach SetEndOfFile Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::FileApi::Cache::SetFileApisToANSI, Functions::FileApi::Overrides::SetFileApisToANSI), "AttachDetours DetourAttach SetFileApisToANSI Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::FileApi::Cache::SetFileApisToOEM, Functions::FileApi::Overrides::SetFileApisToOEM), "AttachDetours DetourAttach SetFileApisToOEM Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::FileApi::Cache::SetFileAttributesA, Functions::FileApi::Overrides::SetFileAttributesA), "AttachDetours DetourAttach SetFileAttributesA Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::FileApi::Cache::SetFileAttributesW, Functions::FileApi::Overrides::SetFileAttributesW), "AttachDetours DetourAttach SetFileAttributesW Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::FileApi::Cache::SetFileInformationByHandle, Functions::FileApi::Overrides::SetFileInformationByHandle), "AttachDetours DetourAttach SetFileInformationByHandle Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::FileApi::Cache::SetFileIoOverlappedRange, Functions::FileApi::Overrides::SetFileIoOverlappedRange), "AttachDetours DetourAttach SetFileIoOverlappedRange Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::FileApi::Cache::SetFilePointer, Functions::FileApi::Overrides::SetFilePointer), "AttachDetours DetourAttach SetFilePointer Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::FileApi::Cache::SetFilePointerEx, Functions::FileApi::Overrides::SetFilePointerEx), "AttachDetours DetourAttach SetFilePointerEx Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::FileApi::Cache::SetFileTime, Functions::FileApi::Overrides::SetFileTime), "AttachDetours DetourAttach SetFileTime Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::FileApi::Cache::SetFileValidData, Functions::FileApi::Overrides::SetFileValidData), "AttachDetours DetourAttach SetFileValidData Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::FileApi::Cache::UnlockFile, Functions::FileApi::Overrides::UnlockFile), "AttachDetours DetourAttach UnlockFile Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::FileApi::Cache::UnlockFileEx, Functions::FileApi::Overrides::UnlockFileEx), "AttachDetours DetourAttach UnlockFileEx Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::FileApi::Cache::WriteFile, Functions::FileApi::Overrides::WriteFile), "AttachDetours DetourAttach WriteFile Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::FileApi::Cache::WriteFileEx, Functions::FileApi::Overrides::WriteFileEx), "AttachDetours DetourAttach WriteFileEx Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::FileApi::Cache::WriteFileGather, Functions::FileApi::Overrides::WriteFileGather), "AttachDetours DetourAttach WriteFileGather Failed"); + + // LibLoaderApi + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::LibLoaderApi::Cache::LoadLibraryA, Functions::LibLoaderApi::Overrides::LoadLibraryA), "AttachDetours DetourAttach LoadLibraryA Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::LibLoaderApi::Cache::LoadLibraryW, Functions::LibLoaderApi::Overrides::LoadLibraryW), "AttachDetours DetourAttach LoadLibraryW Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::LibLoaderApi::Cache::LoadLibraryExA, Functions::LibLoaderApi::Overrides::LoadLibraryExA), "AttachDetours DetourAttach LoadLibraryExA Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::LibLoaderApi::Cache::LoadLibraryExW, Functions::LibLoaderApi::Overrides::LoadLibraryExW), "AttachDetours DetourAttach LoadLibraryExW Failed"); + + // ProcessEnv + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::ProcessEnv::Cache::SearchPathA, Functions::ProcessEnv::Overrides::SearchPathA), "AttachDetours DetourAttach SearchPathA Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::ProcessEnv::Cache::SearchPathW, Functions::ProcessEnv::Overrides::SearchPathW), "AttachDetours DetourAttach SearchPathW Failed"); + + // ProcessThreadsApi + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::ProcessThreadsApi::Cache::CreateProcessA, Functions::ProcessThreadsApi::Overrides::CreateProcessA), "AttachDetours DetourAttach CreateProcessA Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::ProcessThreadsApi::Cache::CreateProcessW, Functions::ProcessThreadsApi::Overrides::CreateProcessW), "AttachDetours DetourAttach CreateProcessW Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::ProcessThreadsApi::Cache::CreateProcessAsUserA, Functions::ProcessThreadsApi::Overrides::CreateProcessAsUserA), "AttachDetours DetourAttach CreateProcessAsUserA Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::ProcessThreadsApi::Cache::CreateProcessAsUserW, Functions::ProcessThreadsApi::Overrides::CreateProcessAsUserW), "AttachDetours DetourAttach CreateProcessAsUserW Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::ProcessThreadsApi::Cache::ExitProcess, Functions::ProcessThreadsApi::Overrides::ExitProcess), "AttachDetours DetourAttach ExitProcess Failed"); + + // UndocumentedApi + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::UndocumentedApi::Cache::EntryPoint, Functions::UndocumentedApi::Overrides::EntryPoint), "AttachDetours DetourAttach EntryPoint Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::UndocumentedApi::Cache::PrivCopyFileExA, Functions::UndocumentedApi::Overrides::PrivCopyFileExA), "AttachDetours DetourAttach PrivCopyFileExA Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::UndocumentedApi::Cache::PrivCopyFileExW, Functions::UndocumentedApi::Overrides::PrivCopyFileExW), "AttachDetours DetourAttach PrivCopyFileExW Failed"); + + // WinBase + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::WinBase::Cache::CopyFileA, Functions::WinBase::Overrides::CopyFileA), "AttachDetours DetourAttach CopyFileA Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::WinBase::Cache::CopyFileW, Functions::WinBase::Overrides::CopyFileW), "AttachDetours DetourAttach CopyFileW Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::WinBase::Cache::CopyFile2, Functions::WinBase::Overrides::CopyFile2), "AttachDetours DetourAttach CopyFile2 Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::WinBase::Cache::CopyFileExA, Functions::WinBase::Overrides::CopyFileExA), "AttachDetours DetourAttach CopyFileExA Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::WinBase::Cache::CopyFileExW, Functions::WinBase::Overrides::CopyFileExW), "AttachDetours DetourAttach CopyFileExW Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::WinBase::Cache::CopyFileTransactedA, Functions::WinBase::Overrides::CopyFileTransactedA), "AttachDetours DetourAttach CopyFileTransactedA Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::WinBase::Cache::CopyFileTransactedW, Functions::WinBase::Overrides::CopyFileTransactedW), "AttachDetours DetourAttach CopyFileTransactedW Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::WinBase::Cache::CreateDirectoryExA, Functions::WinBase::Overrides::CreateDirectoryExA), "AttachDetours DetourAttach CreateDirectoryExA Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::WinBase::Cache::CreateDirectoryExW, Functions::WinBase::Overrides::CreateDirectoryExW), "AttachDetours DetourAttach CreateDirectoryExW Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::WinBase::Cache::CreateDirectoryTransactedA, Functions::WinBase::Overrides::CreateDirectoryTransactedA), "AttachDetours DetourAttach CreateDirectoryTransactedA Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::WinBase::Cache::CreateDirectoryTransactedW, Functions::WinBase::Overrides::CreateDirectoryTransactedW), "AttachDetours DetourAttach CreateDirectoryTransactedW Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::WinBase::Cache::CreateFileTransactedA, Functions::WinBase::Overrides::CreateFileTransactedA), "AttachDetours DetourAttach CreateFileTransactedA Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::WinBase::Cache::CreateFileTransactedW, Functions::WinBase::Overrides::CreateFileTransactedW), "AttachDetours DetourAttach CreateFileTransactedW Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::WinBase::Cache::CreateHardLinkA, Functions::WinBase::Overrides::CreateHardLinkA), "AttachDetours DetourAttach CreateHardLinkA Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::WinBase::Cache::CreateHardLinkW, Functions::WinBase::Overrides::CreateHardLinkW), "AttachDetours DetourAttach CreateHardLinkW Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::WinBase::Cache::CreateHardLinkTransactedA, Functions::WinBase::Overrides::CreateHardLinkTransactedA), "AttachDetours DetourAttach CreateHardLinkTransactedA Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::WinBase::Cache::CreateHardLinkTransactedW, Functions::WinBase::Overrides::CreateHardLinkTransactedW), "AttachDetours DetourAttach CreateHardLinkTransactedW Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::WinBase::Cache::CreateProcessWithLogonW, Functions::WinBase::Overrides::CreateProcessWithLogonW), "AttachDetours DetourAttach CreateProcessWithLogonW Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::WinBase::Cache::CreateProcessWithTokenW, Functions::WinBase::Overrides::CreateProcessWithTokenW), "AttachDetours DetourAttach CreateProcessWithTokenW Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::WinBase::Cache::CreateSymbolicLinkA, Functions::WinBase::Overrides::CreateSymbolicLinkA), "AttachDetours DetourAttach CreateSymbolicLinkA Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::WinBase::Cache::CreateSymbolicLinkW, Functions::WinBase::Overrides::CreateSymbolicLinkW), "AttachDetours DetourAttach CreateSymbolicLinkW Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::WinBase::Cache::CreateSymbolicLinkTransactedA, Functions::WinBase::Overrides::CreateSymbolicLinkTransactedA), "AttachDetours DetourAttach CreateSymbolicLinkTransactedA Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::WinBase::Cache::CreateSymbolicLinkTransactedW, Functions::WinBase::Overrides::CreateSymbolicLinkTransactedW), "AttachDetours DetourAttach CreateSymbolicLinkTransactedW Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::WinBase::Cache::DecryptFileA, Functions::WinBase::Overrides::DecryptFileA), "AttachDetours DetourAttach DecryptFileA Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::WinBase::Cache::DecryptFileW, Functions::WinBase::Overrides::DecryptFileW), "AttachDetours DetourAttach DecryptFileW Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::WinBase::Cache::DeleteFileTransactedA, Functions::WinBase::Overrides::DeleteFileTransactedA), "AttachDetours DetourAttach DeleteFileTransactedA Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::WinBase::Cache::DeleteFileTransactedW, Functions::WinBase::Overrides::DeleteFileTransactedW), "AttachDetours DetourAttach DeleteFileTransactedW Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::WinBase::Cache::EncryptFileA, Functions::WinBase::Overrides::EncryptFileA), "AttachDetours DetourAttach EncryptFileA Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::WinBase::Cache::EncryptFileW, Functions::WinBase::Overrides::EncryptFileW), "AttachDetours DetourAttach EncryptFileW Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::WinBase::Cache::FileEncryptionStatusA, Functions::WinBase::Overrides::FileEncryptionStatusA), "AttachDetours DetourAttach FileEncryptionStatusA Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::WinBase::Cache::FileEncryptionStatusW, Functions::WinBase::Overrides::FileEncryptionStatusW), "AttachDetours DetourAttach FileEncryptionStatusW Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::WinBase::Cache::FindFirstFileNameTransactedW, Functions::WinBase::Overrides::FindFirstFileNameTransactedW), "AttachDetours DetourAttach FindFirstFileNameTransactedW Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::WinBase::Cache::FindFirstFileTransactedA, Functions::WinBase::Overrides::FindFirstFileTransactedA), "AttachDetours DetourAttach FindFirstFileTransactedA Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::WinBase::Cache::FindFirstFileTransactedW, Functions::WinBase::Overrides::FindFirstFileTransactedW), "AttachDetours DetourAttach FindFirstFileTransactedW Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::WinBase::Cache::FindFirstStreamTransactedW, Functions::WinBase::Overrides::FindFirstStreamTransactedW), "AttachDetours DetourAttach FindFirstStreamTransactedW Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::WinBase::Cache::GetBinaryTypeA, Functions::WinBase::Overrides::GetBinaryTypeA), "AttachDetours DetourAttach GetBinaryTypeA Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::WinBase::Cache::GetBinaryTypeW, Functions::WinBase::Overrides::GetBinaryTypeW), "AttachDetours DetourAttach GetBinaryTypeW Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::WinBase::Cache::GetCompressedFileSizeTransactedA, Functions::WinBase::Overrides::GetCompressedFileSizeTransactedA), "AttachDetours DetourAttach GetCompressedFileSizeTransactedA Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::WinBase::Cache::GetCompressedFileSizeTransactedW, Functions::WinBase::Overrides::GetCompressedFileSizeTransactedW), "AttachDetours DetourAttach GetCompressedFileSizeTransactedW Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::WinBase::Cache::GetDllDirectoryA, Functions::WinBase::Overrides::GetDllDirectoryA), "AttachDetours DetourAttach GetDllDirectoryA Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::WinBase::Cache::GetDllDirectoryW, Functions::WinBase::Overrides::GetDllDirectoryW), "AttachDetours DetourAttach GetDllDirectoryW Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::WinBase::Cache::GetFileAttributesTransactedA, Functions::WinBase::Overrides::GetFileAttributesTransactedA), "AttachDetours DetourAttach GetFileAttributesTransactedA Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::WinBase::Cache::GetFileAttributesTransactedW, Functions::WinBase::Overrides::GetFileAttributesTransactedW), "AttachDetours DetourAttach GetFileAttributesTransactedW Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::WinBase::Cache::GetFileBandwidthReservation, Functions::WinBase::Overrides::GetFileBandwidthReservation), "AttachDetours DetourAttach GetFileBandwidthReservation Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::WinBase::Cache::GetFileInformationByHandleEx, Functions::WinBase::Overrides::GetFileInformationByHandleEx), "AttachDetours DetourAttach GetFileInformationByHandleEx Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::WinBase::Cache::GetFileSecurityA, Functions::WinBase::Overrides::GetFileSecurityA), "AttachDetours DetourAttach GetFileSecurityA Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::WinBase::Cache::GetFullPathNameTransactedA, Functions::WinBase::Overrides::GetFullPathNameTransactedA), "AttachDetours DetourAttach GetFullPathNameTransactedA Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::WinBase::Cache::GetFullPathNameTransactedW, Functions::WinBase::Overrides::GetFullPathNameTransactedW), "AttachDetours DetourAttach GetFullPathNameTransactedW Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::WinBase::Cache::GetLongPathNameTransactedA, Functions::WinBase::Overrides::GetLongPathNameTransactedA), "AttachDetours DetourAttach GetLongPathNameTransactedA Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::WinBase::Cache::GetLongPathNameTransactedW, Functions::WinBase::Overrides::GetLongPathNameTransactedW), "AttachDetours DetourAttach GetLongPathNameTransactedW Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::WinBase::Cache::GetQueuedCompletionStatus, Functions::WinBase::Overrides::GetQueuedCompletionStatus), "AttachDetours DetourAttach GetQueuedCompletionStatus Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::WinBase::Cache::GetQueuedCompletionStatusEx, Functions::WinBase::Overrides::GetQueuedCompletionStatusEx), "AttachDetours DetourAttach GetQueuedCompletionStatusEx Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::WinBase::Cache::GetShortPathNameA, Functions::WinBase::Overrides::GetShortPathNameA), "AttachDetours DetourAttach GetShortPathNameA Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::WinBase::Cache::LoadModule, Functions::WinBase::Overrides::LoadModule), "AttachDetours DetourAttach LoadModule Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::WinBase::Cache::LoadPackagedLibrary, Functions::WinBase::Overrides::LoadPackagedLibrary), "AttachDetours DetourAttach LoadPackagedLibrary Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::WinBase::Cache::MoveFileA, Functions::WinBase::Overrides::MoveFileA), "AttachDetours DetourAttach MoveFileA Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::WinBase::Cache::MoveFileW, Functions::WinBase::Overrides::MoveFileW), "AttachDetours DetourAttach MoveFileW Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::WinBase::Cache::MoveFileExA, Functions::WinBase::Overrides::MoveFileExA), "AttachDetours DetourAttach MoveFileExA Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::WinBase::Cache::MoveFileExW, Functions::WinBase::Overrides::MoveFileExW), "AttachDetours DetourAttach MoveFileExW Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::WinBase::Cache::MoveFileTransactedA, Functions::WinBase::Overrides::MoveFileTransactedA), "AttachDetours DetourAttach MoveFileTransactedA Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::WinBase::Cache::MoveFileTransactedW, Functions::WinBase::Overrides::MoveFileTransactedW), "AttachDetours DetourAttach MoveFileTransactedW Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::WinBase::Cache::MoveFileWithProgressA, Functions::WinBase::Overrides::MoveFileWithProgressA), "AttachDetours DetourAttach MoveFileWithProgressA Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::WinBase::Cache::MoveFileWithProgressW, Functions::WinBase::Overrides::MoveFileWithProgressW), "AttachDetours DetourAttach MoveFileWithProgressW Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::WinBase::Cache::OpenEncryptedFileRawA, Functions::WinBase::Overrides::OpenEncryptedFileRawA), "AttachDetours DetourAttach OpenEncryptedFileRawA Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::WinBase::Cache::OpenEncryptedFileRawW, Functions::WinBase::Overrides::OpenEncryptedFileRawW), "AttachDetours DetourAttach OpenEncryptedFileRawW Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::WinBase::Cache::OpenFile, Functions::WinBase::Overrides::OpenFile), "AttachDetours DetourAttach OpenFile Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::WinBase::Cache::OpenFileById, Functions::WinBase::Overrides::OpenFileById), "AttachDetours DetourAttach OpenFileById Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::WinBase::Cache::ReadEncryptedFileRaw, Functions::WinBase::Overrides::ReadEncryptedFileRaw), "AttachDetours DetourAttach ReadEncryptedFileRaw Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::WinBase::Cache::RemoveDirectoryTransactedA, Functions::WinBase::Overrides::RemoveDirectoryTransactedA), "AttachDetours DetourAttach RemoveDirectoryTransactedA Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::WinBase::Cache::RemoveDirectoryTransactedW, Functions::WinBase::Overrides::RemoveDirectoryTransactedW), "AttachDetours DetourAttach RemoveDirectoryTransactedW Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::WinBase::Cache::ReOpenFile, Functions::WinBase::Overrides::ReOpenFile), "AttachDetours DetourAttach ReOpenFile Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::WinBase::Cache::ReplaceFileA, Functions::WinBase::Overrides::ReplaceFileA), "AttachDetours DetourAttach ReplaceFileA Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::WinBase::Cache::ReplaceFileW, Functions::WinBase::Overrides::ReplaceFileW), "AttachDetours DetourAttach ReplaceFileW Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::WinBase::Cache::SetCurrentDirectoryA, Functions::WinBase::Overrides::SetCurrentDirectoryA), "AttachDetours DetourAttach SetCurrentDirectoryA Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::WinBase::Cache::SetCurrentDirectoryW, Functions::WinBase::Overrides::SetCurrentDirectoryW), "AttachDetours DetourAttach SetCurrentDirectoryW Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::WinBase::Cache::SetDllDirectoryA, Functions::WinBase::Overrides::SetDllDirectoryA), "AttachDetours DetourAttach SetDllDirectoryA Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::WinBase::Cache::SetDllDirectoryW, Functions::WinBase::Overrides::SetDllDirectoryW), "AttachDetours DetourAttach SetDllDirectoryW Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::WinBase::Cache::SetFileAttributesTransactedA, Functions::WinBase::Overrides::SetFileAttributesTransactedA), "AttachDetours DetourAttach SetFileAttributesTransactedA Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::WinBase::Cache::SetFileAttributesTransactedW, Functions::WinBase::Overrides::SetFileAttributesTransactedW), "AttachDetours DetourAttach SetFileAttributesTransactedW Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::WinBase::Cache::SetFileBandwidthReservation, Functions::WinBase::Overrides::SetFileBandwidthReservation), "AttachDetours DetourAttach SetFileBandwidthReservation Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::WinBase::Cache::SetFileCompletionNotificationModes, Functions::WinBase::Overrides::SetFileCompletionNotificationModes), "AttachDetours DetourAttach SetFileCompletionNotificationModes Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::WinBase::Cache::SetFileSecurityA, Functions::WinBase::Overrides::SetFileSecurityA), "AttachDetours DetourAttach SetFileSecurityA Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::WinBase::Cache::SetFileShortNameA, Functions::WinBase::Overrides::SetFileShortNameA), "AttachDetours DetourAttach SetFileShortNameA Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::WinBase::Cache::SetFileShortNameW, Functions::WinBase::Overrides::SetFileShortNameW), "AttachDetours DetourAttach SetFileShortNameW Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::WinBase::Cache::SetSearchPathMode, Functions::WinBase::Overrides::SetSearchPathMode), "AttachDetours DetourAttach SetSearchPathMode Failed"); + ThrowIfFailed(DetourAttach(&(PVOID&)Functions::WinBase::Cache::WriteEncryptedFileRaw, Functions::WinBase::Overrides::WriteEncryptedFileRaw), "AttachDetours DetourAttach WriteEncryptedFileRaw Failed"); + + ThrowIfFailed(DetourTransactionCommit(), "AttachDetours DetourTransactionCommit Failed"); +} + +void DetachDetours() +{ + ThrowIfFailed(DetourTransactionBegin(), "DetachDetours DetourTransactionBegin Failed"); + ThrowIfFailed(DetourUpdateThread(GetCurrentThread()), "DetachDetours DetourUpdateThread Failed"); + + // FileApi + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::FileApi::Cache::AreFileApisANSI, Functions::FileApi::Overrides::AreFileApisANSI), "DetachDetours DetourDetach AreFileApisANSI Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::FileApi::Cache::CompareFileTime, Functions::FileApi::Overrides::CompareFileTime), "DetachDetours DetourDetach CompareFileTime Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::FileApi::Cache::CreateDirectoryA, Functions::FileApi::Overrides::CreateDirectoryA), "DetachDetours DetourDetach CreateDirectoryA Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::FileApi::Cache::CreateDirectoryW, Functions::FileApi::Overrides::CreateDirectoryW), "DetachDetours DetourDetach CreateDirectoryW Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::FileApi::Cache::CreateFile2, Functions::FileApi::Overrides::CreateFile2), "DetachDetours DetourDetach CreateFile2 Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::FileApi::Cache::CreateFileA, Functions::FileApi::Overrides::CreateFileA), "DetachDetours DetourDetach CreateFileA Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::FileApi::Cache::CreateFileW, Functions::FileApi::Overrides::CreateFileW), "DetachDetours DetourDetach CreateFileW Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::FileApi::Cache::DefineDosDeviceW, Functions::FileApi::Overrides::DefineDosDeviceW), "DetachDetours DetourDetach DefineDosDeviceW Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::FileApi::Cache::DeleteFileA, Functions::FileApi::Overrides::DeleteFileA), "DetachDetours DetourDetach DeleteFileA Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::FileApi::Cache::DeleteFileW, Functions::FileApi::Overrides::DeleteFileW), "DetachDetours DetourDetach DeleteFileW Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::FileApi::Cache::DeleteVolumeMountPointW, Functions::FileApi::Overrides::DeleteVolumeMountPointW), "DetachDetours DetourDetach DeleteVolumeMountPointW Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::FileApi::Cache::FileTimeToLocalFileTime, Functions::FileApi::Overrides::FileTimeToLocalFileTime), "DetachDetours DetourDetach FileTimeToLocalFileTime Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::FileApi::Cache::FindClose, Functions::FileApi::Overrides::FindClose), "DetachDetours DetourDetach FindClose Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::FileApi::Cache::FindCloseChangeNotification, Functions::FileApi::Overrides::FindCloseChangeNotification), "DetachDetours DetourDetach FindCloseChangeNotification Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::FileApi::Cache::FindFirstChangeNotificationA, Functions::FileApi::Overrides::FindFirstChangeNotificationA), "DetachDetours DetourDetach FindFirstChangeNotificationA Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::FileApi::Cache::FindFirstChangeNotificationW, Functions::FileApi::Overrides::FindFirstChangeNotificationW), "DetachDetours DetourDetach FindFirstChangeNotificationW Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::FileApi::Cache::FindFirstFileA, Functions::FileApi::Overrides::FindFirstFileA), "DetachDetours DetourDetach FindFirstFileA Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::FileApi::Cache::FindFirstFileW, Functions::FileApi::Overrides::FindFirstFileW), "DetachDetours DetourDetach FindFirstFileW Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::FileApi::Cache::FindFirstFileExA, Functions::FileApi::Overrides::FindFirstFileExA), "DetachDetours DetourDetach FindFirstFileExA Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::FileApi::Cache::FindFirstFileExW, Functions::FileApi::Overrides::FindFirstFileExW), "DetachDetours DetourDetach FindFirstFileExW Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::FileApi::Cache::FindFirstFileNameW, Functions::FileApi::Overrides::FindFirstFileNameW), "DetachDetours DetourDetach FindFirstFileNameW Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::FileApi::Cache::FindFirstStreamW, Functions::FileApi::Overrides::FindFirstStreamW), "DetachDetours DetourDetach FindFirstStreamW Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::FileApi::Cache::FindFirstVolumeW, Functions::FileApi::Overrides::FindFirstVolumeW), "DetachDetours DetourDetach FindFirstVolumeW Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::FileApi::Cache::FindNextChangeNotification, Functions::FileApi::Overrides::FindNextChangeNotification), "DetachDetours DetourDetach FindNextChangeNotification Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::FileApi::Cache::FindNextFileA, Functions::FileApi::Overrides::FindNextFileA), "DetachDetours DetourDetach FindNextFileA Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::FileApi::Cache::FindNextFileW, Functions::FileApi::Overrides::FindNextFileW), "DetachDetours DetourDetach FindNextFileW Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::FileApi::Cache::FindNextFileNameW, Functions::FileApi::Overrides::FindNextFileNameW), "DetachDetours DetourDetach FindNextFileNameW Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::FileApi::Cache::FindNextStreamW, Functions::FileApi::Overrides::FindNextStreamW), "DetachDetours DetourDetach FindNextStreamW Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::FileApi::Cache::FindNextVolumeW, Functions::FileApi::Overrides::FindNextVolumeW), "DetachDetours DetourDetach FindNextVolumeW Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::FileApi::Cache::FindVolumeClose, Functions::FileApi::Overrides::FindVolumeClose), "DetachDetours DetourDetach FindVolumeClose Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::FileApi::Cache::FlushFileBuffers, Functions::FileApi::Overrides::FlushFileBuffers), "DetachDetours DetourDetach FlushFileBuffers Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::FileApi::Cache::GetCompressedFileSizeA, Functions::FileApi::Overrides::GetCompressedFileSizeA), "DetachDetours DetourDetach GetCompressedFileSizeA Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::FileApi::Cache::GetCompressedFileSizeW, Functions::FileApi::Overrides::GetCompressedFileSizeW), "DetachDetours DetourDetach GetCompressedFileSizeW Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::FileApi::Cache::GetDiskFreeSpaceA, Functions::FileApi::Overrides::GetDiskFreeSpaceA), "DetachDetours DetourDetach GetDiskFreeSpaceA Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::FileApi::Cache::GetDiskFreeSpaceW, Functions::FileApi::Overrides::GetDiskFreeSpaceW), "DetachDetours DetourDetach GetDiskFreeSpaceW Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::FileApi::Cache::GetDiskFreeSpaceExA, Functions::FileApi::Overrides::GetDiskFreeSpaceExA), "DetachDetours DetourDetach GetDiskFreeSpaceExA Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::FileApi::Cache::GetDiskFreeSpaceExW, Functions::FileApi::Overrides::GetDiskFreeSpaceExW), "DetachDetours DetourDetach GetDiskFreeSpaceExW Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::FileApi::Cache::GetDriveTypeA, Functions::FileApi::Overrides::GetDriveTypeA), "DetachDetours DetourDetach GetDriveTypeA Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::FileApi::Cache::GetDriveTypeW, Functions::FileApi::Overrides::GetDriveTypeW), "DetachDetours DetourDetach GetDriveTypeW Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::FileApi::Cache::GetFileAttributesA, Functions::FileApi::Overrides::GetFileAttributesA), "DetachDetours DetourDetach GetFileAttributesA Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::FileApi::Cache::GetFileAttributesW, Functions::FileApi::Overrides::GetFileAttributesW), "DetachDetours DetourDetach GetFileAttributesW Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::FileApi::Cache::GetFileAttributesExA, Functions::FileApi::Overrides::GetFileAttributesExA), "DetachDetours DetourDetach GetFileAttributesExA Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::FileApi::Cache::GetFileAttributesExW, Functions::FileApi::Overrides::GetFileAttributesExW), "DetachDetours DetourDetach GetFileAttributesExW Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::FileApi::Cache::GetFileInformationByHandle, Functions::FileApi::Overrides::GetFileInformationByHandle), "DetachDetours DetourDetach GetFileInformationByHandle Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::FileApi::Cache::GetFileSize, Functions::FileApi::Overrides::GetFileSize), "DetachDetours DetourDetach GetFileSize Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::FileApi::Cache::GetFileSizeEx, Functions::FileApi::Overrides::GetFileSizeEx), "DetachDetours DetourDetach GetFileSizeEx Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::FileApi::Cache::GetFileTime, Functions::FileApi::Overrides::GetFileTime), "DetachDetours DetourDetach GetFileTime Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::FileApi::Cache::GetFileType, Functions::FileApi::Overrides::GetFileType), "DetachDetours DetourDetach GetFileType Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::FileApi::Cache::GetFinalPathNameByHandleA, Functions::FileApi::Overrides::GetFinalPathNameByHandleA), "DetachDetours DetourDetach GetFinalPathNameByHandleA Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::FileApi::Cache::GetFinalPathNameByHandleW, Functions::FileApi::Overrides::GetFinalPathNameByHandleW), "DetachDetours DetourDetach GetFinalPathNameByHandleW Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::FileApi::Cache::GetFullPathNameA, Functions::FileApi::Overrides::GetFullPathNameA), "DetachDetours DetourDetach GetFullPathNameA Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::FileApi::Cache::GetFullPathNameW, Functions::FileApi::Overrides::GetFullPathNameW), "DetachDetours DetourDetach GetFullPathNameW Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::FileApi::Cache::GetLogicalDrives, Functions::FileApi::Overrides::GetLogicalDrives), "DetachDetours DetourDetach GetLogicalDrives Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::FileApi::Cache::GetLogicalDriveStringsW, Functions::FileApi::Overrides::GetLogicalDriveStringsW), "DetachDetours DetourDetach GetLogicalDriveStringsW Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::FileApi::Cache::GetLongPathNameA, Functions::FileApi::Overrides::GetLongPathNameA), "DetachDetours DetourDetach GetLongPathNameA Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::FileApi::Cache::GetLongPathNameW, Functions::FileApi::Overrides::GetLongPathNameW), "DetachDetours DetourDetach GetLongPathNameW Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::FileApi::Cache::GetShortPathNameW, Functions::FileApi::Overrides::GetShortPathNameW), "DetachDetours DetourDetach GetShortPathNameW Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::FileApi::Cache::GetTempFileNameA, Functions::FileApi::Overrides::GetTempFileNameA), "DetachDetours DetourDetach GetTempFileNameA Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::FileApi::Cache::GetTempFileNameW, Functions::FileApi::Overrides::GetTempFileNameW), "DetachDetours DetourDetach GetTempFileNameW Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::FileApi::Cache::GetTempPathA, Functions::FileApi::Overrides::GetTempPathA), "DetachDetours DetourDetach GetTempPathA Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::FileApi::Cache::GetTempPathW, Functions::FileApi::Overrides::GetTempPathW), "DetachDetours DetourDetach GetTempPathW Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::FileApi::Cache::GetVolumeInformationA, Functions::FileApi::Overrides::GetVolumeInformationA), "DetachDetours DetourDetach GetVolumeInformationA Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::FileApi::Cache::GetVolumeInformationW, Functions::FileApi::Overrides::GetVolumeInformationW), "DetachDetours DetourDetach GetVolumeInformationW Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::FileApi::Cache::GetVolumeInformationByHandleW, Functions::FileApi::Overrides::GetVolumeInformationByHandleW), "DetachDetours DetourDetach GetVolumeInformationByHandleW Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::FileApi::Cache::GetVolumeNameForVolumeMountPointW, Functions::FileApi::Overrides::GetVolumeNameForVolumeMountPointW), "DetachDetours DetourDetach GetVolumeNameForVolumeMountPointW Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::FileApi::Cache::GetVolumePathNamesForVolumeNameW, Functions::FileApi::Overrides::GetVolumePathNamesForVolumeNameW), "DetachDetours DetourDetach GetVolumePathNamesForVolumeNameW Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::FileApi::Cache::GetVolumePathNameW, Functions::FileApi::Overrides::GetVolumePathNameW), "DetachDetours DetourDetach GetVolumePathNameW Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::FileApi::Cache::LocalFileTimeToFileTime, Functions::FileApi::Overrides::LocalFileTimeToFileTime), "DetachDetours DetourDetach LocalFileTimeToFileTime Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::FileApi::Cache::LockFile, Functions::FileApi::Overrides::LockFile), "DetachDetours DetourDetach LockFile Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::FileApi::Cache::LockFileEx, Functions::FileApi::Overrides::LockFileEx), "DetachDetours DetourDetach LockFileEx Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::FileApi::Cache::QueryDosDeviceW, Functions::FileApi::Overrides::QueryDosDeviceW), "DetachDetours DetourDetach QueryDosDeviceW Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::FileApi::Cache::ReadFile, Functions::FileApi::Overrides::ReadFile), "DetachDetours DetourDetach ReadFile Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::FileApi::Cache::ReadFileEx, Functions::FileApi::Overrides::ReadFileEx), "DetachDetours DetourDetach ReadFileEx Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::FileApi::Cache::ReadFileScatter, Functions::FileApi::Overrides::ReadFileScatter), "DetachDetours DetourDetach ReadFileScatter Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::FileApi::Cache::RemoveDirectoryA, Functions::FileApi::Overrides::RemoveDirectoryA), "DetachDetours DetourDetach RemoveDirectoryA Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::FileApi::Cache::RemoveDirectoryW, Functions::FileApi::Overrides::RemoveDirectoryW), "DetachDetours DetourDetach RemoveDirectoryW Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::FileApi::Cache::SetEndOfFile, Functions::FileApi::Overrides::SetEndOfFile), "DetachDetours DetourDetach SetEndOfFile Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::FileApi::Cache::SetFileApisToANSI, Functions::FileApi::Overrides::SetFileApisToANSI), "DetachDetours DetourDetach SetFileApisToANSI Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::FileApi::Cache::SetFileApisToOEM, Functions::FileApi::Overrides::SetFileApisToOEM), "DetachDetours DetourDetach SetFileApisToOEM Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::FileApi::Cache::SetFileAttributesA, Functions::FileApi::Overrides::SetFileAttributesA), "DetachDetours DetourDetach SetFileAttributesA Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::FileApi::Cache::SetFileAttributesW, Functions::FileApi::Overrides::SetFileAttributesW), "DetachDetours DetourDetach SetFileAttributesW Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::FileApi::Cache::SetFileInformationByHandle, Functions::FileApi::Overrides::SetFileInformationByHandle), "DetachDetours DetourDetach SetFileInformationByHandle Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::FileApi::Cache::SetFileIoOverlappedRange, Functions::FileApi::Overrides::SetFileIoOverlappedRange), "DetachDetours DetourDetach SetFileIoOverlappedRange Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::FileApi::Cache::SetFilePointer, Functions::FileApi::Overrides::SetFilePointer), "DetachDetours DetourDetach SetFilePointer Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::FileApi::Cache::SetFilePointerEx, Functions::FileApi::Overrides::SetFilePointerEx), "DetachDetours DetourDetach SetFilePointerEx Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::FileApi::Cache::SetFileTime, Functions::FileApi::Overrides::SetFileTime), "DetachDetours DetourDetach SetFileTime Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::FileApi::Cache::SetFileValidData, Functions::FileApi::Overrides::SetFileValidData), "DetachDetours DetourDetach SetFileValidData Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::FileApi::Cache::UnlockFile, Functions::FileApi::Overrides::UnlockFile), "DetachDetours DetourDetach UnlockFile Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::FileApi::Cache::UnlockFileEx, Functions::FileApi::Overrides::UnlockFileEx), "DetachDetours DetourDetach UnlockFileEx Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::FileApi::Cache::WriteFile, Functions::FileApi::Overrides::WriteFile), "DetachDetours DetourDetach WriteFile Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::FileApi::Cache::WriteFileEx, Functions::FileApi::Overrides::WriteFileEx), "DetachDetours DetourDetach WriteFileEx Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::FileApi::Cache::WriteFileGather, Functions::FileApi::Overrides::WriteFileGather), "DetachDetours DetourDetach WriteFileGather Failed"); + + // LibLoaderApi + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::LibLoaderApi::Cache::LoadLibraryA, Functions::LibLoaderApi::Overrides::LoadLibraryA), "DetachDetours DetourDetach LoadLibraryA Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::LibLoaderApi::Cache::LoadLibraryW, Functions::LibLoaderApi::Overrides::LoadLibraryW), "DetachDetours DetourDetach LoadLibraryW Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::LibLoaderApi::Cache::LoadLibraryExA, Functions::LibLoaderApi::Overrides::LoadLibraryExA), "DetachDetours DetourDetach LoadLibraryExA Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::LibLoaderApi::Cache::LoadLibraryExW, Functions::LibLoaderApi::Overrides::LoadLibraryExW), "DetachDetours DetourDetach LoadLibraryExW Failed"); + + // ProcessEnv + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::ProcessEnv::Cache::SearchPathA, Functions::ProcessEnv::Overrides::SearchPathA), "DetachDetours DetourDetach SearchPathA Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::ProcessEnv::Cache::SearchPathW, Functions::ProcessEnv::Overrides::SearchPathW), "DetachDetours DetourDetach SearchPathW Failed"); + + // ProcessThreadsApi + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::ProcessThreadsApi::Cache::CreateProcessA, Functions::ProcessThreadsApi::Overrides::CreateProcessA), "DetachDetours DetourDetach CreateProcessA Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::ProcessThreadsApi::Cache::CreateProcessW, Functions::ProcessThreadsApi::Overrides::CreateProcessW), "DetachDetours DetourDetach CreateProcessW Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::ProcessThreadsApi::Cache::CreateProcessAsUserA, Functions::ProcessThreadsApi::Overrides::CreateProcessAsUserA), "DetachDetours DetourDetach CreateProcessAsUserA Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::ProcessThreadsApi::Cache::CreateProcessAsUserW, Functions::ProcessThreadsApi::Overrides::CreateProcessAsUserW), "DetachDetours DetourDetach CreateProcessAsUserW Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::ProcessThreadsApi::Cache::ExitProcess, Functions::ProcessThreadsApi::Overrides::ExitProcess), "DetachDetours DetourDetach ExitProcess Failed"); + + // UndocumentedApi + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::UndocumentedApi::Cache::EntryPoint, Functions::UndocumentedApi::Overrides::EntryPoint), "DetachDetours DetourDetach EntryPoint Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::UndocumentedApi::Cache::PrivCopyFileExA, Functions::UndocumentedApi::Overrides::PrivCopyFileExA), "DetachDetours DetourDetach PrivCopyFileExA Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::UndocumentedApi::Cache::PrivCopyFileExW, Functions::UndocumentedApi::Overrides::PrivCopyFileExW), "DetachDetours DetourDetach PrivCopyFileExW Failed"); + + // WinBase + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::WinBase::Cache::CopyFileA, Functions::WinBase::Overrides::CopyFileA), "DetachDetours DetourDetach CopyFileA Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::WinBase::Cache::CopyFileW, Functions::WinBase::Overrides::CopyFileW), "DetachDetours DetourDetach CopyFileW Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::WinBase::Cache::CopyFile2, Functions::WinBase::Overrides::CopyFile2), "DetachDetours DetourDetach CopyFile2 Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::WinBase::Cache::CopyFileExA, Functions::WinBase::Overrides::CopyFileExA), "DetachDetours DetourDetach CopyFileExA Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::WinBase::Cache::CopyFileExW, Functions::WinBase::Overrides::CopyFileExW), "DetachDetours DetourDetach CopyFileExW Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::WinBase::Cache::CopyFileTransactedA, Functions::WinBase::Overrides::CopyFileTransactedA), "DetachDetours DetourDetach CopyFileTransactedA Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::WinBase::Cache::CopyFileTransactedW, Functions::WinBase::Overrides::CopyFileTransactedW), "DetachDetours DetourDetach CopyFileTransactedW Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::WinBase::Cache::CreateDirectoryExA, Functions::WinBase::Overrides::CreateDirectoryExA), "DetachDetours DetourDetach CreateDirectoryExA Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::WinBase::Cache::CreateDirectoryExW, Functions::WinBase::Overrides::CreateDirectoryExW), "DetachDetours DetourDetach CreateDirectoryExW Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::WinBase::Cache::CreateDirectoryTransactedA, Functions::WinBase::Overrides::CreateDirectoryTransactedA), "DetachDetours DetourDetach CreateDirectoryTransactedA Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::WinBase::Cache::CreateDirectoryTransactedW, Functions::WinBase::Overrides::CreateDirectoryTransactedW), "DetachDetours DetourDetach CreateDirectoryTransactedW Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::WinBase::Cache::CreateFileTransactedA, Functions::WinBase::Overrides::CreateFileTransactedA), "DetachDetours DetourDetach CreateFileTransactedA Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::WinBase::Cache::CreateFileTransactedW, Functions::WinBase::Overrides::CreateFileTransactedW), "DetachDetours DetourDetach CreateFileTransactedW Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::WinBase::Cache::CreateHardLinkA, Functions::WinBase::Overrides::CreateHardLinkA), "DetachDetours DetourDetach CreateHardLinkA Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::WinBase::Cache::CreateHardLinkW, Functions::WinBase::Overrides::CreateHardLinkW), "DetachDetours DetourDetach CreateHardLinkW Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::WinBase::Cache::CreateHardLinkTransactedA, Functions::WinBase::Overrides::CreateHardLinkTransactedA), "DetachDetours DetourDetach CreateHardLinkTransactedA Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::WinBase::Cache::CreateHardLinkTransactedW, Functions::WinBase::Overrides::CreateHardLinkTransactedW), "DetachDetours DetourDetach CreateHardLinkTransactedW Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::WinBase::Cache::CreateProcessWithLogonW, Functions::WinBase::Overrides::CreateProcessWithLogonW), "DetachDetours DetourDetach CreateProcessWithLogonW Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::WinBase::Cache::CreateProcessWithTokenW, Functions::WinBase::Overrides::CreateProcessWithTokenW), "DetachDetours DetourDetach CreateProcessWithTokenW Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::WinBase::Cache::CreateSymbolicLinkA, Functions::WinBase::Overrides::CreateSymbolicLinkA), "DetachDetours DetourDetach CreateSymbolicLinkA Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::WinBase::Cache::CreateSymbolicLinkW, Functions::WinBase::Overrides::CreateSymbolicLinkW), "DetachDetours DetourDetach CreateSymbolicLinkW Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::WinBase::Cache::CreateSymbolicLinkTransactedA, Functions::WinBase::Overrides::CreateSymbolicLinkTransactedA), "DetachDetours DetourDetach CreateSymbolicLinkTransactedA Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::WinBase::Cache::CreateSymbolicLinkTransactedW, Functions::WinBase::Overrides::CreateSymbolicLinkTransactedW), "DetachDetours DetourDetach CreateSymbolicLinkTransactedW Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::WinBase::Cache::DecryptFileA, Functions::WinBase::Overrides::DecryptFileA), "DetachDetours DetourDetach DecryptFileA Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::WinBase::Cache::DecryptFileW, Functions::WinBase::Overrides::DecryptFileW), "DetachDetours DetourDetach DecryptFileW Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::WinBase::Cache::DeleteFileTransactedA, Functions::WinBase::Overrides::DeleteFileTransactedA), "DetachDetours DetourDetach DeleteFileTransactedA Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::WinBase::Cache::DeleteFileTransactedW, Functions::WinBase::Overrides::DeleteFileTransactedW), "DetachDetours DetourDetach DeleteFileTransactedW Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::WinBase::Cache::EncryptFileA, Functions::WinBase::Overrides::EncryptFileA), "DetachDetours DetourDetach EncryptFileA Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::WinBase::Cache::EncryptFileW, Functions::WinBase::Overrides::EncryptFileW), "DetachDetours DetourDetach EncryptFileW Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::WinBase::Cache::FileEncryptionStatusA, Functions::WinBase::Overrides::FileEncryptionStatusA), "DetachDetours DetourDetach FileEncryptionStatusA Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::WinBase::Cache::FileEncryptionStatusW, Functions::WinBase::Overrides::FileEncryptionStatusW), "DetachDetours DetourDetach FileEncryptionStatusW Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::WinBase::Cache::FindFirstFileNameTransactedW, Functions::WinBase::Overrides::FindFirstFileNameTransactedW), "DetachDetours DetourDetach FindFirstFileNameTransactedW Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::WinBase::Cache::FindFirstFileTransactedA, Functions::WinBase::Overrides::FindFirstFileTransactedA), "DetachDetours DetourDetach FindFirstFileTransactedA Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::WinBase::Cache::FindFirstFileTransactedW, Functions::WinBase::Overrides::FindFirstFileTransactedW), "DetachDetours DetourDetach FindFirstFileTransactedW Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::WinBase::Cache::FindFirstStreamTransactedW, Functions::WinBase::Overrides::FindFirstStreamTransactedW), "DetachDetours DetourDetach FindFirstStreamTransactedW Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::WinBase::Cache::GetBinaryTypeA, Functions::WinBase::Overrides::GetBinaryTypeA), "DetachDetours DetourDetach GetBinaryTypeA Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::WinBase::Cache::GetBinaryTypeW, Functions::WinBase::Overrides::GetBinaryTypeW), "DetachDetours DetourDetach GetBinaryTypeW Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::WinBase::Cache::GetCompressedFileSizeTransactedA, Functions::WinBase::Overrides::GetCompressedFileSizeTransactedA), "DetachDetours DetourDetach GetCompressedFileSizeTransactedA Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::WinBase::Cache::GetCompressedFileSizeTransactedW, Functions::WinBase::Overrides::GetCompressedFileSizeTransactedW), "DetachDetours DetourDetach GetCompressedFileSizeTransactedW Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::WinBase::Cache::GetDllDirectoryA, Functions::WinBase::Overrides::GetDllDirectoryA), "DetachDetours DetourDetach GetDllDirectoryA Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::WinBase::Cache::GetDllDirectoryW, Functions::WinBase::Overrides::GetDllDirectoryW), "DetachDetours DetourDetach GetDllDirectoryW Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::WinBase::Cache::GetFileAttributesTransactedA, Functions::WinBase::Overrides::GetFileAttributesTransactedA), "DetachDetours DetourDetach GetFileAttributesTransactedA Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::WinBase::Cache::GetFileAttributesTransactedW, Functions::WinBase::Overrides::GetFileAttributesTransactedW), "DetachDetours DetourDetach GetFileAttributesTransactedW Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::WinBase::Cache::GetFileBandwidthReservation, Functions::WinBase::Overrides::GetFileBandwidthReservation), "DetachDetours DetourDetach GetFileBandwidthReservation Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::WinBase::Cache::GetFileInformationByHandleEx, Functions::WinBase::Overrides::GetFileInformationByHandleEx), "DetachDetours DetourDetach GetFileInformationByHandleEx Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::WinBase::Cache::GetFileSecurityA, Functions::WinBase::Overrides::GetFileSecurityA), "DetachDetours DetourDetach GetFileSecurityA Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::WinBase::Cache::GetFullPathNameTransactedA, Functions::WinBase::Overrides::GetFullPathNameTransactedA), "DetachDetours DetourDetach GetFullPathNameTransactedA Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::WinBase::Cache::GetFullPathNameTransactedW, Functions::WinBase::Overrides::GetFullPathNameTransactedW), "DetachDetours DetourDetach GetFullPathNameTransactedW Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::WinBase::Cache::GetLongPathNameTransactedA, Functions::WinBase::Overrides::GetLongPathNameTransactedA), "DetachDetours DetourDetach GetLongPathNameTransactedA Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::WinBase::Cache::GetLongPathNameTransactedW, Functions::WinBase::Overrides::GetLongPathNameTransactedW), "DetachDetours DetourDetach GetLongPathNameTransactedW Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::WinBase::Cache::GetQueuedCompletionStatus, Functions::WinBase::Overrides::GetQueuedCompletionStatus), "DetachDetours DetourDetach GetQueuedCompletionStatus Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::WinBase::Cache::GetQueuedCompletionStatusEx, Functions::WinBase::Overrides::GetQueuedCompletionStatusEx), "DetachDetours DetourDetach GetQueuedCompletionStatusEx Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::WinBase::Cache::GetShortPathNameA, Functions::WinBase::Overrides::GetShortPathNameA), "DetachDetours DetourDetach GetShortPathNameA Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::WinBase::Cache::LoadModule, Functions::WinBase::Overrides::LoadModule), "DetachDetours DetourDetach LoadModule Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::WinBase::Cache::LoadPackagedLibrary, Functions::WinBase::Overrides::LoadPackagedLibrary), "DetachDetours DetourDetach LoadPackagedLibrary Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::WinBase::Cache::MoveFileA, Functions::WinBase::Overrides::MoveFileA), "DetachDetours DetourDetach MoveFileA Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::WinBase::Cache::MoveFileW, Functions::WinBase::Overrides::MoveFileW), "DetachDetours DetourDetach MoveFileW Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::WinBase::Cache::MoveFileExA, Functions::WinBase::Overrides::MoveFileExA), "DetachDetours DetourDetach MoveFileExA Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::WinBase::Cache::MoveFileExW, Functions::WinBase::Overrides::MoveFileExW), "DetachDetours DetourDetach MoveFileExW Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::WinBase::Cache::MoveFileTransactedA, Functions::WinBase::Overrides::MoveFileTransactedA), "DetachDetours DetourDetach MoveFileTransactedA Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::WinBase::Cache::MoveFileTransactedW, Functions::WinBase::Overrides::MoveFileTransactedW), "DetachDetours DetourDetach MoveFileTransactedW Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::WinBase::Cache::MoveFileWithProgressA, Functions::WinBase::Overrides::MoveFileWithProgressA), "DetachDetours DetourDetach MoveFileWithProgressA Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::WinBase::Cache::MoveFileWithProgressW, Functions::WinBase::Overrides::MoveFileWithProgressW), "DetachDetours DetourDetach MoveFileWithProgressW Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::WinBase::Cache::OpenEncryptedFileRawA, Functions::WinBase::Overrides::OpenEncryptedFileRawA), "DetachDetours DetourDetach OpenEncryptedFileRawA Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::WinBase::Cache::OpenEncryptedFileRawW, Functions::WinBase::Overrides::OpenEncryptedFileRawW), "DetachDetours DetourDetach OpenEncryptedFileRawW Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::WinBase::Cache::OpenFile, Functions::WinBase::Overrides::OpenFile), "DetachDetours DetourDetach OpenFile Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::WinBase::Cache::OpenFileById, Functions::WinBase::Overrides::OpenFileById), "DetachDetours DetourDetach OpenFileById Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::WinBase::Cache::ReadEncryptedFileRaw, Functions::WinBase::Overrides::ReadEncryptedFileRaw), "DetachDetours DetourDetach ReadEncryptedFileRaw Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::WinBase::Cache::RemoveDirectoryTransactedA, Functions::WinBase::Overrides::RemoveDirectoryTransactedA), "DetachDetours DetourDetach RemoveDirectoryTransactedA Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::WinBase::Cache::RemoveDirectoryTransactedW, Functions::WinBase::Overrides::RemoveDirectoryTransactedW), "DetachDetours DetourDetach RemoveDirectoryTransactedW Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::WinBase::Cache::ReOpenFile, Functions::WinBase::Overrides::ReOpenFile), "DetachDetours DetourDetach ReOpenFile Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::WinBase::Cache::ReplaceFileA, Functions::WinBase::Overrides::ReplaceFileA), "DetachDetours DetourDetach ReplaceFileA Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::WinBase::Cache::ReplaceFileW, Functions::WinBase::Overrides::ReplaceFileW), "DetachDetours DetourDetach ReplaceFileW Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::WinBase::Cache::SetCurrentDirectoryA, Functions::WinBase::Overrides::SetCurrentDirectoryA), "DetachDetours DetourDetach SetCurrentDirectoryA Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::WinBase::Cache::SetCurrentDirectoryW, Functions::WinBase::Overrides::SetCurrentDirectoryW), "DetachDetours DetourDetach SetCurrentDirectoryW Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::WinBase::Cache::SetDllDirectoryA, Functions::WinBase::Overrides::SetDllDirectoryA), "DetachDetours DetourDetach SetDllDirectoryA Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::WinBase::Cache::SetDllDirectoryW, Functions::WinBase::Overrides::SetDllDirectoryW), "DetachDetours DetourDetach SetDllDirectoryW Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::WinBase::Cache::SetFileAttributesTransactedA, Functions::WinBase::Overrides::SetFileAttributesTransactedA), "DetachDetours DetourDetach SetFileAttributesTransactedA Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::WinBase::Cache::SetFileAttributesTransactedW, Functions::WinBase::Overrides::SetFileAttributesTransactedW), "DetachDetours DetourDetach SetFileAttributesTransactedW Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::WinBase::Cache::SetFileBandwidthReservation, Functions::WinBase::Overrides::SetFileBandwidthReservation), "DetachDetours DetourDetach SetFileBandwidthReservation Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::WinBase::Cache::SetFileCompletionNotificationModes, Functions::WinBase::Overrides::SetFileCompletionNotificationModes), "DetachDetours DetourDetach SetFileCompletionNotificationModes Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::WinBase::Cache::SetFileSecurityA, Functions::WinBase::Overrides::SetFileSecurityA), "DetachDetours DetourDetach SetFileSecurityA Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::WinBase::Cache::SetFileShortNameA, Functions::WinBase::Overrides::SetFileShortNameA), "DetachDetours DetourDetach SetFileShortNameA Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::WinBase::Cache::SetFileShortNameW, Functions::WinBase::Overrides::SetFileShortNameW), "DetachDetours DetourDetach SetFileShortNameW Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::WinBase::Cache::SetSearchPathMode, Functions::WinBase::Overrides::SetSearchPathMode), "DetachDetours DetourDetach SetSearchPathMode Failed"); + ThrowIfFailed(DetourDetach(&(PVOID&)Functions::WinBase::Cache::WriteEncryptedFileRaw, Functions::WinBase::Overrides::WriteEncryptedFileRaw), "DetachDetours DetourDetach WriteEncryptedFileRaw Failed"); + + ThrowIfFailed(DetourTransactionCommit(), "DetachDetours DetourTransactionCommit Failed"); +} + + +bool ThreadAttach(HMODULE hDll) +{ + return true; +} + +bool ThreadDetach(HMODULE hDll) +{ + return true; +} + +bool ProcessAttach(HMODULE hDll) +{ + InitializeCriticalSection(&s_csChildPayload); + + s_hInst = hDll; + s_hKernel32 = nullptr; + + PBYTE xCreate = (PBYTE)DetourCodeFromPointer((PVOID)Functions::ProcessThreadsApi::Cache::CreateProcessW, nullptr); + Monitor::DetourPayload* pPayload = nullptr; + + for (HMODULE hMod = nullptr; (hMod = DetourEnumerateModules(hMod)) != nullptr;) + { + ULONG cbData; + PVOID pvData = DetourFindPayload(hMod, Monitor::GuidTrace, &cbData); + + if (pvData != nullptr && pPayload == nullptr) + { + pPayload = (Monitor::DetourPayload*)pvData; + } + + ULONG cbMod = DetourGetModuleSize(hMod); + + if (((PBYTE)hMod) < xCreate && ((PBYTE)hMod + cbMod) > xCreate) + { + s_hKernel32 = hMod; + } + } + + ZeroMemory(&s_Payload, sizeof(s_Payload)); + + if (pPayload == nullptr) + { + return false; + } + + CopyMemory(&s_Payload, pPayload, sizeof(s_Payload)); + + s_nTraceProcessId = s_Payload.nTraceProcessId; + + GetModuleFileNameA(s_hInst, s_szDllPath, ARRAYSIZE(s_szDllPath)); + + try + { + // Find hidden functions. + Functions::UndocumentedApi::Cache::PrivCopyFileExA = + (BOOL (WINAPI *)(LPCSTR, LPCSTR, LPPROGRESS_ROUTINE, LPVOID, LPBOOL, DWORD)) + GetProcAddress(s_hKernel32, "PrivCopyFileExW"); + if (Functions::UndocumentedApi::Cache::PrivCopyFileExA == nullptr) + { + throw std::runtime_error("Failed to GetProcAddress PrivCopyFileExA"); + } + + // Find hidden functions. + Functions::UndocumentedApi::Cache::PrivCopyFileExW = + (BOOL (WINAPI *)(LPCWSTR, LPCWSTR, LPPROGRESS_ROUTINE, LPVOID, LPBOOL, DWORD)) + GetProcAddress(s_hKernel32, "PrivCopyFileExW"); + if (Functions::UndocumentedApi::Cache::PrivCopyFileExW == nullptr) + { + throw std::runtime_error("Failed to GetProcAddress PrivCopyFileExW"); + } + + AttachDetours(); + } + catch (const std::exception& ex) + { + EventLogger::WriteError(ex.what()); + } + catch (...) + { + EventLogger::WriteError("Unknown error attaching detours"); + } + + ThreadAttach(hDll); + + return true; +} + +bool ProcessDetach(HMODULE hDll) +{ + ThreadDetach(hDll); + + try + { + DetachDetours(); + } + catch (const std::exception& ex) + { + EventLogger::WriteError(ex.what()); + } + catch (...) + { + EventLogger::WriteError("Unknown error detaching detours"); + } + + EventLogger::Shutdown(); + + return true; +} + +bool APIENTRY DllMain(HINSTANCE hModule, DWORD dwReason, PVOID lpReserved) +{ + (void)hModule; + (void)lpReserved; + +#ifdef ENABLE_MONITOR_DEBUG + while (!IsDebuggerPresent()) + { + Sleep(0); + } +#endif + + if (DetourIsHelperProcess()) + { + return true; + } + + if (dwReason == DLL_PROCESS_ATTACH) + { + DetourRestoreAfterWith(); + Functions::UndocumentedApi::Cache::EntryPoint = (int (WINAPI *)(void))DetourGetEntryPoint(nullptr); + return ProcessAttach(hModule); + } + else if (dwReason == DLL_PROCESS_DETACH) + { + return ProcessDetach(hModule); + } + else if (dwReason == DLL_THREAD_ATTACH) + { + return ThreadAttach(hModule); + } + else if (dwReason == DLL_THREAD_DETACH) + { + return ThreadDetach(hModule); + } + + return true; +} \ No newline at end of file diff --git a/Source/Monitor/Detours/Recipe.toml b/Source/Monitor/Detours/Recipe.toml new file mode 100644 index 00000000..1e64e104 --- /dev/null +++ b/Source/Monitor/Detours/Recipe.toml @@ -0,0 +1,11 @@ +Name = "Monitor.Detours" +Version = "1.0.0" +Type = "DynamicLibrary" +Dependencies = [ + "../../../Dependencies/Detours/src/", + "../Shared/", +] +Defines = [ + # "ENABLE_MONITOR_DEBUG", +] +Public = "Module.cpp" diff --git a/Source/Monitor/Log/Build.cmd b/Source/Monitor/Log/Build.cmd new file mode 100644 index 00000000..4f80639e --- /dev/null +++ b/Source/Monitor/Log/Build.cmd @@ -0,0 +1,23 @@ +@echo off +SET HostDir=%~dp0 +SET DetoursDir=%HostDir%..\Detours +SET BinaryDirectorPath=out\bin\MSVC\debug\win32 +SET HostBinaryDirectory=%HostDir%\%BinaryDirectorPath% +SET DetoursBinaryDirectory=%DetoursDir%\%BinaryDirectorPath% +REM - Build the host +echo soup build %HostDir% +call soup build %HostDir% +if %ERRORLEVEL% NEQ 0 exit /B %ERRORLEVEL% +REM - Build Each version of the detours dll +echo soup build %DetoursDir% -architecture x64 +call soup build %DetoursDir% -architecture x64 +if %ERRORLEVEL% NEQ 0 exit /B %ERRORLEVEL% +echo copy %DetoursBinaryDirectory%\x64\Monitor.Detours.dll %HostBinaryDirectory%\x64\Monitor.Detours.64.dll +copy %DetoursBinaryDirectory%\x64\Monitor.Detours.dll %HostBinaryDirectory%\x64\Monitor.Detours.64.dll > nul +copy %DetoursBinaryDirectory%\x64\Monitor.Detours.pdb %HostBinaryDirectory%\x64\Monitor.Detours.64.pdb > nul +echo soup build %DetoursDir% -architecture x86 +call soup build %DetoursDir% -architecture x86 +if %ERRORLEVEL% NEQ 0 exit /B %ERRORLEVEL% +echo copy %DetoursBinaryDirectory%\x86\Monitor.Detours.dll %HostBinaryDirectory%\x64\Monitor.Detours.32.dll +copy %DetoursBinaryDirectory%\x86\Monitor.Detours.dll %HostBinaryDirectory%\x64\Monitor.Detours.32.dll > nul +copy %DetoursBinaryDirectory%\x86\Monitor.Detours.pdb %HostBinaryDirectory%\x64\Monitor.Detours.32.pdb > nul \ No newline at end of file diff --git a/Source/Monitor/Log/DetourCallbackLogger.h b/Source/Monitor/Log/DetourCallbackLogger.h new file mode 100644 index 00000000..d2392f8a --- /dev/null +++ b/Source/Monitor/Log/DetourCallbackLogger.h @@ -0,0 +1,1004 @@ +#pragma once + +namespace Monitor +{ + class DetourCallbackLogger : public IDetourCallback + { + public: + DetourCallbackLogger(std::ostream& stream) : + m_stream(stream) + { + } + + void OnShutdown() override final + { + m_stream << "Shutdown: " << std::endl; + } + + void OnError(std::string_view message) override final + { + m_stream << "Error: " << message << std::endl; + } + + // FileApi + void OnAreFileApisANSI(bool result) override final + { + m_stream << "AreFileApisANSI: " << std::endl; + } + + void OnCompareFileTime(int32_t result) override final + { + m_stream << "CompareFileTime: " << std::endl; + } + + void OnCreateDirectoryA(std::string_view pathName, bool result) override final + { + m_stream << "CreateDirectoryA: " << pathName << std::endl; + } + + void OnCreateDirectoryW(std::wstring_view pathName, bool result) override final + { + std::wstring_convert, wchar_t> converter; + m_stream << "CreateDirectoryW: " << converter.to_bytes(pathName.data()) << std::endl; + } + + void OnCreateFile2( + std::wstring_view fileName, + uint32_t desiredAccess, + uint32_t sharedMode, + uint32_t creationDisposition, + uint64_t result) override final + { + std::wstring_convert, wchar_t> converter; + m_stream << "CreateFile2: " << converter.to_bytes(fileName.data()) << std::endl; + } + + void OnCreateFileA(std::string_view fileName, uint32_t desiredAccess, uint32_t sharedMode, uint32_t creationDisposition, uint32_t flagsAndAttributes) override final + { + m_stream << "CreateFileA: " << fileName << std::endl; + } + + void OnCreateFileW(std::wstring_view fileName, uint32_t desiredAccess, uint32_t sharedMode, uint32_t creationDisposition, uint32_t flagsAndAttributes) override final + { + std::wstring_convert, wchar_t> converter; + m_stream << "CreateFileW: " << converter.to_bytes(fileName.data()) << std::endl; + } + + void OnDefineDosDeviceW(uint32_t flags, std::wstring_view deviceName, std::wstring_view targetPath, bool result) override final + { + m_stream << "DefineDosDeviceW: " << std::endl; + } + + void OnDeleteFileA(std::string_view fileName, bool result) override final + { + m_stream << "DeleteFileA: " << fileName << std::endl; + } + + void OnDeleteFileW(std::wstring_view fileName, bool result) override final + { + std::wstring_convert, wchar_t> converter; + m_stream << "DeleteFileW: " << converter.to_bytes(fileName.data()) << std::endl; + } + + void OnDeleteVolumeMountPointW(std::wstring_view volumeMountPoint, bool result) override final + { + m_stream << "DeleteVolumeMountPointW: " << std::endl; + } + + void OnFileTimeToLocalFileTime(bool result) override final + { + m_stream << "FileTimeToLocalFileTime: " << std::endl; + } + + void OnFindClose(bool result) override final + { + m_stream << "FindClose: " << std::endl; + } + + void OnFindCloseChangeNotification(bool result) override final + { + m_stream << "FindCloseChangeNotification: " << std::endl; + } + + void OnFindFirstChangeNotificationA(std::string_view pathName, bool watchSubtree, uint32_t notifyFilter) override final + { + m_stream << "FindFirstChangeNotificationA: " << std::endl; + } + + void OnFindFirstChangeNotificationW(std::wstring_view pathName, bool watchSubtree, uint32_t notifyFilter) override final + { + m_stream << "FindFirstChangeNotificationW: " << std::endl; + } + + void OnFindFirstFileA(std::string_view fileName) override final + { + m_stream << "FindFirstFileA: " << std::endl; + } + + void OnFindFirstFileW(std::wstring_view fileName) override final + { + m_stream << "FindFirstFileW: " << std::endl; + } + + void OnFindFirstFileExA(std::string_view fileName) override final + { + m_stream << "FindFirstFileExA: " << std::endl; + } + + void OnFindFirstFileExW(std::wstring_view fileName) override final + { + m_stream << "FindFirstFileExW: " << std::endl; + } + + void OnFindFirstFileNameW(std::wstring_view fileName, uint32_t flags) override final + { + m_stream << "FindFirstFileNameW: " << std::endl; + } + + void OnFindFirstStreamW(std::wstring_view fileName) override final + { + m_stream << "FindFirstStreamW: " << std::endl; + } + + void OnFindFirstVolumeW(std::wstring_view fileName) override final + { + m_stream << "FindFirstVolumeW: " << std::endl; + } + + void OnFindNextChangeNotification(bool result) override final + { + m_stream << "FindNextChangeNotification: " << std::endl; + } + + void OnFindNextFileA(bool result) override final + { + m_stream << "FindNextFileA: " << std::endl; + } + + void OnFindNextFileW(bool result) override final + { + m_stream << "FindNextFileW: " << std::endl; + } + + void OnFindNextFileNameW(bool result) override final + { + m_stream << "FindNextFileNameW: " << std::endl; + } + + void OnFindNextStreamW(bool result) override final + { + m_stream << "FindNextStreamW: " << std::endl; + } + + void OnFindNextVolumeW(bool result) override final + { + m_stream << "FindNextVolumeW: " << std::endl; + } + + void OnFindVolumeClose(bool result) override final + { + m_stream << "FindVolumeClose: " << std::endl; + } + + void OnFlushFileBuffers(bool result) override final + { + m_stream << "FlushFileBuffers: " << std::endl; + } + + void OnGetCompressedFileSizeA(std::string_view fileName, uint32_t result) override final + { + m_stream << "GetCompressedFileSizeA: " << fileName << std::endl; + } + + void OnGetCompressedFileSizeW(std::wstring_view fileName, uint32_t result) override final + { + std::wstring_convert, wchar_t> converter; + m_stream << "GetCompressedFileSizeW: " << converter.to_bytes(fileName.data()) << std::endl; + } + + void OnGetDiskFreeSpaceA(std::string_view rootPathName, bool result) override final + { + m_stream << "GetDiskFreeSpaceA: " << std::endl; + } + + void OnGetDiskFreeSpaceW(std::wstring_view rootPathName, bool result) override final + { + m_stream << "GetDiskFreeSpaceW: " << std::endl; + } + + void OnGetDiskFreeSpaceExA(std::string_view directoryName, bool result) override final + { + m_stream << "GetDiskFreeSpaceExA: " << std::endl; + } + + void OnGetDiskFreeSpaceExW(std::wstring_view directoryName, bool result) override final + { + m_stream << "GetDiskFreeSpaceExW: " << std::endl; + } + + void OnGetDriveTypeA(std::string_view rootPathName, uint32_t result) override final + { + m_stream << "GetDriveTypeA: " << std::endl; + } + + void OnGetDriveTypeW(std::wstring_view rootPathName, uint32_t result) override final + { + m_stream << "GetDriveTypeW: " << std::endl; + } + + void OnGetFileAttributesA(std::string_view fileName, uint32_t result) override final + { + m_stream << "GetFileAttributesA: " << fileName << std::endl; + } + + void OnGetFileAttributesW(std::wstring_view fileName, uint32_t result) override final + { + std::wstring_convert, wchar_t> converter; + m_stream << "GetFileAttributesW: " << converter.to_bytes(fileName.data()) << std::endl; + } + + void OnGetFileAttributesExA(std::string_view fileName, bool result) override final + { + m_stream << "GetFileAttributesExA: " << fileName << std::endl; + } + + void OnGetFileAttributesExW(std::wstring_view fileName, bool result) override final + { + std::wstring_convert, wchar_t> converter; + m_stream << "GetFileAttributesExW: " << converter.to_bytes(fileName.data()) << std::endl; + } + + void OnGetFileInformationByHandle(bool result) override final + { + m_stream << "GetFileInformationByHandle: " << std::endl; + } + + void OnGetFileSize(uint32_t result) override final + { + m_stream << "GetFileSize: " << std::endl; + } + + void OnGetFileSizeEx(uint32_t result) override final + { + m_stream << "GetFileSizeEx: " << std::endl; + } + + void OnGetFileTime(bool result) override final + { + m_stream << "GetFileTime: " << std::endl; + } + + void OnGetFileType(uint32_t result) override final + { + m_stream << "GetFileType: " << std::endl; + } + + void OnGetFinalPathNameByHandleA(uint32_t result) override final + { + m_stream << "GetFinalPathNameByHandleA: " << std::endl; + } + + void OnGetFinalPathNameByHandleW(uint32_t result) override final + { + m_stream << "GetFinalPathNameByHandleW: " << std::endl; + } + + void OnGetFullPathNameA(std::string_view fileName, uint32_t result) override final + { + m_stream << "GetFullPathNameA: " << fileName << std::endl; + } + + void OnGetFullPathNameW(std::wstring_view fileName, std::wstring_view buffer, uint32_t result) override final + { + std::wstring_convert, wchar_t> converter; + m_stream << "GetFullPathNameW: " << converter.to_bytes(fileName.data()) << std::endl; + } + + void OnGetLogicalDrives(uint32_t result) override final + { + m_stream << "GetLogicalDrives: " << std::endl; + } + + void OnGetLogicalDriveStringsW(std::wstring_view buffer, uint32_t result) override final + { + m_stream << "GetLogicalDriveStringsW: " << std::endl; + } + + void OnGetLongPathNameA(std::string_view shortPath, std::string_view longPath, uint32_t result) override final + { + m_stream << "GetLongPathNameA: " << std::endl; + } + + void OnGetLongPathNameW(std::wstring_view shortPath, std::wstring_view longPath, uint32_t result) override final + { + m_stream << "GetLongPathNameW: " << std::endl; + } + + void OnGetShortPathNameW(std::wstring_view longPath, std::wstring_view shortPath, uint32_t result) override final + { + m_stream << "GetShortPathNameW: " << std::endl; + } + + void OnGetTempFileNameA(std::string_view pathName, std::string_view prefixString, uint32_t unique, std::string_view tempFileName, uint32_t result) override final + { + m_stream << "GetTempFileNameA: " << std::endl; + } + + void OnGetTempFileNameW(std::wstring_view pathName, std::wstring_view prefixString, uint32_t unique, std::wstring_view tempFileName, uint32_t result) override final + { + m_stream << "GetTempFileNameW: " << std::endl; + } + + void OnGetTempPathA(std::string_view buffer, uint32_t result) override final + { + m_stream << "GetTempPathA: " << std::endl; + } + + void OnGetTempPathW(std::wstring_view buffer, uint32_t result) override final + { + m_stream << "GetTempPathW: " << std::endl; + } + + void OnGetVolumeInformationA(bool result) override final + { + m_stream << "GetVolumeInformationA: " << std::endl; + } + + void OnGetVolumeInformationW(bool result) override final + { + m_stream << "GetVolumeInformationW: " << std::endl; + } + + void OnGetVolumeInformationByHandleW(bool result) override final + { + m_stream << "GetVolumeInformationByHandleW: " << std::endl; + } + + void OnGetVolumeNameForVolumeMountPointW(bool result) override final + { + m_stream << "GetVolumeNameForVolumeMountPointW: " << std::endl; + } + + void OnGetVolumePathNamesForVolumeNameW(bool result) override final + { + m_stream << "GetVolumePathNamesForVolumeNameW: " << std::endl; + } + + void OnGetVolumePathNameW(std::wstring_view filename, bool result) override final + { + m_stream << "GetVolumePathNameW: " << std::endl; + } + + void OnLocalFileTimeToFileTime(bool result) override final + { + m_stream << "LocalFileTimeToFileTime: " << std::endl; + } + + void OnLockFile(bool result) override final + { + m_stream << "LockFile: " << std::endl; + } + + void OnLockFileEx(bool result) override final + { + m_stream << "LockFileEx: " << std::endl; + } + + void OnQueryDosDeviceW(std::wstring_view deviceName, uint32_t result) override final + { + m_stream << "QueryDosDeviceW: " << std::endl; + } + + void OnReadFile(bool result) override final + { + m_stream << "ReadFile: " << std::endl; + } + + void OnReadFileEx(bool result) override final + { + m_stream << "ReadFileEx: " << std::endl; + } + + void OnReadFileScatter(bool result) override final + { + m_stream << "ReadFileScatter: " << std::endl; + } + + void OnRemoveDirectoryA(std::string_view pathName, bool result) override final + { + m_stream << "RemoveDirectoryA: " << pathName << std::endl; + } + + void OnRemoveDirectoryW(std::wstring_view pathName, bool result) override final + { + std::wstring_convert, wchar_t> converter; + m_stream << "RemoveDirectoryW: " << converter.to_bytes(pathName.data()) << std::endl; + } + + void OnSetEndOfFile(bool result) override final + { + m_stream << "SetEndOfFile: " << std::endl; + } + + void OnSetFileApisToANSI() override final + { + m_stream << "SetFileApisToANSI: " << std::endl; + } + + void OnSetFileApisToOEM() override final + { + m_stream << "SetFileApisToOEM: " << std::endl; + } + + void OnSetFileAttributesA(std::string_view fileName, bool result) override final + { + m_stream << "SetFileAttributesA: " << fileName << std::endl; + } + + void OnSetFileAttributesW(std::wstring_view fileName, bool result) override final + { + std::wstring_convert, wchar_t> converter; + m_stream << "SetFileAttributesW: " << converter.to_bytes(fileName.data()) << std::endl; + } + + void OnSetFileInformationByHandle(bool result) override final + { + m_stream << "SetFileInformationByHandle: " << std::endl; + } + + void OnSetFileIoOverlappedRange(bool result) override final + { + m_stream << "SetFileIoOverlappedRange: " << std::endl; + } + + void OnSetFilePointer(uint32_t result) override final + { + m_stream << "SetFilePointer: " << std::endl; + } + + void OnSetFilePointerEx(bool result) override final + { + m_stream << "SetFilePointerEx: " << std::endl; + } + + void OnSetFileTime(bool result) override final + { + m_stream << "SetFileTime: " << std::endl; + } + + void OnSetFileValidData(bool result) override final + { + m_stream << "SetFileValidData: " << std::endl; + } + + void OnUnlockFile(bool result) override final + { + m_stream << "UnlockFile: " << std::endl; + } + + void OnUnlockFileEx(bool result) override final + { + m_stream << "UnlockFileEx: " << std::endl; + } + + void OnWriteFile(bool result) override final + { + m_stream << "WriteFile: " << std::endl; + } + + void OnWriteFileEx(bool result) override final + { + m_stream << "WriteFileEx: " << std::endl; + } + + void OnWriteFileGather(bool result) override final + { + m_stream << "WriteFileGather: " << std::endl; + } + + // LibLoaderApi + void OnLoadLibraryA(std::string_view libFileName) override final + { + m_stream << "LoadLibraryA: " << libFileName << std::endl; + } + + void OnLoadLibraryW(std::wstring_view libFileName) override final + { + std::wstring_convert, wchar_t> converter; + m_stream << "LoadLibraryW: " << converter.to_bytes(libFileName.data()) << std::endl; + } + + void OnLoadLibraryExA(std::string_view libFileName) override final + { + m_stream << "LoadLibraryExA: " << libFileName << std::endl; + } + + void OnLoadLibraryExW(std::wstring_view libFileName) override final + { + std::wstring_convert, wchar_t> converter; + m_stream << "LoadLibraryExW: " << converter.to_bytes(libFileName.data()) << std::endl; + } + + // ProcessEnv + void OnSearchPathA(std::string_view path, std::string_view fileName, std::string_view extension, uint32_t result) override final + { + m_stream << "SearchPathA: " << std::endl; + } + + void OnSearchPathW(std::wstring_view path, std::wstring_view fileName, std::wstring_view extension, uint32_t result) override final + { + m_stream << "SearchPathW: " << std::endl; + } + + // ProcessThreadsApi + void OnCreateProcessA(std::string_view applicationName, bool result) override final + { + m_stream << "CreateProcessA: " << std::endl; + } + + void OnCreateProcessW(std::wstring_view applicationName, bool result) override final + { + m_stream << "CreateProcessW: " << std::endl; + } + + void OnCreateProcessAsUserA(std::string_view applicationName, bool result) override final + { + m_stream << "CreateProcessAsUserA: " << std::endl; + } + + void OnCreateProcessAsUserW(std::wstring_view applicationName, bool result) override final + { + m_stream << "CreateProcessAsUserW: " << std::endl; + } + + void OnExitProcess(uint32_t exitCode) override final + { + m_stream << "ExitProcess: " << std::endl; + } + + // UndocumentedApi + void OnPrivCopyFileExA(std::string_view existingFileName, std::string_view newFileName, bool result) override final + { + m_stream << "PrivCopyFileExA: " << std::endl; + } + + void OnPrivCopyFileExW(std::wstring_view existingFileName, std::wstring_view newFileName, bool result) override final + { + m_stream << "PrivCopyFileExW: " << std::endl; + } + + // WinBase + void OnCopyFileA(std::string_view existingFileName, std::string_view newFileName, bool failIfExists, bool result) override final + { + m_stream << "CopyFileA: " << std::endl; + } + + void OnCopyFileW(std::wstring_view existingFileName, std::wstring_view newFileName, bool failIfExists, bool result) override final + { + m_stream << "CopyFileW: " << std::endl; + } + + void OnCopyFile2(std::wstring_view existingFileName, std::wstring_view newFileName) override final + { + m_stream << "CopyFile2: " << std::endl; + } + + void OnCopyFileExA(std::string_view existingFileName, std::string_view newFileName, bool result) override final + { + m_stream << "CopyFileExA: " << std::endl; + } + + void OnCopyFileExW(std::wstring_view existingFileName, std::wstring_view newFileName, bool result) override final + { + m_stream << "CopyFileExW: " << std::endl; + } + + void OnCopyFileTransactedA(std::string_view existingFileName, std::string_view newFileName, bool result) override final + { + m_stream << "CopyFileTransactedA: " << std::endl; + } + + void OnCopyFileTransactedW(std::wstring_view existingFileName, std::wstring_view newFileName, bool result) override final + { + m_stream << "CopyFileTransactedW: " << std::endl; + } + + void OnCreateDirectoryExA(std::string_view templateDirectory, std::string_view newDirectory, bool result) override final + { + m_stream << "CreateDirectoryExA: " << std::endl; + } + + void OnCreateDirectoryExW(std::wstring_view templateDirectory, std::wstring_view newDirectory, bool result) override final + { + m_stream << "CreateDirectoryExW: " << std::endl; + } + + void OnCreateDirectoryTransactedA(std::string_view templateDirectory, std::string_view newDirectory, bool result) override final + { + m_stream << "CreateDirectoryTransactedA: " << std::endl; + } + + void OnCreateDirectoryTransactedW(std::wstring_view templateDirectory, std::wstring_view newDirectory, bool result) override final + { + m_stream << "CreateDirectoryTransactedW: " << std::endl; + } + + void OnCreateFileTransactedA(std::string_view fileName, uint32_t desiredAccess, uint32_t shareMode) override final + { + m_stream << "CreateFileTransactedA: " << std::endl; + } + + void OnCreateFileTransactedW(std::wstring_view fileName, uint32_t desiredAccess, uint32_t shareMode) override final + { + m_stream << "CreateFileTransactedW: " << std::endl; + } + + void OnCreateHardLinkA(std::string_view fileName, std::string_view existingFileName, bool result) override final + { + m_stream << "CreateHardLinkA: " << std::endl; + } + + void OnCreateHardLinkW(std::wstring_view fileName, std::wstring_view existingFileName, bool result) override final + { + m_stream << "CreateHardLinkW: " << std::endl; + } + + void OnCreateHardLinkTransactedA(std::string_view fileName, std::string_view existingFileName, bool result) override final + { + m_stream << "CreateHardLinkTransactedA: " << std::endl; + } + + void OnCreateHardLinkTransactedW(std::wstring_view fileName, std::wstring_view existingFileName, bool result) override final + { + m_stream << "CreateHardLinkTransactedW: " << std::endl; + } + + void OnCreateProcessWithLogonW(std::wstring_view applicationName, bool result) override final + { + m_stream << "CreateProcessWithLogonW: " << std::endl; + } + + void OnCreateProcessWithTokenW(std::wstring_view applicationName, bool result) override final + { + m_stream << "CreateProcessWithTokenW: " << std::endl; + } + + void OnCreateSymbolicLinkA(std::string_view symlinkFileName, std::string_view targetFileName, uint32_t flags, bool result) override final + { + m_stream << "CreateSymbolicLinkA: " << std::endl; + } + + void OnCreateSymbolicLinkW(std::wstring_view symlinkFileName, std::wstring_view targetFileName, uint32_t flags, bool result) override final + { + m_stream << "CreateSymbolicLinkW: " << std::endl; + } + + void OnCreateSymbolicLinkTransactedA(std::string_view symlinkFileName, std::string_view targetFileName, uint32_t flags, bool result) override final + { + m_stream << "CreateSymbolicLinkTransactedA: " << std::endl; + } + + void OnCreateSymbolicLinkTransactedW(std::wstring_view symlinkFileName, std::wstring_view targetFileName, uint32_t flags, bool result) override final + { + m_stream << "CreateSymbolicLinkTransactedW: " << std::endl; + } + + void OnDecryptFileA(std::string_view fileName, bool result) override final + { + m_stream << "DecryptFileA: " << std::endl; + } + + void OnDecryptFileW(std::wstring_view fileName, bool result) override final + { + m_stream << "DecryptFileW: " << std::endl; + } + + void OnDeleteFileTransactedA(std::string_view fileName, bool result) override final + { + m_stream << "DeleteFileTransactedA: " << std::endl; + } + + void OnDeleteFileTransactedW(std::wstring_view fileName, bool result) override final + { + m_stream << "DeleteFileTransactedW: " << std::endl; + } + + void OnEncryptFileA(std::string_view fileName, bool result) override final + { + m_stream << "EncryptFileA: " << std::endl; + } + + void OnEncryptFileW(std::wstring_view fileName, bool result) override final + { + m_stream << "EncryptFileW: " << std::endl; + } + + void OnFileEncryptionStatusA(std::string_view fileName, bool result) override final + { + m_stream << "FileEncryptionStatusA: " << std::endl; + } + + void OnFileEncryptionStatusW(std::wstring_view fileName, bool result) override final + { + m_stream << "FileEncryptionStatusW: " << std::endl; + } + + void OnFindFirstFileNameTransactedW(std::wstring_view fileName, bool result) override final + { + m_stream << "FindFirstFileNameTransactedW: " << std::endl; + } + + void OnFindFirstFileTransactedA(std::string_view fileName) override final + { + m_stream << "FindFirstFileTransactedA: " << std::endl; + } + + void OnFindFirstFileTransactedW(std::wstring_view fileName) override final + { + m_stream << "FindFirstFileTransactedW: " << std::endl; + } + + void OnFindFirstStreamTransactedW(std::wstring_view fileName) override final + { + m_stream << "FindFirstStreamTransactedW: " << std::endl; + } + + void OnGetBinaryTypeA(std::string_view applicationName, bool result) override final + { + m_stream << "GetBinaryTypeA: " << std::endl; + } + + void OnGetBinaryTypeW(std::wstring_view applicationName, bool result) override final + { + m_stream << "GetBinaryTypeW: " << std::endl; + } + + void OnGetCompressedFileSizeTransactedA(std::string_view fileName, uint32_t result) override final + { + m_stream << "GetCompressedFileSizeTransactedA: " << std::endl; + } + + void OnGetCompressedFileSizeTransactedW(std::wstring_view fileName, uint32_t result) override final + { + m_stream << "GetCompressedFileSizeTransactedW: " << std::endl; + } + + void OnGetDllDirectoryA(uint32_t result) override final + { + m_stream << "GetDllDirectoryA: " << std::endl; + } + + void OnGetDllDirectoryW(uint32_t result) override final + { + m_stream << "GetDllDirectoryW: " << std::endl; + } + + void OnGetFileAttributesTransactedA(std::string_view fileName, uint32_t result) override final + { + m_stream << "GetFileAttributesTransactedA: " << std::endl; + } + + void OnGetFileAttributesTransactedW(std::wstring_view fileName, uint32_t result) override final + { + m_stream << "GetFileAttributesTransactedW: " << std::endl; + } + + void OnGetFileBandwidthReservation(bool result) override final + { + m_stream << "GetFileBandwidthReservation: " << std::endl; + } + + void OnGetFileInformationByHandleEx(bool result) override final + { + m_stream << "GetFileInformationByHandleEx: " << std::endl; + } + + void OnGetFileSecurityA(std::string_view fileName, bool result) override final + { + m_stream << "GetFileSecurityA: " << std::endl; + } + + void OnGetFullPathNameTransactedA(std::string_view fileName, uint32_t result) override final + { + m_stream << "GetFullPathNameTransactedA: " << std::endl; + } + + void OnGetFullPathNameTransactedW(std::wstring_view fileName, uint32_t result) override final + { + m_stream << "GetFullPathNameTransactedW: " << std::endl; + } + + void OnGetLongPathNameTransactedA(std::string_view shortPath, std::string_view longPath, uint32_t result) override final + { + m_stream << "GetLongPathNameTransactedA: " << std::endl; + } + + void OnGetLongPathNameTransactedW(std::wstring_view shortPath, std::wstring_view longPath, uint32_t result) override final + { + m_stream << "GetLongPathNameTransactedW: " << std::endl; + } + + void OnGetQueuedCompletionStatus(bool result) override final + { + m_stream << "GetQueuedCompletionStatus: " << std::endl; + } + + void OnGetQueuedCompletionStatusEx(bool result) override final + { + m_stream << "GetQueuedCompletionStatusEx: " << std::endl; + } + + void OnGetShortPathNameA(std::string_view longPath, std::string_view shortPath, uint32_t result) override final + { + m_stream << "GetShortPathNameA: " << std::endl; + } + + void OnLoadModule(std::string_view moduleName, uint32_t result) override final + { + m_stream << "LoadModule: " << std::endl; + } + + void OnLoadPackagedLibrary(std::string_view libFileName) override final + { + m_stream << "LoadPackagedLibrary: " << std::endl; + } + + void OnMoveFileA(std::string_view existingFileName, std::string_view newFileName, bool result) override final + { + m_stream << "MoveFileA: " << std::endl; + } + + void OnMoveFileW(std::wstring_view existingFileName, std::wstring_view newFileName, bool result) override final + { + m_stream << "MoveFileW: " << std::endl; + } + + void OnMoveFileExA(std::string_view existingFileName, std::string_view newFileName, uint32_t flags, bool result) override final + { + m_stream << "MoveFileExA: " << std::endl; + } + + void OnMoveFileExW(std::wstring_view existingFileName, std::wstring_view newFileName, uint32_t flags, bool result) override final + { + m_stream << "MoveFileExW: " << std::endl; + } + + void OnMoveFileTransactedA(std::string_view existingFileName, std::string_view newFileName, uint32_t flags, bool result) override final + { + m_stream << "MoveFileTransactedA: " << std::endl; + } + + void OnMoveFileTransactedW(std::wstring_view existingFileName, std::wstring_view newFileName, uint32_t flags, bool result) override final + { + m_stream << "MoveFileTransactedW: " << std::endl; + } + + void OnMoveFileWithProgressA(std::string_view existingFileName, std::string_view newFileName, uint32_t flags, bool result) override final + { + m_stream << "MoveFileWithProgressA: " << std::endl; + } + + void OnMoveFileWithProgressW(std::wstring_view existingFileName, std::wstring_view newFileName, uint32_t flags, bool result) override final + { + m_stream << "MoveFileWithProgressW: " << std::endl; + } + + void OnOpenEncryptedFileRawA(std::string_view fileName, uint32_t flags, uint32_t result) override final + { + m_stream << "OpenEncryptedFileRawA: " << std::endl; + } + + void OnOpenEncryptedFileRawW(std::wstring_view fileName, uint32_t flags, uint32_t result) override final + { + m_stream << "OpenEncryptedFileRawW: " << std::endl; + } + + void OnOpenFile(std::string_view fileName) override final + { + m_stream << "OpenFile: " << std::endl; + } + + void OnOpenFileById() override final + { + m_stream << "OpenFileById: " << std::endl; + } + + void OnReadEncryptedFileRaw(uint32_t result) override final + { + m_stream << "ReadEncryptedFileRaw: " << std::endl; + } + + void OnRemoveDirectoryTransactedA(std::string_view pathName, bool result) override final + { + m_stream << "RemoveDirectoryTransactedA: " << std::endl; + } + + void OnRemoveDirectoryTransactedW(std::wstring_view pathName, bool result) override final + { + m_stream << "RemoveDirectoryTransactedW: " << std::endl; + } + + void OnReOpenFile() override final + { + m_stream << "ReOpenFile: " << std::endl; + } + + void OnReplaceFileA(std::string_view replacedFileName, std::string_view replacementFileName, std::string_view backupFileName, uint32_t replaceFlags, bool result) override final + { + m_stream << "ReplaceFileA: " << std::endl; + } + + void OnReplaceFileW(std::wstring_view replacedFileName, std::wstring_view replacementFileName, std::wstring_view backupFileName, uint32_t replaceFlags, bool result) override final + { + m_stream << "ReplaceFileW: " << std::endl; + } + + void OnSetCurrentDirectoryA(std::string_view pathName, bool result) override final + { + m_stream << "SetCurrentDirectoryA: " << std::endl; + } + + void OnSetCurrentDirectoryW(std::wstring_view pathName, bool result) override final + { + m_stream << "SetCurrentDirectoryW: " << std::endl; + } + + void OnSetDllDirectoryA(std::string_view pathName, bool result) override final + { + m_stream << "SetDllDirectoryA: " << std::endl; + } + + void OnSetDllDirectoryW(std::wstring_view pathName, bool result) override final + { + m_stream << "SetDllDirectoryW: " << std::endl; + } + + void OnSetFileAttributesTransactedA(std::string_view pathName, uint32_t fileAttributes, bool result) override final + { + m_stream << "SetFileAttributesTransactedA: " << std::endl; + } + + void OnSetFileAttributesTransactedW(std::wstring_view pathName, uint32_t fileAttributes, bool result) override final + { + m_stream << "SetFileAttributesTransactedW: " << std::endl; + } + + void OnSetFileBandwidthReservation(bool result) override final + { + m_stream << "SetFileBandwidthReservation: " << std::endl; + } + + void OnSetFileCompletionNotificationModes(bool result) override final + { + m_stream << "SetFileCompletionNotificationModes: " << std::endl; + } + + void OnSetFileSecurityA(std::string_view fileName, bool result) override final + { + m_stream << "SetFileSecurityA: " << std::endl; + } + + void OnSetFileShortNameA(std::string_view shortName, bool result) override final + { + m_stream << "SetFileShortNameA: " << std::endl; + } + + void OnSetFileShortNameW(std::wstring_view shortName, bool result) override final + { + m_stream << "SetFileShortNameW: " << std::endl; + } + + void OnSetSearchPathMode(uint32_t flags, bool result) override final + { + m_stream << "SetSearchPathMode: " << std::endl; + } + + void OnWriteEncryptedFileRaw(uint32_t result) override final + { + m_stream << "WriteEncryptedFileRaw: " << std::endl; + } + + private: + std::ostream& m_stream; + }; +} diff --git a/Source/Monitor/Log/Main.cpp b/Source/Monitor/Log/Main.cpp new file mode 100644 index 00000000..ab23c8af --- /dev/null +++ b/Source/Monitor/Log/Main.cpp @@ -0,0 +1,62 @@ +import Monitor.Shared; +import Opal; + +using namespace Opal; + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "DetourCallbackLogger.h" + +int main(int argc, char **argv) +{ + try + { + if (argc <= 1) + { + std::cout << "Missing executable parameter." << std::endl; + return 1; + } + + System::IFileSystem::Register(std::make_shared()); + Monitor::IDetourProcessManager::Register(std::make_shared()); + System::IProcessManager::Register(std::make_shared()); + + auto application = Path(argv[1]); + std::stringstream argumentsValue; + for (int i = 2; i < argc; i++) + { + argumentsValue << " " << argv[i]; + } + + std::string argumentsString = argumentsValue.str(); + auto workingDirectory = Path(); + + auto file = std::fstream("Access.txt", std::fstream::out); + + auto callback = std::make_shared(file); + auto process = Monitor::IDetourProcessManager::Current().CreateDetourProcess( + application, + argumentsString, + workingDirectory, + callback); + process->Start(); + process->WaitForExit(); + auto result = process->GetExitCode(); + + file.close(); + + return result; + } + catch(const std::exception& ex) + { + std::cerr << "Error: " << ex.what() << std::endl; + return -1; + } +} diff --git a/Source/Monitor/Log/Recipe.toml b/Source/Monitor/Log/Recipe.toml new file mode 100644 index 00000000..0571ad8c --- /dev/null +++ b/Source/Monitor/Log/Recipe.toml @@ -0,0 +1,12 @@ +# A sample Monitor that logs all access to disk +Name = "LogMonitor" +Version = "1.0.0" +Type = "Executable" +Dependencies = [ + "../../../Dependencies/Detours/src/", + "../../../Dependencies/Opal/Source/", + "../Shared/", +] +Source = [ + "Main.cpp", +] diff --git a/Source/Monitor/Shared/EventListener.h b/Source/Monitor/Shared/EventListener.h new file mode 100644 index 00000000..0c21edf7 --- /dev/null +++ b/Source/Monitor/Shared/EventListener.h @@ -0,0 +1,1472 @@ +// +// Copyright (c) Soup. All rights reserved. +// + +#pragma once + +namespace Monitor +{ + /// + /// The event listener knows how to parse an incoming message and pass it along to the + /// registered callback. + /// + export class EventListener + { + public: + /// + /// Initializes a new instance of the class. + /// + EventListener( + std::shared_ptr callback) : + m_callback(std::move(callback)) + { + } + + void LogMessage(DetourMessage& message) + { + int32_t offset = 0; + switch (message.Type) + { + // Info + case DetourMessageType::Info_Shutdown: + { + m_callback->OnShutdown(); + break; + } + case DetourMessageType::Info_Error: + { + auto errorMessage = ReadStringValue(message, offset); + m_callback->OnError(errorMessage); + break; + } + + // FileApi + case DetourMessageType::AreFileApisANSI: + { + auto result = ReadBoolValue(message, offset); + m_callback->OnAreFileApisANSI(result); + break; + } + case DetourMessageType::CompareFileTime: + { + auto result = ReadInt32Value(message, offset); + m_callback->OnCompareFileTime(result); + break; + } + case DetourMessageType::CreateDirectoryA: + { + auto pathName = ReadStringValue(message, offset); + auto result = ReadBoolValue(message, offset); + m_callback->OnCreateDirectoryA(pathName, result); + break; + } + case DetourMessageType::CreateDirectoryW: + { + auto pathName = ReadWStringValue(message, offset); + auto result = ReadBoolValue(message, offset); + m_callback->OnCreateDirectoryW(pathName, result); + break; + } + case DetourMessageType::CreateFile2: + { + auto fileName = ReadWStringValue(message, offset); + auto desiredAccess = ReadUInt32Value(message, offset); + auto sharedMode = ReadUInt32Value(message, offset); + auto creationDisposition = ReadUInt32Value(message, offset); + auto result = ReadUInt64Value(message, offset); + m_callback->OnCreateFile2(fileName, desiredAccess, sharedMode, creationDisposition, result); + break; + } + case DetourMessageType::CreateFileA: + { + auto fileName = ReadStringValue(message, offset); + auto desiredAccess = ReadUInt32Value(message, offset); + auto sharedMode = ReadUInt32Value(message, offset); + auto creationDisposition = ReadUInt32Value(message, offset); + auto flagsAndAttributes = ReadUInt32Value(message, offset); + auto result = ReadUInt64Value(message, offset); + m_callback->OnCreateFileA(fileName, desiredAccess, sharedMode, creationDisposition, flagsAndAttributes, result); + break; + } + case DetourMessageType::CreateFileW: + { + auto fileName = ReadWStringValue(message, offset); + auto desiredAccess = ReadUInt32Value(message, offset); + auto sharedMode = ReadUInt32Value(message, offset); + auto creationDisposition = ReadUInt32Value(message, offset); + auto flagsAndAttributes = ReadUInt32Value(message, offset); + auto result = ReadUInt64Value(message, offset); + m_callback->OnCreateFileW(fileName, desiredAccess, sharedMode, creationDisposition, flagsAndAttributes, result); + break; + } + case DetourMessageType::DefineDosDeviceW: + { + auto flags = ReadUInt32Value(message, offset); + auto deviceName = ReadWStringValue(message, offset); + auto targetPath = ReadWStringValue(message, offset); + auto result = ReadBoolValue(message, offset); + m_callback->OnDefineDosDeviceW(flags, deviceName, targetPath, result); + break; + } + case DetourMessageType::DeleteFileA: + { + auto fileName = ReadStringValue(message, offset); + auto result = ReadBoolValue(message, offset); + m_callback->OnDeleteFileA(fileName, result); + break; + } + case DetourMessageType::DeleteFileW: + { + auto fileName = ReadWStringValue(message, offset); + auto result = ReadBoolValue(message, offset); + m_callback->OnDeleteFileW(fileName, result); + break; + } + case DetourMessageType::DeleteVolumeMountPointW: + { + auto volumeMountPoint = ReadWStringValue(message, offset); + auto result = ReadBoolValue(message, offset); + m_callback->OnDeleteVolumeMountPointW(volumeMountPoint, result); + break; + } + case DetourMessageType::FileTimeToLocalFileTime: + { + auto result = ReadBoolValue(message, offset); + m_callback->OnFileTimeToLocalFileTime(result); + break; + } + case DetourMessageType::FindClose: + { + auto result = ReadBoolValue(message, offset); + m_callback->OnFindClose(result); + break; + } + case DetourMessageType::FindCloseChangeNotification: + { + auto result = ReadBoolValue(message, offset); + m_callback->OnFindCloseChangeNotification(result); + break; + } + case DetourMessageType::FindFirstChangeNotificationA: + { + auto pathName = ReadStringValue(message, offset); + auto watchSubtree = ReadBoolValue(message, offset); + auto notifyFilter = ReadUInt32Value(message, offset); + m_callback->OnFindFirstChangeNotificationA(pathName, watchSubtree, notifyFilter); + break; + } + case DetourMessageType::FindFirstChangeNotificationW: + { + auto pathName = ReadWStringValue(message, offset); + auto watchSubtree = ReadBoolValue(message, offset); + auto notifyFilter = ReadUInt32Value(message, offset); + m_callback->OnFindFirstChangeNotificationW(pathName, watchSubtree, notifyFilter); + break; + } + case DetourMessageType::FindFirstFileA: + { + auto fileName = ReadStringValue(message, offset); + m_callback->OnFindFirstFileA(fileName); + break; + } + case DetourMessageType::FindFirstFileW: + { + auto fileName = ReadWStringValue(message, offset); + m_callback->OnFindFirstFileW(fileName); + break; + } + case DetourMessageType::FindFirstFileExA: + { + auto fileName = ReadStringValue(message, offset); + m_callback->OnFindFirstFileExA(fileName); + break; + } + case DetourMessageType::FindFirstFileExW: + { + auto fileName = ReadWStringValue(message, offset); + m_callback->OnFindFirstFileExW(fileName); + break; + } + case DetourMessageType::FindFirstFileNameW: + { + auto fileName = ReadWStringValue(message, offset); + auto flags = ReadUInt32Value(message, offset); + m_callback->OnFindFirstFileNameW(fileName, flags); + break; + } + case DetourMessageType::FindFirstStreamW: + { + auto fileName = ReadWStringValue(message, offset); + m_callback->OnFindFirstStreamW(fileName); + break; + } + case DetourMessageType::FindFirstVolumeW: + { + auto fileName = ReadWStringValue(message, offset); + m_callback->OnFindFirstVolumeW(fileName); + break; + } + case DetourMessageType::FindNextChangeNotification: + { + auto result = ReadBoolValue(message, offset); + m_callback->OnFindNextChangeNotification(result); + break; + } + case DetourMessageType::FindNextFileA: + { + auto result = ReadBoolValue(message, offset); + m_callback->OnFindNextFileA(result); + break; + } + case DetourMessageType::FindNextFileW: + { + auto result = ReadBoolValue(message, offset); + m_callback->OnFindNextFileW(result); + break; + } + case DetourMessageType::FindNextFileNameW: + { + auto result = ReadBoolValue(message, offset); + m_callback->OnFindNextFileNameW(result); + break; + } + case DetourMessageType::FindNextStreamW: + { + auto result = ReadBoolValue(message, offset); + m_callback->OnFindNextStreamW(result); + break; + } + case DetourMessageType::FindNextVolumeW: + { + auto result = ReadBoolValue(message, offset); + m_callback->OnFindNextVolumeW(result); + break; + } + case DetourMessageType::FindVolumeClose: + { + auto result = ReadBoolValue(message, offset); + m_callback->OnFindVolumeClose(result); + break; + } + case DetourMessageType::FlushFileBuffers: + { + auto result = ReadBoolValue(message, offset); + m_callback->OnFlushFileBuffers(result); + break; + } + case DetourMessageType::GetCompressedFileSizeA: + { + auto fileName = ReadStringValue(message, offset); + auto result = ReadUInt32Value(message, offset); + m_callback->OnGetCompressedFileSizeA(fileName, result); + break; + } + case DetourMessageType::GetCompressedFileSizeW: + { + auto fileName = ReadWStringValue(message, offset); + auto result = ReadUInt32Value(message, offset); + m_callback->OnGetCompressedFileSizeW(fileName, result); + break; + } + case DetourMessageType::GetDiskFreeSpaceA: + { + auto rootPathName = ReadStringValue(message, offset); + auto result = ReadBoolValue(message, offset); + m_callback->OnGetDiskFreeSpaceA(rootPathName, result); + break; + } + case DetourMessageType::GetDiskFreeSpaceW: + { + auto rootPathName = ReadWStringValue(message, offset); + auto result = ReadBoolValue(message, offset); + m_callback->OnGetDiskFreeSpaceW(rootPathName, result); + break; + } + case DetourMessageType::GetDiskFreeSpaceExA: + { + auto directoryName = ReadStringValue(message, offset); + auto result = ReadBoolValue(message, offset); + m_callback->OnGetDiskFreeSpaceExA(directoryName, result); + break; + } + case DetourMessageType::GetDiskFreeSpaceExW: + { + auto directoryName = ReadWStringValue(message, offset); + auto result = ReadBoolValue(message, offset); + m_callback->OnGetDiskFreeSpaceExW(directoryName, result); + break; + } + case DetourMessageType::GetDriveTypeA: + { + auto rootPathName = ReadStringValue(message, offset); + auto result = ReadUInt32Value(message, offset); + m_callback->OnGetDriveTypeA(rootPathName, result); + break; + } + case DetourMessageType::GetDriveTypeW: + { + auto rootPathName = ReadWStringValue(message, offset); + auto result = ReadUInt32Value(message, offset); + m_callback->OnGetDriveTypeW(rootPathName, result); + break; + } + case DetourMessageType::GetFileAttributesA: + { + auto fileName = ReadStringValue(message, offset); + auto result = ReadUInt32Value(message, offset); + m_callback->OnGetFileAttributesA(fileName, result); + break; + } + case DetourMessageType::GetFileAttributesW: + { + auto fileName = ReadWStringValue(message, offset); + auto result = ReadUInt32Value(message, offset); + m_callback->OnGetFileAttributesW(fileName, result); + break; + } + case DetourMessageType::GetFileAttributesExA: + { + auto fileName = ReadStringValue(message, offset); + auto result = ReadBoolValue(message, offset); + m_callback->OnGetFileAttributesExA(fileName, result); + break; + } + case DetourMessageType::GetFileAttributesExW: + { + auto fileName = ReadWStringValue(message, offset); + auto result = ReadBoolValue(message, offset); + m_callback->OnGetFileAttributesExW(fileName, result); + break; + } + case DetourMessageType::GetFileInformationByHandle: + { + auto result = ReadBoolValue(message, offset); + m_callback->OnGetFileInformationByHandle(result); + break; + } + case DetourMessageType::GetFileSize: + { + auto result = ReadUInt32Value(message, offset); + m_callback->OnGetFileSize(result); + break; + } + case DetourMessageType::GetFileSizeEx: + { + auto result = ReadUInt32Value(message, offset); + m_callback->OnGetFileSizeEx(result); + break; + } + case DetourMessageType::GetFileTime: + { + auto result = ReadBoolValue(message, offset); + m_callback->OnGetFileTime(result); + break; + } + case DetourMessageType::GetFileType: + { + auto result = ReadUInt32Value(message, offset); + m_callback->OnGetFileType(result); + break; + } + case DetourMessageType::GetFinalPathNameByHandleA: + { + auto result = ReadUInt32Value(message, offset); + m_callback->OnGetFinalPathNameByHandleA(result); + break; + } + case DetourMessageType::GetFinalPathNameByHandleW: + { + auto result = ReadUInt32Value(message, offset); + m_callback->OnGetFinalPathNameByHandleW(result); + break; + } + case DetourMessageType::GetFullPathNameA: + { + auto fileName = ReadStringValue(message, offset); + auto result = ReadUInt32Value(message, offset); + m_callback->OnGetFullPathNameA(fileName, result); + break; + } + case DetourMessageType::GetFullPathNameW: + { + auto fileName = ReadWStringValue(message, offset); + auto buffer = ReadWStringValue(message, offset); + auto result = ReadUInt32Value(message, offset); + m_callback->OnGetFullPathNameW(fileName, buffer, result); + break; + } + case DetourMessageType::GetLogicalDrives: + { + auto result = ReadUInt32Value(message, offset); + m_callback->OnGetLogicalDrives(result); + break; + } + case DetourMessageType::GetLogicalDriveStringsW: + { + auto buffer = ReadWStringValue(message, offset); + auto result = ReadUInt32Value(message, offset); + m_callback->OnGetLogicalDriveStringsW(buffer, result); + break; + } + case DetourMessageType::GetLongPathNameA: + { + auto shortPath = ReadStringValue(message, offset); + auto longPath = ReadStringValue(message, offset); + auto result = ReadUInt32Value(message, offset); + m_callback->OnGetLongPathNameA(shortPath, longPath, result); + break; + } + case DetourMessageType::GetLongPathNameW: + { + auto shortPath = ReadWStringValue(message, offset); + auto longPath = ReadWStringValue(message, offset); + auto result = ReadUInt32Value(message, offset); + m_callback->OnGetLongPathNameW(shortPath, longPath, result); + break; + } + case DetourMessageType::GetShortPathNameW: + { + auto longPath = ReadWStringValue(message, offset); + auto shortPath = ReadWStringValue(message, offset); + auto result = ReadUInt32Value(message, offset); + m_callback->OnGetShortPathNameW(longPath, shortPath, result); + break; + } + case DetourMessageType::GetTempFileNameA: + { + auto pathName = ReadStringValue(message, offset); + auto prefixString = ReadStringValue(message, offset); + auto unique = ReadUInt32Value(message, offset); + auto tempFileName = ReadStringValue(message, offset); + auto result = ReadUInt32Value(message, offset); + m_callback->OnGetTempFileNameA(pathName, prefixString, unique, tempFileName, result); + break; + } + case DetourMessageType::GetTempFileNameW: + { + auto pathName = ReadWStringValue(message, offset); + auto prefixString = ReadWStringValue(message, offset); + auto unique = ReadUInt32Value(message, offset); + auto tempFileName = ReadWStringValue(message, offset); + auto result = ReadUInt32Value(message, offset); + m_callback->OnGetTempFileNameW(pathName, prefixString, unique, tempFileName, result); + break; + } + case DetourMessageType::GetTempPathA: + { + auto buffer = ReadStringValue(message, offset); + auto result = ReadUInt32Value(message, offset); + m_callback->OnGetTempPathA(buffer, result); + break; + } + case DetourMessageType::GetTempPathW: + { + auto buffer = ReadWStringValue(message, offset); + auto result = ReadUInt32Value(message, offset); + m_callback->OnGetTempPathW(buffer, result); + break; + } + case DetourMessageType::GetVolumeInformationA: + { + auto result = ReadBoolValue(message, offset); + m_callback->OnGetVolumeInformationA(result); + break; + } + case DetourMessageType::GetVolumeInformationW: + { + auto result = ReadBoolValue(message, offset); + m_callback->OnGetVolumeInformationW(result); + break; + } + case DetourMessageType::GetVolumeInformationByHandleW: + { + auto result = ReadBoolValue(message, offset); + m_callback->OnGetVolumeInformationByHandleW(result); + break; + } + case DetourMessageType::GetVolumeNameForVolumeMountPointW: + { + auto result = ReadBoolValue(message, offset); + m_callback->OnGetVolumeNameForVolumeMountPointW(result); + break; + } + case DetourMessageType::GetVolumePathNamesForVolumeNameW: + { + auto result = ReadBoolValue(message, offset); + m_callback->OnGetVolumePathNamesForVolumeNameW(result); + break; + } + case DetourMessageType::GetVolumePathNameW: + { + auto fileName = ReadWStringValue(message, offset); + auto result = ReadBoolValue(message, offset); + m_callback->OnGetVolumePathNameW(fileName, result); + break; + } + case DetourMessageType::LocalFileTimeToFileTime: + { + auto result = ReadBoolValue(message, offset); + m_callback->OnLocalFileTimeToFileTime(result); + break; + } + case DetourMessageType::LockFile: + { + auto result = ReadBoolValue(message, offset); + m_callback->OnLockFile(result); + break; + } + case DetourMessageType::LockFileEx: + { + auto result = ReadBoolValue(message, offset); + m_callback->OnLockFileEx(result); + break; + } + case DetourMessageType::QueryDosDeviceW: + { + auto deviceName = ReadWStringValue(message, offset); + auto result = ReadUInt32Value(message, offset); + m_callback->OnQueryDosDeviceW(deviceName, result); + break; + } + case DetourMessageType::ReadFile: + { + auto result = ReadBoolValue(message, offset); + m_callback->OnReadFile(result); + break; + } + case DetourMessageType::ReadFileEx: + { + auto result = ReadBoolValue(message, offset); + m_callback->OnReadFileEx(result); + break; + } + case DetourMessageType::ReadFileScatter: + { + auto result = ReadBoolValue(message, offset); + m_callback->OnReadFileScatter(result); + break; + } + case DetourMessageType::RemoveDirectoryA: + { + auto pathName = ReadStringValue(message, offset); + auto result = ReadBoolValue(message, offset); + m_callback->OnRemoveDirectoryA(pathName, result); + break; + } + case DetourMessageType::RemoveDirectoryW: + { + auto pathName = ReadWStringValue(message, offset); + auto result = ReadBoolValue(message, offset); + m_callback->OnRemoveDirectoryW(pathName, result); + break; + } + case DetourMessageType::SetEndOfFile: + { + auto result = ReadBoolValue(message, offset); + m_callback->OnSetEndOfFile(result); + break; + } + case DetourMessageType::SetFileApisToANSI: + { + m_callback->OnSetFileApisToANSI(); + break; + } + case DetourMessageType::SetFileApisToOEM: + { + m_callback->OnSetFileApisToOEM(); + break; + } + case DetourMessageType::SetFileAttributesA: + { + auto fileName = ReadStringValue(message, offset); + auto result = ReadBoolValue(message, offset); + m_callback->OnSetFileAttributesA(fileName, result); + break; + } + case DetourMessageType::SetFileAttributesW: + { + auto fileName = ReadWStringValue(message, offset); + auto result = ReadBoolValue(message, offset); + m_callback->OnSetFileAttributesW(fileName, result); + break; + } + case DetourMessageType::SetFileInformationByHandle: + { + auto result = ReadBoolValue(message, offset); + m_callback->OnSetFileInformationByHandle(result); + break; + } + case DetourMessageType::SetFileIoOverlappedRange: + { + auto result = ReadBoolValue(message, offset); + m_callback->OnSetFileIoOverlappedRange(result); + break; + } + case DetourMessageType::SetFilePointer: + { + auto result = ReadUInt32Value(message, offset); + m_callback->OnSetFilePointer(result); + break; + } + case DetourMessageType::SetFilePointerEx: + { + auto result = ReadBoolValue(message, offset); + m_callback->OnSetFilePointerEx(result); + break; + } + case DetourMessageType::SetFileTime: + { + auto result = ReadBoolValue(message, offset); + m_callback->OnSetFileTime(result); + break; + } + case DetourMessageType::SetFileValidData: + { + auto result = ReadBoolValue(message, offset); + m_callback->OnSetFileValidData(result); + break; + } + case DetourMessageType::UnlockFile: + { + auto result = ReadBoolValue(message, offset); + m_callback->OnUnlockFile(result); + break; + } + case DetourMessageType::UnlockFileEx: + { + auto result = ReadBoolValue(message, offset); + m_callback->OnUnlockFileEx(result); + break; + } + case DetourMessageType::WriteFile: + { + auto result = ReadBoolValue(message, offset); + m_callback->OnWriteFile(result); + break; + } + case DetourMessageType::WriteFileEx: + { + auto result = ReadBoolValue(message, offset); + m_callback->OnWriteFileEx(result); + break; + } + case DetourMessageType::WriteFileGather: + { + auto result = ReadBoolValue(message, offset); + m_callback->OnWriteFileGather(result); + break; + } + + // LibLoaderApi + case DetourMessageType::LoadLibraryA: + { + auto libFileName = ReadStringValue(message, offset); + m_callback->OnLoadLibraryA(libFileName); + break; + } + case DetourMessageType::LoadLibraryW: + { + auto libFileName = ReadWStringValue(message, offset); + m_callback->OnLoadLibraryW(libFileName); + break; + } + case DetourMessageType::LoadLibraryExA: + { + auto libFileName = ReadStringValue(message, offset); + m_callback->OnLoadLibraryExA(libFileName); + break; + } + case DetourMessageType::LoadLibraryExW: + { + auto libFileName = ReadWStringValue(message, offset); + m_callback->OnLoadLibraryExW(libFileName); + break; + } + + // ProcessEnv + case DetourMessageType::SearchPathA: + { + auto path = ReadStringValue(message, offset); + auto fileName = ReadStringValue(message, offset); + auto extension = ReadStringValue(message, offset); + auto result = ReadUInt32Value(message, offset); + m_callback->OnSearchPathA(path, fileName, extension, result); + break; + } + case DetourMessageType::SearchPathW: + { + auto path = ReadWStringValue(message, offset); + auto fileName = ReadWStringValue(message, offset); + auto extension = ReadWStringValue(message, offset); + auto result = ReadUInt32Value(message, offset); + m_callback->OnSearchPathW(path, fileName, extension, result); + break; + } + + // ProcessThreadsApi + case DetourMessageType::CreateProcessA: + { + auto applicationName = ReadStringValue(message, offset); + auto result = ReadBoolValue(message, offset); + m_callback->OnCreateProcessA(applicationName, result); + break; + } + case DetourMessageType::CreateProcessW: + { + auto applicationName = ReadWStringValue(message, offset); + auto result = ReadBoolValue(message, offset); + m_callback->OnCreateProcessW(applicationName, result); + break; + } + case DetourMessageType::CreateProcessAsUserA: + { + auto applicationName = ReadStringValue(message, offset); + auto result = ReadBoolValue(message, offset); + m_callback->OnCreateProcessAsUserA(applicationName, result); + break; + } + case DetourMessageType::CreateProcessAsUserW: + { + auto applicationName = ReadWStringValue(message, offset); + auto result = ReadBoolValue(message, offset); + m_callback->OnCreateProcessAsUserW(applicationName, result); + break; + } + case DetourMessageType::ExitProcess: + { + auto exitCode = ReadUInt32Value(message, offset); + m_callback->OnExitProcess(exitCode); + break; + } + + // UndocumentedApi + case DetourMessageType::PrivCopyFileExA: + { + auto existingFileName = ReadStringValue(message, offset); + auto newFileName = ReadStringValue(message, offset); + auto result = ReadBoolValue(message, offset); + m_callback->OnPrivCopyFileExA(existingFileName, newFileName, result); + break; + } + case DetourMessageType::PrivCopyFileExW: + { + auto existingFileName = ReadWStringValue(message, offset); + auto newFileName = ReadWStringValue(message, offset); + auto result = ReadBoolValue(message, offset); + m_callback->OnPrivCopyFileExW(existingFileName, newFileName, result); + break; + } + + // WinBase + case DetourMessageType::CopyFileA: + { + auto existingFileName = ReadStringValue(message, offset); + auto newFileName = ReadStringValue(message, offset); + auto failIfExists = ReadBoolValue(message, offset); + auto result = ReadBoolValue(message, offset); + m_callback->OnCopyFileA(existingFileName, newFileName, failIfExists, result); + break; + } + case DetourMessageType::CopyFileW: + { + auto existingFileName = ReadWStringValue(message, offset); + auto newFileName = ReadWStringValue(message, offset); + auto failIfExists = ReadBoolValue(message, offset); + auto result = ReadBoolValue(message, offset); + m_callback->OnCopyFileW(existingFileName, newFileName, failIfExists, result); + break; + } + case DetourMessageType::CopyFile2: + { + auto existingFileName = ReadWStringValue(message, offset); + auto newFileName = ReadWStringValue(message, offset); + auto result = ReadUInt64Value(message, offset); + m_callback->OnCopyFile2(existingFileName, newFileName, result); + break; + } + case DetourMessageType::CopyFileExA: + { + auto existingFileName = ReadStringValue(message, offset); + auto newFileName = ReadStringValue(message, offset); + auto result = ReadBoolValue(message, offset); + m_callback->OnCopyFileExA(existingFileName, newFileName, result); + break; + } + case DetourMessageType::CopyFileExW: + { + auto existingFileName = ReadWStringValue(message, offset); + auto newFileName = ReadWStringValue(message, offset); + auto result = ReadBoolValue(message, offset); + m_callback->OnCopyFileExW(existingFileName, newFileName, result); + break; + } + case DetourMessageType::CopyFileTransactedA: + { + auto existingFileName = ReadStringValue(message, offset); + auto newFileName = ReadStringValue(message, offset); + auto result = ReadBoolValue(message, offset); + m_callback->OnCopyFileTransactedA(existingFileName, newFileName, result); + break; + } + case DetourMessageType::CopyFileTransactedW: + { + auto existingFileName = ReadWStringValue(message, offset); + auto newFileName = ReadWStringValue(message, offset); + auto result = ReadBoolValue(message, offset); + m_callback->OnCopyFileTransactedW(existingFileName, newFileName, result); + break; + } + case DetourMessageType::CreateDirectoryExA: + { + auto templateDirectory = ReadStringValue(message, offset); + auto newDirectory = ReadStringValue(message, offset); + auto result = ReadBoolValue(message, offset); + m_callback->OnCreateDirectoryExA(templateDirectory, newDirectory, result); + break; + } + case DetourMessageType::CreateDirectoryExW: + { + auto templateDirectory = ReadWStringValue(message, offset); + auto newDirectory = ReadWStringValue(message, offset); + auto result = ReadBoolValue(message, offset); + m_callback->OnCreateDirectoryExW(templateDirectory, newDirectory, result); + break; + } + case DetourMessageType::CreateDirectoryTransactedA: + { + auto templateDirectory = ReadStringValue(message, offset); + auto newDirectory = ReadStringValue(message, offset); + auto result = ReadBoolValue(message, offset); + m_callback->OnCreateDirectoryTransactedA(templateDirectory, newDirectory, result); + break; + } + case DetourMessageType::CreateDirectoryTransactedW: + { + auto templateDirectory = ReadWStringValue(message, offset); + auto newDirectory = ReadWStringValue(message, offset); + auto result = ReadBoolValue(message, offset); + m_callback->OnCreateDirectoryTransactedW(templateDirectory, newDirectory, result); + break; + } + case DetourMessageType::CreateFileTransactedA: + { + auto fileName = ReadStringValue(message, offset); + auto desiredAccess = ReadUInt32Value(message, offset); + auto shareMode = ReadUInt32Value(message, offset); + auto result = ReadUInt64Value(message, offset); + m_callback->OnCreateFileTransactedA(fileName, desiredAccess, shareMode, result); + break; + } + case DetourMessageType::CreateFileTransactedW: + { + auto fileName = ReadWStringValue(message, offset); + auto desiredAccess = ReadUInt32Value(message, offset); + auto shareMode = ReadUInt32Value(message, offset); + auto result = ReadUInt64Value(message, offset); + m_callback->OnCreateFileTransactedW(fileName, desiredAccess, shareMode, result); + break; + } + case DetourMessageType::CreateHardLinkA: + { + auto fileName = ReadStringValue(message, offset); + auto existingFileName = ReadStringValue(message, offset); + auto result = ReadBoolValue(message, offset); + m_callback->OnCreateHardLinkA(fileName, existingFileName, result); + break; + } + case DetourMessageType::CreateHardLinkW: + { + auto fileName = ReadWStringValue(message, offset); + auto existingFileName = ReadWStringValue(message, offset); + auto result = ReadBoolValue(message, offset); + m_callback->OnCreateHardLinkW(fileName, existingFileName, result); + break; + } + case DetourMessageType::CreateHardLinkTransactedA: + { + auto fileName = ReadStringValue(message, offset); + auto existingFileName = ReadStringValue(message, offset); + auto result = ReadBoolValue(message, offset); + m_callback->OnCreateHardLinkTransactedA(fileName, existingFileName, result); + break; + } + case DetourMessageType::CreateHardLinkTransactedW: + { + auto fileName = ReadWStringValue(message, offset); + auto existingFileName = ReadWStringValue(message, offset); + auto result = ReadBoolValue(message, offset); + m_callback->OnCreateHardLinkTransactedW(fileName, existingFileName, result); + break; + } + case DetourMessageType::CreateProcessWithLogonW: + { + auto applicationName = ReadWStringValue(message, offset); + auto result = ReadBoolValue(message, offset); + m_callback->OnCreateProcessWithLogonW(applicationName, result); + break; + } + case DetourMessageType::CreateProcessWithTokenW: + { + auto applicationName = ReadWStringValue(message, offset); + auto result = ReadBoolValue(message, offset); + m_callback->OnCreateProcessWithTokenW(applicationName, result); + break; + } + case DetourMessageType::CreateSymbolicLinkA: + { + auto symlinkFileName = ReadStringValue(message, offset); + auto targetFileName = ReadStringValue(message, offset); + auto flags = ReadUInt32Value(message, offset); + auto result = ReadBoolValue(message, offset); + m_callback->OnCreateSymbolicLinkA(symlinkFileName, targetFileName, flags, result); + break; + } + case DetourMessageType::CreateSymbolicLinkW: + { + auto symlinkFileName = ReadWStringValue(message, offset); + auto targetFileName = ReadWStringValue(message, offset); + auto flags = ReadUInt32Value(message, offset); + auto result = ReadBoolValue(message, offset); + m_callback->OnCreateSymbolicLinkW(symlinkFileName, targetFileName, flags, result); + break; + } + case DetourMessageType::CreateSymbolicLinkTransactedA: + { + auto symlinkFileName = ReadStringValue(message, offset); + auto targetFileName = ReadStringValue(message, offset); + auto flags = ReadUInt32Value(message, offset); + auto result = ReadBoolValue(message, offset); + m_callback->OnCreateSymbolicLinkTransactedA(symlinkFileName, targetFileName, flags, result); + break; + } + case DetourMessageType::CreateSymbolicLinkTransactedW: + { + auto symlinkFileName = ReadWStringValue(message, offset); + auto targetFileName = ReadWStringValue(message, offset); + auto flags = ReadUInt32Value(message, offset); + auto result = ReadBoolValue(message, offset); + m_callback->OnCreateSymbolicLinkTransactedW(symlinkFileName, targetFileName, flags, result); + break; + } + case DetourMessageType::DecryptFileA: + { + auto fileName = ReadStringValue(message, offset); + auto result = ReadBoolValue(message, offset); + m_callback->OnDecryptFileA(fileName, result); + break; + } + case DetourMessageType::DecryptFileW: + { + auto fileName = ReadWStringValue(message, offset); + auto result = ReadBoolValue(message, offset); + m_callback->OnDecryptFileW(fileName, result); + break; + } + case DetourMessageType::DeleteFileTransactedA: + { + auto fileName = ReadStringValue(message, offset); + auto result = ReadBoolValue(message, offset); + m_callback->OnDeleteFileTransactedA(fileName, result); + break; + } + case DetourMessageType::DeleteFileTransactedW: + { + auto fileName = ReadWStringValue(message, offset); + auto result = ReadBoolValue(message, offset); + m_callback->OnDeleteFileTransactedW(fileName, result); + break; + } + case DetourMessageType::EncryptFileA: + { + auto fileName = ReadStringValue(message, offset); + auto result = ReadBoolValue(message, offset); + m_callback->OnEncryptFileA(fileName, result); + break; + } + case DetourMessageType::EncryptFileW: + { + auto fileName = ReadWStringValue(message, offset); + auto result = ReadBoolValue(message, offset); + m_callback->OnEncryptFileW(fileName, result); + break; + } + case DetourMessageType::FileEncryptionStatusA: + { + auto fileName = ReadStringValue(message, offset); + auto result = ReadBoolValue(message, offset); + m_callback->OnFileEncryptionStatusA(fileName, result); + break; + } + case DetourMessageType::FileEncryptionStatusW: + { + auto fileName = ReadWStringValue(message, offset); + auto result = ReadBoolValue(message, offset); + m_callback->OnFileEncryptionStatusW(fileName, result); + break; + } + case DetourMessageType::FindFirstFileNameTransactedW: + { + auto fileName = ReadWStringValue(message, offset); + auto result = ReadBoolValue(message, offset); + m_callback->OnFindFirstFileNameTransactedW(fileName, result); + break; + } + case DetourMessageType::FindFirstFileTransactedA: + { + auto fileName = ReadStringValue(message, offset); + m_callback->OnFindFirstFileTransactedA(fileName); + break; + } + case DetourMessageType::FindFirstFileTransactedW: + { + auto fileName = ReadWStringValue(message, offset); + m_callback->OnFindFirstFileTransactedW(fileName); + break; + } + case DetourMessageType::FindFirstStreamTransactedW: + { + auto fileName = ReadWStringValue(message, offset); + m_callback->OnFindFirstStreamTransactedW(fileName); + break; + } + case DetourMessageType::GetBinaryTypeA: + { + auto applicationName = ReadStringValue(message, offset); + auto result = ReadBoolValue(message, offset); + m_callback->OnGetBinaryTypeA(applicationName, result); + break; + } + case DetourMessageType::GetBinaryTypeW: + { + auto applicationName = ReadWStringValue(message, offset); + auto result = ReadBoolValue(message, offset); + m_callback->OnGetBinaryTypeW(applicationName, result); + break; + } + case DetourMessageType::GetCompressedFileSizeTransactedA: + { + auto fileName = ReadStringValue(message, offset); + auto result = ReadUInt32Value(message, offset); + m_callback->OnGetCompressedFileSizeTransactedA(fileName, result); + break; + } + case DetourMessageType::GetCompressedFileSizeTransactedW: + { + auto fileName = ReadWStringValue(message, offset); + auto result = ReadUInt32Value(message, offset); + m_callback->OnGetCompressedFileSizeTransactedW(fileName, result); + break; + } + case DetourMessageType::GetDllDirectoryA: + { + auto result = ReadUInt32Value(message, offset); + m_callback->OnGetDllDirectoryA(result); + break; + } + case DetourMessageType::GetDllDirectoryW: + { + auto result = ReadUInt32Value(message, offset); + m_callback->OnGetDllDirectoryW(result); + break; + } + case DetourMessageType::GetFileAttributesTransactedA: + { + auto fileName = ReadStringValue(message, offset); + auto result = ReadBoolValue(message, offset); + m_callback->OnGetFileAttributesTransactedA(fileName, result); + break; + } + case DetourMessageType::GetFileAttributesTransactedW: + { + auto fileName = ReadWStringValue(message, offset); + auto result = ReadBoolValue(message, offset); + m_callback->OnGetFileAttributesTransactedW(fileName, result); + break; + } + case DetourMessageType::GetFileBandwidthReservation: + { + auto result = ReadBoolValue(message, offset); + m_callback->OnGetFileBandwidthReservation(result); + break; + } + case DetourMessageType::GetFileInformationByHandleEx: + { + auto result = ReadBoolValue(message, offset); + m_callback->OnGetFileInformationByHandleEx(result); + break; + } + case DetourMessageType::GetFileSecurityA: + { + auto fileName = ReadStringValue(message, offset); + auto result = ReadBoolValue(message, offset); + m_callback->OnGetFileSecurityA(fileName, result); + break; + } + case DetourMessageType::GetFullPathNameTransactedA: + { + auto fileName = ReadStringValue(message, offset); + auto result = ReadUInt32Value(message, offset); + m_callback->OnGetFullPathNameTransactedA(fileName, result); + break; + } + case DetourMessageType::GetFullPathNameTransactedW: + { + auto fileName = ReadWStringValue(message, offset); + auto result = ReadUInt32Value(message, offset); + m_callback->OnGetFullPathNameTransactedW(fileName, result); + break; + } + case DetourMessageType::GetLongPathNameTransactedA: + { + auto shortPath = ReadStringValue(message, offset); + auto longPath = ReadStringValue(message, offset); + auto result = ReadUInt32Value(message, offset); + m_callback->OnGetLongPathNameTransactedA(shortPath, longPath, result); + break; + } + case DetourMessageType::GetLongPathNameTransactedW: + { + auto shortPath = ReadWStringValue(message, offset); + auto longPath = ReadWStringValue(message, offset); + auto result = ReadUInt32Value(message, offset); + m_callback->OnGetLongPathNameTransactedW(shortPath, longPath, result); + break; + } + case DetourMessageType::GetQueuedCompletionStatus: + { + auto result = ReadBoolValue(message, offset); + m_callback->OnGetQueuedCompletionStatus(result); + break; + } + case DetourMessageType::GetQueuedCompletionStatusEx: + { + auto result = ReadBoolValue(message, offset); + m_callback->OnGetQueuedCompletionStatusEx(result); + break; + } + case DetourMessageType::GetShortPathNameA: + { + auto longPath = ReadStringValue(message, offset); + auto shortPath = ReadStringValue(message, offset); + auto result = ReadUInt32Value(message, offset); + m_callback->OnGetShortPathNameA(longPath, shortPath, result); + break; + } + case DetourMessageType::LoadModule: + { + auto moduleName = ReadStringValue(message, offset); + auto result = ReadUInt32Value(message, offset); + m_callback->OnLoadModule(moduleName, result); + break; + } + case DetourMessageType::LoadPackagedLibrary: + { + auto libFileName = ReadStringValue(message, offset); + m_callback->OnLoadPackagedLibrary(libFileName); + break; + } + case DetourMessageType::MoveFileA: + { + auto existingFileName = ReadStringValue(message, offset); + auto newFileName = ReadStringValue(message, offset); + auto result = ReadBoolValue(message, offset); + m_callback->OnMoveFileA(existingFileName, newFileName, result); + break; + } + case DetourMessageType::MoveFileW: + { + auto existingFileName = ReadWStringValue(message, offset); + auto newFileName = ReadWStringValue(message, offset); + auto result = ReadBoolValue(message, offset); + m_callback->OnMoveFileW(existingFileName, newFileName, result); + break; + } + case DetourMessageType::MoveFileExA: + { + auto existingFileName = ReadStringValue(message, offset); + auto newFileName = ReadStringValue(message, offset); + auto flags = ReadUInt32Value(message, offset); + auto result = ReadBoolValue(message, offset); + m_callback->OnMoveFileExA(existingFileName, newFileName, flags, result); + break; + } + case DetourMessageType::MoveFileExW: + { + auto existingFileName = ReadWStringValue(message, offset); + auto newFileName = ReadWStringValue(message, offset); + auto flags = ReadUInt32Value(message, offset); + auto result = ReadBoolValue(message, offset); + m_callback->OnMoveFileExW(existingFileName, newFileName, flags, result); + break; + } + case DetourMessageType::MoveFileTransactedA: + { + auto existingFileName = ReadStringValue(message, offset); + auto newFileName = ReadStringValue(message, offset); + auto flags = ReadUInt32Value(message, offset); + auto result = ReadBoolValue(message, offset); + m_callback->OnMoveFileTransactedA(existingFileName, newFileName, flags, result); + break; + } + case DetourMessageType::MoveFileTransactedW: + { + auto existingFileName = ReadWStringValue(message, offset); + auto newFileName = ReadWStringValue(message, offset); + auto flags = ReadUInt32Value(message, offset); + auto result = ReadBoolValue(message, offset); + m_callback->OnMoveFileTransactedW(existingFileName, newFileName, flags, result); + break; + } + case DetourMessageType::MoveFileWithProgressA: + { + auto existingFileName = ReadStringValue(message, offset); + auto newFileName = ReadStringValue(message, offset); + auto flags = ReadUInt32Value(message, offset); + auto result = ReadBoolValue(message, offset); + m_callback->OnMoveFileWithProgressA(existingFileName, newFileName, flags, result); + break; + } + case DetourMessageType::MoveFileWithProgressW: + { + auto existingFileName = ReadWStringValue(message, offset); + auto newFileName = ReadWStringValue(message, offset); + auto flags = ReadUInt32Value(message, offset); + auto result = ReadBoolValue(message, offset); + m_callback->OnMoveFileWithProgressW(existingFileName, newFileName, flags, result); + break; + } + case DetourMessageType::OpenEncryptedFileRawA: + { + auto fileName = ReadStringValue(message, offset); + auto flags = ReadUInt32Value(message, offset); + auto result = ReadUInt32Value(message, offset); + m_callback->OnOpenEncryptedFileRawA(fileName, flags, result); + break; + } + case DetourMessageType::OpenEncryptedFileRawW: + { + auto fileName = ReadWStringValue(message, offset); + auto flags = ReadUInt32Value(message, offset); + auto result = ReadUInt32Value(message, offset); + m_callback->OnOpenEncryptedFileRawW(fileName, flags, result); + break; + } + case DetourMessageType::OpenFile: + { + auto fileName = ReadStringValue(message, offset); + m_callback->OnOpenFile(fileName); + break; + } + case DetourMessageType::OpenFileById: + { + m_callback->OnOpenFileById(); + break; + } + case DetourMessageType::ReadEncryptedFileRaw: + { + auto result = ReadUInt32Value(message, offset); + m_callback->OnReadEncryptedFileRaw(result); + break; + } + case DetourMessageType::RemoveDirectoryTransactedA: + { + auto pathName = ReadStringValue(message, offset); + auto result = ReadBoolValue(message, offset); + m_callback->OnRemoveDirectoryTransactedA(pathName, result); + break; + } + case DetourMessageType::RemoveDirectoryTransactedW: + { + auto pathName = ReadWStringValue(message, offset); + auto result = ReadBoolValue(message, offset); + m_callback->OnRemoveDirectoryTransactedW(pathName, result); + break; + } + case DetourMessageType::ReOpenFile: + { + m_callback->OnReOpenFile(); + break; + } + case DetourMessageType::ReplaceFileA: + { + auto replacedFileName = ReadStringValue(message, offset); + auto replacementFileName = ReadStringValue(message, offset); + auto backupFileName = ReadStringValue(message, offset); + auto replaceFlags = ReadUInt32Value(message, offset); + auto result = ReadBoolValue(message, offset); + m_callback->OnReplaceFileA(replacedFileName, replacementFileName, backupFileName, replaceFlags, result); + break; + } + case DetourMessageType::ReplaceFileW: + { + auto replacedFileName = ReadWStringValue(message, offset); + auto replacementFileName = ReadWStringValue(message, offset); + auto backupFileName = ReadWStringValue(message, offset); + auto replaceFlags = ReadUInt32Value(message, offset); + auto result = ReadBoolValue(message, offset); + m_callback->OnReplaceFileW(replacedFileName, replacementFileName, backupFileName, replaceFlags, result); + break; + } + case DetourMessageType::SetCurrentDirectoryA: + { + auto pathName = ReadStringValue(message, offset); + auto result = ReadBoolValue(message, offset); + m_callback->OnSetCurrentDirectoryA(pathName, result); + break; + } + case DetourMessageType::SetCurrentDirectoryW: + { + auto pathName = ReadWStringValue(message, offset); + auto result = ReadBoolValue(message, offset); + m_callback->OnSetCurrentDirectoryW(pathName, result); + break; + } + case DetourMessageType::SetDllDirectoryA: + { + auto pathName = ReadStringValue(message, offset); + auto result = ReadBoolValue(message, offset); + m_callback->OnSetDllDirectoryA(pathName, result); + break; + } + case DetourMessageType::SetDllDirectoryW: + { + auto pathName = ReadWStringValue(message, offset); + auto result = ReadBoolValue(message, offset); + m_callback->OnSetDllDirectoryW(pathName, result); + break; + } + case DetourMessageType::SetFileAttributesTransactedA: + { + auto fileName = ReadStringValue(message, offset); + auto fileAttributes = ReadUInt32Value(message, offset); + auto result = ReadBoolValue(message, offset); + m_callback->OnSetFileAttributesTransactedA(fileName, fileAttributes, result); + break; + } + case DetourMessageType::SetFileAttributesTransactedW: + { + auto fileName = ReadWStringValue(message, offset); + auto fileAttributes = ReadUInt32Value(message, offset); + auto result = ReadBoolValue(message, offset); + m_callback->OnSetFileAttributesTransactedW(fileName, fileAttributes, result); + break; + } + case DetourMessageType::SetFileBandwidthReservation: + { + auto result = ReadBoolValue(message, offset); + m_callback->OnSetFileBandwidthReservation(result); + break; + } + case DetourMessageType::SetFileCompletionNotificationModes: + { + auto result = ReadBoolValue(message, offset); + m_callback->OnSetFileCompletionNotificationModes(result); + break; + } + case DetourMessageType::SetFileSecurityA: + { + auto fileName = ReadStringValue(message, offset); + auto result = ReadBoolValue(message, offset); + m_callback->OnSetFileSecurityA(fileName, result); + break; + } + case DetourMessageType::SetFileShortNameA: + { + auto shortName = ReadStringValue(message, offset); + auto result = ReadBoolValue(message, offset); + m_callback->OnSetFileShortNameA(shortName, result); + break; + } + case DetourMessageType::SetFileShortNameW: + { + auto shortName = ReadWStringValue(message, offset); + auto result = ReadBoolValue(message, offset); + m_callback->OnSetFileShortNameW(shortName, result); + break; + } + case DetourMessageType::SetSearchPathMode: + { + auto flags = ReadUInt32Value(message, offset); + auto result = ReadBoolValue(message, offset); + m_callback->OnSetSearchPathMode(flags, result); + break; + } + case DetourMessageType::WriteEncryptedFileRaw: + { + auto result = ReadUInt32Value(message, offset); + m_callback->OnWriteEncryptedFileRaw(result); + break; + } + default: + { + throw std::runtime_error("Unknown message type"); + } + } + + // Verify that we read the entire message + if (offset != message.ContentSize) + { + throw std::runtime_error("Did not read the entire message"); + } + } + + private: + bool ReadBoolValue(DetourMessage& message, int32_t& offset) + { + auto result = *reinterpret_cast(message.Content + offset); + offset += sizeof(uint32_t); + if (offset > message.ContentSize) + throw std::runtime_error("ReadBoolValue past end of content"); + return result > 0; + } + + int32_t ReadInt32Value(DetourMessage& message, int32_t& offset) + { + auto result = *reinterpret_cast(message.Content + offset); + offset += sizeof(int32_t); + if (offset > message.ContentSize) + throw std::runtime_error("ReadInt32Value past end of content"); + return result; + } + + uint32_t ReadUInt32Value(DetourMessage& message, int32_t& offset) + { + auto result = *reinterpret_cast(message.Content + offset); + offset += sizeof(uint32_t); + if (offset > message.ContentSize) + throw std::runtime_error("ReadUInt32Value past end of content"); + return result; + } + + uint64_t ReadUInt64Value(DetourMessage& message, int32_t& offset) + { + auto result = *reinterpret_cast(message.Content + offset); + offset += sizeof(uint64_t); + if (offset > message.ContentSize) + throw std::runtime_error("ReadUInt64Value past end of content"); + return result; + } + + std::string_view ReadStringValue(DetourMessage& message, int32_t& offset) + { + auto result = std::string_view(reinterpret_cast(message.Content + offset)); + offset += result.size() + 1; + if (offset > message.ContentSize) + throw std::runtime_error("ReadStringValue past end of content"); + return result; + } + + std::wstring_view ReadWStringValue(DetourMessage& message, int32_t& offset) + { + auto result = std::wstring_view(reinterpret_cast(message.Content + offset)); + offset += 2 * (result.size() + 1); + if (offset > message.ContentSize) + throw std::runtime_error("ReadWStringValue past end of content"); + return result; + } + + private: + // Input + std::shared_ptr m_callback; + }; +} diff --git a/Source/Monitor/Shared/IDetourCallback.h b/Source/Monitor/Shared/IDetourCallback.h new file mode 100644 index 00000000..8fd4057d --- /dev/null +++ b/Source/Monitor/Shared/IDetourCallback.h @@ -0,0 +1,214 @@ +#pragma once + +namespace Monitor +{ + export class IDetourCallback + { + public: + virtual void OnShutdown() = 0; + virtual void OnError(std::string_view message) = 0; + + // FileApi + virtual void OnAreFileApisANSI(bool result) = 0; + virtual void OnCompareFileTime(int32_t result) = 0; + virtual void OnCreateDirectoryA(std::string_view pathName, bool result) = 0; + virtual void OnCreateDirectoryW(std::wstring_view pathName, bool result) = 0; + virtual void OnCreateFile2(std::wstring_view fileName, uint32_t desiredAccess, uint32_t sharedMode, uint32_t creationDisposition, uint64_t result) = 0; + virtual void OnCreateFileA(std::string_view fileName, uint32_t desiredAccess, uint32_t sharedMode, uint32_t creationDisposition, uint32_t flagsAndAttributes, uint64_t result) = 0; + virtual void OnCreateFileW(std::wstring_view fileName, uint32_t desiredAccess, uint32_t sharedMode, uint32_t creationDisposition, uint32_t flagsAndAttributes, uint64_t result) = 0; + virtual void OnDefineDosDeviceW(uint32_t flags, std::wstring_view deviceName, std::wstring_view targetPath, bool result) = 0; + virtual void OnDeleteFileA(std::string_view fileName, bool result) = 0; + virtual void OnDeleteFileW(std::wstring_view fileName, bool result) = 0; + virtual void OnDeleteVolumeMountPointW(std::wstring_view volumeMountPoint, bool result) = 0; + virtual void OnFileTimeToLocalFileTime(bool result) = 0; + virtual void OnFindClose(bool result) = 0; + virtual void OnFindCloseChangeNotification(bool result) = 0; + virtual void OnFindFirstChangeNotificationA(std::string_view pathName, bool watchSubtree, uint32_t notifyFilter) = 0; + virtual void OnFindFirstChangeNotificationW(std::wstring_view pathName, bool watchSubtree, uint32_t notifyFilter) = 0; + virtual void OnFindFirstFileA(std::string_view fileName) = 0; + virtual void OnFindFirstFileW(std::wstring_view fileName) = 0; + virtual void OnFindFirstFileExA(std::string_view fileName) = 0; + virtual void OnFindFirstFileExW(std::wstring_view fileName) = 0; + virtual void OnFindFirstFileNameW(std::wstring_view fileName, uint32_t flags) = 0; + virtual void OnFindFirstStreamW(std::wstring_view fileName) = 0; + virtual void OnFindFirstVolumeW(std::wstring_view fileName) = 0; + virtual void OnFindNextChangeNotification(bool result) = 0; + virtual void OnFindNextFileA(bool result) = 0; + virtual void OnFindNextFileW(bool result) = 0; + virtual void OnFindNextFileNameW(bool result) = 0; + virtual void OnFindNextStreamW(bool result) = 0; + virtual void OnFindNextVolumeW(bool result) = 0; + virtual void OnFindVolumeClose(bool result) = 0; + virtual void OnFlushFileBuffers(bool result) = 0; + virtual void OnGetCompressedFileSizeA(std::string_view fileName, uint32_t result) = 0; + virtual void OnGetCompressedFileSizeW(std::wstring_view fileName, uint32_t result) = 0; + virtual void OnGetDiskFreeSpaceA(std::string_view rootPathName, bool result) = 0; + virtual void OnGetDiskFreeSpaceW(std::wstring_view rootPathName, bool result) = 0; + virtual void OnGetDiskFreeSpaceExA(std::string_view directoryName, bool result) = 0; + virtual void OnGetDiskFreeSpaceExW(std::wstring_view directoryName, bool result) = 0; + virtual void OnGetDriveTypeA(std::string_view rootPathName, uint32_t result) = 0; + virtual void OnGetDriveTypeW(std::wstring_view rootPathName, uint32_t result) = 0; + virtual void OnGetFileAttributesA(std::string_view fileName, uint32_t result) = 0; + virtual void OnGetFileAttributesW(std::wstring_view fileName, uint32_t result) = 0; + virtual void OnGetFileAttributesExA(std::string_view fileName, bool result) = 0; + virtual void OnGetFileAttributesExW(std::wstring_view fileName, bool result) = 0; + virtual void OnGetFileInformationByHandle(bool result) = 0; + virtual void OnGetFileSize(uint32_t result) = 0; + virtual void OnGetFileSizeEx(uint32_t result) = 0; + virtual void OnGetFileTime(bool result) = 0; + virtual void OnGetFileType(uint32_t result) = 0; + virtual void OnGetFinalPathNameByHandleA(uint32_t result) = 0; + virtual void OnGetFinalPathNameByHandleW(uint32_t result) = 0; + virtual void OnGetFullPathNameA(std::string_view fileName, uint32_t result) = 0; + virtual void OnGetFullPathNameW(std::wstring_view fileName, std::wstring_view buffer, uint32_t result) = 0; + virtual void OnGetLogicalDrives(uint32_t result) = 0; + virtual void OnGetLogicalDriveStringsW(std::wstring_view buffer, uint32_t result) = 0; + virtual void OnGetLongPathNameA(std::string_view shortPath, std::string_view longPath, uint32_t result) = 0; + virtual void OnGetLongPathNameW(std::wstring_view shortPath, std::wstring_view longPath, uint32_t result) = 0; + virtual void OnGetShortPathNameW(std::wstring_view longPath, std::wstring_view shortPath, uint32_t result) = 0; + virtual void OnGetTempFileNameA(std::string_view pathName, std::string_view prefixString, uint32_t unique, std::string_view tempFileName, uint32_t result) = 0; + virtual void OnGetTempFileNameW(std::wstring_view pathName, std::wstring_view prefixString, uint32_t unique, std::wstring_view tempFileName, uint32_t result) = 0; + virtual void OnGetTempPathA(std::string_view buffer, uint32_t result) = 0; + virtual void OnGetTempPathW(std::wstring_view buffer, uint32_t result) = 0; + virtual void OnGetVolumeInformationA(bool result) = 0; + virtual void OnGetVolumeInformationW(bool result) = 0; + virtual void OnGetVolumeInformationByHandleW(bool result) = 0; + virtual void OnGetVolumeNameForVolumeMountPointW(bool result) = 0; + virtual void OnGetVolumePathNamesForVolumeNameW(bool result) = 0; + virtual void OnGetVolumePathNameW(std::wstring_view filename, bool result) = 0; + virtual void OnLocalFileTimeToFileTime(bool result) = 0; + virtual void OnLockFile(bool result) = 0; + virtual void OnLockFileEx(bool result) = 0; + virtual void OnQueryDosDeviceW(std::wstring_view deviceName, uint32_t result) = 0; + virtual void OnReadFile(bool result) = 0; + virtual void OnReadFileEx(bool result) = 0; + virtual void OnReadFileScatter(bool result) = 0; + virtual void OnRemoveDirectoryA(std::string_view pathName, bool result) = 0; + virtual void OnRemoveDirectoryW(std::wstring_view pathName, bool result) = 0; + virtual void OnSetEndOfFile(bool result) = 0; + virtual void OnSetFileApisToANSI() = 0; + virtual void OnSetFileApisToOEM() = 0; + virtual void OnSetFileAttributesA(std::string_view fileName, bool result) = 0; + virtual void OnSetFileAttributesW(std::wstring_view fileName, bool result) = 0; + virtual void OnSetFileInformationByHandle(bool result) = 0; + virtual void OnSetFileIoOverlappedRange(bool result) = 0; + virtual void OnSetFilePointer(uint32_t result) = 0; + virtual void OnSetFilePointerEx(bool result) = 0; + virtual void OnSetFileTime(bool result) = 0; + virtual void OnSetFileValidData(bool result) = 0; + virtual void OnUnlockFile(bool result) = 0; + virtual void OnUnlockFileEx(bool result) = 0; + virtual void OnWriteFile(bool result) = 0; + virtual void OnWriteFileEx(bool result) = 0; + virtual void OnWriteFileGather(bool result) = 0; + + // LibLoaderApi + virtual void OnLoadLibraryA(std::string_view libFileName) = 0; + virtual void OnLoadLibraryW(std::wstring_view libFileName) = 0; + virtual void OnLoadLibraryExA(std::string_view libFileName) = 0; + virtual void OnLoadLibraryExW(std::wstring_view libFileName) = 0; + + // ProcessEnv + virtual void OnSearchPathA(std::string_view path, std::string_view fileName, std::string_view extension, uint32_t result) = 0; + virtual void OnSearchPathW(std::wstring_view path, std::wstring_view fileName, std::wstring_view extension, uint32_t result) = 0; + + // ProcessThreadsApi + virtual void OnCreateProcessA(std::string_view applicationName, bool result) = 0; + virtual void OnCreateProcessW(std::wstring_view applicationName, bool result) = 0; + virtual void OnCreateProcessAsUserA(std::string_view applicationName, bool result) = 0; + virtual void OnCreateProcessAsUserW(std::wstring_view applicationName, bool result) = 0; + virtual void OnExitProcess(uint32_t exitCode) = 0; + + // UndocumentedApi + virtual void OnPrivCopyFileExA(std::string_view existingFileName, std::string_view newFileName, bool result) = 0; + virtual void OnPrivCopyFileExW(std::wstring_view existingFileName, std::wstring_view newFileName, bool result) = 0; + + // WinBase + virtual void OnCopyFileA(std::string_view existingFileName, std::string_view newFileName, bool failIfExists, bool result) = 0; + virtual void OnCopyFileW(std::wstring_view existingFileName, std::wstring_view newFileName, bool failIfExists, bool result) = 0; + virtual void OnCopyFile2(std::wstring_view existingFileName, std::wstring_view newFileName, uint64_t result) = 0; + virtual void OnCopyFileExA(std::string_view existingFileName, std::string_view newFileName, bool result) = 0; + virtual void OnCopyFileExW(std::wstring_view existingFileName, std::wstring_view newFileName, bool result) = 0; + virtual void OnCopyFileTransactedA(std::string_view existingFileName, std::string_view newFileName, bool result) = 0; + virtual void OnCopyFileTransactedW(std::wstring_view existingFileName, std::wstring_view newFileName, bool result) = 0; + virtual void OnCreateDirectoryExA(std::string_view templateDirectory, std::string_view newDirectory, bool result) = 0; + virtual void OnCreateDirectoryExW(std::wstring_view templateDirectory, std::wstring_view newDirectory, bool result) = 0; + virtual void OnCreateDirectoryTransactedA(std::string_view templateDirectory, std::string_view newDirectory, bool result) = 0; + virtual void OnCreateDirectoryTransactedW(std::wstring_view templateDirectory, std::wstring_view newDirectory, bool result) = 0; + virtual void OnCreateFileTransactedA(std::string_view fileName, uint32_t desiredAccess, uint32_t shareMode, uint64_t result) = 0; + virtual void OnCreateFileTransactedW(std::wstring_view fileName, uint32_t desiredAccess, uint32_t shareMode, uint64_t result) = 0; + virtual void OnCreateHardLinkA(std::string_view fileName, std::string_view existingFileName, bool result) = 0; + virtual void OnCreateHardLinkW(std::wstring_view fileName, std::wstring_view existingFileName, bool result) = 0; + virtual void OnCreateHardLinkTransactedA(std::string_view fileName, std::string_view existingFileName, bool result) = 0; + virtual void OnCreateHardLinkTransactedW(std::wstring_view fileName, std::wstring_view existingFileName, bool result) = 0; + virtual void OnCreateProcessWithLogonW(std::wstring_view applicationName, bool result) = 0; + virtual void OnCreateProcessWithTokenW(std::wstring_view applicationName, bool result) = 0; + virtual void OnCreateSymbolicLinkA(std::string_view symlinkFileName, std::string_view targetFileName, uint32_t flags, bool result) = 0; + virtual void OnCreateSymbolicLinkW(std::wstring_view symlinkFileName, std::wstring_view targetFileName, uint32_t flags, bool result) = 0; + virtual void OnCreateSymbolicLinkTransactedA(std::string_view symlinkFileName, std::string_view targetFileName, uint32_t flags, bool result) = 0; + virtual void OnCreateSymbolicLinkTransactedW(std::wstring_view symlinkFileName, std::wstring_view targetFileName, uint32_t flags, bool result) = 0; + virtual void OnDecryptFileA(std::string_view fileName, bool result) = 0; + virtual void OnDecryptFileW(std::wstring_view fileName, bool result) = 0; + virtual void OnDeleteFileTransactedA(std::string_view fileName, bool result) = 0; + virtual void OnDeleteFileTransactedW(std::wstring_view fileName, bool result) = 0; + virtual void OnEncryptFileA(std::string_view fileName, bool result) = 0; + virtual void OnEncryptFileW(std::wstring_view fileName, bool result) = 0; + virtual void OnFileEncryptionStatusA(std::string_view fileName, bool result) = 0; + virtual void OnFileEncryptionStatusW(std::wstring_view fileName, bool result) = 0; + virtual void OnFindFirstFileNameTransactedW(std::wstring_view fileName, bool result) = 0; + virtual void OnFindFirstFileTransactedA(std::string_view fileName) = 0; + virtual void OnFindFirstFileTransactedW(std::wstring_view fileName) = 0; + virtual void OnFindFirstStreamTransactedW(std::wstring_view fileName) = 0; + virtual void OnGetBinaryTypeA(std::string_view applicationName, bool result) = 0; + virtual void OnGetBinaryTypeW(std::wstring_view applicationName, bool result) = 0; + virtual void OnGetCompressedFileSizeTransactedA(std::string_view fileName, uint32_t result) = 0; + virtual void OnGetCompressedFileSizeTransactedW(std::wstring_view fileName, uint32_t result) = 0; + virtual void OnGetDllDirectoryA(uint32_t result) = 0; + virtual void OnGetDllDirectoryW(uint32_t result) = 0; + virtual void OnGetFileAttributesTransactedA(std::string_view fileName, uint32_t result) = 0; + virtual void OnGetFileAttributesTransactedW(std::wstring_view fileName, uint32_t result) = 0; + virtual void OnGetFileBandwidthReservation(bool result) = 0; + virtual void OnGetFileInformationByHandleEx(bool result) = 0; + virtual void OnGetFileSecurityA(std::string_view fileName, bool result) = 0; + virtual void OnGetFullPathNameTransactedA(std::string_view fileName, uint32_t result) = 0; + virtual void OnGetFullPathNameTransactedW(std::wstring_view fileName, uint32_t result) = 0; + virtual void OnGetLongPathNameTransactedA(std::string_view shortPath, std::string_view longPath, uint32_t result) = 0; + virtual void OnGetLongPathNameTransactedW(std::wstring_view shortPath, std::wstring_view longPath, uint32_t result) = 0; + virtual void OnGetQueuedCompletionStatus(bool result) = 0; + virtual void OnGetQueuedCompletionStatusEx(bool result) = 0; + virtual void OnGetShortPathNameA(std::string_view longPath, std::string_view shortPath, uint32_t result) = 0; + virtual void OnLoadModule(std::string_view moduleName, uint32_t result) = 0; + virtual void OnLoadPackagedLibrary(std::string_view libFileName) = 0; + virtual void OnMoveFileA(std::string_view existingFileName, std::string_view newFileName, bool result) = 0; + virtual void OnMoveFileW(std::wstring_view existingFileName, std::wstring_view newFileName, bool result) = 0; + virtual void OnMoveFileExA(std::string_view existingFileName, std::string_view newFileName, uint32_t flags, bool result) = 0; + virtual void OnMoveFileExW(std::wstring_view existingFileName, std::wstring_view newFileName, uint32_t flags, bool result) = 0; + virtual void OnMoveFileTransactedA(std::string_view existingFileName, std::string_view newFileName, uint32_t flags, bool result) = 0; + virtual void OnMoveFileTransactedW(std::wstring_view existingFileName, std::wstring_view newFileName, uint32_t flags, bool result) = 0; + virtual void OnMoveFileWithProgressA(std::string_view existingFileName, std::string_view newFileName, uint32_t flags, bool result) = 0; + virtual void OnMoveFileWithProgressW(std::wstring_view existingFileName, std::wstring_view newFileName, uint32_t flags, bool result) = 0; + virtual void OnOpenEncryptedFileRawA(std::string_view fileName, uint32_t flags, uint32_t result) = 0; + virtual void OnOpenEncryptedFileRawW(std::wstring_view fileName, uint32_t flags, uint32_t result) = 0; + virtual void OnOpenFile(std::string_view fileName) = 0; + virtual void OnOpenFileById() = 0; + virtual void OnReadEncryptedFileRaw(uint32_t result) = 0; + virtual void OnRemoveDirectoryTransactedA(std::string_view pathName, bool result) = 0; + virtual void OnRemoveDirectoryTransactedW(std::wstring_view pathName, bool result) = 0; + virtual void OnReOpenFile() = 0; + virtual void OnReplaceFileA(std::string_view replacedFileName, std::string_view replacementFileName, std::string_view backupFileName, uint32_t replaceFlags, bool result) = 0; + virtual void OnReplaceFileW(std::wstring_view replacedFileName, std::wstring_view replacementFileName, std::wstring_view backupFileName, uint32_t replaceFlags, bool result) = 0; + virtual void OnSetCurrentDirectoryA(std::string_view pathName, bool result) = 0; + virtual void OnSetCurrentDirectoryW(std::wstring_view pathName, bool result) = 0; + virtual void OnSetDllDirectoryA(std::string_view pathName, bool result) = 0; + virtual void OnSetDllDirectoryW(std::wstring_view pathName, bool result) = 0; + virtual void OnSetFileAttributesTransactedA(std::string_view pathName, uint32_t fileAttributes, bool result) = 0; + virtual void OnSetFileAttributesTransactedW(std::wstring_view pathName, uint32_t fileAttributes, bool result) = 0; + virtual void OnSetFileBandwidthReservation(bool result) = 0; + virtual void OnSetFileCompletionNotificationModes(bool result) = 0; + virtual void OnSetFileSecurityA(std::string_view fileName, bool result) = 0; + virtual void OnSetFileShortNameA(std::string_view shortName, bool result) = 0; + virtual void OnSetFileShortNameW(std::wstring_view shortName, bool result) = 0; + virtual void OnSetSearchPathMode(uint32_t flags, bool result) = 0; + virtual void OnWriteEncryptedFileRaw(uint32_t result) = 0; + }; +} diff --git a/Source/Monitor/Shared/IDetourProcessManager.h b/Source/Monitor/Shared/IDetourProcessManager.h new file mode 100644 index 00000000..4a52ba85 --- /dev/null +++ b/Source/Monitor/Shared/IDetourProcessManager.h @@ -0,0 +1,50 @@ +// +// Copyright (c) Soup. All rights reserved. +// + +#pragma once +#include "IDetourCallback.h" + +namespace Monitor +{ + /// + /// The process manager interface that supports detour callbacks + /// Interface mainly used to allow for unit testing client code + /// + export class IDetourProcessManager + { + public: + /// + /// Gets the current active process manager + /// + static IDetourProcessManager& Current() + { + if (_current == nullptr) + throw std::runtime_error("No detour process manager implementation registered."); + return *_current; + } + + /// + /// Register a new active process manager + /// + static void Register(std::shared_ptr value) + { + _current = std::move(value); + } + + public: + /// + /// Creates a process for the provided executable path + /// + virtual std::shared_ptr CreateDetourProcess( + const Path& executable, + const std::string& arguments, + const Path& workingDirectory, + std::shared_ptr callback) = 0; + + private: + static std::shared_ptr _current; + }; + + std::shared_ptr IDetourProcessManager::_current = nullptr; +} diff --git a/Source/Monitor/Shared/MockDetourProcessManager.h b/Source/Monitor/Shared/MockDetourProcessManager.h new file mode 100644 index 00000000..f587304f --- /dev/null +++ b/Source/Monitor/Shared/MockDetourProcessManager.h @@ -0,0 +1,87 @@ +// +// Copyright (c) Soup. All rights reserved. +// + +#pragma once +#include "IDetourProcessManager.h" + +namespace Monitor +{ + /// + /// The mock detour process manager + /// TODO: Move into test project + /// + export class MockDetourProcessManager : public IDetourProcessManager + { + public: + /// + /// Initializes a new instance of the class. + /// + MockDetourProcessManager() : + m_uniqueId(1), + _requests(), + _executeResults() + { + } + + /// + /// Create a result + /// + void RegisterExecuteResult(std::string command, std::string output) + { + _executeResults.emplace( + std::move(command), + std::move(output)); + } + + /// + /// Get the load requests + /// + const std::vector& GetRequests() const + { + return _requests; + } + + /// + /// Creates a process for the provided executable path + /// + std::shared_ptr CreateDetourProcess( + const Path& executable, + const std::string& arguments, + const Path& workingDirectory, + std::shared_ptr callback) override final + { + std::stringstream message; + auto id = m_uniqueId++; + message << "CreateDetourProcess: " << id << " [" << workingDirectory.ToString() << "] " << executable.ToString() << " " << arguments; + + _requests.push_back(message.str()); + + // Check if there is a registered output + auto findOutput = _executeResults.find(message.str()); + if (findOutput != _executeResults.end()) + { + return std::make_shared( + id, + _requests, + 0, + findOutput->second, + std::string()); + } + else + { + return std::make_shared( + id, + _requests, + 0, + std::string(), + std::string()); + } + } + + private: + std::atomic m_uniqueId; + std::vector _requests; + std::map _executeResults; + }; +} diff --git a/Source/Monitor/Shared/Module.cpp b/Source/Monitor/Shared/Module.cpp new file mode 100644 index 00000000..4c54c161 --- /dev/null +++ b/Source/Monitor/Shared/Module.cpp @@ -0,0 +1,283 @@ +module; + +#include + +#ifdef CreateProcess +#undef CreateProcess +#endif + +#include +#include +#include +#pragma warning(push) +#if _MSC_VER > 1400 +#pragma warning(disable:6102 6103) +#endif +#include +#pragma warning(pop) + +#include +#include +#include +#include +#include +#include +#include +#include + +export module Monitor.Shared; +import Detours; +import Opal; + +using namespace Opal; + +export constexpr const char* TBLOG_PIPE_NAMEA = "\\\\.\\pipe\\tracebuild"; +export constexpr const wchar_t* TBLOG_PIPE_NAMEW = L"\\\\.\\pipe\\tracebuild"; +#ifdef UNICODE +export constexpr const char* TBLOG_PIPE_NAME = TBLOG_PIPE_NAMEW; +#else +export constexpr const char* TBLOG_PIPE_NAME = TBLOG_PIPE_NAMEA; +#endif + +namespace Monitor +{ + export enum class DetourMessageType : uint32_t + { + Info_Shutdown, + Info_Error, + + // FileApi + AreFileApisANSI, + CompareFileTime, + CreateDirectoryA, + CreateDirectoryW, + CreateFile2, + CreateFileA, + CreateFileW, + DefineDosDeviceW, + DeleteFileA, + DeleteFileW, + DeleteVolumeMountPointW, + FileTimeToLocalFileTime, + FindClose, + FindCloseChangeNotification, + FindFirstChangeNotificationA, + FindFirstChangeNotificationW, + FindFirstFileA, + FindFirstFileW, + FindFirstFileExA, + FindFirstFileExW, + FindFirstFileNameW, + FindFirstStreamW, + FindFirstVolumeW, + FindNextChangeNotification, + FindNextFileA, + FindNextFileW, + FindNextFileNameW, + FindNextStreamW, + FindNextVolumeW, + FindVolumeClose, + FlushFileBuffers, + GetCompressedFileSizeA, + GetCompressedFileSizeW, + GetDiskFreeSpaceA, + GetDiskFreeSpaceW, + GetDiskFreeSpaceExA, + GetDiskFreeSpaceExW, + GetDriveTypeA, + GetDriveTypeW, + GetFileAttributesA, + GetFileAttributesW, + GetFileAttributesExA, + GetFileAttributesExW, + GetFileInformationByHandle, + GetFileSize, + GetFileSizeEx, + GetFileTime, + GetFileType, + GetFinalPathNameByHandleA, + GetFinalPathNameByHandleW, + GetFullPathNameA, + GetFullPathNameW, + GetLogicalDrives, + GetLogicalDriveStringsW, + GetLongPathNameA, + GetLongPathNameW, + GetShortPathNameW, + GetTempFileNameA, + GetTempFileNameW, + GetTempPathA, + GetTempPathW, + GetVolumeInformationA, + GetVolumeInformationW, + GetVolumeInformationByHandleW, + GetVolumeNameForVolumeMountPointW, + GetVolumePathNamesForVolumeNameW, + GetVolumePathNameW, + LocalFileTimeToFileTime, + LockFile, + LockFileEx, + QueryDosDeviceW, + ReadFile, + ReadFileEx, + ReadFileScatter, + RemoveDirectoryA, + RemoveDirectoryW, + SetEndOfFile, + SetFileApisToANSI, + SetFileApisToOEM, + SetFileAttributesA, + SetFileAttributesW, + SetFileInformationByHandle, + SetFileIoOverlappedRange, + SetFilePointer, + SetFilePointerEx, + SetFileTime, + SetFileValidData, + UnlockFile, + UnlockFileEx, + WriteFile, + WriteFileEx, + WriteFileGather, + + // LibLoaderApi + LoadLibraryA, + LoadLibraryW, + LoadLibraryExA, + LoadLibraryExW, + + // ProcessEnv + SearchPathA, + SearchPathW, + + // ProcessThreadsApi + CreateProcessA, + CreateProcessW, + CreateProcessAsUserA, + CreateProcessAsUserW, + ExitProcess, + + // UndocumentedApi + PrivCopyFileExA, + PrivCopyFileExW, + + // WinBase + CopyFileA, + CopyFileW, + CopyFile2, + CopyFileExA, + CopyFileExW, + CopyFileTransactedA, + CopyFileTransactedW, + CreateDirectoryExA, + CreateDirectoryExW, + CreateDirectoryTransactedA, + CreateDirectoryTransactedW, + CreateFileTransactedA, + CreateFileTransactedW, + CreateHardLinkA, + CreateHardLinkW, + CreateHardLinkTransactedA, + CreateHardLinkTransactedW, + CreateProcessWithLogonW, + CreateProcessWithTokenW, + CreateSymbolicLinkA, + CreateSymbolicLinkW, + CreateSymbolicLinkTransactedA, + CreateSymbolicLinkTransactedW, + DecryptFileA, + DecryptFileW, + DeleteFileTransactedA, + DeleteFileTransactedW, + EncryptFileA, + EncryptFileW, + FileEncryptionStatusA, + FileEncryptionStatusW, + FindFirstFileNameTransactedW, + FindFirstFileTransactedA, + FindFirstFileTransactedW, + FindFirstStreamTransactedW, + GetBinaryTypeA, + GetBinaryTypeW, + GetCompressedFileSizeTransactedA, + GetCompressedFileSizeTransactedW, + GetDllDirectoryA, + GetDllDirectoryW, + GetFileAttributesTransactedA, + GetFileAttributesTransactedW, + GetFileBandwidthReservation, + GetFileInformationByHandleEx, + GetFileSecurityA, + GetFullPathNameTransactedA, + GetFullPathNameTransactedW, + GetLongPathNameTransactedA, + GetLongPathNameTransactedW, + GetQueuedCompletionStatus, + GetQueuedCompletionStatusEx, + GetShortPathNameA, + LoadModule, + LoadPackagedLibrary, + MoveFileA, + MoveFileW, + MoveFileExA, + MoveFileExW, + MoveFileTransactedA, + MoveFileTransactedW, + MoveFileWithProgressA, + MoveFileWithProgressW, + OpenEncryptedFileRawA, + OpenEncryptedFileRawW, + OpenFile, + OpenFileById, + ReadEncryptedFileRaw, + RemoveDirectoryTransactedA, + RemoveDirectoryTransactedW, + ReOpenFile, + ReplaceFileA, + ReplaceFileW, + SetCurrentDirectoryA, + SetCurrentDirectoryW, + SetDllDirectoryA, + SetDllDirectoryW, + SetFileAttributesTransactedA, + SetFileAttributesTransactedW, + SetFileBandwidthReservation, + SetFileCompletionNotificationModes, + SetFileSecurityA, + SetFileShortNameA, + SetFileShortNameW, + SetSearchPathMode, + WriteEncryptedFileRaw, + }; + + export struct DetourMessage + { + DetourMessageType Type; + uint32_t ContentSize; + byte Content[2048 - sizeof(Type) - sizeof(ContentSize)]; + }; + + export struct DetourPayload + { + DWORD nParentProcessId; + DWORD nTraceProcessId; + DWORD nGeneology; + DWORD rGeneology[64]; + WCHAR wzParents[256]; + }; + + // Shared state payload guid. + // + export constexpr GUID GuidTrace = { 0xd8e2dc69, 0x3004, 0x453e, { 0x94, 0x15, 0x19, 0x0e, 0x79, 0xe8, 0x93, 0x52 } }; +} + +export void ThrowIfFailed(int32_t result, std::string_view message) +{ + if (result != NO_ERROR) + { + throw std::runtime_error(message.data()); + } +} + +#include "MockDetourProcessManager.h" +#include "WindowsDetourProcessManager.h" \ No newline at end of file diff --git a/Source/Monitor/Shared/Recipe.toml b/Source/Monitor/Shared/Recipe.toml new file mode 100644 index 00000000..a2655f50 --- /dev/null +++ b/Source/Monitor/Shared/Recipe.toml @@ -0,0 +1,7 @@ +Name = "Monitor.Shared" +Version = "1.0.0" +Dependencies = [ + "../../../Dependencies/Detours/src/", + "../../../Dependencies/Opal/Source/", +] +Public = "Module.cpp" diff --git a/Source/Monitor/Shared/WindowsDetourProcess.h b/Source/Monitor/Shared/WindowsDetourProcess.h new file mode 100644 index 00000000..d6812edb --- /dev/null +++ b/Source/Monitor/Shared/WindowsDetourProcess.h @@ -0,0 +1,684 @@ +// +// Copyright (c) Soup. All rights reserved. +// + +#pragma once +#include "EventListener.h" + +namespace Monitor +{ + /// + /// The Pipe Server Instance that keeps track of the required state for each individual connection + /// to a client. + /// + struct ServerPipeInstance + { + OVERLAPPED Overlap; + Opal::System::SmartHandle EventHandle; + Opal::System::SmartHandle PipeHandle; + DetourMessage Message; + bool IsConnected; + bool HasPendingIO; + }; + + /// + /// A windows platform specific detour process executable + /// + export class WindowsDetourProcess : public Opal::System::IProcess + { + public: + /// + /// Initializes a new instance of the class. + /// + WindowsDetourProcess( + const Path& executable, + const std::string& arguments, + const Path& workingDirectory, + std::shared_ptr callback) : + m_executable(executable), + m_arguments(arguments), + m_workingDirectory(workingDirectory), + m_eventListener(std::move(callback)), + m_pipes(), + m_rawEventHandles(), + m_workerThread(), + m_workerFailed(false), + m_threadHandle(), + m_processHandle(), + m_stdOutReadHandle(), + m_stdOutWriteHandle(), + m_stdErrReadHandle(), + m_stdErrWriteHandle(), + m_stdInReadHandle(), + m_stdInWriteHandle(), + m_isFinished(false), + m_stdOut(), + m_stdErr(), + m_exitCode(-1) + { + } + + /// + /// Execute a process for the provided + /// + void Start() override final + { + DebugTrace("Start"); + std::stringstream argumentsValue; + argumentsValue << "\"" << m_executable.ToAlternateString() << "\"" << " " << m_arguments; + std::string argumentsString = argumentsValue.str(); + + // Setup the input/output streams + // TODO: We need to read from the buffer to ensure it doesn't deadlock on the wait forever + int pipeBufferSize = 5 * 1024 * 1024; + + // Set the bInheritHandle flag so pipe handles are inherited. + SECURITY_ATTRIBUTES securityAttributes; + securityAttributes.nLength = sizeof(SECURITY_ATTRIBUTES); + securityAttributes.bInheritHandle = true; + securityAttributes.lpSecurityDescriptor = nullptr; + + // Create a pipe for the child process's STDOUT. + HANDLE childStdOutRead; + HANDLE childStdOutWrite; + if (!CreatePipe(&childStdOutRead, &childStdOutWrite, &securityAttributes, pipeBufferSize)) + throw std::runtime_error("Execute CreatePipe Failed"); + m_stdOutReadHandle = Opal::System::SmartHandle(childStdOutRead); + m_stdOutWriteHandle = Opal::System::SmartHandle(childStdOutWrite); + + // Ensure the read handle to the pipe for STDOUT is not inherited. + if (!SetHandleInformation(m_stdOutReadHandle.Get(), HANDLE_FLAG_INHERIT, 0)) + throw std::runtime_error("Execute SetHandleInformation Failed"); + + // Create a pipe for the child process's STDERR. + HANDLE childStdErrRead; + HANDLE childStdErrWrite; + if (!CreatePipe(&childStdErrRead, &childStdErrWrite, &securityAttributes, pipeBufferSize)) + throw std::runtime_error("Execute CreatePipe Failed"); + m_stdErrReadHandle = Opal::System::SmartHandle(childStdErrRead); + m_stdErrWriteHandle = Opal::System::SmartHandle(childStdErrWrite); + + // Ensure the read handle to the pipe for STDERR is not inherited. + if (!SetHandleInformation(m_stdErrReadHandle.Get(), HANDLE_FLAG_INHERIT, 0)) + throw std::runtime_error("Execute SetHandleInformation Failed"); + + // Create a pipe for the child process's STDIN. + HANDLE childStdInRead; + HANDLE childStdInWrite; + if (!CreatePipe(&childStdInRead, &childStdInWrite, &securityAttributes, 0)) + throw std::runtime_error("Execute CreatePipe Failed"); + m_stdInReadHandle = Opal::System::SmartHandle(childStdInRead); + m_stdInWriteHandle = Opal::System::SmartHandle(childStdInWrite); + + // Ensure the write handle to the pipe for STDIN is not inherited. + if (!SetHandleInformation(m_stdInWriteHandle.Get(), HANDLE_FLAG_INHERIT, 0)) + throw std::runtime_error("Execute SetHandleInformation Failed"); + + // Create the worker thread that will act as the pipe server + m_processRunning = true; + m_workerFailed = false; + m_workerThread = std::thread(&WindowsDetourProcess::WorkerThread, std::ref(*this)); + + // Build up the detour dlls absolute path + auto moduleName = System::IProcessManager::Current().GetCurrentProcessFileName(); + auto moduleFolder = moduleName.GetParent(); + auto dllPath = moduleFolder + Path("Monitor.Detours.64.dll"); + auto dllPathString = dllPath.ToAlternateString(); + + // Setup the process creation parameters + LPSECURITY_ATTRIBUTES processAttributes = nullptr; + LPSECURITY_ATTRIBUTES threadAttributes = nullptr; + bool inheritHandles = true; + DWORD creationFlags = CREATE_DEFAULT_ERROR_MODE | CREATE_SUSPENDED; + void* environment = nullptr; + + STARTUPINFOA startupInfo = {}; + ZeroMemory(&startupInfo, sizeof(STARTUPINFOA)); + startupInfo.cb = sizeof(startupInfo); + startupInfo.hStdError = m_stdErrWriteHandle.Get(); + startupInfo.hStdOutput = m_stdOutWriteHandle.Get(); + startupInfo.hStdInput = m_stdInReadHandle.Get(); + startupInfo.dwFlags |= STARTF_USESTDHANDLES; + + PROCESS_INFORMATION processInfo = {}; + ZeroMemory(&processInfo, sizeof(PROCESS_INFORMATION)); + + // Create the requested process with our detour dll loaded + if (!DetourCreateProcessWithDllExA( + m_executable.ToString().c_str(), + argumentsString.data(), + processAttributes, + threadAttributes, + inheritHandles, + creationFlags, + environment, + m_workingDirectory.ToString().c_str(), + &startupInfo, + &processInfo, + dllPathString.c_str(), + nullptr)) + { + auto error = GetLastError(); + switch (error) + { + case ERROR_FILE_NOT_FOUND: + throw std::runtime_error("Execute DetourCreateProcessWithDllExA the requested executable does not exist"); + default: + throw std::runtime_error("Execute DetourCreateProcessWithDllExA Failed: " + std::to_string(error)); + } + } + + // Store the runtime handles + m_processHandle = Opal::System::SmartHandle(processInfo.hProcess); + m_threadHandle = Opal::System::SmartHandle(processInfo.hThread); + + // Set the detoured process payload + DetourPayload payload; + ZeroMemory(&payload, sizeof(payload)); + payload.nParentProcessId = GetCurrentProcessId(); + payload.nTraceProcessId = GetCurrentProcessId(); + payload.nGeneology = 1; + payload.rGeneology[0] = 0; + payload.wzParents[0] = 0; + if (!DetourCopyPayloadToProcess( + m_processHandle.Get(), + GuidTrace, + &payload, + sizeof(payload))) + { + throw std::runtime_error("DetourCopyPayloadToProcess failed: " + std::to_string(GetLastError())); + } + + // Restart the process + auto hr = ResumeThread(m_threadHandle.Get()); + } + + /// + /// Wait for the process to exit + /// + void WaitForExit() override final + { + // Wait until child process exits. + DebugTrace("WaitForExit"); + auto waitResult = WaitForSingleObject(m_processHandle.Get(), INFINITE); + DebugTrace("WaitForExit Signal"); + m_processRunning = false; + switch (waitResult) + { + case WAIT_OBJECT_0: + // All good + break; + case WAIT_ABANDONED: + throw std::runtime_error("Execute WaitForSingleObject Abandoned"); + break; + case WAIT_TIMEOUT: + throw std::runtime_error("Execute WaitForSingleObject Timeout"); + break; + case WAIT_FAILED: + throw std::runtime_error("Execute WaitForSingleObject Failed: " + std::to_string(GetLastError())); + break; + default: + throw std::runtime_error("Execute WaitForSingleObject Failed Unknown"); + } + + // Get the exit code + DWORD exitCode; + if (!GetExitCodeProcess(m_processHandle.Get(), &exitCode)) + { + auto error = GetLastError(); + throw std::runtime_error("Execute GetExitCodeProcess Failed: " + std::to_string(error)); + } + m_exitCode = exitCode; + + // Close the child write handle to ensure we stop reading + m_stdOutWriteHandle.Close(); + m_stdErrWriteHandle.Close(); + + // Read all and write to stdout + // TODO: May want to switch over to a background thread with peak to read in order + DWORD dwRead = -1; + const int BufferSize = 256; + char buffer[BufferSize + 1]; + + // Read on output + while (true) + { + if(!ReadFile(m_stdOutReadHandle.Get(), buffer, BufferSize, &dwRead, nullptr)) + break; + if (dwRead == 0) + break; + + m_stdOut << std::string_view(buffer, dwRead); + } + + // Read all errors + while (true) + { + if(!ReadFile(m_stdErrReadHandle.Get(), buffer, BufferSize, &dwRead, nullptr)) + break; + if (dwRead == 0) + break; + + // Make the string null terminated + m_stdErr << std::string_view(buffer, dwRead); + } + + // Wait for the worker thread to exit + m_workerThread.join(); + + if (m_workerFailed) + { + std::rethrow_exception(m_workerException); + } + + m_isFinished = true; + } + + /// + /// Get the exit code + /// + int GetExitCode() override final + { + if (!m_isFinished) + throw std::runtime_error("Process has not finished."); + return m_exitCode; + } + + /// + /// Get the standard output + /// + std::string GetStandardOutput() override final + { + if (!m_isFinished) + throw std::runtime_error("Process has not finished."); + return m_stdOut.str(); + } + + /// + /// Get the standard error output + /// + std::string GetStandardError() override final + { + if (!m_isFinished) + throw std::runtime_error("Process has not finished."); + return m_stdErr.str(); + } + + private: + /// + /// The main entry point for the worker thread that will monitor incoming messages from all + /// client connections. + /// + void WorkerThread() + { + try + { + DebugTrace("WorkerThread Start"); + InitializePipes(); + + // Read until we get a client and then all clients disconnect + m_hasAnyClients = false; + m_activeClientCount = 0; + while (!m_hasAnyClients || m_activeClientCount > 0) + { + // Wait for any of the pipe instances to signal + // This indicates that either a client connected to wrote to + // and open connection. + // Check every 5 seconds if the process has terminated unexpectedly + bool waitForAll = false; + DWORD timoutMilliseconds = 5000; + DebugTrace("WorkerThread WaitForMultipleObjects"); + auto waitResult = WaitForMultipleObjects( + m_rawEventHandles.size(), + m_rawEventHandles.data(), + waitForAll, + timoutMilliseconds); + switch (waitResult) + { + case WAIT_TIMEOUT: + if (!m_processRunning) + { + throw std::runtime_error("The child process exited unexpectedly"); + } + else + { + // The process hasn't done anything for awhile. + // Continue waiting... + continue; + } + + case WAIT_FAILED: + throw std::runtime_error("WaitForMultipleObjects failed: " + std::to_string(GetLastError())); + } + + // Determine which pipe completed the operation. + auto pipeIndex = waitResult - WAIT_OBJECT_0; + if (pipeIndex < 0 || pipeIndex > (m_rawEventHandles.size() - 1)) + { + throw std::runtime_error("The event signaled outside the range of pipes"); + } + + // Handle the event + DebugTrace(std::to_string(pipeIndex)); + HandlePipeEvent(m_pipes[pipeIndex]); + } + } + catch (...) + { + DebugTrace("WorkerThread Failed"); + m_workerException = std::current_exception(); + m_workerFailed = true; + } + + // Cleanup + CleanupConnections(); + } + + /// + /// Initialize the default set of connections + /// + void InitializePipes() + { + DebugTrace("InitializePipes"); + for (int i = 0; i < m_pipes.size(); i++) + { + // Create an unamed event object for this instance that is in the signaled state + SECURITY_ATTRIBUTES* eventAttributes = nullptr; + bool isManualReset = true; + bool initialState = true; + const char* eventName = nullptr; + auto eventHandle = CreateEventA( + eventAttributes, + isManualReset, + initialState, + eventName); + if (eventHandle == NULL) + { + throw std::runtime_error("CreateEventA failed: " + std::to_string(GetLastError())); + } + + // Save the event handle on the pipe instance and register it in the raw array to + // allow for wait all calls and finally register this event in he overlap object + // so it will be signaled during overlapped calls to the pipe object + m_pipes[i].EventHandle = Opal::System::SmartHandle(eventHandle); + m_rawEventHandles[i] = m_pipes[i].EventHandle.Get(); + m_pipes[i].Overlap.hEvent = m_pipes[i].EventHandle.Get(); + + // Create the new pipe object instance + m_pipes[i].PipeHandle = CreateNamedPipeInstance(); + + // Create the connection so the clients can connect + // Note: This call will either connect to a client or initialize the event to notify + // when a client is connected. + ConnectToNewClient(m_pipes[i]); + } + } + + /// + /// Create a single instance of the named pipe that will allow a + /// single client to connect to the pipe server. + /// + Opal::System::SmartHandle CreateNamedPipeInstance() + { + // Create a name for the pipe + DebugTrace("CreateNamedPipeInstance"); + std::stringstream pipeName; + pipeName << TBLOG_PIPE_NAMEA << "." << GetCurrentProcessId(); + std::string pipeNameString = pipeName.str(); + + // Open in Read-Only mode with overlapped operations enabled + // Turn on message type pipe in read mode with blocking waits + DWORD openMode = PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED; + DWORD pipeMode = PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT; + DWORD maxInstances = PIPE_UNLIMITED_INSTANCES; + DWORD outBufferSize = 0; + DWORD inBufferSize = 0; + DWORD defaultTimeOut = 20000; + HANDLE hPipe = CreateNamedPipeA( + pipeNameString.c_str(), + openMode, + pipeMode, + maxInstances, + outBufferSize, + inBufferSize, + defaultTimeOut, + nullptr); + if (hPipe == INVALID_HANDLE_VALUE) + { + DWORD error = GetLastError(); + throw std::runtime_error("CreateNamedPipeA failed: " + std::to_string(error)); + } + + return Opal::System::SmartHandle(hPipe); + } + + /// + /// Attempt to connect to a new client or register the event callback when a client + /// connects in the future. + /// + void ConnectToNewClient(ServerPipeInstance& pipe) + { + // Connect to the pipe + DebugTrace("ConnectNamedPipe"); + if (ConnectNamedPipe(pipe.PipeHandle.Get(), &pipe.Overlap)) + { + // Asynchronous call to Connect Named Pipe always return zero + throw std::runtime_error("ConnectNamedPipe should not succeed."); + } + + // Check the error to determine the actual result + DWORD error = GetLastError(); + switch (error) + { + case ERROR_PIPE_CONNECTED: + // The client connected in the time between create named pipe and connect + // Rare, but possible. + DebugTrace("ConnectNamedPipe - Connected"); + pipe.IsConnected = true; + pipe.HasPendingIO = false; + m_hasAnyClients = true; + m_activeClientCount++; + + // Signal the event manually to force the update loop to signal on wait all events + if (!SetEvent(pipe.EventHandle.Get())) + { + throw std::runtime_error("Client already connected -> SetEvent failed: " + std::to_string(GetLastError())); + } + + break; + case ERROR_IO_PENDING: + DebugTrace("ConnectNamedPipe - Pending"); + pipe.IsConnected = false; + pipe.HasPendingIO = true; + break; + default: + throw std::runtime_error("ConnectNamedPipe failed: " + std::to_string(error)); + } + } + + /// + /// Disconnect from a client and reset the pipe to prepare for a new client to connect. + /// + VOID DisconnectAndReconnect(ServerPipeInstance& pipe) + { + // Disconnect the old pipe instance + DebugTrace("DisconnectAndReconnect"); + if (!DisconnectNamedPipe(pipe.PipeHandle.Get())) + { + throw std::runtime_error("DisconnectNamedPipe failed: " + std::to_string(GetLastError())); + } + + m_activeClientCount--; + + // Connect to a new client + ConnectToNewClient(pipe); + } + + void HandlePipeEvent(ServerPipeInstance& pipe) + { + // Check if a pending IO operation requires a call to get Overlapped result + DebugTrace("HandlePipeEvent"); + if (pipe.HasPendingIO) + { + bool shouldWait = false; + DWORD bytesTransferred = 0; + DebugTrace("HandlePipeEvent - GetOverlappedResult"); + bool overlappedResult = GetOverlappedResult( + pipe.PipeHandle.Get(), + &pipe.Overlap, + &bytesTransferred, + shouldWait); + + if (!pipe.IsConnected) + { + if (!overlappedResult) + { + throw std::runtime_error("GetOverlappedResult failed when connecting: " + std::to_string(GetLastError())); + } + + // Connected to a new client + // Fall through and perform an initial read check + DebugTrace("HandlePipeEvent - GetOverlappedResult - Connected"); + pipe.IsConnected = true; + m_hasAnyClients = true; + m_activeClientCount++; + } + else + { + // Check if the client is gone + DebugTrace("HandlePipeEvent - GetOverlappedResult - Read Finished"); + if (!overlappedResult || bytesTransferred == 0) + { + DebugTrace("HandlePipeEvent - GetOverlappedResult - Error: " + std::to_string(GetLastError())); + DisconnectAndReconnect(pipe); + return; + } + + DWORD expectedSize = pipe.Message.ContentSize + + sizeof(Monitor::DetourMessage::Type) + + sizeof(Monitor::DetourMessage::ContentSize); + if (bytesTransferred != expectedSize) + { + DebugTrace("HandlePipeEvent - GetOverlappedResult - Size Mismatched"); + DisconnectAndReconnect(pipe); + return; + } + + // Otherwise the Pending read has finished succesfully + LogMessage(pipe.Message); + } + } + + // If we are connected attempt to perform a read + if (pipe.IsConnected) + { + // Read the next message + DebugTrace("HandlePipeEvent - ReadFile"); + DWORD bytesRead = 0; + if (!ReadFile( + pipe.PipeHandle.Get(), + &pipe.Message, + sizeof(pipe.Message), + &bytesRead, + &pipe.Overlap)) + { + DWORD error = GetLastError(); + switch (error) + { + case ERROR_IO_PENDING: + DebugTrace("HandlePipeEvent - ReadFile - Pending"); + pipe.HasPendingIO = true; + break; + case ERROR_BROKEN_PIPE: + // The client is gone + DebugTrace("HandlePipeEvent - ReadFile - Pipe Ended"); + DisconnectAndReconnect(pipe); + break; + default: + // Unknown error + DebugTrace("HandlePipeEvent - ReadFile - Error: " + std::to_string(GetLastError())); + DisconnectAndReconnect(pipe); + break; + } + + return; + } + + if (bytesRead == 0) + { + throw std::runtime_error("Bytes read did not match expected"); + } + + DWORD expectedSize = pipe.Message.ContentSize + + sizeof(Monitor::DetourMessage::Type) + + sizeof(Monitor::DetourMessage::ContentSize); + if (bytesRead != expectedSize) + { + throw std::runtime_error("HandlePipeEvent - GetOverlappedResult - Size Mismatched"); + } + + LogMessage(pipe.Message); + pipe.HasPendingIO = false; + } + } + + void LogMessage(DetourMessage& message) + { + DebugTrace("LogMessage"); + m_eventListener.LogMessage(message); + } + + void CleanupConnections() + { + DebugTrace("CleanupConnections"); + for (int i = 0; i < m_pipes.size(); i++) + { + m_pipes[i].EventHandle.Close(); + m_rawEventHandles[i] = NULL; + m_pipes[i].Overlap.hEvent = NULL; + m_pipes[i].PipeHandle.Close(); + } + } + + void DebugTrace(std::string_view message) + { +// #define TRACE_DETOUR_SERVER +#ifdef TRACE_DETOUR_SERVER + std::cout << message << std::endl; +#endif + } + + private: + // Input + Path m_executable; + std::string m_arguments; + Path m_workingDirectory; + EventListener m_eventListener; + + // Runtime + std::thread m_workerThread; + std::array m_pipes; + std::array m_rawEventHandles; + bool m_hasAnyClients; + int m_activeClientCount; + + std::atomic m_processRunning; + std::atomic m_workerFailed; + std::exception_ptr m_workerException = nullptr; + + Opal::System::SmartHandle m_processHandle; + Opal::System::SmartHandle m_threadHandle; + Opal::System::SmartHandle m_stdOutReadHandle; + Opal::System::SmartHandle m_stdOutWriteHandle; + Opal::System::SmartHandle m_stdErrReadHandle; + Opal::System::SmartHandle m_stdErrWriteHandle; + Opal::System::SmartHandle m_stdInReadHandle; + Opal::System::SmartHandle m_stdInWriteHandle; + + // Result + bool m_isFinished; + std::stringstream m_stdOut; + std::stringstream m_stdErr; + int m_exitCode; + }; +} diff --git a/Source/Monitor/Shared/WindowsDetourProcessManager.h b/Source/Monitor/Shared/WindowsDetourProcessManager.h new file mode 100644 index 00000000..a5a7ac5d --- /dev/null +++ b/Source/Monitor/Shared/WindowsDetourProcessManager.h @@ -0,0 +1,40 @@ +// +// Copyright (c) Soup. All rights reserved. +// + +#pragma once +#include "IDetourProcessManager.h" +#include "WindowsDetourProcess.h" + +namespace Monitor +{ + /// + /// A windows splatform specific process executable using system + /// + export class WindowsDetourProcessManager : public IDetourProcessManager + { + public: + /// + /// Initializes a new instance of the class. + /// + WindowsDetourProcessManager() + { + } + + /// + /// Creates a process for the provided executable path + /// + std::shared_ptr CreateDetourProcess( + const Path& executable, + const std::string& arguments, + const Path& workingDirectory, + std::shared_ptr callback) override final + { + return std::make_shared( + executable, + arguments, + workingDirectory, + std::move(callback)); + } + }; +} diff --git a/Source/Monitor/Test/Main.cpp b/Source/Monitor/Test/Main.cpp new file mode 100644 index 00000000..72ff0359 --- /dev/null +++ b/Source/Monitor/Test/Main.cpp @@ -0,0 +1,11 @@ +#include +#include + +int main(int argc, char** argv) +{ + std::ofstream outfile("test.txt"); + outfile << "my text here!" << std::endl; + outfile.close(); + + return 0; +} \ No newline at end of file diff --git a/Source/Monitor/Test/Recipe.toml b/Source/Monitor/Test/Recipe.toml new file mode 100644 index 00000000..d3ced8e6 --- /dev/null +++ b/Source/Monitor/Test/Recipe.toml @@ -0,0 +1,6 @@ +Name = "Monitor.Test" +Version = "1.0.0" +Type = "Executable" +Source = [ + "Main.cpp", +] diff --git a/Source/TestUtilities/AssertExtensions.h b/Source/TestUtilities/AssertExtensions.h index 07ad9fff..5f814a20 100644 --- a/Source/TestUtilities/AssertExtensions.h +++ b/Source/TestUtilities/AssertExtensions.h @@ -10,8 +10,8 @@ namespace Soup { public: static void AreEqual( - Build::Extensions::BuildOperationWrapper& expected, - Build::Extensions::BuildOperationWrapper& actual) + Build::Utilities::BuildOperationWrapper& expected, + Build::Utilities::BuildOperationWrapper& actual) { Assert::AreEqual( expected.GetTitle(), @@ -42,26 +42,26 @@ namespace Soup } static void AreEqual( - Memory::Reference& expected, - Memory::Reference& actual) + Memory::Reference& expected, + Memory::Reference& actual) { AreEqual( - Build::Extensions::BuildOperationWrapper(expected), - Build::Extensions::BuildOperationWrapper(actual)); + Build::Utilities::BuildOperationWrapper(expected), + Build::Utilities::BuildOperationWrapper(actual)); } static void AreEqual( - Memory::Reference& expected, - Build::Extensions::BuildOperationWrapper& actual) + Memory::Reference& expected, + Build::Utilities::BuildOperationWrapper& actual) { AreEqual( - Build::Extensions::BuildOperationWrapper(expected), + Build::Utilities::BuildOperationWrapper(expected), actual); } static void AreEqual( - Build::Extensions::BuildOperationListWrapper& expected, - Build::Extensions::BuildOperationListWrapper& actual) + Build::Utilities::BuildOperationListWrapper& expected, + Build::Utilities::BuildOperationListWrapper& actual) { Assert::AreEqual( expected.GetSize(), @@ -75,8 +75,8 @@ namespace Soup } static void AreEqual( - std::vector>& expected, - std::vector& actual) + std::vector>& expected, + std::vector& actual) { Assert::AreEqual( expected.size(), diff --git a/Source/TestUtilities/Module.cpp b/Source/TestUtilities/Module.cpp index 39537e4d..53a6797f 100644 --- a/Source/TestUtilities/Module.cpp +++ b/Source/TestUtilities/Module.cpp @@ -10,7 +10,7 @@ export module SoupTestUtilities; import Opal; import SoupTest; import Soup.Build; -import Soup.Build.Extensions; +import Soup.Build.Utilities; using namespace Opal; using namespace SoupTest; diff --git a/Source/TestUtilities/Recipe.toml b/Source/TestUtilities/Recipe.toml index 07ffa67b..bd4356e2 100644 --- a/Source/TestUtilities/Recipe.toml +++ b/Source/TestUtilities/Recipe.toml @@ -5,6 +5,6 @@ Dependencies = [ "SoupTest@0.1.0", "../../Dependencies/Opal/Source/", # "Opal@0.1.2", - "../Build/Extensions/", + "../Build/Utilities/", ] Public = "Module.cpp" diff --git a/Source/Tools/Copy/Main.cpp b/Source/Tools/Copy/Main.cpp new file mode 100644 index 00000000..937756ec --- /dev/null +++ b/Source/Tools/Copy/Main.cpp @@ -0,0 +1,32 @@ +#include +#include +#include + +void PrintUsage() +{ + std::cout << "copy [source] [destination]" << std::endl; +} + +int main(int argc, char** argv) +{ + if (argc != 3) + { + PrintUsage(); + return 1; + } + + try + { + auto sourcePath = std::string_view(argv[1]); + auto destinationPath = std::string_view(argv[2]); + auto copyOptions = std::filesystem::copy_options::update_existing; + std::filesystem::copy(sourcePath, destinationPath, copyOptions); + } + catch(const std::exception& e) + { + std::cerr << e.what() << std::endl; + return 2; + } + + return 0; +} \ No newline at end of file diff --git a/Source/Tools/Copy/Recipe.toml b/Source/Tools/Copy/Recipe.toml new file mode 100644 index 00000000..104627de --- /dev/null +++ b/Source/Tools/Copy/Recipe.toml @@ -0,0 +1,6 @@ +Name = "copy" +Version = "1.0.0" +Type = "Executable" +Source = [ + "Main.cpp", +] diff --git a/Source/Tools/Mkdir/Main.cpp b/Source/Tools/Mkdir/Main.cpp new file mode 100644 index 00000000..d72d4103 --- /dev/null +++ b/Source/Tools/Mkdir/Main.cpp @@ -0,0 +1,53 @@ +#include +#include +#include + +void PrintUsage() +{ + std::cout << "mkdir [path]" << std::endl; +} + +void CreateDirectory(const std::filesystem::path& directory) +{ + std::error_code errorCode; + if (!std::filesystem::create_directory(directory, errorCode)) + { + if (!errorCode) + { + // The directory already existed + } + else if (errorCode == std::errc::no_such_file_or_directory) + { + // Create the parent recursively and then retry this folder + auto parentPath = directory.parent_path(); + CreateDirectory(parentPath); + std::filesystem::create_directory(directory); + } + else + { + throw std::system_error(errorCode); + } + } +} + +int main(int argc, char** argv) +{ + if (argc != 2) + { + PrintUsage(); + return 1; + } + + try + { + auto directory = std::string_view(argv[1]); + CreateDirectory(directory); + } + catch(const std::exception& e) + { + std::cerr << e.what() << std::endl; + return 2; + } + + return 0; +} \ No newline at end of file diff --git a/Source/Tools/Mkdir/Recipe.toml b/Source/Tools/Mkdir/Recipe.toml new file mode 100644 index 00000000..fdb20549 --- /dev/null +++ b/Source/Tools/Mkdir/Recipe.toml @@ -0,0 +1,6 @@ +Name = "mkdir" +Version = "1.0.0" +Type = "Executable" +Source = [ + "Main.cpp", +] diff --git a/init.cmd b/init.cmd index 1429f653..9c30b8c9 100644 --- a/init.cmd +++ b/init.cmd @@ -1,4 +1,3 @@ @echo off SET ROOT=%cd% -SET CONFIG=Debug SET PATH=%ROOT%\Scripts\;%PATH% \ No newline at end of file