diff --git a/GlosSITarget/AppLauncher.cpp b/GlosSITarget/AppLauncher.cpp index 4ed9ec0..92ebe32 100644 --- a/GlosSITarget/AppLauncher.cpp +++ b/GlosSITarget/AppLauncher.cpp @@ -112,30 +112,6 @@ void AppLauncher::close() #endif } -void AppLauncher::launchWatchdog() -{ - // wchar_t buff[MAX_PATH]; - // GetModuleFileName(GetModuleHandle(NULL), buff, MAX_PATH); - // const std::wstring glossipath(buff); - - // GetWindowsDirectory(buff, MAX_PATH); - // const std::wstring winpath(buff); - - // launchWin32App( - // (glossipath.substr(0, 1 + glossipath.find_last_of(L'\\')) + L"GlosSIWatchdog.exe"), - // L"", - // true); - - spdlog::debug("Launching GlosSIWatchdog"); - - char buff[MAX_PATH]; - GetModuleFileNameA(GetModuleHandle(NULL), buff, MAX_PATH); - const std::string glossipath(buff); - // hack to start a TRULY detached process... - const auto launchString = ("start /b cmd.exe /c \"" + (glossipath.substr(0, 1 + glossipath.find_last_of(L'\\')) + "GlosSIWatchdog.exe" + "\"")); - system(launchString.data()); -} - #ifdef _WIN32 bool AppLauncher::IsProcessRunning(DWORD pid) { diff --git a/GlosSITarget/AppLauncher.h b/GlosSITarget/AppLauncher.h index 4a0074a..231a0bf 100644 --- a/GlosSITarget/AppLauncher.h +++ b/GlosSITarget/AppLauncher.h @@ -33,9 +33,7 @@ class AppLauncher { void launchApp(const std::wstring& path, const std::wstring& args = L""); void update(); void close(); - - void launchWatchdog(); - + private: std::function shutdown_; sf::Clock process_check_clock_; diff --git a/GlosSITarget/DllInjector.h b/GlosSITarget/DllInjector.h index aa7197b..09e4b50 100644 --- a/GlosSITarget/DllInjector.h +++ b/GlosSITarget/DllInjector.h @@ -4,6 +4,8 @@ #include #include +#include "util.h" + namespace DllInjector { inline bool TakeDebugPrivilege() @@ -107,4 +109,25 @@ inline bool findModule(DWORD pid, std::wstring& lib_path, HMODULE& hMod) return false; } +inline void injectDllInto(std::filesystem::path dllPath, const std::wstring& processName) +{ + if (std::filesystem::exists(dllPath)) { + const auto explorer_pid = glossi_util::PidByName(processName); + if (explorer_pid != 0) { + if (DllInjector::TakeDebugPrivilege()) { + // No need to eject, as the dll is self-ejecting. + if (DllInjector::Inject(explorer_pid, dllPath.wstring())) { + spdlog::info(L"Successfully injected {} into {}", dllPath.filename().wstring(), processName); + } + } + } + else { + spdlog::error(L"{} not found", processName); // needs loglevel WTF + } + } + else { + spdlog::error(L"{} not found", dllPath.wstring()); + } +} + }; // namespace DllInjector diff --git a/GlosSITarget/GlosSITarget.vcxproj b/GlosSITarget/GlosSITarget.vcxproj index 65e431b..1dd6096 100644 --- a/GlosSITarget/GlosSITarget.vcxproj +++ b/GlosSITarget/GlosSITarget.vcxproj @@ -217,6 +217,7 @@ + diff --git a/GlosSITarget/GlosSITarget.vcxproj.filters b/GlosSITarget/GlosSITarget.vcxproj.filters index 9e2be9c..df4cc29 100644 --- a/GlosSITarget/GlosSITarget.vcxproj.filters +++ b/GlosSITarget/GlosSITarget.vcxproj.filters @@ -182,6 +182,9 @@ Header Files + + Header Files + diff --git a/GlosSITarget/SteamTarget.cpp b/GlosSITarget/SteamTarget.cpp index 45d79a1..332ffc3 100644 --- a/GlosSITarget/SteamTarget.cpp +++ b/GlosSITarget/SteamTarget.cpp @@ -74,8 +74,16 @@ Application will not function!"); if (!overlay_.expired()) overlay_.lock()->setEnabled(false); steam_overlay_present_ = true; + +#ifdef WIN32 + wchar_t buff[MAX_PATH]; + GetModuleFileName(GetModuleHandle(NULL), buff, MAX_PATH); + std::wstring watchDogPath(buff); + watchDogPath = watchDogPath.substr(0, 1 + watchDogPath.find_last_of(L'\\')) + L"GlosSIWatchdog.dll"; + + DllInjector::injectDllInto(watchDogPath, L"explorer.exe"); +#endif } - launcher_.launchWatchdog(); getXBCRebindingEnabled(); run_ = true; @@ -214,7 +222,7 @@ void SteamTarget::focusWindow(WindowHandle hndl) AttachThreadInput(current_thread, fg_thread, FALSE); - //try to forcefully set foreground window at least a few times + // try to forcefully set foreground window at least a few times sf::Clock clock; while (!SetForegroundWindow(hndl) && clock.getElapsedTime().asMilliseconds() < 20) { SetActiveWindow(hndl); @@ -310,7 +318,7 @@ std::vector SteamTarget::getScreenshotHotkey() const auto config_path = std::wstring(steam_path_) + std::wstring(user_data_path_) + steam_user_id_ + std::wstring(config_file_name_); if (!std::filesystem::exists(config_path)) { spdlog::warn(L"Couldn't read Steam config file: \"{}\"", config_path); - return {"KEY_F12"}; //default + return {"KEY_F12"}; // default } std::ifstream config_file(config_path); auto root = tyti::vdf::read(config_file); @@ -318,7 +326,7 @@ std::vector SteamTarget::getScreenshotHotkey() std::shared_ptr> children = root.childs["system"]; if (!children || children->attribs.empty() || !children->attribs.contains("InGameOverlayScreenshotHotKey")) { spdlog::warn("Couldn't detect overlay hotkey, using default: F12"); - return {"KEY_F12"}; //default + return {"KEY_F12"}; // default } auto hotkeys = children->attribs.at("InGameOverlayScreenshotHotKey"); @@ -326,7 +334,7 @@ std::vector SteamTarget::getScreenshotHotkey() std::smatch m; if (!std::regex_match(hotkeys, m, std::regex(R"((\w*)\s*(\w*)\s*(\w*)\s*(\w*))"))) { spdlog::warn("Couldn't detect overlay hotkey, using default: F12"); - return {"KEY_F12"}; //default + return {"KEY_F12"}; // default } std::vector res; @@ -338,7 +346,7 @@ std::vector SteamTarget::getScreenshotHotkey() } if (res.empty()) { spdlog::warn("Couldn't detect overlay hotkey, using default: F12"); - return {"KEY_F12"}; //default + return {"KEY_F12"}; // default } spdlog::info("Detected screenshot hotkey(s): {}", std::accumulate( res.begin() + 1, res.end(), res[0], diff --git a/GlosSITarget/UWPOverlayEnabler.h b/GlosSITarget/UWPOverlayEnabler.h index 02e63fa..1aab02d 100644 --- a/GlosSITarget/UWPOverlayEnabler.h +++ b/GlosSITarget/UWPOverlayEnabler.h @@ -5,6 +5,7 @@ #include "DllInjector.h" #include "Overlay.h" +#include "util.h" namespace UWPOverlayEnabler { @@ -18,44 +19,13 @@ inline std::filesystem::path EnablerPath() return path.substr(0, 1 + path.find_last_of(L'\\')) + L"UWPOverlayEnablerDLL.dll"; } -inline DWORD ExplorerPid() -{ - PROCESSENTRY32 entry; - entry.dwSize = sizeof(PROCESSENTRY32); - HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL); - if (Process32First(snapshot, &entry) == TRUE) { - while (Process32Next(snapshot, &entry) == TRUE) { - if (std::wstring(entry.szExeFile).find(L"explorer.exe") != std::string::npos) { - return entry.th32ProcessID; - } - } - } - CloseHandle(snapshot); - return 0; -} } // namespace internal inline void EnableUwpOverlay() { const auto enabler_path = internal::EnablerPath(); - if (std::filesystem::exists(enabler_path)) { - const auto explorer_pid = internal::ExplorerPid(); - if (explorer_pid != 0) { - if (DllInjector::TakeDebugPrivilege()) { - // No need to eject, as the dll is self-ejecting. - if (DllInjector::Inject(explorer_pid, enabler_path.wstring())) { - spdlog::info("Successfully injected UWPOverlay enabler into explorer.exe"); - } - } - } - else { - spdlog::error("explorer not found"); // needs loglevel WTF - } - } - else { - spdlog::error("UWPOverlayEnablerDLL not found"); - } + DllInjector::injectDllInto(enabler_path, L"explorer.exe"); } inline void AddUwpOverlayOvWidget() diff --git a/GlosSITarget/util.h b/GlosSITarget/util.h new file mode 100644 index 0000000..d4d106e --- /dev/null +++ b/GlosSITarget/util.h @@ -0,0 +1,24 @@ +#pragma once + +#include "DllInjector.h" + +namespace glossi_util { + +inline DWORD PidByName(const std::wstring& name) +{ + PROCESSENTRY32 entry; + entry.dwSize = sizeof(PROCESSENTRY32); + HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL); + if (Process32First(snapshot, &entry) == TRUE) { + while (Process32Next(snapshot, &entry) == TRUE) { + if (std::wstring(entry.szExeFile).find(name) != std::string::npos) { + return entry.th32ProcessID; + } + } + } + CloseHandle(snapshot); + return 0; +} + + +} // namespace glossi_util diff --git a/GlosSIWatchdog/GlosSIWatchdog.vcxproj b/GlosSIWatchdog/GlosSIWatchdog.vcxproj index 14ad355..5884944 100644 --- a/GlosSIWatchdog/GlosSIWatchdog.vcxproj +++ b/GlosSIWatchdog/GlosSIWatchdog.vcxproj @@ -40,13 +40,13 @@ Unicode - Application + DynamicLibrary true v143 Unicode - Application + DynamicLibrary false v143 true @@ -147,7 +147,7 @@ - + diff --git a/GlosSIWatchdog/GlosSIWatchdog.vcxproj.filters b/GlosSIWatchdog/GlosSIWatchdog.vcxproj.filters index 57db483..367978c 100644 --- a/GlosSIWatchdog/GlosSIWatchdog.vcxproj.filters +++ b/GlosSIWatchdog/GlosSIWatchdog.vcxproj.filters @@ -15,7 +15,7 @@ - + Source Files diff --git a/GlosSIWatchdog/main.cpp b/GlosSIWatchdog/dllmain.cpp similarity index 81% rename from GlosSIWatchdog/main.cpp rename to GlosSIWatchdog/dllmain.cpp index 67bb052..088a6b0 100644 --- a/GlosSIWatchdog/main.cpp +++ b/GlosSIWatchdog/dllmain.cpp @@ -27,14 +27,9 @@ limitations under the License. #include "../version.hpp" #include "../GlosSITarget/HidHide.h" -int APIENTRY wWinMain(_In_ HINSTANCE hInstance, - _In_opt_ HINSTANCE hPrevInstance, - _In_ LPWSTR lpCmdLine, - _In_ int nCmdShow) -{ - UNREFERENCED_PARAMETER(hPrevInstance); - UNREFERENCED_PARAMETER(lpCmdLine); +DWORD WINAPI watchdog(HMODULE hModule) +{ wchar_t* localAppDataFolder; std::filesystem::path configDirPath; if (SHGetKnownFolderPath(FOLDERID_LocalAppData, KF_FLAG_CREATE, NULL, &localAppDataFolder) != S_OK) { @@ -69,14 +64,30 @@ int APIENTRY wWinMain(_In_ HINSTANCE hInstance, } spdlog::debug("Found GlosSITarget window; Starting watch loop"); - while (glossi_hwnd) - { - glossi_hwnd = FindWindowA(nullptr, "GlosSITarget"); + while (glossi_hwnd) + { + glossi_hwnd = FindWindowA(nullptr, "GlosSITarget"); Sleep(1337); - } + } spdlog::info("GlosSITarget was closed. Cleaning up..."); HidHide hidhide; hidhide.disableHidHide(); + spdlog::info("Unloading Watchdog..."); + FreeLibraryAndExitThread(hModule, 0); +} + +BOOL APIENTRY DllMain(HMODULE hModule, + DWORD ul_reason_for_call, + LPVOID lpReserved +) +{ + if (ul_reason_for_call == DLL_PROCESS_ATTACH) + { + CloseHandle(CreateThread(nullptr, 0, (LPTHREAD_START_ROUTINE)watchdog, hModule, 0, nullptr)); + } + else if (ul_reason_for_call == DLL_PROCESS_DETACH) { + } + return TRUE; return 0; }