diff --git a/GlosSIConfig/UIModel.cpp b/GlosSIConfig/UIModel.cpp index 04e1371..70817a8 100644 --- a/GlosSIConfig/UIModel.cpp +++ b/GlosSIConfig/UIModel.cpp @@ -28,13 +28,21 @@ limitations under the License. #ifdef _WIN32 #include "UWPFetch.h" #include +#include #endif #include "../version.hpp" UIModel::UIModel() : QObject(nullptr) { - auto path = std::filesystem::temp_directory_path().parent_path().parent_path().parent_path(); + wchar_t* localAppDataFolder; + std::filesystem::path path; + if (SHGetKnownFolderPath(FOLDERID_LocalAppData, KF_FLAG_CREATE, NULL, &localAppDataFolder) != S_OK) { + path = std::filesystem::temp_directory_path().parent_path().parent_path().parent_path(); + } + else { + path = std::filesystem::path(localAppDataFolder).parent_path(); + } path /= "Roaming"; path /= "GlosSI"; @@ -307,7 +315,14 @@ void UIModel::updateCheck() QVariantMap UIModel::getDefaultConf() const { - auto path = std::filesystem::temp_directory_path().parent_path().parent_path().parent_path(); + wchar_t* localAppDataFolder; + std::filesystem::path path; + if (SHGetKnownFolderPath(FOLDERID_LocalAppData, KF_FLAG_CREATE, NULL, &localAppDataFolder) != S_OK) { + path = std::filesystem::temp_directory_path().parent_path().parent_path().parent_path(); + } + else { + path = std::filesystem::path(localAppDataFolder).parent_path(); + } path /= "Roaming"; path /= "GlosSI"; @@ -371,8 +386,14 @@ QVariantMap UIModel::getDefaultConf() const void UIModel::saveDefaultConf(QVariantMap conf) const { - auto path = std::filesystem::temp_directory_path().parent_path().parent_path().parent_path(); - + wchar_t* localAppDataFolder; + std::filesystem::path path; + if (SHGetKnownFolderPath(FOLDERID_LocalAppData, KF_FLAG_CREATE, NULL, &localAppDataFolder) != S_OK) { + path = std::filesystem::temp_directory_path().parent_path().parent_path().parent_path(); + } + else { + path = std::filesystem::path(localAppDataFolder).parent_path(); + } path /= "Roaming"; path /= "GlosSI"; path /= "default.json"; diff --git a/GlosSIConfig/main.cpp b/GlosSIConfig/main.cpp index 98388b8..8ad85de 100644 --- a/GlosSIConfig/main.cpp +++ b/GlosSIConfig/main.cpp @@ -26,6 +26,7 @@ limitations under the License. #include #include #include +#include #pragma comment(lib, "Dwmapi.lib") #include "ExeImageProvider.h" #endif @@ -89,10 +90,14 @@ void myMessageHandler(QtMsgType type, const QMessageLogContext&, const QString& break; } - auto path = std::filesystem::temp_directory_path() - .parent_path() - .parent_path() - .parent_path(); + wchar_t* localAppDataFolder; + std::filesystem::path path; + if (SHGetKnownFolderPath(FOLDERID_LocalAppData, KF_FLAG_CREATE, NULL, &localAppDataFolder) != S_OK) { + path = std::filesystem::temp_directory_path().parent_path().parent_path().parent_path(); + } + else { + path = std::filesystem::path(localAppDataFolder).parent_path(); + } path /= "Roaming"; path /= "GlosSI"; @@ -115,11 +120,14 @@ int main(int argc, char* argv[]) #endif if (argc < 3) { - auto path = std::filesystem::temp_directory_path() - .parent_path() - .parent_path() - .parent_path(); - + wchar_t* localAppDataFolder; + std::filesystem::path path; + if (SHGetKnownFolderPath(FOLDERID_LocalAppData, KF_FLAG_CREATE, NULL, &localAppDataFolder) != S_OK) { + path = std::filesystem::temp_directory_path().parent_path().parent_path().parent_path(); + } + else { + path = std::filesystem::path(localAppDataFolder).parent_path(); + } path /= "Roaming"; path /= "GlosSI"; if (!std::filesystem::exists(path)) diff --git a/GlosSIConfig/qml/main.qml b/GlosSIConfig/qml/main.qml index cfc7b38..3894e96 100644 --- a/GlosSIConfig/qml/main.qml +++ b/GlosSIConfig/qml/main.qml @@ -117,8 +117,8 @@ Window { titleText: qsTr("New version available!") text: uiModel.newVersionName + "\n\n" + qsTr("Would you like to visit the download page now?") onConfirmed: function (callback) { + Qt.openUrlExternally(`https://glossi.flatspot.pictures/#downloads${ uiModel.newVersionName.includes('snapshot') ? '-snapshots' : '' }-${uiModel.newVersionName}`); callback(); - Qt.openUrlExternally(`https://glossi.flatspot.pictures/#downloads-${uiModel.newVersionName}`); } buttonText: qsTr("Yes") extraButton: true 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/InputRedirector.cpp b/GlosSITarget/InputRedirector.cpp index 15ba653..883c420 100644 --- a/GlosSITarget/InputRedirector.cpp +++ b/GlosSITarget/InputRedirector.cpp @@ -242,7 +242,7 @@ void InputRedirector::runLoop() unplugVigemPad(i); } } - sf::sleep(sf::milliseconds(1)); + sf::sleep(sf::milliseconds(4)); #endif } diff --git a/GlosSITarget/Overlay.cpp b/GlosSITarget/Overlay.cpp index a7451a5..39b3d31 100644 --- a/GlosSITarget/Overlay.cpp +++ b/GlosSITarget/Overlay.cpp @@ -20,6 +20,7 @@ limitations under the License. #include #include #include +#include #include "Roboto.h" #include "Settings.h" @@ -51,10 +52,14 @@ Overlay::Overlay( ImGui::SFML::UpdateFontTexture(); #ifdef _WIN32 - auto config_path = std::filesystem::temp_directory_path() - .parent_path() - .parent_path() - .parent_path(); + wchar_t* localAppDataFolder; + std::filesystem::path config_path; + if (SHGetKnownFolderPath(FOLDERID_LocalAppData, KF_FLAG_CREATE, NULL, &localAppDataFolder) != S_OK) { + config_path = std::filesystem::temp_directory_path().parent_path().parent_path().parent_path(); + } + else { + config_path = std::filesystem::path(localAppDataFolder).parent_path(); + } config_path /= "Roaming"; config_path /= "GlosSI"; diff --git a/GlosSITarget/Settings.h b/GlosSITarget/Settings.h index f5ada8c..eaef719 100644 --- a/GlosSITarget/Settings.h +++ b/GlosSITarget/Settings.h @@ -26,6 +26,8 @@ limitations under the License. #ifdef WIN32 #define NOMINMAX #include +#include +#include #endif namespace Settings { @@ -122,10 +124,14 @@ inline void Parse(std::wstring arg1) arg1 += L".json"; } } - std::filesystem::path path = std::filesystem::temp_directory_path() - .parent_path() - .parent_path() - .parent_path(); + wchar_t* localAppDataFolder; + std::filesystem::path path; + if (SHGetKnownFolderPath(FOLDERID_LocalAppData, KF_FLAG_CREATE, NULL, &localAppDataFolder) != S_OK) { + path = std::filesystem::temp_directory_path().parent_path().parent_path().parent_path(); + } + else { + path = std::filesystem::path(localAppDataFolder).parent_path(); + } path /= "Roaming"; path /= "GlosSI"; diff --git a/GlosSITarget/SteamTarget.cpp b/GlosSITarget/SteamTarget.cpp index 5e05f98..332ffc3 100644 --- a/GlosSITarget/SteamTarget.cpp +++ b/GlosSITarget/SteamTarget.cpp @@ -74,7 +74,15 @@ Application will not function!"); if (!overlay_.expired()) overlay_.lock()->setEnabled(false); steam_overlay_present_ = true; - launcher_.launchWatchdog(); + +#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 } getXBCRebindingEnabled(); @@ -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/main.cpp b/GlosSITarget/main.cpp index 347bbf0..6ce5a1e 100644 --- a/GlosSITarget/main.cpp +++ b/GlosSITarget/main.cpp @@ -17,6 +17,7 @@ limitations under the License. #define NOMINMAX #include #include +#include #endif #include @@ -67,10 +68,14 @@ LONG Win32FaultHandler(struct _EXCEPTION_POINTERS* ExInfo) MINIDUMP_EXCEPTION_INFORMATION M; HANDLE hDump_File; - auto path = std::filesystem::temp_directory_path() - .parent_path() - .parent_path() - .parent_path(); + wchar_t* localAppDataFolder; + std::filesystem::path path; + if (SHGetKnownFolderPath(FOLDERID_LocalAppData, KF_FLAG_CREATE, NULL, &localAppDataFolder) != S_OK) { + path = std::filesystem::temp_directory_path().parent_path().parent_path().parent_path(); + } + else { + path = std::filesystem::path(localAppDataFolder).parent_path(); + } path /= "Roaming"; path /= "GlosSI"; @@ -119,10 +124,14 @@ int main(int argc, char* argv[]) const auto console_sink = std::make_shared(); console_sink->set_level(spdlog::level::trace); #ifdef _WIN32 - auto path = std::filesystem::temp_directory_path() - .parent_path() - .parent_path() - .parent_path(); + wchar_t* localAppDataFolder; + std::filesystem::path path; + if (SHGetKnownFolderPath(FOLDERID_LocalAppData, KF_FLAG_CREATE, NULL, &localAppDataFolder) != S_OK) { + path = std::filesystem::temp_directory_path().parent_path().parent_path().parent_path(); + } + else { + path = std::filesystem::path(localAppDataFolder).parent_path(); + } path /= "Roaming"; path /= "GlosSI"; 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 67% rename from GlosSIWatchdog/main.cpp rename to GlosSIWatchdog/dllmain.cpp index 2de92ba..088a6b0 100644 --- a/GlosSIWatchdog/main.cpp +++ b/GlosSIWatchdog/dllmain.cpp @@ -16,6 +16,7 @@ limitations under the License. #define NOMINMAX #include +#include #include @@ -26,18 +27,17 @@ 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); - auto configDirPath = std::filesystem::temp_directory_path() - .parent_path() - .parent_path() - .parent_path(); +DWORD WINAPI watchdog(HMODULE hModule) +{ + wchar_t* localAppDataFolder; + std::filesystem::path configDirPath; + if (SHGetKnownFolderPath(FOLDERID_LocalAppData, KF_FLAG_CREATE, NULL, &localAppDataFolder) != S_OK) { + configDirPath = std::filesystem::temp_directory_path().parent_path().parent_path().parent_path(); + } + else { + configDirPath = std::filesystem::path(localAppDataFolder).parent_path(); + } configDirPath /= "Roaming"; configDirPath /= "GlosSI"; @@ -64,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; } diff --git a/UWPOverlayEnablerDLL/dllmain.cpp b/UWPOverlayEnablerDLL/dllmain.cpp index e657f0d..21bd67a 100644 --- a/UWPOverlayEnablerDLL/dllmain.cpp +++ b/UWPOverlayEnablerDLL/dllmain.cpp @@ -44,6 +44,7 @@ There are two (known to me, at time of writing) ways to get a working overlay fo #define WIN32_LEAN_AND_MEAN #include +#include #define SUBHOOK_STATIC #include @@ -140,11 +141,14 @@ BOOL APIENTRY DllMain( HMODULE hModule, { if (ul_reason_for_call == DLL_PROCESS_ATTACH) { - - auto configDirPath = std::filesystem::temp_directory_path() - .parent_path() - .parent_path() - .parent_path(); + wchar_t* localAppDataFolder; + std::filesystem::path configDirPath; + if (SHGetKnownFolderPath(FOLDERID_LocalAppData, KF_FLAG_CREATE, NULL, &localAppDataFolder) != S_OK) { + configDirPath = std::filesystem::temp_directory_path().parent_path().parent_path().parent_path(); + } + else { + configDirPath = std::filesystem::path(localAppDataFolder).parent_path(); + } configDirPath /= "Roaming"; configDirPath /= "GlosSI"; diff --git a/deps/Shortcuts_VDF b/deps/Shortcuts_VDF index 59108a7..c078257 160000 --- a/deps/Shortcuts_VDF +++ b/deps/Shortcuts_VDF @@ -1 +1 @@ -Subproject commit 59108a7f9a938911e1cc237003a396c886be85f8 +Subproject commit c07825730f509fb6ae0244df17fed6216c392557