From b0a75547f28ff50d7c7fa535a63f606acd17f47d Mon Sep 17 00:00:00 2001 From: isanae <14251494+isanae@users.noreply.github.com> Date: Sat, 3 Aug 2019 09:25:21 -0400 Subject: [PATCH 01/20] fixes a handle leak in the tracker because GetFileType() was called too late --- src/usvfs_dll/hooks/ntdll.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/usvfs_dll/hooks/ntdll.cpp b/src/usvfs_dll/hooks/ntdll.cpp index 4e3618a5..faa20fd9 100644 --- a/src/usvfs_dll/hooks/ntdll.cpp +++ b/src/usvfs_dll/hooks/ntdll.cpp @@ -1320,13 +1320,13 @@ NTSTATUS WINAPI usvfs::hook_NtClose(HANDLE Handle) } } + if (GetFileType(Handle) == FILE_TYPE_DISK) + ntdllHandleTracker.erase(Handle); + PRE_REALCALL res = ::NtClose(Handle); POST_REALCALL - if (GetFileType(Handle) == FILE_TYPE_DISK) - ntdllHandleTracker.erase(Handle); - if (log) { LOG_CALL().PARAM(Handle).PARAMWRAP(res); } From 52bb0f5ee1016693c042ee2ae2da0fd6b4a44184 Mon Sep 17 00:00:00 2001 From: isanae <14251494+isanae@users.noreply.github.com> Date: Thu, 5 Sep 2019 08:10:47 -0400 Subject: [PATCH 02/20] handle relative paths in the DeleteFileW() hook this is a targeted fix for the CK when saving files across drives usvfs has problems with relative paths and those are currently only handled manually in a few hooks as problems arise --- src/usvfs_dll/hooks/kernel32.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/usvfs_dll/hooks/kernel32.cpp b/src/usvfs_dll/hooks/kernel32.cpp index 1c00edca..2f4a7d2a 100644 --- a/src/usvfs_dll/hooks/kernel32.cpp +++ b/src/usvfs_dll/hooks/kernel32.cpp @@ -512,13 +512,15 @@ BOOL WINAPI usvfs::hook_DeleteFileW(LPCWSTR lpFileName) HOOK_START_GROUP(MutExHookGroup::DELETE_FILE) // Why is the usual if (!callContext.active()... check missing? - RerouteW reroute = RerouteW::create(READ_CONTEXT(), callContext, lpFileName); + const std::wstring path = RerouteW::canonizePath(RerouteW::absolutePath(lpFileName)).wstring(); + + RerouteW reroute = RerouteW::create(READ_CONTEXT(), callContext, path.c_str()); PRE_REALCALL if (reroute.wasRerouted()) { res = ::DeleteFileW(reroute.fileName()); } else { - res = ::DeleteFileW(lpFileName); + res = ::DeleteFileW(path.c_str()); } POST_REALCALL @@ -868,7 +870,7 @@ BOOL WINAPI usvfs::hook_MoveFileWithProgressW(LPCWSTR lpExistingFileName, LPCWST if (res) { //TODO: this call causes the node to be removed twice in case of MOVEFILE_COPY_ALLOWED as the deleteFile hook lower level already takes care of it, - //but deleteFile can't be disabled since we are relying on it in case of MOVEFILE_REPLACE_EXISTING for the destination file. + //but deleteFile can't be disabled since we are relying on it in case of MOVEFILE_REPLACE_EXISTING for the destination file. readReroute.removeMapping(READ_CONTEXT(), isDirectory); // Updating the rerouteCreate to check deleted file entries should make this okay (not related to comments above) if (writeReroute.newReroute()) { From fad051000c5f427c0f08833fef7ac022bbc68c65 Mon Sep 17 00:00:00 2001 From: isanae <14251494+isanae@users.noreply.github.com> Date: Sun, 8 Sep 2019 02:19:20 -0400 Subject: [PATCH 03/20] added a delay parameter: adds a sleep before unfreezing the process so there's time to hook a debugger --- include/usvfs.h | 3 ++- include/usvfsparameters.h | 2 ++ src/usvfs_dll/usvfs.cpp | 9 ++++++++- 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/include/usvfs.h b/include/usvfs.h index 38027618..2f842816 100644 --- a/include/usvfs.h +++ b/include/usvfs.h @@ -176,7 +176,8 @@ DLLEXPORT void WINAPI USVFSInitParameters(USVFSParameters *parameters, bool debugMode, LogLevel logLevel, CrashDumpsType crashDumpsType, - const char *crashDumpsPath); + const char *crashDumpsPath, + std::chrono::milliseconds delayProcess={}); DLLEXPORT int WINAPI CreateMiniDump(PEXCEPTION_POINTERS exceptionPtrs, CrashDumpsType type, const wchar_t* dumpPath); diff --git a/include/usvfsparameters.h b/include/usvfsparameters.h index c6461d30..7aaf4d73 100644 --- a/include/usvfsparameters.h +++ b/include/usvfsparameters.h @@ -22,6 +22,7 @@ along with usvfs. If not, see . #include "logging.h" #include "dllimport.h" +#include enum class CrashDumpsType : uint8_t { None, @@ -40,6 +41,7 @@ struct USVFSParameters { LogLevel logLevel{LogLevel::Debug}; CrashDumpsType crashDumpsType{CrashDumpsType::None}; char crashDumpsPath[260]; + std::chrono::milliseconds delayProcess{0}; }; } diff --git a/src/usvfs_dll/usvfs.cpp b/src/usvfs_dll/usvfs.cpp index 5779dd91..c0915009 100644 --- a/src/usvfs_dll/usvfs.cpp +++ b/src/usvfs_dll/usvfs.cpp @@ -327,6 +327,10 @@ void __cdecl InitHooks(LPVOID parameters, size_t) usvfs_dump_type = params->crashDumpsType; usvfs_dump_path = ush::string_cast(params->crashDumpsPath, ush::CodePage::UTF8); + if (params->delayProcess.count() > 0) { + ::Sleep(static_cast(params->delayProcess.count())); + } + SetLogLevel(params->logLevel); if (exceptionHandler == nullptr) { @@ -775,11 +779,14 @@ void WINAPI USVFSInitParameters(USVFSParameters *parameters, const char *instanceName, bool debugMode, LogLevel logLevel, CrashDumpsType crashDumpsType, - const char *crashDumpsPath) + const char *crashDumpsPath, + std::chrono::milliseconds delayProcess) { parameters->debugMode = debugMode; parameters->logLevel = logLevel; parameters->crashDumpsType = crashDumpsType; + parameters->delayProcess = delayProcess; + strncpy_s(parameters->instanceName, instanceName, _TRUNCATE); if (crashDumpsPath && *crashDumpsPath && strlen(crashDumpsPath) < _countof(parameters->crashDumpsPath)) { memcpy(parameters->crashDumpsPath, crashDumpsPath, strlen(crashDumpsPath)+1); From 7ba3d9229580a1fd16c7c00b732be65e75d7e956 Mon Sep 17 00:00:00 2001 From: Silarn Date: Fri, 27 Sep 2019 23:47:31 -0500 Subject: [PATCH 04/20] Dependency and compatibility updates --- appveyor.yml | 2 +- src/shared/test_helpers.h | 2 +- src/usvfs_dll/usvfs.cpp | 2 +- test/test_file_operations/test_filesystem.h | 2 +- vsbuild/external_dependencies.props | 2 +- vsbuild/shared.vcxproj | 4 ++++ vsbuild/shared_test.vcxproj | 4 ++++ vsbuild/test_common.props | 1 + vsbuild/test_file_operations.vcxproj | 4 ++++ vsbuild/testinject_bin.vcxproj | 4 ++++ vsbuild/testinject_dll.vcxproj | 4 ++++ vsbuild/thooklib.vcxproj | 4 ++++ vsbuild/thooklib_test.vcxproj | 4 ++++ vsbuild/tinjectlib.vcxproj | 4 ++++ vsbuild/tinjectlib_test.vcxproj | 2 ++ vsbuild/tvfs_test.vcxproj | 2 ++ vsbuild/usvfs_dll.vcxproj | 2 ++ vsbuild/usvfs_helper.vcxproj | 2 ++ vsbuild/usvfs_proxy.vcxproj | 2 ++ vsbuild/usvfs_test.vcxproj | 2 ++ vsbuild/usvfs_test_runner.vcxproj | 2 ++ 21 files changed, 52 insertions(+), 5 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 09d4638d..c7570c5e 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -6,7 +6,7 @@ platform: - x86 environment: GTEST_PATH: C:\Libraries\googletest - BOOST_PATH: C:\Libraries\boost_1_70_0 + BOOST_PATH: C:\Libraries\boost_1_71_0 WEBHOOK_URL: secure: gOKbXaZM9ImtMD5XrYITvdyZUW/az082G9OIN1EC1VZ2CuYaUUM6WY2eiNxaFeOL7/9Jyu/m+Vm1fH54CEyigcUUaxA7d8F5IMWlOgE/7YYdaAFSMUTFD7EK+++3FBYfmU1F/nZ61wsiWE6hB9Au5FpGBSCeQ0Tf8U8m0ybPmD0= before_build: diff --git a/src/shared/test_helpers.h b/src/shared/test_helpers.h index fb2b1b63..59e4fb4c 100644 --- a/src/shared/test_helpers.h +++ b/src/shared/test_helpers.h @@ -69,7 +69,7 @@ namespace test { FILE* m_f; }; - using std::experimental::filesystem::path; + using std::filesystem::path; // path functions assume they are called by a test executable // (calculate the requested path relative to the current executable path) diff --git a/src/usvfs_dll/usvfs.cpp b/src/usvfs_dll/usvfs.cpp index c0915009..5717288a 100644 --- a/src/usvfs_dll/usvfs.cpp +++ b/src/usvfs_dll/usvfs.cpp @@ -357,7 +357,7 @@ void __cdecl InitHooks(LPVOID parameters, size_t) auto exePath = boost::dll::program_location(); auto libraries = context->librariesToForceLoad(exePath.filename().c_str()); for (auto library : libraries) { - if (std::experimental::filesystem::exists(library)) { + if (std::filesystem::exists(library)) { const auto ret = LoadLibraryExW(library.c_str(), NULL, 0); if (ret) { spdlog::get("usvfs") diff --git a/test/test_file_operations/test_filesystem.h b/test/test_file_operations/test_filesystem.h index e888d8f8..0d8e4e4a 100644 --- a/test/test_file_operations/test_filesystem.h +++ b/test/test_file_operations/test_filesystem.h @@ -10,7 +10,7 @@ class TestFileSystem public: static constexpr auto FILE_CONTENTS_PRINT_PREFIX = "== "; - typedef std::experimental::filesystem::path path; + typedef std::filesystem::path path; typedef std::FILE FILE; static path current_directory(); diff --git a/vsbuild/external_dependencies.props b/vsbuild/external_dependencies.props index 1ff0ab33..cc7be094 100644 --- a/vsbuild/external_dependencies.props +++ b/vsbuild/external_dependencies.props @@ -4,7 +4,7 @@ - ..\..\boost_1_70_0 + ..\..\boost_1_71_0 $(BOOST_PATH) ..\..\googletest diff --git a/vsbuild/shared.vcxproj b/vsbuild/shared.vcxproj index 537a95a5..df8e3b8a 100644 --- a/vsbuild/shared.vcxproj +++ b/vsbuild/shared.vcxproj @@ -81,11 +81,13 @@ Disabled + stdcpp17 Disabled + stdcpp17 @@ -95,6 +97,7 @@ Default true false + stdcpp17 true @@ -108,6 +111,7 @@ Default true false + stdcpp17 true diff --git a/vsbuild/shared_test.vcxproj b/vsbuild/shared_test.vcxproj index 77fe9e42..8e83cef3 100644 --- a/vsbuild/shared_test.vcxproj +++ b/vsbuild/shared_test.vcxproj @@ -81,6 +81,7 @@ Disabled + stdcpp17 Console @@ -89,6 +90,7 @@ Disabled + stdcpp17 Console @@ -99,6 +101,7 @@ MaxSpeed true true + stdcpp17 true @@ -111,6 +114,7 @@ MaxSpeed true true + stdcpp17 true diff --git a/vsbuild/test_common.props b/vsbuild/test_common.props index 0e095312..adbb8a65 100644 --- a/vsbuild/test_common.props +++ b/vsbuild/test_common.props @@ -12,6 +12,7 @@ %(AdditionalIncludeDirectories);$(GTEST_PATH)\googletest\include UNITTEST;%(PreprocessorDefinitions) + stdcpp17 %(AdditionalLibraryDirectories);$(GTEST_PATH)\build$(PLATFORM_32)\lib diff --git a/vsbuild/test_file_operations.vcxproj b/vsbuild/test_file_operations.vcxproj index 2dc21bf1..26a80744 100644 --- a/vsbuild/test_file_operations.vcxproj +++ b/vsbuild/test_file_operations.vcxproj @@ -81,6 +81,7 @@ Disabled + stdcpp17 Console @@ -90,6 +91,7 @@ Disabled + stdcpp17 Console @@ -101,6 +103,7 @@ MaxSpeed true true + stdcpp17 true @@ -114,6 +117,7 @@ MaxSpeed true true + stdcpp17 true diff --git a/vsbuild/testinject_bin.vcxproj b/vsbuild/testinject_bin.vcxproj index 83d8f9d5..290c4786 100644 --- a/vsbuild/testinject_bin.vcxproj +++ b/vsbuild/testinject_bin.vcxproj @@ -81,6 +81,7 @@ Disabled + stdcpp17 Console @@ -89,6 +90,7 @@ Disabled + stdcpp17 Console @@ -99,6 +101,7 @@ MaxSpeed true true + stdcpp17 true @@ -111,6 +114,7 @@ MaxSpeed true true + stdcpp17 true diff --git a/vsbuild/testinject_dll.vcxproj b/vsbuild/testinject_dll.vcxproj index 7d872001..92a36821 100644 --- a/vsbuild/testinject_dll.vcxproj +++ b/vsbuild/testinject_dll.vcxproj @@ -81,11 +81,13 @@ Disabled + stdcpp17 Disabled + stdcpp17 @@ -93,6 +95,7 @@ MaxSpeed true true + stdcpp17 true @@ -104,6 +107,7 @@ MaxSpeed true true + stdcpp17 true diff --git a/vsbuild/thooklib.vcxproj b/vsbuild/thooklib.vcxproj index b95263dc..1ba6525e 100644 --- a/vsbuild/thooklib.vcxproj +++ b/vsbuild/thooklib.vcxproj @@ -81,11 +81,13 @@ Disabled + stdcpp17 Disabled + stdcpp17 @@ -95,6 +97,7 @@ Default true false + stdcpp17 true @@ -108,6 +111,7 @@ Default true false + stdcpp17 true diff --git a/vsbuild/thooklib_test.vcxproj b/vsbuild/thooklib_test.vcxproj index af19ce6c..2700afdf 100644 --- a/vsbuild/thooklib_test.vcxproj +++ b/vsbuild/thooklib_test.vcxproj @@ -81,6 +81,7 @@ Disabled + stdcpp17 Console @@ -89,6 +90,7 @@ Disabled + stdcpp17 Console @@ -99,6 +101,7 @@ MaxSpeed true true + stdcpp17 true @@ -111,6 +114,7 @@ MaxSpeed true true + stdcpp17 true diff --git a/vsbuild/tinjectlib.vcxproj b/vsbuild/tinjectlib.vcxproj index da60a0a8..6aa7ed96 100644 --- a/vsbuild/tinjectlib.vcxproj +++ b/vsbuild/tinjectlib.vcxproj @@ -81,11 +81,13 @@ Disabled + stdcpp17 Disabled + stdcpp17 @@ -95,6 +97,7 @@ Default true false + stdcpp17 true @@ -108,6 +111,7 @@ Default true false + stdcpp17 true diff --git a/vsbuild/tinjectlib_test.vcxproj b/vsbuild/tinjectlib_test.vcxproj index 57bf8785..3d054127 100644 --- a/vsbuild/tinjectlib_test.vcxproj +++ b/vsbuild/tinjectlib_test.vcxproj @@ -99,6 +99,7 @@ MaxSpeed true true + stdcpp17 true @@ -111,6 +112,7 @@ MaxSpeed true true + stdcpp17 true diff --git a/vsbuild/tvfs_test.vcxproj b/vsbuild/tvfs_test.vcxproj index bee11a01..640e127a 100644 --- a/vsbuild/tvfs_test.vcxproj +++ b/vsbuild/tvfs_test.vcxproj @@ -104,6 +104,7 @@ true true ..\src\usvfs_dll;%(AdditionalIncludeDirectories) + stdcpp17 true @@ -118,6 +119,7 @@ true true ..\src\usvfs_dll;%(AdditionalIncludeDirectories) + stdcpp17 true diff --git a/vsbuild/usvfs_dll.vcxproj b/vsbuild/usvfs_dll.vcxproj index cb76b298..3446d90f 100644 --- a/vsbuild/usvfs_dll.vcxproj +++ b/vsbuild/usvfs_dll.vcxproj @@ -153,6 +153,7 @@ Default true false + stdcpp17 true @@ -180,6 +181,7 @@ Default true false + stdcpp17 true diff --git a/vsbuild/usvfs_helper.vcxproj b/vsbuild/usvfs_helper.vcxproj index 1bf2a8b6..e20673e5 100644 --- a/vsbuild/usvfs_helper.vcxproj +++ b/vsbuild/usvfs_helper.vcxproj @@ -98,6 +98,7 @@ Default true false + stdcpp17 true @@ -112,6 +113,7 @@ Default true false + stdcpp17 true diff --git a/vsbuild/usvfs_proxy.vcxproj b/vsbuild/usvfs_proxy.vcxproj index a1ffb7be..668f10ee 100644 --- a/vsbuild/usvfs_proxy.vcxproj +++ b/vsbuild/usvfs_proxy.vcxproj @@ -125,6 +125,7 @@ Default true false + stdcpp17 true @@ -144,6 +145,7 @@ Default true false + stdcpp17 true diff --git a/vsbuild/usvfs_test.vcxproj b/vsbuild/usvfs_test.vcxproj index f4fe449d..ed5cbe88 100644 --- a/vsbuild/usvfs_test.vcxproj +++ b/vsbuild/usvfs_test.vcxproj @@ -104,6 +104,7 @@ true true ..\src\usvfs_dll;%(AdditionalIncludeDirectories) + stdcpp17 true @@ -118,6 +119,7 @@ true true ..\src\usvfs_dll;%(AdditionalIncludeDirectories) + stdcpp17 true diff --git a/vsbuild/usvfs_test_runner.vcxproj b/vsbuild/usvfs_test_runner.vcxproj index b5d2818e..829482d5 100644 --- a/vsbuild/usvfs_test_runner.vcxproj +++ b/vsbuild/usvfs_test_runner.vcxproj @@ -99,6 +99,7 @@ MaxSpeed true true + stdcpp17 true @@ -111,6 +112,7 @@ MaxSpeed true true + stdcpp17 true From 846f74de6ea3c445fb7e9bd64259632e01404130 Mon Sep 17 00:00:00 2001 From: Silarn Date: Sat, 28 Sep 2019 00:39:21 -0500 Subject: [PATCH 05/20] Update Appveyor to official VS 2019 image --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index c7570c5e..83d017e8 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,5 +1,5 @@ version: 1.0.{build} -image: Visual Studio 2019 Preview +image: Visual Studio 2019 configuration: Release platform: - x64 From a60e0878bc211c831b8d631bb1a193396a9bdb8a Mon Sep 17 00:00:00 2001 From: Silarn Date: Sat, 28 Sep 2019 00:50:27 -0500 Subject: [PATCH 06/20] Update VS path in appveyor script --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index 83d017e8..f4199870 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -10,7 +10,7 @@ environment: WEBHOOK_URL: secure: gOKbXaZM9ImtMD5XrYITvdyZUW/az082G9OIN1EC1VZ2CuYaUUM6WY2eiNxaFeOL7/9Jyu/m+Vm1fH54CEyigcUUaxA7d8F5IMWlOgE/7YYdaAFSMUTFD7EK+++3FBYfmU1F/nZ61wsiWE6hB9Au5FpGBSCeQ0Tf8U8m0ybPmD0= before_build: -- ps: "echo $env:Platform\nif (${env:Platform} -eq \"x64\") {\n set-item -path Env:BOOST_LIBPATH -value ${Env:BOOST_PATH}\\lib64-msvc-14.1\n set-item -path Env:GTEST_BUILDDIR -value c:\\libraries\\googletest\\build \n}\nElse {\n set-item -path Env:BOOST_LIBPATH -value ${Env:BOOST_PATH}\\lib32-msvc-14.1\n set-item -path Env:GTEST_BUILDDIR -value c:\\libraries\\googletest\\build_32\n}\n\n. git clone --depth=1 --branch=master https://github.com/google/googletest.git c:\\libraries\\googletest 2> $null\nNew-Item $Env:GTEST_BUILDDIR -type directory\nSet-Location -Path $Env:GTEST_BUILDDIR\n. cmd /c \"`\"C:\\Program Files (x86)\\Microsoft Visual Studio\\2017\\Community\\VC\\Auxiliary\\Build\\vcvarsall.bat`\" $env:Platform && cmake -G `\"NMake Makefiles`\" -DCMAKE_BUILD_TYPE=Release ..`\"\"\n. cmd /c \"`\"C:\\Program Files (x86)\\Microsoft Visual Studio\\2017\\Community\\VC\\Auxiliary\\Build\\vcvarsall.bat`\" $env:Platform && nmake\"\n\nSet-Location -Path c:\\projects\\usvfs\\vsbuild\n#Tempory fix due to that appveyor has boost lib files in a custom output folder\nGet-ChildItem -Path *.props -recurse | ForEach {If (Get-Content $_.FullName | Select-String -Pattern '\\$\\(BOOST_PATH\\)\\\\.*\\\\lib') {(Get-Content $_ | ForEach {$_ -replace '\\$\\(BOOST_PATH\\)\\\\.*\\\\lib', \"$Env:BOOST_LIBPATH\"}) | Set-Content $_ }}\n\n#Need to tell usvfs to not use the BOOST_BUILDID\nGet-ChildItem -Path *.props -recurse | ForEach {If (Get-Content $_.FullName | Select-String -Pattern 'BOOST_LIB_BUILDID=x86;') {(Get-Content $_ | ForEach {$_ -replace 'BOOST_LIB_BUILDID=x86;', \"\"}) | Set-Content $_ }}\n\nSet-Location -Path c:\\projects\\usvfs\ngit submodule -q update --init --recursive" +- ps: "echo $env:Platform\nif (${env:Platform} -eq \"x64\") {\n set-item -path Env:BOOST_LIBPATH -value ${Env:BOOST_PATH}\\lib64-msvc-14.1\n set-item -path Env:GTEST_BUILDDIR -value c:\\libraries\\googletest\\build \n}\nElse {\n set-item -path Env:BOOST_LIBPATH -value ${Env:BOOST_PATH}\\lib32-msvc-14.1\n set-item -path Env:GTEST_BUILDDIR -value c:\\libraries\\googletest\\build_32\n}\n\n. git clone --depth=1 --branch=master https://github.com/google/googletest.git c:\\libraries\\googletest 2> $null\nNew-Item $Env:GTEST_BUILDDIR -type directory\nSet-Location -Path $Env:GTEST_BUILDDIR\n. cmd /c \"`\"C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Community\\VC\\Auxiliary\\Build\\vcvarsall.bat`\" $env:Platform && cmake -G `\"NMake Makefiles`\" -DCMAKE_BUILD_TYPE=Release ..`\"\"\n. cmd /c \"`\"C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Community\\VC\\Auxiliary\\Build\\vcvarsall.bat`\" $env:Platform && nmake\"\n\nSet-Location -Path c:\\projects\\usvfs\\vsbuild\n#Tempory fix due to that appveyor has boost lib files in a custom output folder\nGet-ChildItem -Path *.props -recurse | ForEach {If (Get-Content $_.FullName | Select-String -Pattern '\\$\\(BOOST_PATH\\)\\\\.*\\\\lib') {(Get-Content $_ | ForEach {$_ -replace '\\$\\(BOOST_PATH\\)\\\\.*\\\\lib', \"$Env:BOOST_LIBPATH\"}) | Set-Content $_ }}\n\n#Need to tell usvfs to not use the BOOST_BUILDID\nGet-ChildItem -Path *.props -recurse | ForEach {If (Get-Content $_.FullName | Select-String -Pattern 'BOOST_LIB_BUILDID=x86;') {(Get-Content $_ | ForEach {$_ -replace 'BOOST_LIB_BUILDID=x86;', \"\"}) | Set-Content $_ }}\n\nSet-Location -Path c:\\projects\\usvfs\ngit submodule -q update --init --recursive" build: project: vsbuild/usvfs.sln parallel: true From 4699329309cc49b05d51e5dcfad0b803cb4ae9c1 Mon Sep 17 00:00:00 2001 From: isanae <14251494+isanae@users.noreply.github.com> Date: Mon, 7 Oct 2019 07:00:49 -0400 Subject: [PATCH 07/20] propagate the delay parameter to the spawned process --- src/usvfs_dll/hookcontext.cpp | 7 +++++-- src/usvfs_dll/hookcontext.h | 5 ++++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/usvfs_dll/hookcontext.cpp b/src/usvfs_dll/hookcontext.cpp index 3690afc1..b0a13049 100644 --- a/src/usvfs_dll/hookcontext.cpp +++ b/src/usvfs_dll/hookcontext.cpp @@ -63,7 +63,8 @@ USVFSParameters SharedParameters::makeLocal() const currentSHMName.c_str(), currentInverseSHMName.c_str(), debugMode, logLevel, crashDumpsType, - crashDumpsPath.c_str()); + crashDumpsPath.c_str(), + delayProcess); return result; } @@ -75,11 +76,13 @@ void usvfs::USVFSInitParametersInt(USVFSParameters *parameters, bool debugMode, LogLevel logLevel, CrashDumpsType crashDumpsType, - const char *crashDumpsPath) + const char *crashDumpsPath, + std::chrono::milliseconds delayProcess) { parameters->debugMode = debugMode; parameters->logLevel = logLevel; parameters->crashDumpsType = crashDumpsType; + parameters->delayProcess = delayProcess; strncpy_s(parameters->instanceName, instanceName, _TRUNCATE); strncpy_s(parameters->currentSHMName, currentSHMName, _TRUNCATE); strncpy_s(parameters->currentInverseSHMName, currentInverseSHMName, _TRUNCATE); diff --git a/src/usvfs_dll/hookcontext.h b/src/usvfs_dll/hookcontext.h index 9b4dff6f..fda4598c 100644 --- a/src/usvfs_dll/hookcontext.h +++ b/src/usvfs_dll/hookcontext.h @@ -49,7 +49,8 @@ void USVFSInitParametersInt(USVFSParameters *parameters, bool debugMode, LogLevel logLevel, CrashDumpsType crashDumpsType, - const char *crashDumpsPath); + const char *crashDumpsPath, + std::chrono::milliseconds delayProcess); typedef shared::VoidAllocatorT::rebind::other DWORDAllocatorT; @@ -86,6 +87,7 @@ struct SharedParameters { , logLevel(reference.logLevel) , crashDumpsType(reference.crashDumpsType) , crashDumpsPath(reference.crashDumpsPath, allocator) + , delayProcess(reference.delayProcess) , userCount(1) , processBlacklist(allocator) , processList(allocator) @@ -102,6 +104,7 @@ struct SharedParameters { LogLevel logLevel; CrashDumpsType crashDumpsType; shared::StringT crashDumpsPath; + std::chrono::milliseconds delayProcess; uint32_t userCount; boost::container::flat_set, StringAllocatorT> processBlacklist; From 2e2b82a817aa308c0b0eb83a1c37286723114b5a Mon Sep 17 00:00:00 2001 From: isanae <14251494+isanae@users.noreply.github.com> Date: Wed, 9 Oct 2019 01:35:58 -0400 Subject: [PATCH 08/20] added USVFSVersionString() bumped to 0.4.4.4 --- include/usvfs.h | 2 ++ include/usvfs_version.h | 2 +- src/usvfs_dll/usvfs.cpp | 5 +++++ 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/include/usvfs.h b/include/usvfs.h index 2f842816..40bd9d3c 100644 --- a/include/usvfs.h +++ b/include/usvfs.h @@ -181,4 +181,6 @@ DLLEXPORT void WINAPI USVFSInitParameters(USVFSParameters *parameters, DLLEXPORT int WINAPI CreateMiniDump(PEXCEPTION_POINTERS exceptionPtrs, CrashDumpsType type, const wchar_t* dumpPath); +DLLEXPORT const char* WINAPI USVFSVersionString(); + } diff --git a/include/usvfs_version.h b/include/usvfs_version.h index f562aa74..c185a4cf 100644 --- a/include/usvfs_version.h +++ b/include/usvfs_version.h @@ -3,7 +3,7 @@ #define USVFS_VERSION_MAJOR 0 #define USVFS_VERSION_MINOR 4 #define USVFS_VERSION_BUILD 4 -#define USVFS_VERSION_REVISION 0 +#define USVFS_VERSION_REVISION 4 #define USVFS_BUILD_STRING "" #define USVFS_BUILD_WSTRING L"" diff --git a/src/usvfs_dll/usvfs.cpp b/src/usvfs_dll/usvfs.cpp index 5717288a..39d84db7 100644 --- a/src/usvfs_dll/usvfs.cpp +++ b/src/usvfs_dll/usvfs.cpp @@ -805,6 +805,11 @@ void WINAPI USVFSInitParameters(USVFSParameters *parameters, } +const char* WINAPI USVFSVersionString() +{ + return USVFS_VERSION_STRING; +} + // // DllMain // From b9b16456c4db9b5a026a335190abd3d2d2194441 Mon Sep 17 00:00:00 2001 From: isanae <14251494+isanae@users.noreply.github.com> Date: Thu, 10 Oct 2019 06:16:49 -0400 Subject: [PATCH 09/20] changed CompanyName and FileDescription --- src/usvfs_proxy/version.rc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/usvfs_proxy/version.rc b/src/usvfs_proxy/version.rc index 446807b9..7897f8cb 100644 --- a/src/usvfs_proxy/version.rc +++ b/src/usvfs_proxy/version.rc @@ -21,8 +21,8 @@ BEGIN BLOCK "040904B0" BEGIN VALUE "FileVersion", VER_FILEVERSION_STR - VALUE "CompanyName", "Community Edition\0" - VALUE "FileDescription", "Windows OverlayFS\0" + VALUE "CompanyName", "Mod Organizer 2 Team\0" + VALUE "FileDescription", "USVFS\0" #ifdef _WIN64 VALUE "OriginalFilename", "usvfs_proxy_x64.exe\0" #else From a1c8675add94105578600536e4cf2ee4ff336ad7 Mon Sep 17 00:00:00 2001 From: isanae <14251494+isanae@users.noreply.github.com> Date: Thu, 10 Oct 2019 10:33:58 -0400 Subject: [PATCH 10/20] changed CompanyName and FileDescription --- src/usvfs_dll/version.rc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/usvfs_dll/version.rc b/src/usvfs_dll/version.rc index 4dbb04aa..b06dd06e 100644 --- a/src/usvfs_dll/version.rc +++ b/src/usvfs_dll/version.rc @@ -21,8 +21,8 @@ BEGIN BLOCK "040904B0" BEGIN VALUE "FileVersion", VER_FILEVERSION_STR - VALUE "CompanyName", "Community Edition\0" - VALUE "FileDescription", "Windows OverlayFS\0" + VALUE "CompanyName", "Mod Organizer 2 Team\0" + VALUE "FileDescription", "USVFS\0" #ifdef _WIN64 VALUE "OriginalFilename", "usvfs_x64.dll\0" #else From f215542bde3c6e970c7a8796e0b28882d97d4ceb Mon Sep 17 00:00:00 2001 From: isanae <14251494+isanae@users.noreply.github.com> Date: Thu, 10 Oct 2019 10:16:38 -0400 Subject: [PATCH 11/20] added new usvfsParameters to replace old USVFSParameters deprecated everything having to do with USVFSParameters removed delayProcess from the old stuff to preserve ABI --- include/usvfs.h | 27 +++++++---- include/usvfsparameters.h | 21 ++++++++- src/usvfs_dll/hookcontext.cpp | 62 ++++++++++++------------- src/usvfs_dll/hookcontext.h | 36 +++++++-------- src/usvfs_dll/hookmanager.cpp | 2 +- src/usvfs_dll/hookmanager.h | 2 +- src/usvfs_dll/hooks/kernel32.cpp | 2 +- src/usvfs_dll/usvfs.cpp | 76 +++++++++++++++++++++++-------- src/usvfs_helper/inject.cpp | 7 +-- src/usvfs_helper/inject.h | 4 +- src/usvfs_proxy/main.cpp | 2 +- vsbuild/usvfs_dll.vcxproj | 2 + vsbuild/usvfs_dll.vcxproj.filters | 6 +++ 13 files changed, 158 insertions(+), 91 deletions(-) diff --git a/include/usvfs.h b/include/usvfs.h index 40bd9d3c..470c986d 100644 --- a/include/usvfs.h +++ b/include/usvfs.h @@ -80,14 +80,20 @@ DLLEXPORT BOOL WINAPI VirtualLinkDirectoryStatic(LPCWSTR source, LPCWSTR destina * connect to a virtual filesystem as a controller, without hooking the calling process. Please note that * you can only be connected to one vfs, so this will silently disconnect from a previous vfs. */ +[[deprecated("deprecated, use usvfsConnectVFS()")]] DLLEXPORT BOOL WINAPI ConnectVFS(const USVFSParameters *parameters); +DLLEXPORT BOOL WINAPI usvfsConnectVFS(const usvfsParameters* p); + /** * @brief create a new VFS. This is similar to ConnectVFS except it guarantees * the vfs is reset before use. */ +[[deprecated("deprecated, use usvfsCreateVFS()")]] DLLEXPORT BOOL WINAPI CreateVFS(const USVFSParameters *parameters); +DLLEXPORT BOOL WINAPI usvfsCreateVFS(const usvfsParameters* p); + /** * disconnect from a virtual filesystem. This removes hooks if necessary */ @@ -117,11 +123,6 @@ DLLEXPORT BOOL WINAPI CreateProcessHooked( */ DLLEXPORT bool WINAPI GetLogMessages(LPSTR buffer, size_t size, bool blocking = false); -/** - * @brief Used to change parameters which can be changed in runtime - */ -DLLEXPORT void WINAPI USVFSUpdateParams(LogLevel level, CrashDumpsType type); - /** * retrieves a readable representation of the vfs tree * @param buffer the buffer to write to. this may be null if you only want to determine the required @@ -170,14 +171,24 @@ DLLEXPORT void WINAPI InitLogging(bool toLocal = false); */ DLLEXPORT void __cdecl InitHooks(LPVOID userData, size_t userDataSize); - +[[deprecated("deprecated, use usvfsCreateParameters()")]] DLLEXPORT void WINAPI USVFSInitParameters(USVFSParameters *parameters, const char *instanceName, bool debugMode, LogLevel logLevel, CrashDumpsType crashDumpsType, - const char *crashDumpsPath, - std::chrono::milliseconds delayProcess={}); + const char *crashDumpsPath); + +/** +* @brief Used to change parameters which can be changed in runtime +*/ +[[deprecated("deprecated, use usvfsUpdateParameters()")]] +DLLEXPORT void WINAPI USVFSUpdateParams(LogLevel level, CrashDumpsType type); + +// the only information used from the parameters are the crash dump type, log +// level and process delay +// +DLLEXPORT void WINAPI usvfsUpdateParameters(usvfsParameters* p); DLLEXPORT int WINAPI CreateMiniDump(PEXCEPTION_POINTERS exceptionPtrs, CrashDumpsType type, const wchar_t* dumpPath); diff --git a/include/usvfsparameters.h b/include/usvfsparameters.h index 7aaf4d73..f0710b8f 100644 --- a/include/usvfsparameters.h +++ b/include/usvfsparameters.h @@ -31,8 +31,11 @@ enum class CrashDumpsType : uint8_t { Full }; -extern "C" { +extern "C" +{ +// deprecated, use usvfsParameters and usvfsCreateParameters() +// struct USVFSParameters { char instanceName[65]; char currentSHMName[65]; @@ -41,7 +44,21 @@ struct USVFSParameters { LogLevel logLevel{LogLevel::Debug}; CrashDumpsType crashDumpsType{CrashDumpsType::None}; char crashDumpsPath[260]; - std::chrono::milliseconds delayProcess{0}; }; + +struct usvfsParameters; + +DLLEXPORT usvfsParameters* usvfsCreateParameters(); +DLLEXPORT usvfsParameters* usvfsDupeParameters(usvfsParameters* p); +DLLEXPORT void usvfsCopyParameters(const usvfsParameters* source, usvfsParameters* dest); +DLLEXPORT void usvfsFreeParameters(usvfsParameters* p); + +DLLEXPORT void usvfsSetInstanceName(usvfsParameters* p, const char* name); +DLLEXPORT void usvfsSetDebugMode(usvfsParameters* p, BOOL debugMode); +DLLEXPORT void usvfsSetLogLevel(usvfsParameters* p, LogLevel level); +DLLEXPORT void usvfsSetCrashDumpType(usvfsParameters* p, CrashDumpsType type); +DLLEXPORT void usvfsSetCrashDumpPath(usvfsParameters* p, const char* path); +DLLEXPORT void usvfsSetProcessDelay(usvfsParameters* p, int milliseconds); + } diff --git a/src/usvfs_dll/hookcontext.cpp b/src/usvfs_dll/hookcontext.cpp index b0a13049..72965a32 100644 --- a/src/usvfs_dll/hookcontext.cpp +++ b/src/usvfs_dll/hookcontext.cpp @@ -56,41 +56,19 @@ void printBuffer(const char *buffer, size_t size) } -USVFSParameters SharedParameters::makeLocal() const +usvfsParameters SharedParameters::makeLocal() const { - USVFSParameters result; - USVFSInitParametersInt(&result, instanceName.c_str(), - currentSHMName.c_str(), - currentInverseSHMName.c_str(), - debugMode, logLevel, crashDumpsType, - crashDumpsPath.c_str(), - delayProcess); - return result; -} - - -void usvfs::USVFSInitParametersInt(USVFSParameters *parameters, - const char *instanceName, - const char *currentSHMName, - const char *currentInverseSHMName, - bool debugMode, - LogLevel logLevel, - CrashDumpsType crashDumpsType, - const char *crashDumpsPath, - std::chrono::milliseconds delayProcess) -{ - parameters->debugMode = debugMode; - parameters->logLevel = logLevel; - parameters->crashDumpsType = crashDumpsType; - parameters->delayProcess = delayProcess; - strncpy_s(parameters->instanceName, instanceName, _TRUNCATE); - strncpy_s(parameters->currentSHMName, currentSHMName, _TRUNCATE); - strncpy_s(parameters->currentInverseSHMName, currentInverseSHMName, _TRUNCATE); - strncpy_s(parameters->crashDumpsPath, crashDumpsPath, _TRUNCATE); + return usvfsParameters( + instanceName.c_str(), + currentSHMName.c_str(), + currentInverseSHMName.c_str(), + debugMode, logLevel, crashDumpsType, + crashDumpsPath.c_str(), + delayProcess.count()); } -HookContext::HookContext(const USVFSParameters ¶ms, HMODULE module) +HookContext::HookContext(const usvfsParameters& params, HMODULE module) : m_ConfigurationSHM(bi::open_or_create, params.instanceName, 8192) , m_Parameters(retrieveParameters(params)) , m_Tree(m_Parameters->currentSHMName.c_str(), 65536) @@ -135,7 +113,7 @@ HookContext::~HookContext() } } -SharedParameters *HookContext::retrieveParameters(const USVFSParameters ¶ms) +SharedParameters *HookContext::retrieveParameters(const usvfsParameters& params) { std::pair res = m_ConfigurationSHM.find("parameters"); @@ -182,13 +160,18 @@ void HookContext::setCrashDumpsType(CrashDumpsType type) m_Parameters->crashDumpsType = type; } +void HookContext::setDelayProcess(std::chrono::milliseconds delay) +{ + m_Parameters->delayProcess = delay; +} + void HookContext::updateParameters() const { m_Parameters->currentSHMName = m_Tree.shmName().c_str(); m_Parameters->currentInverseSHMName = m_InverseTree.shmName().c_str(); } -USVFSParameters HookContext::callParameters() const +usvfsParameters HookContext::callParameters() const { updateParameters(); return m_Parameters->makeLocal(); @@ -308,7 +291,18 @@ void HookContext::unlockShared(const HookContext *instance) instance->m_Mutex.signal(); } -extern "C" DLLEXPORT HookContext *__cdecl CreateHookContext(const USVFSParameters ¶ms, HMODULE module) + +// deprecated +// +extern "C" DLLEXPORT HookContext *__cdecl CreateHookContext( + const USVFSParameters &oldParams, HMODULE module) +{ + const usvfsParameters p(oldParams); + return usvfsCreateHookContext(p, module); +} + +extern "C" DLLEXPORT usvfs::HookContext* WINAPI usvfsCreateHookContext( + const usvfsParameters& params, HMODULE module) { return new HookContext(params, module); } diff --git a/src/usvfs_dll/hookcontext.h b/src/usvfs_dll/hookcontext.h index fda4598c..f23c71bc 100644 --- a/src/usvfs_dll/hookcontext.h +++ b/src/usvfs_dll/hookcontext.h @@ -24,6 +24,7 @@ along with usvfs. If not, see . #include "dllimport.h" #include "semaphore.h" #include +#include #include #include #include @@ -42,17 +43,6 @@ along with usvfs. If not, see . namespace usvfs { -void USVFSInitParametersInt(USVFSParameters *parameters, - const char *instanceName, - const char *currentSHMName, - const char *currentInverseSHMName, - bool debugMode, - LogLevel logLevel, - CrashDumpsType crashDumpsType, - const char *crashDumpsPath, - std::chrono::milliseconds delayProcess); - - typedef shared::VoidAllocatorT::rebind::other DWORDAllocatorT; typedef shared::VoidAllocatorT::rebind::other StringAllocatorT; @@ -78,7 +68,7 @@ struct SharedParameters { SharedParameters &operator=(const SharedParameters &reference) = delete; - SharedParameters(const USVFSParameters &reference, + SharedParameters(const usvfsParameters& reference, const shared::VoidAllocatorT &allocator) : instanceName(reference.instanceName, allocator) , currentSHMName(reference.currentSHMName, allocator) @@ -87,7 +77,7 @@ struct SharedParameters { , logLevel(reference.logLevel) , crashDumpsType(reference.crashDumpsType) , crashDumpsPath(reference.crashDumpsPath, allocator) - , delayProcess(reference.delayProcess) + , delayProcess(reference.delayProcessMs) , userCount(1) , processBlacklist(allocator) , processList(allocator) @@ -95,7 +85,7 @@ struct SharedParameters { { } - DLLEXPORT USVFSParameters makeLocal() const; + DLLEXPORT usvfsParameters makeLocal() const; shared::StringT instanceName; shared::StringT currentSHMName; @@ -127,7 +117,7 @@ class HookContext typedef unsigned int DataIDT; public: - HookContext(const USVFSParameters ¶ms, HMODULE module); + HookContext(const usvfsParameters& params, HMODULE module); HookContext(const HookContext &reference) = delete; @@ -180,7 +170,7 @@ class HookContext /** * @return the parameters passed in on dll initialisation */ - USVFSParameters callParameters() const; + usvfsParameters callParameters() const; /** * @return true if usvfs is running in debug mode @@ -228,6 +218,7 @@ class HookContext void setLogLevel(LogLevel level); void setCrashDumpsType(CrashDumpsType type); + void setDelayProcess(std::chrono::milliseconds delay); void updateParameters() const; @@ -239,7 +230,7 @@ class HookContext static void unlock(HookContext *instance); static void unlockShared(const HookContext *instance); - SharedParameters *retrieveParameters(const USVFSParameters ¶ms); + SharedParameters* retrieveParameters(const usvfsParameters& params); private: static HookContext *s_Instance; @@ -261,12 +252,19 @@ class HookContext // mutable std::recursive_mutex m_Mutex; mutable RecursiveBenaphore m_Mutex; }; -} + +} // namespace + // exposed only to unit tests for easier testability -extern "C" DLLEXPORT usvfs::HookContext *__cdecl CreateHookContext( +extern "C" [[deprecated("deprecated, use usvfsCreateHookContext()")]] +DLLEXPORT usvfs::HookContext *__cdecl CreateHookContext( const USVFSParameters ¶ms, HMODULE module); +extern "C" DLLEXPORT usvfs::HookContext* WINAPI usvfsCreateHookContext( + const usvfsParameters& params, HMODULE module); + + class PreserveGetLastError { public: diff --git a/src/usvfs_dll/hookmanager.cpp b/src/usvfs_dll/hookmanager.cpp index 7bb1634b..cfca76a8 100644 --- a/src/usvfs_dll/hookmanager.cpp +++ b/src/usvfs_dll/hookmanager.cpp @@ -46,7 +46,7 @@ namespace usvfs { HookManager *HookManager::s_Instance = nullptr; -HookManager::HookManager(const USVFSParameters ¶ms, HMODULE module) +HookManager::HookManager(const usvfsParameters& params, HMODULE module) : m_Context(params, module) { if (s_Instance != nullptr) { diff --git a/src/usvfs_dll/hookmanager.h b/src/usvfs_dll/hookmanager.h index 68c1e557..bc0a65fb 100644 --- a/src/usvfs_dll/hookmanager.h +++ b/src/usvfs_dll/hookmanager.h @@ -32,7 +32,7 @@ class HookManager { public: - HookManager(const USVFSParameters ¶ms, HMODULE module); + HookManager(const usvfsParameters& params, HMODULE module); ~HookManager(); HookManager(const HookManager &reference) = delete; diff --git a/src/usvfs_dll/hooks/kernel32.cpp b/src/usvfs_dll/hooks/kernel32.cpp index 2f4a7d2a..3e788369 100644 --- a/src/usvfs_dll/hooks/kernel32.cpp +++ b/src/usvfs_dll/hooks/kernel32.cpp @@ -226,7 +226,7 @@ BOOL WINAPI usvfs::hook_CreateProcessInternalW( LPWSTR cend = nullptr; std::wstring dllPath; - USVFSParameters callParameters; + usvfsParameters callParameters; { // scope for context lock auto context = READ_CONTEXT(); diff --git a/src/usvfs_dll/usvfs.cpp b/src/usvfs_dll/usvfs.cpp index 39d84db7..31070f33 100644 --- a/src/usvfs_dll/usvfs.cpp +++ b/src/usvfs_dll/usvfs.cpp @@ -21,6 +21,7 @@ along with usvfs. If not, see . #include "usvfs.h" #include "usvfs_version.h" #include "hookmanager.h" +#include "usvfsparametersprivate.h" #include "redirectiontree.h" #include "loghelpers.h" #include @@ -144,7 +145,7 @@ void WINAPI InitLogging(bool toConsole) InitLoggingInternal(toConsole, false); } -extern "C" DLLEXPORT bool WINAPI GetLogMessages(char *buffer, size_t size, +extern "C" DLLEXPORT bool WINAPI GetLogMessages(LPSTR buffer, size_t size, bool blocking) { buffer[0] = '\0'; @@ -168,16 +169,32 @@ void SetLogLevel(LogLevel level) spdlog::get("hooks")->set_level(ConvertLogLevel(level)); } -extern "C" void WINAPI USVFSUpdateParams(LogLevel level, CrashDumpsType type) +// deprecated +// +void WINAPI USVFSUpdateParams(LogLevel level, CrashDumpsType type) +{ + auto* p = usvfsCreateParameters(); + + usvfsSetLogLevel(p, level); + usvfsSetCrashDumpType(p, type); + + usvfsUpdateParameters(p); + usvfsFreeParameters(p); +} + +void WINAPI usvfsUpdateParameters(usvfsParameters* p) { // update actual values used: - usvfs_dump_type = type; - SetLogLevel(level); + usvfs_dump_type = p->crashDumpsType; + SetLogLevel(p->logLevel); + // update parameters in context so spawned process will inherit changes: - context->setLogLevel(level); - context->setCrashDumpsType(type); + context->setLogLevel(p->logLevel); + context->setCrashDumpsType(p->crashDumpsType); + context->setDelayProcess(std::chrono::milliseconds(p->delayProcessMs)); } + // // Structured Exception handling // @@ -265,8 +282,8 @@ int WINAPI CreateMiniDump(PEXCEPTION_POINTERS exceptionPtrs, CrashDumpsType type } static bool exceptionInUSVFS(PEXCEPTION_POINTERS exceptionPtrs) { - if (!dllModule) // shouldn't happend, check just in case - return true; // create dump to better understand how this could happend + if (!dllModule) // shouldn't happen, check just in case + return true; // create dump to better understand how this could happen std::pair range = winapi::ex::getSectionRange(dllModule); @@ -299,7 +316,7 @@ LONG WINAPI VEHandler(PEXCEPTION_POINTERS exceptionPtrs) // inside our hooks at least on x64, which is the main reason why want a crash collection // from usvfs. // As a workaround/compromise we catch vectored exception but only ones that originate - // direactly within the usvfs code: + // directly within the usvfs code: if (!exceptionInUSVFS(exceptionPtrs)) return EXCEPTION_CONTINUE_SEARCH; @@ -323,12 +340,12 @@ void __cdecl InitHooks(LPVOID parameters, size_t) { InitLoggingInternal(false, true); - const USVFSParameters *params = reinterpret_cast(parameters); + const usvfsParameters* params = reinterpret_cast(parameters); usvfs_dump_type = params->crashDumpsType; usvfs_dump_path = ush::string_cast(params->crashDumpsPath, ush::CodePage::UTF8); - if (params->delayProcess.count() > 0) { - ::Sleep(static_cast(params->delayProcess.count())); + if (params->delayProcessMs > 0) { + ::Sleep(static_cast(params->delayProcessMs)); } SetLogLevel(params->logLevel); @@ -384,13 +401,34 @@ void WINAPI GetCurrentVFSName(char *buffer, size_t size) } -BOOL WINAPI CreateVFS(const USVFSParameters *params) +// deprecated +// +BOOL WINAPI CreateVFS(const USVFSParameters *oldParams) +{ + const usvfsParameters p(*oldParams); + const auto r = usvfsCreateVFS(&p); + + return r; +} + +BOOL WINAPI usvfsCreateVFS(const usvfsParameters* p) +{ + usvfs::HookContext::remove(p->instanceName); + return usvfsConnectVFS(p); +} + + +// deprecated +// +BOOL WINAPI ConnectVFS(const USVFSParameters *oldParams) { - usvfs::HookContext::remove(params->instanceName); - return ConnectVFS(params); + const usvfsParameters p(*oldParams); + const auto r = usvfsConnectVFS(&p); + + return r; } -BOOL WINAPI ConnectVFS(const USVFSParameters *params) +BOOL WINAPI usvfsConnectVFS(const usvfsParameters* params) { if (spdlog::get("usvfs").get() == nullptr) { // create temporary logger so we don't get null-pointer exceptions @@ -775,17 +813,17 @@ VOID WINAPI PrintDebugInfo() } +// deprecated +// void WINAPI USVFSInitParameters(USVFSParameters *parameters, const char *instanceName, bool debugMode, LogLevel logLevel, CrashDumpsType crashDumpsType, - const char *crashDumpsPath, - std::chrono::milliseconds delayProcess) + const char *crashDumpsPath) { parameters->debugMode = debugMode; parameters->logLevel = logLevel; parameters->crashDumpsType = crashDumpsType; - parameters->delayProcess = delayProcess; strncpy_s(parameters->instanceName, instanceName, _TRUNCATE); if (crashDumpsPath && *crashDumpsPath && strlen(crashDumpsPath) < _countof(parameters->crashDumpsPath)) { diff --git a/src/usvfs_helper/inject.cpp b/src/usvfs_helper/inject.cpp index 0f275094..7835c4dd 100644 --- a/src/usvfs_helper/inject.cpp +++ b/src/usvfs_helper/inject.cpp @@ -19,6 +19,7 @@ You should have received a copy of the GNU General Public License along with usvfs. If not, see . */ #include "inject.h" +#include "usvfsparametersprivate.h" #include #include #include @@ -36,14 +37,14 @@ namespace ush = usvfs::shared; using namespace winapi; void usvfs::injectProcess(const std::wstring &applicationPath - , const USVFSParameters ¶meters + , const usvfsParameters ¶meters , const PROCESS_INFORMATION &processInfo) { injectProcess(applicationPath, parameters, processInfo.hProcess, processInfo.hThread); } void usvfs::injectProcess(const std::wstring &applicationPath - , const USVFSParameters ¶meters + , const usvfsParameters ¶meters , HANDLE processHandle , HANDLE threadHandle) { @@ -106,7 +107,7 @@ void usvfs::injectProcess(const std::wstring &applicationPath spdlog::get("usvfs")->info("dll path: {}", log::wrap(dllPath.wstring())); InjectLib::InjectDLL(processHandle, threadHandle, dllPath.c_str(), - "InitHooks", ¶meters, sizeof(USVFSParameters)); + "InitHooks", ¶meters, sizeof(parameters)); spdlog::get("usvfs")->info("injection to same bitness process {} successful", ::GetProcessId(processHandle)); } else { diff --git a/src/usvfs_helper/inject.h b/src/usvfs_helper/inject.h index 737ef53e..cfec39aa 100644 --- a/src/usvfs_helper/inject.h +++ b/src/usvfs_helper/inject.h @@ -33,7 +33,7 @@ namespace usvfs { * @param processInfo */ void injectProcess(const std::wstring &applicationPath - , const USVFSParameters ¶meters + , const usvfsParameters ¶meters , const PROCESS_INFORMATION &processInfo); /** @@ -45,7 +45,7 @@ void injectProcess(const std::wstring &applicationPath * a new thread is created in the process */ void injectProcess(const std::wstring &applicationPath - , const USVFSParameters ¶meters + , const usvfsParameters ¶meters , HANDLE process, HANDLE thread); } diff --git a/src/usvfs_proxy/main.cpp b/src/usvfs_proxy/main.cpp index c1f4a983..31cd5abd 100644 --- a/src/usvfs_proxy/main.cpp +++ b/src/usvfs_proxy/main.cpp @@ -151,7 +151,7 @@ int main(int argc, char **argv) { return 1; } - USVFSParameters par = params.first->makeLocal(); + usvfsParameters par = params.first->makeLocal(); boost::filesystem::path p(winapi::wide::getModuleFileName(nullptr)); diff --git a/vsbuild/usvfs_dll.vcxproj b/vsbuild/usvfs_dll.vcxproj index 3446d90f..968a9a50 100644 --- a/vsbuild/usvfs_dll.vcxproj +++ b/vsbuild/usvfs_dll.vcxproj @@ -214,12 +214,14 @@ + + diff --git a/vsbuild/usvfs_dll.vcxproj.filters b/vsbuild/usvfs_dll.vcxproj.filters index 407a9c5f..c8033810 100644 --- a/vsbuild/usvfs_dll.vcxproj.filters +++ b/vsbuild/usvfs_dll.vcxproj.filters @@ -56,6 +56,9 @@ Source Files + + Source Files + @@ -106,5 +109,8 @@ Header Files + + Header Files\include + \ No newline at end of file From dc845548488390e13e8deb2f4ade675d1fedf637 Mon Sep 17 00:00:00 2001 From: isanae <14251494+isanae@users.noreply.github.com> Date: Thu, 10 Oct 2019 10:48:33 -0400 Subject: [PATCH 12/20] add Proxy to the file description --- src/usvfs_proxy/version.rc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/usvfs_proxy/version.rc b/src/usvfs_proxy/version.rc index 7897f8cb..e95c58c5 100644 --- a/src/usvfs_proxy/version.rc +++ b/src/usvfs_proxy/version.rc @@ -22,7 +22,7 @@ BEGIN BEGIN VALUE "FileVersion", VER_FILEVERSION_STR VALUE "CompanyName", "Mod Organizer 2 Team\0" - VALUE "FileDescription", "USVFS\0" + VALUE "FileDescription", "USVFS Proxy\0" #ifdef _WIN64 VALUE "OriginalFilename", "usvfs_proxy_x64.exe\0" #else From be8e2e41965e67a0f784b933acff7bb4d0dda54f Mon Sep 17 00:00:00 2001 From: isanae <14251494+isanae@users.noreply.github.com> Date: Thu, 10 Oct 2019 10:51:17 -0400 Subject: [PATCH 13/20] missing files --- include/usvfsparametersprivate.h | 37 +++++++ src/usvfs_dll/usvfsparameters.cpp | 165 ++++++++++++++++++++++++++++++ 2 files changed, 202 insertions(+) create mode 100644 include/usvfsparametersprivate.h create mode 100644 src/usvfs_dll/usvfsparameters.cpp diff --git a/include/usvfsparametersprivate.h b/include/usvfsparametersprivate.h new file mode 100644 index 00000000..688d1e0f --- /dev/null +++ b/include/usvfsparametersprivate.h @@ -0,0 +1,37 @@ +#pragma once +#include "usvfsparameters.h" + +struct usvfsParameters +{ + char instanceName[65]; + char currentSHMName[65]; + char currentInverseSHMName[65]; + bool debugMode; + LogLevel logLevel{LogLevel::Debug}; + CrashDumpsType crashDumpsType{CrashDumpsType::None}; + char crashDumpsPath[260]; + int delayProcessMs; + + usvfsParameters(); + usvfsParameters(const usvfsParameters&) = default; + usvfsParameters& operator=(const usvfsParameters&) = default; + + usvfsParameters( + const char* instanceName, + const char* currentSHMName, + const char* currentInverseSHMName, + bool debugMode, + LogLevel logLevel, + CrashDumpsType crashDumpsType, + const char* crashDumpsPath, + int delayProcessMs); + + usvfsParameters(const USVFSParameters& oldParams); + + void setInstanceName(const char* name); + void setDebugMode(bool debugMode); + void setLogLevel(LogLevel level); + void setCrashDumpType(CrashDumpsType type); + void setCrashDumpPath(const char* path); + void setProcessDelay(int milliseconds); +}; diff --git a/src/usvfs_dll/usvfsparameters.cpp b/src/usvfs_dll/usvfsparameters.cpp new file mode 100644 index 00000000..60900b4f --- /dev/null +++ b/src/usvfs_dll/usvfsparameters.cpp @@ -0,0 +1,165 @@ +#include "usvfsparametersprivate.h" +#include + +usvfsParameters::usvfsParameters() : + debugMode(false), logLevel(LogLevel::Debug), + crashDumpsType(CrashDumpsType::None), delayProcessMs(0) +{ + std::fill(std::begin(instanceName), std::end(instanceName), 0); + std::fill(std::begin(currentSHMName), std::end(currentSHMName), 0); + std::fill(std::begin(currentInverseSHMName), std::end(currentInverseSHMName), 0); + std::fill(std::begin(crashDumpsPath), std::end(crashDumpsPath), 0); +} + +usvfsParameters::usvfsParameters( + const char *instanceName, + const char *currentSHMName, + const char *currentInverseSHMName, + bool debugMode, + LogLevel logLevel, + CrashDumpsType crashDumpsType, + const char *crashDumpsPath, + int delayProcessMs) + : usvfsParameters() +{ + strncpy_s(this->instanceName, instanceName, _TRUNCATE); + strncpy_s(this->currentSHMName, currentSHMName, _TRUNCATE); + strncpy_s(this->currentInverseSHMName, currentInverseSHMName, _TRUNCATE); + this->debugMode = debugMode; + this->logLevel = logLevel; + this->crashDumpsType = crashDumpsType; + strncpy_s(this->crashDumpsPath, crashDumpsPath, _TRUNCATE); + this->delayProcessMs = delayProcessMs; +} + +usvfsParameters::usvfsParameters(const USVFSParameters& oldParams) : + usvfsParameters( + oldParams.instanceName, + oldParams.currentSHMName, + oldParams.currentInverseSHMName, + oldParams.debugMode, + oldParams.logLevel, + oldParams.crashDumpsType, + oldParams.crashDumpsPath, + 0) +{ +} + +void usvfsParameters::setInstanceName(const char* name) +{ + strncpy_s(instanceName, name, _TRUNCATE); + strncpy_s(currentSHMName, 60, name, _TRUNCATE); + memset(currentInverseSHMName, '\0', _countof(currentInverseSHMName)); + _snprintf(currentInverseSHMName, 60, "inv_%s", name); +} + +void usvfsParameters::setDebugMode(bool b) +{ + debugMode = b; +} + +void usvfsParameters::setLogLevel(LogLevel level) +{ + logLevel = level; +} + +void usvfsParameters::setCrashDumpType(CrashDumpsType type) +{ + crashDumpsType = type; +} + +void usvfsParameters::setCrashDumpPath(const char* path) +{ + if (path && *path && strlen(path) < _countof(crashDumpsPath)) { + memcpy(crashDumpsPath, path, strlen(path)+1); + } else { + // crashDumpsPath invalid or overflow of USVFSParameters variable so disable + // crash dumps: + crashDumpsPath[0] = 0; + crashDumpsType = CrashDumpsType::None; + } +} + +void usvfsParameters::setProcessDelay(int milliseconds) +{ + delayProcessMs = milliseconds; +} + + +extern "C" +{ + +usvfsParameters* usvfsCreateParameters() +{ + return new (std::nothrow) usvfsParameters; +} + +usvfsParameters* usvfsDupeParameters(usvfsParameters* p) +{ + if (!p) { + return nullptr; + } + + auto* dupe = usvfsCreateParameters(); + if (!dupe) { + return nullptr; + } + + *dupe = *p; + + return dupe; +} + +void usvfsCopyParameters(const usvfsParameters* source, usvfsParameters* dest) +{ + *dest = *source; +} + +void usvfsFreeParameters(usvfsParameters* p) +{ + delete p; +} + +void usvfsSetInstanceName(usvfsParameters* p, const char* name) +{ + if (p) { + p->setInstanceName(name); + } +} + +void usvfsSetDebugMode(usvfsParameters* p, BOOL debugMode) +{ + if (p) { + p->setDebugMode(debugMode); + } +} + +void usvfsSetLogLevel(usvfsParameters* p, LogLevel level) +{ + if (p) { + p->setLogLevel(level); + } +} + +void usvfsSetCrashDumpType(usvfsParameters* p, CrashDumpsType type) +{ + if (p) { + p->setCrashDumpType(type); + } +} + +void usvfsSetCrashDumpPath(usvfsParameters* p, const char* path) +{ + if (p) { + p->setCrashDumpPath(path); + } +} + +void usvfsSetProcessDelay(usvfsParameters* p, int milliseconds) +{ + if (p) { + p->setProcessDelay(milliseconds); + } +} + +} // extern "C" From 2d515e7a43b5a0a408a564dfe7b36c8d135efb14 Mon Sep 17 00:00:00 2001 From: isanae <14251494+isanae@users.noreply.github.com> Date: Fri, 11 Oct 2019 08:17:40 -0400 Subject: [PATCH 14/20] added build log files to ignore list --- .gitignore | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.gitignore b/.gitignore index 65fc28fe..14ef70b2 100644 --- a/.gitignore +++ b/.gitignore @@ -19,3 +19,7 @@ *.vcxproj.user msbuild.log +/stderr.log +/stderr_32.log +/stdout.log +/stdout_32.log From fdb8fb669c6a648865c98276538af05fe8846869 Mon Sep 17 00:00:00 2001 From: isanae <14251494+isanae@users.noreply.github.com> Date: Thu, 17 Oct 2019 11:00:50 -0400 Subject: [PATCH 15/20] handle null pointer in MoveFileExA() and MoveFileWithProgressA() bumped to 4.4.5 --- include/usvfs_version.h | 2 +- src/usvfs_dll/hooks/kernel32.cpp | 30 +++++++++++++++++++++++++----- 2 files changed, 26 insertions(+), 6 deletions(-) diff --git a/include/usvfs_version.h b/include/usvfs_version.h index c185a4cf..261600c2 100644 --- a/include/usvfs_version.h +++ b/include/usvfs_version.h @@ -3,7 +3,7 @@ #define USVFS_VERSION_MAJOR 0 #define USVFS_VERSION_MINOR 4 #define USVFS_VERSION_BUILD 4 -#define USVFS_VERSION_REVISION 4 +#define USVFS_VERSION_REVISION 5 #define USVFS_BUILD_STRING "" #define USVFS_BUILD_WSTRING L"" diff --git a/src/usvfs_dll/hooks/kernel32.cpp b/src/usvfs_dll/hooks/kernel32.cpp index 3e788369..05e445aa 100644 --- a/src/usvfs_dll/hooks/kernel32.cpp +++ b/src/usvfs_dll/hooks/kernel32.cpp @@ -675,11 +675,21 @@ BOOL WINAPI usvfs::hook_MoveFileExA(LPCSTR lpExistingFileName, HOOK_END HOOK_START - const auto& existingFileName = ush::string_cast(lpExistingFileName); - const auto& newFileName = ush::string_cast(lpNewFileName); + const std::wstring existingFileName = ush::string_cast(lpExistingFileName); + + // careful: lpNewFileName can be null if dwFlags is + // MOVEFILE_DELAY_UNTIL_REBOOT, so don't blindly cast the string and make sure + // the null pointer is forwarded correctly + std::wstring newFileNameWstring; + const wchar_t* newFileName = nullptr; + + if (lpNewFileName) { + newFileNameWstring = ush::string_cast(lpNewFileName); + newFileName = newFileNameWstring.c_str(); + } PRE_REALCALL - res = MoveFileExW(existingFileName.c_str(), newFileName.c_str(), dwFlags); + res = MoveFileExW(existingFileName.c_str(), newFileName, dwFlags); POST_REALCALL HOOK_END @@ -792,10 +802,20 @@ BOOL WINAPI usvfs::hook_MoveFileWithProgressA(LPCSTR lpExistingFileName, LPCSTR HOOK_START const auto& existingFileName = ush::string_cast(lpExistingFileName); - const auto& newFileName = ush::string_cast(lpNewFileName); + + // careful: lpNewFileName can be null if dwFlags is + // MOVEFILE_DELAY_UNTIL_REBOOT, so don't blindly cast the string and make sure + // the null pointer is forwarded correctly + std::wstring newFileNameWstring; + const wchar_t* newFileName = nullptr; + + if (lpNewFileName) { + newFileNameWstring = ush::string_cast(lpNewFileName); + newFileName = newFileNameWstring.c_str(); + } PRE_REALCALL - res = MoveFileWithProgressW(existingFileName.c_str(), newFileName.c_str(), lpProgressRoutine, lpData, dwFlags); + res = MoveFileWithProgressW(existingFileName.c_str(), newFileName, lpProgressRoutine, lpData, dwFlags); POST_REALCALL HOOK_END From 496d2f8930e82b2c0e8265077727fc8fb25d31e8 Mon Sep 17 00:00:00 2001 From: Silarn Date: Sat, 19 Oct 2019 16:04:49 -0500 Subject: [PATCH 16/20] Update boost build path --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index f4199870..7f780a57 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -10,7 +10,7 @@ environment: WEBHOOK_URL: secure: gOKbXaZM9ImtMD5XrYITvdyZUW/az082G9OIN1EC1VZ2CuYaUUM6WY2eiNxaFeOL7/9Jyu/m+Vm1fH54CEyigcUUaxA7d8F5IMWlOgE/7YYdaAFSMUTFD7EK+++3FBYfmU1F/nZ61wsiWE6hB9Au5FpGBSCeQ0Tf8U8m0ybPmD0= before_build: -- ps: "echo $env:Platform\nif (${env:Platform} -eq \"x64\") {\n set-item -path Env:BOOST_LIBPATH -value ${Env:BOOST_PATH}\\lib64-msvc-14.1\n set-item -path Env:GTEST_BUILDDIR -value c:\\libraries\\googletest\\build \n}\nElse {\n set-item -path Env:BOOST_LIBPATH -value ${Env:BOOST_PATH}\\lib32-msvc-14.1\n set-item -path Env:GTEST_BUILDDIR -value c:\\libraries\\googletest\\build_32\n}\n\n. git clone --depth=1 --branch=master https://github.com/google/googletest.git c:\\libraries\\googletest 2> $null\nNew-Item $Env:GTEST_BUILDDIR -type directory\nSet-Location -Path $Env:GTEST_BUILDDIR\n. cmd /c \"`\"C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Community\\VC\\Auxiliary\\Build\\vcvarsall.bat`\" $env:Platform && cmake -G `\"NMake Makefiles`\" -DCMAKE_BUILD_TYPE=Release ..`\"\"\n. cmd /c \"`\"C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Community\\VC\\Auxiliary\\Build\\vcvarsall.bat`\" $env:Platform && nmake\"\n\nSet-Location -Path c:\\projects\\usvfs\\vsbuild\n#Tempory fix due to that appveyor has boost lib files in a custom output folder\nGet-ChildItem -Path *.props -recurse | ForEach {If (Get-Content $_.FullName | Select-String -Pattern '\\$\\(BOOST_PATH\\)\\\\.*\\\\lib') {(Get-Content $_ | ForEach {$_ -replace '\\$\\(BOOST_PATH\\)\\\\.*\\\\lib', \"$Env:BOOST_LIBPATH\"}) | Set-Content $_ }}\n\n#Need to tell usvfs to not use the BOOST_BUILDID\nGet-ChildItem -Path *.props -recurse | ForEach {If (Get-Content $_.FullName | Select-String -Pattern 'BOOST_LIB_BUILDID=x86;') {(Get-Content $_ | ForEach {$_ -replace 'BOOST_LIB_BUILDID=x86;', \"\"}) | Set-Content $_ }}\n\nSet-Location -Path c:\\projects\\usvfs\ngit submodule -q update --init --recursive" +- ps: "echo $env:Platform\nif (${env:Platform} -eq \"x64\") {\n set-item -path Env:BOOST_LIBPATH -value ${Env:BOOST_PATH}\\lib64-msvc-14.2\n set-item -path Env:GTEST_BUILDDIR -value c:\\libraries\\googletest\\build \n}\nElse {\n set-item -path Env:BOOST_LIBPATH -value ${Env:BOOST_PATH}\\lib32-msvc-14.2\n set-item -path Env:GTEST_BUILDDIR -value c:\\libraries\\googletest\\build_32\n}\n\n. git clone --depth=1 --branch=master https://github.com/google/googletest.git c:\\libraries\\googletest 2> $null\nNew-Item $Env:GTEST_BUILDDIR -type directory\nSet-Location -Path $Env:GTEST_BUILDDIR\n. cmd /c \"`\"C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Community\\VC\\Auxiliary\\Build\\vcvarsall.bat`\" $env:Platform && cmake -G `\"NMake Makefiles`\" -DCMAKE_BUILD_TYPE=Release ..`\"\"\n. cmd /c \"`\"C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Community\\VC\\Auxiliary\\Build\\vcvarsall.bat`\" $env:Platform && nmake\"\n\nSet-Location -Path c:\\projects\\usvfs\\vsbuild\n#Tempory fix due to that appveyor has boost lib files in a custom output folder\nGet-ChildItem -Path *.props -recurse | ForEach {If (Get-Content $_.FullName | Select-String -Pattern '\\$\\(BOOST_PATH\\)\\\\.*\\\\lib') {(Get-Content $_ | ForEach {$_ -replace '\\$\\(BOOST_PATH\\)\\\\.*\\\\lib', \"$Env:BOOST_LIBPATH\"}) | Set-Content $_ }}\n\n#Need to tell usvfs to not use the BOOST_BUILDID\nGet-ChildItem -Path *.props -recurse | ForEach {If (Get-Content $_.FullName | Select-String -Pattern 'BOOST_LIB_BUILDID=x86;') {(Get-Content $_ | ForEach {$_ -replace 'BOOST_LIB_BUILDID=x86;', \"\"}) | Set-Content $_ }}\n\nSet-Location -Path c:\\projects\\usvfs\ngit submodule -q update --init --recursive" build: project: vsbuild/usvfs.sln parallel: true From 7e21b4046431069e02655f76faef446d37eb4e7c Mon Sep 17 00:00:00 2001 From: isanae <14251494+isanae@users.noreply.github.com> Date: Fri, 1 Nov 2019 09:43:47 -0400 Subject: [PATCH 17/20] moved SharedParameters to its own file made members private, added functions added logging when changing parameters --- include/sharedparameters.h | 103 +++++++++++++++ include/usvfs.h | 3 +- include/usvfsparameters.h | 3 + src/usvfs_dll/hookcontext.cpp | 171 +++++++++++-------------- src/usvfs_dll/hookcontext.h | 69 +--------- src/usvfs_dll/sharedparameters.cpp | 194 +++++++++++++++++++++++++++++ src/usvfs_dll/usvfs.cpp | 19 ++- src/usvfs_dll/usvfsparameters.cpp | 43 +++++++ src/usvfs_proxy/main.cpp | 42 +++---- vsbuild/usvfs_dll.vcxproj | 2 + vsbuild/usvfs_dll.vcxproj.filters | 6 + 11 files changed, 468 insertions(+), 187 deletions(-) create mode 100644 include/sharedparameters.h create mode 100644 src/usvfs_dll/sharedparameters.cpp diff --git a/include/sharedparameters.h b/include/sharedparameters.h new file mode 100644 index 00000000..9e9c5262 --- /dev/null +++ b/include/sharedparameters.h @@ -0,0 +1,103 @@ +#pragma once + +#include "usvfsparameters.h" +#include "dllimport.h" +#include + +#include +#include +#include +#include + +namespace usvfs +{ + +class ForcedLibrary +{ +public: + ForcedLibrary( + const std::string& processName, const std::string& libraryPath, + const shared::VoidAllocatorT &allocator); + + std::string processName() const; + std::string libraryPath() const; + +private: + shared::StringT m_processName; + shared::StringT m_libraryPath; +}; + + +class DLLEXPORT SharedParameters +{ +public: + SharedParameters() = delete; + SharedParameters(const SharedParameters &reference) = delete; + SharedParameters &operator=(const SharedParameters &reference) = delete; + + SharedParameters(const usvfsParameters& reference, + const shared::VoidAllocatorT &allocator); + + usvfsParameters makeLocal() const; + + std::string instanceName() const; + std::string currentSHMName() const; + std::string currentInverseSHMName() const; + void setSHMNames(const std::string& current, const std::string& inverse); + + void setDebugParameters( + LogLevel level, CrashDumpsType dumpType, const std::string& dumpPath, + std::chrono::milliseconds delayProcess); + + std::size_t userConnected(); + std::size_t userDisconnected(); + std::size_t userCount(); + + std::size_t registeredProcessCount() const; + std::vector registeredProcesses() const; + void registerProcess(DWORD pid); + void unregisterProcess(DWORD pid); + + void blacklistExecutable(const std::string& name); + void clearExecutableBlacklist(); + bool executableBlacklisted(const std::string& app, const std::string& cmd) const; + + void addForcedLibrary(const std::string& process, const std::string& path); + std::vector forcedLibraries(const std::string& processName); + void clearForcedLibraries(); + +private: + using StringAllocatorT = + shared::VoidAllocatorT::rebind::other; + + using DWORDAllocatorT = shared::VoidAllocatorT::rebind::other; + + using ForcedLibraryAllocatorT = + shared::VoidAllocatorT::rebind::other; + + + using ProcessBlacklist = boost::container::flat_set< + shared::StringT, std::less, StringAllocatorT>; + + using ProcessList = boost::container::flat_set< + DWORD, std::less, DWORDAllocatorT>; + + using ForcedLibraries = boost::container::slist< + ForcedLibrary, ForcedLibraryAllocatorT>; + + + shared::StringT m_instanceName; + shared::StringT m_currentSHMName; + shared::StringT m_currentInverseSHMName; + bool m_debugMode; + LogLevel m_logLevel; + CrashDumpsType m_crashDumpsType; + shared::StringT m_crashDumpsPath; + std::chrono::milliseconds m_delayProcess; + uint32_t m_userCount; + ProcessBlacklist m_processBlacklist; + ProcessList m_processList; + ForcedLibraries m_forcedLibraries; +}; + +} // namespace diff --git a/include/usvfs.h b/include/usvfs.h index 470c986d..00f5add5 100644 --- a/include/usvfs.h +++ b/include/usvfs.h @@ -185,8 +185,7 @@ DLLEXPORT void WINAPI USVFSInitParameters(USVFSParameters *parameters, [[deprecated("deprecated, use usvfsUpdateParameters()")]] DLLEXPORT void WINAPI USVFSUpdateParams(LogLevel level, CrashDumpsType type); -// the only information used from the parameters are the crash dump type, log -// level and process delay +// the instance and shm names are not updated // DLLEXPORT void WINAPI usvfsUpdateParameters(usvfsParameters* p); diff --git a/include/usvfsparameters.h b/include/usvfsparameters.h index f0710b8f..d4c96f2e 100644 --- a/include/usvfsparameters.h +++ b/include/usvfsparameters.h @@ -61,4 +61,7 @@ DLLEXPORT void usvfsSetCrashDumpType(usvfsParameters* p, CrashDumpsType type); DLLEXPORT void usvfsSetCrashDumpPath(usvfsParameters* p, const char* path); DLLEXPORT void usvfsSetProcessDelay(usvfsParameters* p, int milliseconds); +DLLEXPORT const char* usvfsLogLevelToString(LogLevel lv); +DLLEXPORT const char* usvfsCrashDumpTypeToString(CrashDumpsType t); + } diff --git a/src/usvfs_dll/hookcontext.cpp b/src/usvfs_dll/hookcontext.cpp index 72965a32..5f661f1b 100644 --- a/src/usvfs_dll/hookcontext.cpp +++ b/src/usvfs_dll/hookcontext.cpp @@ -23,10 +23,10 @@ along with usvfs. If not, see . #include "usvfs.h" #include "hookcallcontext.h" #include +#include #include #include #include "loghelpers.h" -#include namespace bi = boost::interprocess; using usvfs::shared::SharedMemoryT; @@ -56,23 +56,12 @@ void printBuffer(const char *buffer, size_t size) } -usvfsParameters SharedParameters::makeLocal() const -{ - return usvfsParameters( - instanceName.c_str(), - currentSHMName.c_str(), - currentInverseSHMName.c_str(), - debugMode, logLevel, crashDumpsType, - crashDumpsPath.c_str(), - delayProcess.count()); -} - HookContext::HookContext(const usvfsParameters& params, HMODULE module) : m_ConfigurationSHM(bi::open_or_create, params.instanceName, 8192) , m_Parameters(retrieveParameters(params)) - , m_Tree(m_Parameters->currentSHMName.c_str(), 65536) - , m_InverseTree(m_Parameters->currentInverseSHMName.c_str(), 65536) + , m_Tree(m_Parameters->currentSHMName(), 65536) + , m_InverseTree(m_Parameters->currentInverseSHMName(), 65536) , m_DebugMode(params.debugMode) , m_DLLModule(module) { @@ -80,11 +69,11 @@ HookContext::HookContext(const usvfsParameters& params, HMODULE module) throw std::runtime_error("singleton duplicate instantiation (HookContext)"); } - ++m_Parameters->userCount; + const auto userCount = m_Parameters->userConnected(); - spdlog::get("usvfs")->debug("context current shm: {0} (now {1} connections)", - m_Parameters->currentSHMName.c_str(), - m_Parameters->userCount); + spdlog::get("usvfs")->debug( + "context current shm: {0} (now {1} connections)", + m_Parameters->currentSHMName(), userCount); s_Instance = this; @@ -102,14 +91,15 @@ void HookContext::remove(const char *instanceName) HookContext::~HookContext() { spdlog::get("usvfs")->info("releasing hook context"); + s_Instance = nullptr; + const auto userCount = m_Parameters->userDisconnected(); - if (--m_Parameters->userCount == 0) { - spdlog::get("usvfs") - ->info("removing tree {}", m_Parameters->instanceName.c_str()); - bi::shared_memory_object::remove(m_Parameters->instanceName.c_str()); + if (userCount == 0) { + spdlog::get("usvfs")->info("removing tree {}", m_Parameters->instanceName()); + bi::shared_memory_object::remove(m_Parameters->instanceName().c_str()); } else { - spdlog::get("usvfs")->info("{} users left", m_Parameters->userCount); + spdlog::get("usvfs")->info("{} users left", userCount); } } @@ -117,19 +107,25 @@ SharedParameters *HookContext::retrieveParameters(const usvfsParameters& params) { std::pair res = m_ConfigurationSHM.find("parameters"); + if (res.first == nullptr) { // not configured yet spdlog::get("usvfs")->info("create config in {}", ::GetCurrentProcessId()); + res.first = m_ConfigurationSHM.construct("parameters")( params, VoidAllocatorT(m_ConfigurationSHM.get_segment_manager())); + if (res.first == nullptr) { USVFS_THROW_EXCEPTION(bi::bad_alloc()); } } else { - spdlog::get("usvfs") - ->info("access existing config in {}", ::GetCurrentProcessId()); + spdlog::get("usvfs")->info( + "access existing config in {}", ::GetCurrentProcessId()); } - spdlog::get("usvfs")->info("{} processes - {}", res.first->processList.size(), (int)res.first->logLevel); + + spdlog::get("usvfs")->info( + "{} processes", res.first->registeredProcessCount()); + return res.first; } @@ -150,25 +146,17 @@ HookContext::Ptr HookContext::writeAccess(const char*) return Ptr(s_Instance, unlock); } -void HookContext::setLogLevel(LogLevel level) -{ - m_Parameters->logLevel = level; -} -void HookContext::setCrashDumpsType(CrashDumpsType type) +void HookContext::setDebugParameters( + LogLevel level, CrashDumpsType dumpType, const std::string& dumpPath, + std::chrono::milliseconds delayProcess) { - m_Parameters->crashDumpsType = type; -} - -void HookContext::setDelayProcess(std::chrono::milliseconds delay) -{ - m_Parameters->delayProcess = delay; + m_Parameters->setDebugParameters(level, dumpType, dumpPath, delayProcess); } void HookContext::updateParameters() const { - m_Parameters->currentSHMName = m_Tree.shmName().c_str(); - m_Parameters->currentInverseSHMName = m_InverseTree.shmName().c_str(); + m_Parameters->setSHMNames(m_Tree.shmName(), m_InverseTree.shmName()); } usvfsParameters HookContext::callParameters() const @@ -185,90 +173,81 @@ std::wstring HookContext::dllPath() const void HookContext::registerProcess(DWORD pid) { - m_Parameters->processList.insert(pid); + m_Parameters->registerProcess(pid); +} + +void HookContext::unregisterCurrentProcess() +{ + m_Parameters->unregisterProcess(::GetCurrentProcessId()); +} + +std::vector HookContext::registeredProcesses() const +{ + return m_Parameters->registeredProcesses(); } -void HookContext::blacklistExecutable(const std::wstring &executableName) +void HookContext::blacklistExecutable(const std::wstring& wexe) { - m_Parameters->processBlacklist.insert(shared::StringT( - shared::string_cast(executableName, shared::CodePage::UTF8) - .c_str(), - m_Parameters->processBlacklist.get_allocator())); + const auto exe = shared::string_cast( + wexe, shared::CodePage::UTF8); + + spdlog::get("usvfs")->debug("blacklisting '{}'", exe); + m_Parameters->blacklistExecutable(exe); } void HookContext::clearExecutableBlacklist() { - m_Parameters->processBlacklist.clear(); + spdlog::get("usvfs")->debug("clearing blacklist"); + m_Parameters->clearExecutableBlacklist(); } -BOOL HookContext::executableBlacklisted(LPCWSTR lpApplicationName, LPCWSTR lpCommandLine) const +BOOL HookContext::executableBlacklisted(LPCWSTR wapp, LPCWSTR wcmd) const { - BOOL blacklisted = FALSE; - - if (lpApplicationName) { - std::string appName = ush::string_cast(lpApplicationName, ush::CodePage::UTF8); - for (shared::StringT item : m_Parameters->processBlacklist) { - if (boost::algorithm::iends_with(appName, std::string(item.data(), item.size()))) { - spdlog::get("usvfs")->info("application {} is blacklisted", appName); - blacklisted = TRUE; - break; - } - } + std::string app; + if (wapp) { + app = ush::string_cast(wapp, ush::CodePage::UTF8); } - if (lpCommandLine) { - std::string cmdLine = ush::string_cast(lpCommandLine, ush::CodePage::UTF8); - for (shared::StringT item : m_Parameters->processBlacklist) { - if (boost::algorithm::icontains(cmdLine, std::string(item.data(), item.size()))) { - spdlog::get("usvfs")->info("command line {} is blacklisted", cmdLine); - blacklisted = TRUE; - break; - } - } + std::string cmd; + if (wcmd) { + cmd = ush::string_cast(wcmd, ush::CodePage::UTF8); } - return blacklisted; + return m_Parameters->executableBlacklisted(app, cmd); } -void HookContext::forceLoadLibrary(const std::wstring &processName, const std::wstring &libraryPath) +void HookContext::forceLoadLibrary( + const std::wstring& wprocess, const std::wstring& wpath) { - m_Parameters->forcedLibraries.push_front(ForcedLibrary( - shared::string_cast(processName, shared::CodePage::UTF8).c_str(), - shared::string_cast(libraryPath, shared::CodePage::UTF8).c_str(), - m_Parameters->forcedLibraries.get_allocator())); + const auto process = shared::string_cast( + wprocess, shared::CodePage::UTF8); + + const auto path = shared::string_cast( + wpath, shared::CodePage::UTF8); + + spdlog::get("usvfs")->debug( + "adding forced library '{}' for process '{}'", path, process); + + m_Parameters->addForcedLibrary(process, path); } void HookContext::clearLibraryForceLoads() { - m_Parameters->forcedLibraries.clear(); + spdlog::get("usvfs")->debug("clearing forced libraries"); + m_Parameters->clearForcedLibraries(); } std::vector HookContext::librariesToForceLoad(const std::wstring &processName) { - std::vector results; - for (auto library : m_Parameters->forcedLibraries) { - std::string processNameString = shared::string_cast(processName, shared::CodePage::UTF8); - if (stricmp(processNameString.c_str(), library.processName.c_str()) == 0) { - std::wstring libraryPathString = shared::string_cast(library.libraryPath.c_str(), shared::CodePage::UTF8); - results.push_back(libraryPathString); - } - } - return results; -} + const auto v = m_Parameters->forcedLibraries( + shared::string_cast(processName, shared::CodePage::UTF8)); -void HookContext::unregisterCurrentProcess() -{ - auto iter = m_Parameters->processList.find(::GetCurrentProcessId()); - m_Parameters->processList.erase(iter); -} - -std::vector HookContext::registeredProcesses() const -{ - std::vector result; - for (DWORD procId : m_Parameters->processList) { - result.push_back(procId); + std::vector wv; + for (const auto& s : v) { + wv.push_back(shared::string_cast(s, shared::CodePage::UTF8)); } - return result; + + return wv; } void HookContext::registerDelayed(std::future delayed) diff --git a/src/usvfs_dll/hookcontext.h b/src/usvfs_dll/hookcontext.h index f23c71bc..27de0cf8 100644 --- a/src/usvfs_dll/hookcontext.h +++ b/src/usvfs_dll/hookcontext.h @@ -32,9 +32,6 @@ along with usvfs. If not, see . #include #include #include -#include -#include -#include #include #include #include @@ -43,65 +40,7 @@ along with usvfs. If not, see . namespace usvfs { -typedef shared::VoidAllocatorT::rebind::other DWORDAllocatorT; -typedef shared::VoidAllocatorT::rebind::other StringAllocatorT; - -struct ForcedLibrary { - ForcedLibrary(const char *processName, const char *libraryPath, - const shared::VoidAllocatorT &allocator) - : processName(processName, allocator) - , libraryPath(libraryPath, allocator) - { - } - - shared::StringT processName; - shared::StringT libraryPath; -}; - -typedef shared::VoidAllocatorT::rebind::other ForcedLibraryAllocatorT; - -struct SharedParameters { - - SharedParameters() = delete; - - SharedParameters(const SharedParameters &reference) = delete; - - SharedParameters &operator=(const SharedParameters &reference) = delete; - - SharedParameters(const usvfsParameters& reference, - const shared::VoidAllocatorT &allocator) - : instanceName(reference.instanceName, allocator) - , currentSHMName(reference.currentSHMName, allocator) - , currentInverseSHMName(reference.currentInverseSHMName, allocator) - , debugMode(reference.debugMode) - , logLevel(reference.logLevel) - , crashDumpsType(reference.crashDumpsType) - , crashDumpsPath(reference.crashDumpsPath, allocator) - , delayProcess(reference.delayProcessMs) - , userCount(1) - , processBlacklist(allocator) - , processList(allocator) - , forcedLibraries(allocator) - { - } - - DLLEXPORT usvfsParameters makeLocal() const; - - shared::StringT instanceName; - shared::StringT currentSHMName; - shared::StringT currentInverseSHMName; - bool debugMode; - LogLevel logLevel; - CrashDumpsType crashDumpsType; - shared::StringT crashDumpsPath; - std::chrono::milliseconds delayProcess; - uint32_t userCount; - boost::container::flat_set, - StringAllocatorT> processBlacklist; - boost::container::flat_set, DWORDAllocatorT> processList; - boost::container::slist forcedLibraries; -}; - +class DLLEXPORT SharedParameters; /** * @brief context available to hooks. This is protected by a many-reader @@ -216,9 +155,9 @@ class HookContext void clearLibraryForceLoads(); std::vector librariesToForceLoad(const std::wstring &processName); - void setLogLevel(LogLevel level); - void setCrashDumpsType(CrashDumpsType type); - void setDelayProcess(std::chrono::milliseconds delay); + void setDebugParameters( + LogLevel level, CrashDumpsType dumpType, const std::string& dumpPath, + std::chrono::milliseconds delayProcess); void updateParameters() const; diff --git a/src/usvfs_dll/sharedparameters.cpp b/src/usvfs_dll/sharedparameters.cpp new file mode 100644 index 00000000..4424bcbc --- /dev/null +++ b/src/usvfs_dll/sharedparameters.cpp @@ -0,0 +1,194 @@ +#include +#include +#include +#include +#include + +namespace usvfs +{ + +ForcedLibrary::ForcedLibrary( + const std::string& process, const std::string& path, + const shared::VoidAllocatorT& alloc) : + m_processName(process.begin(), process.end(), alloc), + m_libraryPath(path.begin(), path.end(), alloc) +{ +} + +std::string ForcedLibrary::processName() const +{ + return {m_processName.begin(), m_processName.end()}; +} + +std::string ForcedLibrary::libraryPath() const +{ + return {m_libraryPath.begin(), m_libraryPath.end()}; +} + + +SharedParameters::SharedParameters(const usvfsParameters& reference, + const shared::VoidAllocatorT &allocator) + : m_instanceName(reference.instanceName, allocator) + , m_currentSHMName(reference.currentSHMName, allocator) + , m_currentInverseSHMName(reference.currentInverseSHMName, allocator) + , m_debugMode(reference.debugMode) + , m_logLevel(reference.logLevel) + , m_crashDumpsType(reference.crashDumpsType) + , m_crashDumpsPath(reference.crashDumpsPath, allocator) + , m_delayProcess(reference.delayProcessMs) + , m_userCount(1) + , m_processBlacklist(allocator) + , m_processList(allocator) + , m_forcedLibraries(allocator) +{ +} + +usvfsParameters SharedParameters::makeLocal() const +{ + return usvfsParameters( + m_instanceName.c_str(), + m_currentSHMName.c_str(), + m_currentInverseSHMName.c_str(), + m_debugMode, m_logLevel, m_crashDumpsType, + m_crashDumpsPath.c_str(), + m_delayProcess.count()); +} + +std::string SharedParameters::instanceName() const +{ + return {m_instanceName.begin(), m_instanceName.end()}; +} + +std::string SharedParameters::currentSHMName() const +{ + return {m_currentSHMName.begin(), m_currentSHMName.end()}; +} + +std::string SharedParameters::currentInverseSHMName() const +{ + return {m_currentInverseSHMName.begin(), m_currentInverseSHMName.end()}; +} + +void SharedParameters::setSHMNames( + const std::string& current, const std::string& inverse) +{ + m_currentSHMName.assign(current.begin(), current.end()); + m_currentInverseSHMName.assign(inverse.begin(), inverse.end()); +} + +void SharedParameters::setDebugParameters( + LogLevel level, CrashDumpsType dumpType, const std::string& dumpPath, + std::chrono::milliseconds delayProcess) +{ + m_logLevel = level; + m_crashDumpsType = dumpType; + m_crashDumpsPath.assign(dumpPath.begin(), dumpPath.end()); + m_delayProcess = delayProcess; +} + +std::size_t SharedParameters::userConnected() +{ + return ++m_userCount; +} + +std::size_t SharedParameters::userDisconnected() +{ + return --m_userCount; +} + +std::size_t SharedParameters::userCount() +{ + return m_userCount; +} + +std::size_t SharedParameters::registeredProcessCount() const +{ + return m_processList.size(); +} + +std::vector SharedParameters::registeredProcesses() const +{ + return {m_processList.begin(), m_processList.end()}; +} + +void SharedParameters::registerProcess(DWORD pid) +{ + m_processList.insert(pid); +} + +void SharedParameters::unregisterProcess(DWORD pid) +{ + auto itor = m_processList.find(pid); + + if (itor == m_processList.end()) { + spdlog::get("usvfs")->error( + "cannot unregister process {}, not in list", pid); + + return; + } + + m_processList.erase(itor); +} + +void SharedParameters::blacklistExecutable(const std::string& name) +{ + m_processBlacklist.insert(shared::StringT( + name.begin(), name.end(), m_processBlacklist.get_allocator())); +} + +void SharedParameters::clearExecutableBlacklist() +{ + m_processBlacklist.clear(); +} + +bool SharedParameters::executableBlacklisted( + const std::string& appName, const std::string& cmdLine) const +{ + for (const shared::StringT& sitem : m_processBlacklist) { + const auto item = "\\" + std::string(sitem.begin(), sitem.end()); + + if (!appName.empty()) { + if (boost::algorithm::iends_with(appName, item)) { + spdlog::get("usvfs")->info("application {} is blacklisted", appName); + return true; + } + } + + if (!cmdLine.empty()) { + if (boost::algorithm::icontains(cmdLine, item)) { + spdlog::get("usvfs")->info("command line {} is blacklisted", cmdLine); + return true; + } + } + } + + return false; +} + +void SharedParameters::addForcedLibrary( + const std::string& processName, const std::string& libraryPath) +{ + m_forcedLibraries.push_front(ForcedLibrary( + processName, libraryPath, m_forcedLibraries.get_allocator())); +} + +std::vector SharedParameters::forcedLibraries( + const std::string& processName) +{ + std::vector v; + + for (const auto& lib : m_forcedLibraries) { + if (boost::algorithm::iequals(processName, lib.processName())) { + v.push_back(lib.libraryPath()); + } + } + + return v; +} + +void SharedParameters::clearForcedLibraries() +{ + m_forcedLibraries.clear(); +} + +} // namespace diff --git a/src/usvfs_dll/usvfs.cpp b/src/usvfs_dll/usvfs.cpp index 31070f33..560dca24 100644 --- a/src/usvfs_dll/usvfs.cpp +++ b/src/usvfs_dll/usvfs.cpp @@ -184,14 +184,27 @@ void WINAPI USVFSUpdateParams(LogLevel level, CrashDumpsType type) void WINAPI usvfsUpdateParameters(usvfsParameters* p) { + spdlog::get("usvfs")->info( + "updating parameters:\n" + " . debugMode: {}\n" + " . log level: {}\n" + " . dump type: {}\n" + " . dump path: {}\n" + " . delay process: {}ms", + p->debugMode, usvfsLogLevelToString(p->logLevel), + usvfsCrashDumpTypeToString(p->crashDumpsType), p->crashDumpsPath, + p->delayProcessMs); + // update actual values used: usvfs_dump_type = p->crashDumpsType; + usvfs_dump_path = ush::string_cast( + p->crashDumpsPath, ush::CodePage::UTF8); SetLogLevel(p->logLevel); // update parameters in context so spawned process will inherit changes: - context->setLogLevel(p->logLevel); - context->setCrashDumpsType(p->crashDumpsType); - context->setDelayProcess(std::chrono::milliseconds(p->delayProcessMs)); + context->setDebugParameters( + p->logLevel, p->crashDumpsType, p->crashDumpsPath, + std::chrono::milliseconds(p->delayProcessMs)); } diff --git a/src/usvfs_dll/usvfsparameters.cpp b/src/usvfs_dll/usvfsparameters.cpp index 60900b4f..de8a9969 100644 --- a/src/usvfs_dll/usvfsparameters.cpp +++ b/src/usvfs_dll/usvfsparameters.cpp @@ -89,6 +89,49 @@ void usvfsParameters::setProcessDelay(int milliseconds) extern "C" { +const char* usvfsLogLevelToString(LogLevel lv) +{ + switch (lv) + { + case LogLevel::Debug: + return "debug"; + + case LogLevel::Info: + return "info"; + + case LogLevel::Warning: + return "warning"; + + case LogLevel::Error: + return "error"; + + default: + return "unknown"; + } +} + +const char* usvfsCrashDumpTypeToString(CrashDumpsType t) +{ + switch (t) + { + case CrashDumpsType::None: + return "none"; + + case CrashDumpsType::Mini: + return "mini"; + + case CrashDumpsType::Data: + return "data"; + + case CrashDumpsType::Full: + return "full"; + + default: + return "unknown"; + } +} + + usvfsParameters* usvfsCreateParameters() { return new (std::nothrow) usvfsParameters; diff --git a/src/usvfs_proxy/main.cpp b/src/usvfs_proxy/main.cpp index 31cd5abd..e790c0f6 100644 --- a/src/usvfs_proxy/main.cpp +++ b/src/usvfs_proxy/main.cpp @@ -22,6 +22,7 @@ along with usvfs. If not, see . #include #include #include +#include #include <../usvfs_dll/hookcontext.h> #include #include @@ -151,8 +152,6 @@ int main(int argc, char **argv) { return 1; } - usvfsParameters par = params.first->makeLocal(); - boost::filesystem::path p(winapi::wide::getModuleFileName(nullptr)); if (executable.empty()) { @@ -164,20 +163,20 @@ int main(int argc, char **argv) { BOOL blacklisted = FALSE; TCHAR szModName[MAX_PATH]; + if (GetModuleFileNameEx(processHandle, NULL, szModName, sizeof(szModName) / sizeof(TCHAR))) { - for (usvfs::shared::StringT exec : params.first->processBlacklist) { - if (boost::algorithm::iends_with(std::wstring(szModName), - "\\" + std::string(exec.data(), exec.size()))) { - logger->info("not injecting {} as application is blacklisted", - usvfs::shared::string_cast(std::wstring(szModName))); - blacklisted = TRUE; - break; - } + const auto appName = usvfs::shared::string_cast(szModName); + + if (params.first->executableBlacklisted(appName, {})) { + logger->info("not injecting {} as application is blacklisted", appName); + blacklisted = TRUE; } } + if (!blacklisted) { - usvfs::injectProcess(p.parent_path().wstring(), par, processHandle, - threadHandle); + usvfs::injectProcess( + p.parent_path().wstring(), params.first->makeLocal(), + processHandle, threadHandle); } } else { winapi::process::Result process = @@ -191,17 +190,18 @@ int main(int argc, char **argv) { } BOOL blacklisted = FALSE; - for (usvfs::shared::StringT exec : params.first->processBlacklist) { - if (boost::algorithm::iends_with(executable, - "\\" + std::string(exec.data(), exec.size()))) { - logger->info("not injecting {} as application is blacklisted", - std::string(exec.data(), exec.size())); - blacklisted = TRUE; - break; - } + + if (params.first->executableBlacklisted(executable, {})) { + logger->info( + "not injecting {} as application is blacklisted", executable); + + blacklisted = TRUE; } + if (!blacklisted) { - usvfs::injectProcess(p.parent_path().wstring(), par, process.processInfo); + usvfs::injectProcess( + p.parent_path().wstring(), params.first->makeLocal(), + process.processInfo); } ResumeThread(process.processInfo.hThread); diff --git a/vsbuild/usvfs_dll.vcxproj b/vsbuild/usvfs_dll.vcxproj index 968a9a50..df20806c 100644 --- a/vsbuild/usvfs_dll.vcxproj +++ b/vsbuild/usvfs_dll.vcxproj @@ -212,6 +212,7 @@ + @@ -219,6 +220,7 @@ + diff --git a/vsbuild/usvfs_dll.vcxproj.filters b/vsbuild/usvfs_dll.vcxproj.filters index c8033810..f1c63d39 100644 --- a/vsbuild/usvfs_dll.vcxproj.filters +++ b/vsbuild/usvfs_dll.vcxproj.filters @@ -59,6 +59,9 @@ Source Files + + Source Files + @@ -112,5 +115,8 @@ Header Files\include + + Header Files\include + \ No newline at end of file From 60e11109b808fe76804a197595c3c5d55b9862c9 Mon Sep 17 00:00:00 2001 From: isanae <14251494+isanae@users.noreply.github.com> Date: Fri, 1 Nov 2019 10:06:37 -0400 Subject: [PATCH 18/20] added a mutex that's used for all operations on SharedParameters --- include/sharedparameters.h | 1 + src/usvfs_dll/hookcontext.h | 1 - src/usvfs_dll/sharedparameters.cpp | 82 ++++++++++++++++++++++-------- 3 files changed, 63 insertions(+), 21 deletions(-) diff --git a/include/sharedparameters.h b/include/sharedparameters.h index 9e9c5262..ec299cc2 100644 --- a/include/sharedparameters.h +++ b/include/sharedparameters.h @@ -86,6 +86,7 @@ class DLLEXPORT SharedParameters ForcedLibrary, ForcedLibraryAllocatorT>; + mutable bi::interprocess_mutex m_mutex; shared::StringT m_instanceName; shared::StringT m_currentSHMName; shared::StringT m_currentInverseSHMName; diff --git a/src/usvfs_dll/hookcontext.h b/src/usvfs_dll/hookcontext.h index 27de0cf8..c5225c34 100644 --- a/src/usvfs_dll/hookcontext.h +++ b/src/usvfs_dll/hookcontext.h @@ -175,7 +175,6 @@ class HookContext static HookContext *s_Instance; shared::SharedMemoryT m_ConfigurationSHM; -#pragma message("this should be protected by a system-wide named mutex") SharedParameters *m_Parameters{nullptr}; RedirectionTreeContainer m_Tree; RedirectionTreeContainer m_InverseTree; diff --git a/src/usvfs_dll/sharedparameters.cpp b/src/usvfs_dll/sharedparameters.cpp index 4424bcbc..01e22253 100644 --- a/src/usvfs_dll/sharedparameters.cpp +++ b/src/usvfs_dll/sharedparameters.cpp @@ -45,6 +45,8 @@ SharedParameters::SharedParameters(const usvfsParameters& reference, usvfsParameters SharedParameters::makeLocal() const { + bi::scoped_lock lock(m_mutex); + return usvfsParameters( m_instanceName.c_str(), m_currentSHMName.c_str(), @@ -56,22 +58,27 @@ usvfsParameters SharedParameters::makeLocal() const std::string SharedParameters::instanceName() const { + bi::scoped_lock lock(m_mutex); return {m_instanceName.begin(), m_instanceName.end()}; } std::string SharedParameters::currentSHMName() const { + bi::scoped_lock lock(m_mutex); return {m_currentSHMName.begin(), m_currentSHMName.end()}; } std::string SharedParameters::currentInverseSHMName() const { + bi::scoped_lock lock(m_mutex); return {m_currentInverseSHMName.begin(), m_currentInverseSHMName.end()}; } void SharedParameters::setSHMNames( const std::string& current, const std::string& inverse) { + bi::scoped_lock lock(m_mutex); + m_currentSHMName.assign(current.begin(), current.end()); m_currentInverseSHMName.assign(inverse.begin(), inverse.end()); } @@ -80,6 +87,8 @@ void SharedParameters::setDebugParameters( LogLevel level, CrashDumpsType dumpType, const std::string& dumpPath, std::chrono::milliseconds delayProcess) { + bi::scoped_lock lock(m_mutex); + m_logLevel = level; m_crashDumpsType = dumpType; m_crashDumpsPath.assign(dumpPath.begin(), dumpPath.end()); @@ -88,86 +97,114 @@ void SharedParameters::setDebugParameters( std::size_t SharedParameters::userConnected() { + bi::scoped_lock lock(m_mutex); return ++m_userCount; } std::size_t SharedParameters::userDisconnected() { + bi::scoped_lock lock(m_mutex); return --m_userCount; } std::size_t SharedParameters::userCount() { + bi::scoped_lock lock(m_mutex); return m_userCount; } std::size_t SharedParameters::registeredProcessCount() const { + bi::scoped_lock lock(m_mutex); return m_processList.size(); } std::vector SharedParameters::registeredProcesses() const { + bi::scoped_lock lock(m_mutex); return {m_processList.begin(), m_processList.end()}; } void SharedParameters::registerProcess(DWORD pid) { + bi::scoped_lock lock(m_mutex); m_processList.insert(pid); } void SharedParameters::unregisterProcess(DWORD pid) { - auto itor = m_processList.find(pid); + { + bi::scoped_lock lock(m_mutex); - if (itor == m_processList.end()) { - spdlog::get("usvfs")->error( - "cannot unregister process {}, not in list", pid); + auto itor = m_processList.find(pid); - return; + if (itor != m_processList.end()) { + m_processList.erase(itor); + return; + } } - m_processList.erase(itor); + spdlog::get("usvfs")->error( + "cannot unregister process {}, not in list", pid); } void SharedParameters::blacklistExecutable(const std::string& name) { + bi::scoped_lock lock(m_mutex); + m_processBlacklist.insert(shared::StringT( name.begin(), name.end(), m_processBlacklist.get_allocator())); } void SharedParameters::clearExecutableBlacklist() { + bi::scoped_lock lock(m_mutex); m_processBlacklist.clear(); } bool SharedParameters::executableBlacklisted( const std::string& appName, const std::string& cmdLine) const { - for (const shared::StringT& sitem : m_processBlacklist) { - const auto item = "\\" + std::string(sitem.begin(), sitem.end()); + bool blacklisted = false; + std::string log; + + { + bi::scoped_lock lock(m_mutex); + + for (const shared::StringT& sitem : m_processBlacklist) { + const auto item = "\\" + std::string(sitem.begin(), sitem.end()); - if (!appName.empty()) { - if (boost::algorithm::iends_with(appName, item)) { - spdlog::get("usvfs")->info("application {} is blacklisted", appName); - return true; + if (!appName.empty()) { + if (boost::algorithm::iends_with(appName, item)) { + blacklisted = true; + log = fmt::format("application {} is blacklisted", appName); + break; + } } - } - if (!cmdLine.empty()) { - if (boost::algorithm::icontains(cmdLine, item)) { - spdlog::get("usvfs")->info("command line {} is blacklisted", cmdLine); - return true; + if (!cmdLine.empty()) { + if (boost::algorithm::icontains(cmdLine, item)) { + blacklisted = true; + log = fmt::format("command line {} is blacklisted", cmdLine); + break; + } } } } + if (blacklisted) { + spdlog::get("usvfs")->info(log); + return true; + } + return false; } void SharedParameters::addForcedLibrary( const std::string& processName, const std::string& libraryPath) { + bi::scoped_lock lock(m_mutex); + m_forcedLibraries.push_front(ForcedLibrary( processName, libraryPath, m_forcedLibraries.get_allocator())); } @@ -177,9 +214,13 @@ std::vector SharedParameters::forcedLibraries( { std::vector v; - for (const auto& lib : m_forcedLibraries) { - if (boost::algorithm::iequals(processName, lib.processName())) { - v.push_back(lib.libraryPath()); + { + bi::scoped_lock lock(m_mutex); + + for (const auto& lib : m_forcedLibraries) { + if (boost::algorithm::iequals(processName, lib.processName())) { + v.push_back(lib.libraryPath()); + } } } @@ -188,6 +229,7 @@ std::vector SharedParameters::forcedLibraries( void SharedParameters::clearForcedLibraries() { + bi::scoped_lock lock(m_mutex); m_forcedLibraries.clear(); } From fc442823eeed2e55a09eb853996f8b918ea855c7 Mon Sep 17 00:00:00 2001 From: isanae <14251494+isanae@users.noreply.github.com> Date: Fri, 1 Nov 2019 05:02:05 -0400 Subject: [PATCH 19/20] added GetVFSProcessList2() to return all the pids --- include/usvfs.h | 14 ++++++++++++++ src/usvfs_dll/usvfs.cpp | 29 +++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+) diff --git a/include/usvfs.h b/include/usvfs.h index 00f5add5..cde8fbea 100644 --- a/include/usvfs.h +++ b/include/usvfs.h @@ -106,6 +106,20 @@ DLLEXPORT void WINAPI GetCurrentVFSName(char *buffer, size_t size); */ DLLEXPORT BOOL WINAPI GetVFSProcessList(size_t *count, LPDWORD processIDs); +// retrieve a list of all processes connected to the vfs, stores an array +// of `count` elements in `*buffer` +// +// if this returns TRUE and `count` is not 0, the caller must release the buffer +// with `free(*buffer)` +// +// return values: +// - ERROR_INVALID_PARAMETERS: either `count` or `buffer` is NULL +// - ERROR_TOO_MANY_OPEN_FILES: there seems to be way too many usvfs processes +// running, probably some internal error +// - ERROR_NOT_ENOUGH_MEMORY: malloc() failed +// +DLLEXPORT BOOL WINAPI GetVFSProcessList2(size_t* count, DWORD** buffer); + /** * spawn a new process that can see the virtual file system. The signature is identical to CreateProcess */ diff --git a/src/usvfs_dll/usvfs.cpp b/src/usvfs_dll/usvfs.cpp index 560dca24..0c8603d4 100644 --- a/src/usvfs_dll/usvfs.cpp +++ b/src/usvfs_dll/usvfs.cpp @@ -532,6 +532,35 @@ BOOL WINAPI GetVFSProcessList(size_t *count, LPDWORD processIDs) return TRUE; } +BOOL WINAPI GetVFSProcessList2(size_t* count, DWORD** buffer) +{ + if (!count || !buffer) { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + *count = 0; + *buffer = nullptr; + + std::vector pids = context->registeredProcesses(); + auto last = std::remove_if(pids.begin(), pids.end(), [](DWORD id) { + return !processStillActive(id); + }); + + pids.erase(last, pids.end()); + + if (pids.empty()) { + return TRUE; + } + + *count = pids.size(); + *buffer = static_cast(std::calloc(pids.size(), sizeof(DWORD))); + + std::copy(pids.begin(), pids.end(), *buffer); + + return TRUE; +} + void WINAPI ClearVirtualMappings() { context->redirectionTable()->clear(); From 1ed88ab1f513da010fcaace8badddab4c535ec03 Mon Sep 17 00:00:00 2001 From: isanae <14251494+isanae@users.noreply.github.com> Date: Mon, 25 Nov 2019 06:04:05 -0500 Subject: [PATCH 20/20] bumped to 4.4.6 --- include/usvfs_version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/usvfs_version.h b/include/usvfs_version.h index 261600c2..12e91f07 100644 --- a/include/usvfs_version.h +++ b/include/usvfs_version.h @@ -3,7 +3,7 @@ #define USVFS_VERSION_MAJOR 0 #define USVFS_VERSION_MINOR 4 #define USVFS_VERSION_BUILD 4 -#define USVFS_VERSION_REVISION 5 +#define USVFS_VERSION_REVISION 6 #define USVFS_BUILD_STRING "" #define USVFS_BUILD_WSTRING L""