Cleanup: consolidate utils and common code

pull/239/head
Peter Repukat 1 year ago
parent b33b2a0691
commit 738803fa2e

@ -22,21 +22,7 @@ limitations under the License.
#define _SSIZE_T_DEFINED
#include <easywsclient.cpp> // seems like a hack to me, but eh
#include <locale>
#include <codecvt>
namespace nlohmann {
template <>
struct adl_serializer<std::wstring> {
static void to_json(json& j, const std::wstring& str) {
j = std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>>().to_bytes(str);
}
static void from_json(const json& j, std::wstring& str) {
str = std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>>().from_bytes(j.get<std::string>());
}
};
}
#include "../common/nlohmann_json_wstring.h"
namespace CEFInject
{

@ -23,10 +23,14 @@ namespace CEFInject
{
namespace internal {
httplib::Client GetHttpClient(uint16_t port);
static inline uint16_t port_ = 8080;
}
bool CEFDebugAvailable(uint16_t port = 8080);
std::vector<std::wstring> AvailableTabs(uint16_t port = 8080);
nlohmann::json InjectJs(const std::wstring& tabname, const std::wstring& js, uint16_t port = 8080);
inline void setPort(uint16_t port)
{
internal::port_ = port;
}
bool CEFDebugAvailable(uint16_t port = internal::port_);
std::vector<std::wstring> AvailableTabs(uint16_t port = internal::port_);
nlohmann::json InjectJs(const std::wstring& tabname, const std::wstring& js, uint16_t port = internal::port_);
}

@ -16,6 +16,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "GlosSIWatchdog", "GlosSIWat
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CEFInjectLib", "CEFInjectLib\CEFInjectLib.vcxproj", "{74FBA967-AB7E-43EA-B561-3F4821954B3B}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "common", "common\common.vcxproj", "{DFED4B7E-D04C-442B-BB48-5B6068A6B31B}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
@ -62,6 +64,14 @@ Global
{74FBA967-AB7E-43EA-B561-3F4821954B3B}.Release|x64.Build.0 = Release|x64
{74FBA967-AB7E-43EA-B561-3F4821954B3B}.Release|x86.ActiveCfg = Release|Win32
{74FBA967-AB7E-43EA-B561-3F4821954B3B}.Release|x86.Build.0 = Release|Win32
{DFED4B7E-D04C-442B-BB48-5B6068A6B31B}.Debug|x64.ActiveCfg = Debug|x64
{DFED4B7E-D04C-442B-BB48-5B6068A6B31B}.Debug|x64.Build.0 = Debug|x64
{DFED4B7E-D04C-442B-BB48-5B6068A6B31B}.Debug|x86.ActiveCfg = Debug|Win32
{DFED4B7E-D04C-442B-BB48-5B6068A6B31B}.Debug|x86.Build.0 = Debug|Win32
{DFED4B7E-D04C-442B-BB48-5B6068A6B31B}.Release|x64.ActiveCfg = Release|x64
{DFED4B7E-D04C-442B-BB48-5B6068A6B31B}.Release|x64.Build.0 = Release|x64
{DFED4B7E-D04C-442B-BB48-5B6068A6B31B}.Release|x86.ActiveCfg = Release|Win32
{DFED4B7E-D04C-442B-BB48-5B6068A6B31B}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

@ -2,6 +2,7 @@
#include <QQuickImageProvider>
#include <Windows.h>
#include <QRegularExpression>
#include <shellapi.h>
class ExeImageProvider : public QQuickImageProvider {
public:
ExeImageProvider()

@ -136,7 +136,7 @@
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\GlosSITarget\UnhookUtil.cpp" />
<ClCompile Include="..\common\UnhookUtil.cpp" />
<ClCompile Include="ExeImageProvider.cpp" />
<ClCompile Include="main.cpp" />
<ClCompile Include="UIModel.cpp" />

@ -37,7 +37,7 @@
<ClCompile Include="ExeImageProvider.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\GlosSITarget\UnhookUtil.cpp">
<ClCompile Include="..\common\UnhookUtil.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>

@ -51,8 +51,8 @@ END
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 0,1,1,2012005004400
PRODUCTVERSION 0,1,1,2012005004400
FILEVERSION 0,1,2,0010004309958
PRODUCTVERSION 0,1,2,0010004309958
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@ -69,12 +69,12 @@ BEGIN
BEGIN
VALUE "CompanyName", "Peter Repukat - FlatspotSoftware"
VALUE "FileDescription", "GlosSI - Config"
VALUE "FileVersion", "0.1.1.2-12-g5fe44d0"
VALUE "FileVersion", "0.1.2.0-10-g43c9958"
VALUE "InternalName", "GlosSIConfig"
VALUE "LegalCopyright", "Copyright (C) 2021 Peter Repukat - FlatspotSoftware"
VALUE "OriginalFilename", "GlosSIConfig.exe"
VALUE "ProductName", "GlosSI"
VALUE "ProductVersion", "0.1.1.2-12-g5fe44d0"
VALUE "ProductVersion", "0.1.2.0-10-g43c9958"
END
END
BLOCK "VarFileInfo"
@ -1503,6 +1503,22 @@ IDI_ICON1 ICON "..\GlosSI_Icon.ico"

@ -32,30 +32,18 @@ limitations under the License.
#ifdef _WIN32
#include "UWPFetch.h"
#include <Windows.h>
#include <shlobj.h>
#endif
#include "ExeImageProvider.h"
#include "../version.hpp"
#include "../../GlosSITarget/UnhookUtil.h"
#include "../common/UnhookUtil.h"
#include "../common/util.h"
UIModel::UIModel() : QObject(nullptr)
{
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))
std::filesystem::create_directories(path);
auto path = util::path::getDataDirPath();
qDebug() << "Version: " << getVersionString();
@ -395,17 +383,8 @@ void UIModel::updateCheck()
QVariantMap UIModel::getDefaultConf() const
{
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();
}
auto path = util::path::getDataDirPath();
path /= "Roaming";
path /= "GlosSI";
path /= "default.json";
QJsonObject defaults = {
@ -481,16 +460,8 @@ QVariantMap UIModel::getDefaultConf() const
void UIModel::saveDefaultConf(QVariantMap conf) const
{
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";
auto path = util::path::getDataDirPath();
path /= "default.json";
QFile file(path);

@ -22,15 +22,17 @@ limitations under the License.
#include <QFile>
#include <QTextStream>
#include "../common/util.h"
#ifdef _WIN32
#include <Windows.h>
#include <VersionHelpers.h>
#include <dwmapi.h>
#include <ShlObj.h>
#pragma comment(lib, "Dwmapi.lib")
#include "ExeImageProvider.h"
#endif
#include "UIModel.h"
#include "WinEventFilter.h"
@ -90,19 +92,7 @@ void myMessageHandler(QtMsgType type, const QMessageLogContext&, const QString&
break;
}
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))
std::filesystem::create_directories(path);
auto path = util::path::getDataDirPath();
QFile outFile(QString::fromStdWString(path) + "/glossiconfig.log");
outFile.open(QIODevice::WriteOnly | QIODevice::Append);
@ -120,18 +110,7 @@ int main(int argc, char* argv[])
#endif
if (argc < 3) {
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))
std::filesystem::create_directories(path);
auto path = util::path::getDataDirPath();
QFile outFile(QString::fromStdWString(path) + "/glossiconfig.log");
outFile.open(QIODevice::WriteOnly);

@ -27,13 +27,13 @@ limitations under the License.
#pragma comment(lib, "Shell32.lib")
#endif
#include "Settings.h"
#include "..\common\Settings.h"
#include <regex>
#include "Overlay.h"
#include "UnhookUtil.h"
#include "util.h"
#include "../common/UnhookUtil.h"
#include "../common/util.h"
AppLauncher::AppLauncher(
std::vector<HWND>& process_hwnds,
@ -75,10 +75,10 @@ void AppLauncher::launchApp(const std::wstring& path, const std::wstring& args)
if (ImGui::Begin("Launched Processes")) {
ImGui::BeginChild("Inner##LaunchedProcs", {0.f, ImGui::GetItemRectSize().y - 64}, true);
std::ranges::for_each(pids_, [](DWORD pid) {
ImGui::Text("%s | %d", std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>>().to_bytes(glossi_util::GetProcName(pid)).c_str(), pid);
ImGui::Text("%s | %d", util::string::to_string(util::win::process::GetProcName(pid)).c_str(), pid);
ImGui::SameLine();
if (ImGui::Button((" Kill ##" + std::to_string(pid)).c_str())) {
glossi_util::KillProcess(pid);
util::win::process::KillProcess(pid);
}
});
ImGui::EndChild();
@ -101,7 +101,7 @@ void AppLauncher::update()
getChildPids(pids_[0]);
}
if (!IsProcessRunning(pids_[0])) {
spdlog::info(L"Launched App \"{}\" with PID \"{}\" died", glossi_util::GetProcName(pids_[0]), pids_[0]);
spdlog::info(L"Launched App \"{}\" with PID \"{}\" died", util::win::process::GetProcName(pids_[0]), pids_[0]);
if (Settings::launch.closeOnExit && !Settings::launch.waitForChildProcs && Settings::launch.launch) {
spdlog::info("Configured to close on exit. Shutting down...");
shutdown_();
@ -117,12 +117,12 @@ void AppLauncher::update()
}
const auto running = IsProcessRunning(pid);
if (!running)
spdlog::trace(L"Child process \"{}\" with PID \"{}\" died", glossi_util::GetProcName(pid), pid);
spdlog::trace(L"Child process \"{}\" with PID \"{}\" died", util::win::process::GetProcName(pid), pid);
return !running;
});
auto filtered_pids = pids_ | std::ranges::views::filter([](DWORD pid) {
return std::ranges::find(Settings::launch.launcherProcesses, glossi_util::GetProcName(pid)) == Settings::launch.launcherProcesses.end();
return std::ranges::find(Settings::launch.launcherProcesses, util::win::process::GetProcName(pid)) == Settings::launch.launcherProcesses.end();
});
if (has_extra_launchers_ && !filtered_pids.empty()) {
launcher_has_launched_game_ = true;
@ -169,7 +169,7 @@ std::vector<DWORD> AppLauncher::launchedPids()
[](DWORD pid) {
return std::ranges::find(
Settings::launch.launcherProcesses,
glossi_util::GetProcName(pid)) == Settings::launch.launcherProcesses.end();
util::win::process::GetProcName(pid)) == Settings::launch.launcherProcesses.end();
})) {
res.push_back(pid);
}
@ -217,7 +217,7 @@ void AppLauncher::getChildPids(DWORD parent_pid)
if (pe.th32ParentProcessID == parent_pid) {
if (std::ranges::find(pids_, pe.th32ProcessID) == pids_.end()) {
if (Settings::common.extendedLogging) {
spdlog::info(L"Found new child process \"{}\" with PID \"{}\"", glossi_util::GetProcName(pe.th32ProcessID), pe.th32ProcessID);
spdlog::info(L"Found new child process \"{}\" with PID \"{}\"", util::win::process::GetProcName(pe.th32ProcessID), pe.th32ProcessID);
}
pids_.push_back(pe.th32ProcessID);
getChildPids(pe.th32ProcessID);
@ -263,7 +263,7 @@ void AppLauncher::getProcessHwnds()
#ifdef _WIN32
bool AppLauncher::findLauncherPids()
{
if (const auto pid = glossi_util::PidByName(L"EpicGamesLauncher.exe")) {
if (const auto pid = util::win::process::PidByName(L"EpicGamesLauncher.exe")) {
spdlog::debug("Found EGS-Launcher running");
pids_.push_back(pid);
return true;
@ -417,7 +417,7 @@ void AppLauncher::launchURL(const std::wstring& url, const std::wstring& args, c
spdlog::debug("Epic Games launch; Couldn't find egs launcher PID");
pid_mutex_.lock();
const auto pid = glossi_util::PidByName(L"EpicGamesLauncher.exe");
const auto pid = util::win::process::PidByName(L"EpicGamesLauncher.exe");
if (!findLauncherPids()) {
spdlog::debug("Did not find EGS-Launcher not running, retrying later...");
}

@ -1,10 +1,8 @@
#pragma once
#include <windows.h>
#include <tlhelp32.h>
#include <spdlog/spdlog.h>
#include "util.h"
#include "../common/util.h"
namespace DllInjector {
@ -112,7 +110,7 @@ inline bool findModule(DWORD pid, std::wstring& lib_path, HMODULE& hMod)
inline void injectDllInto(std::filesystem::path dllPath, const std::wstring& processName)
{
if (std::filesystem::exists(dllPath)) {
const auto explorer_pid = glossi_util::PidByName(processName);
const auto explorer_pid = util::win::process::PidByName(processName);
if (explorer_pid != 0) {
if (DllInjector::TakeDebugPrivilege()) {
// No need to eject, as the dll is self-ejecting.

@ -168,6 +168,8 @@
</CustomBuildStep>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\common\HidHide.cpp" />
<ClCompile Include="..\common\UnhookUtil.cpp" />
<ClCompile Include="..\deps\imgui-sfml\imgui-SFML.cpp" />
<ClCompile Include="..\deps\imgui\imgui.cpp" />
<ClCompile Include="..\deps\imgui\imgui_draw.cpp" />
@ -187,7 +189,6 @@
<ClCompile Include="..\deps\traypp\tray\src\core\windows\image.cpp" />
<ClCompile Include="..\deps\traypp\tray\src\core\windows\tray.cpp" />
<ClCompile Include="AppLauncher.cpp" />
<ClCompile Include="HidHide.cpp" />
<ClCompile Include="HttpServer.cpp" />
<ClCompile Include="InputRedirector.cpp" />
<ClCompile Include="main.cpp" />
@ -195,7 +196,6 @@
<ClCompile Include="SteamOverlayDetector.cpp" />
<ClCompile Include="SteamTarget.cpp" />
<ClCompile Include="TargetWindow.cpp" />
<ClCompile Include="UnhookUtil.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\deps\imgui-sfml\imgui-SFML.h" />
@ -204,7 +204,6 @@
<ClInclude Include="AppLauncher.h" />
<ClInclude Include="DllInjector.h" />
<ClInclude Include="GlosSI_logo.h" />
<ClInclude Include="HidHide.h" />
<ClInclude Include="HttpServer.h" />
<ClInclude Include="imconfig.h" />
<ClInclude Include="InputRedirector.h" />
@ -213,13 +212,10 @@
<ClInclude Include="ProcessPriority.h" />
<ClInclude Include="resource.h" />
<ClInclude Include="Roboto.h" />
<ClInclude Include="Settings.h" />
<ClInclude Include="SteamOverlayDetector.h" />
<ClInclude Include="SteamTarget.h" />
<ClInclude Include="steam_sf_keymap.h" />
<ClInclude Include="TargetWindow.h" />
<ClInclude Include="UnhookUtil.h" />
<ClInclude Include="util.h" />
<ClInclude Include="UWPOverlayEnabler.h" />
</ItemGroup>
<ItemGroup>

@ -51,9 +51,6 @@
<ClCompile Include="InputRedirector.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="HidHide.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Overlay.cpp">
<Filter>Source Files</Filter>
</ClCompile>
@ -114,10 +111,13 @@
<ClCompile Include="..\deps\traypp\tray\src\components\toggle.cpp">
<Filter>Source Files\tray</Filter>
</ClCompile>
<ClCompile Include="UnhookUtil.cpp">
<ClCompile Include="HttpServer.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="HttpServer.cpp">
<ClCompile Include="..\common\UnhookUtil.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\common\HidHide.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
@ -137,9 +137,6 @@
<ClInclude Include="InputRedirector.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="HidHide.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Overlay.h">
<Filter>Header Files</Filter>
</ClInclude>
@ -161,9 +158,6 @@
<ClInclude Include="AppLauncher.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Settings.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="resource.h">
<Filter>Header Files</Filter>
</ClInclude>
@ -182,12 +176,6 @@
<ClInclude Include="GlosSI_logo.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="UnhookUtil.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="util.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="HttpServer.h">
<Filter>Header Files</Filter>
</ClInclude>

@ -19,7 +19,7 @@ limitations under the License.
#include <nlohmann/json.hpp>
#include "AppLauncher.h"
#include "Settings.h"
#include "..\common\Settings.h"
HttpServer::HttpServer(AppLauncher& app_launcher, std::function<void()> close) : app_launcher_(app_launcher), close_(close)
{

@ -20,7 +20,7 @@ limitations under the License.
#include <spdlog/spdlog.h>
#include "Overlay.h"
#include "Settings.h"
#include "..\common\Settings.h"
InputRedirector::InputRedirector()
{

@ -17,13 +17,11 @@ limitations under the License.
#include <filesystem>
#include <utility>
#include <locale>
#include <codecvt>
#include <regex>
#include <shlobj_core.h>
#include "Roboto.h"
#include "Settings.h"
#include "..\common\Settings.h"
#include "GlosSI_logo.h"
#include "../version.hpp"
@ -52,23 +50,11 @@ Overlay::Overlay(
ImGui::SFML::UpdateFontTexture();
#ifdef _WIN32
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";
if (!std::filesystem::exists(config_path))
std::filesystem::create_directories(config_path);
auto config_path = util::path::getDataDirPath();
config_path /= "imgui.ini";
// This assumes that char is utf8 and wchar_t is utf16, which is guaranteed on Windows.
config_file_name_ = std::wstring_convert<std::codecvt_utf8<wchar_t>>().to_bytes(config_path.wstring());
config_file_name_ = util::string::to_string(config_path.wstring());
io.IniFilename = config_file_name_.data();
#endif

@ -51,8 +51,8 @@ END
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 0,1,0,2045006300001
PRODUCTVERSION 0,1,0,2045006300001
FILEVERSION 0,1,2,0010004309958
PRODUCTVERSION 0,1,2,0010004309958
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@ -69,12 +69,12 @@ BEGIN
BEGIN
VALUE "CompanyName", "Peter Repukat - FlatspotSoftware"
VALUE "FileDescription", "GlosSI - SteamTarget"
VALUE "FileVersion", "0.1.0.2-45-g63fdab1"
VALUE "FileVersion", "0.1.2.0-10-g43c9958"
VALUE "InternalName", "GlosSITarget"
VALUE "LegalCopyright", "Copyright (C) 2021-2022 Peter Repukat - FlatspotSoftware"
VALUE "OriginalFilename", "GlosSITarget.exe"
VALUE "ProductName", "GlosSI"
VALUE "ProductVersion", "0.1.0.2-45-g63fdab1"
VALUE "ProductVersion", "0.1.2.0-10-g43c9958"
END
END
BLOCK "VarFileInfo"
@ -220,6 +220,126 @@ IDI_ICON1 ICON "..\\GlosSI_Icon.ico"

@ -1,336 +0,0 @@
/*
Copyright 2021-2023 Peter Repukat - FlatspotSoftware
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#pragma once
#include <fstream>
#include <regex>
#include <string>
#include <nlohmann/json.hpp>
#include <spdlog/spdlog.h>
#include <locale>
#include <codecvt>
#ifdef WIN32
#define NOMINMAX
#include <Windows.h>
#include <ShlObj.h>
#include <KnownFolders.h>
#endif
namespace Settings {
inline struct Launch {
bool launch = false;
std::wstring launchPath;
std::wstring launchAppArgs;
bool closeOnExit = true;
bool waitForChildProcs = true;
bool isUWP = false;
bool ignoreLauncher = true;
bool killLauncher = false;
std::vector<std::wstring> launcherProcesses{};
} launch;
inline struct Devices {
bool hideDevices = true;
bool realDeviceIds = false;
} devices;
inline struct Window {
bool windowMode = false;
int maxFps = 0;
float scale = 0.f;
bool disableOverlay = false;
bool hideAltTab = true;
bool disableGlosSIOverlay = false;
} window;
inline struct Controller {
int maxControllers = 1;
bool allowDesktopConfig = false;
bool emulateDS4 = false;
} controller;
inline struct Common {
bool no_uwp_overlay = false;
bool disable_watchdog = false;
bool extendedLogging = false;
std::wstring name;
std::wstring icon;
int version;
std::wstring steamPath;
std::wstring steamUserId;
std::wstring standaloneModeGameId; /* = L"12605636929694728192"; */
bool standaloneUseGamepadUI = false;
} common;
inline std::filesystem::path settings_path_ = "";
inline bool checkIsUwp(const std::wstring& launch_path)
{
if (launch_path.find(L"://") != std::wstring::npos) {
return false;
}
std::wsmatch m;
if (!std::regex_search(launch_path, m, std::wregex(L"^.{1,5}:"))) {
return true;
}
return false;
}
#ifdef WIN32
inline bool isWin10 = false;
typedef LONG NTSTATUS, *PNTSTATUS;
#define STATUS_SUCCESS (0x00000000)
typedef NTSTATUS(WINAPI* RtlGetVersionPtr)(PRTL_OSVERSIONINFOW);
inline RTL_OSVERSIONINFOW GetRealOSVersion()
{
HMODULE hMod = ::GetModuleHandleW(L"ntdll.dll");
if (hMod) {
RtlGetVersionPtr fxPtr = (RtlGetVersionPtr)::GetProcAddress(hMod, "RtlGetVersion");
if (fxPtr != nullptr) {
RTL_OSVERSIONINFOW rovi = {0};
rovi.dwOSVersionInfoSize = sizeof(rovi);
if (STATUS_SUCCESS == fxPtr(&rovi)) {
return rovi;
}
}
}
RTL_OSVERSIONINFOW rovi = {0};
return rovi;
}
inline void checkWinVer()
{
auto VN = GetRealOSVersion();
isWin10 = VN.dwBuildNumber < 22000;
if (isWin10) {
spdlog::info("Running on Windows 10; Winver: {}.{}.{}", VN.dwMajorVersion, VN.dwMinorVersion, VN.dwBuildNumber);
}
else {
spdlog::info("Running on Windows 11; Winver: {}.{}.{}", VN.dwMajorVersion, VN.dwMinorVersion, VN.dwBuildNumber);
}
}
#endif
inline void Parse(const nlohmann::basic_json<>& json)
{
auto safeParseValue = [](const auto& object, const auto& key, auto& value) {
try {
if (object.is_null() || object.empty() || object.at(key).empty() || object.at(key).is_null()) {
return;
}
value = object[key];
}
catch (const nlohmann::json::exception& e) {
e.id == 403
? spdlog::trace("Err parsing \"{}\"; {}", key, e.what())
: spdlog::warn("Err parsing \"{}\"; {}", key, e.what());
}
catch (const std::exception& e) {
spdlog::warn("Err parsing \"{}\"; {}", key, e.what());
}
};
auto safeWStringParse = [&safeParseValue](const auto& object, const auto& key, std::wstring& value) {
std::string meh;
safeParseValue(object, key, meh);
if (!meh.empty()) {
// This assumes that char is utf8 and wchar_t is utf16, which is guaranteed on Windows.
value = std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>>().from_bytes(meh);
}
};
int version;
safeParseValue(json, "version", version);
if (version != 1) { // TODO: versioning stuff
spdlog::warn("Config version doesn't match application version.");
}
// TODO: make this as much generic as fits in about the same amount of code if one would parse every value separately.
try {
if (auto launchconf = json["launch"]; !launchconf.is_null() && !launchconf.empty() && launchconf.is_object()) {
safeParseValue(launchconf, "launch", launch.launch);
safeWStringParse(launchconf, "launchPath", launch.launchPath);
safeWStringParse(launchconf, "launchAppArgs", launch.launchAppArgs);
safeParseValue(launchconf, "closeOnExit", launch.closeOnExit);
safeParseValue(launchconf, "waitForChildProcs", launch.waitForChildProcs);
safeParseValue(launchconf, "killLauncher", launch.killLauncher);
safeParseValue(launchconf, "ignoreLauncher", launch.ignoreLauncher);
if (auto launcherProcs = launchconf["launcherProcesses"];
!launcherProcs.is_null() && !launcherProcs.empty() && launcherProcs.is_array()) {
launch.launcherProcesses.clear();
launch.launcherProcesses.reserve(launcherProcs.size());
for (auto& proc : launcherProcs) {
launch.launcherProcesses.push_back(std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>>().from_bytes(proc));
}
}
}
if (auto devconf = json["devices"]; !devconf.is_null() && !devconf.empty() && devconf.is_object()) {
safeParseValue(devconf, "hideDevices", devices.hideDevices);
safeParseValue(devconf, "realDeviceIds", devices.realDeviceIds);
}
if (auto winconf = json["window"]; !winconf.is_null() && !winconf.empty() && winconf.is_object()) {
safeParseValue(winconf, "windowMode", window.windowMode);
safeParseValue(winconf, "maxFps", window.maxFps);
safeParseValue(winconf, "scale", window.scale);
safeParseValue(winconf, "disableOverlay", window.disableOverlay);
safeParseValue(winconf, "hideAltTab", window.hideAltTab);
safeParseValue(winconf, "disableGlosSIOverlay", window.disableGlosSIOverlay);
}
if (auto controllerConf = json["controller"]; !controllerConf.is_null() && !controllerConf.empty() && controllerConf.is_object()) {
safeParseValue(controllerConf, "maxControllers", controller.maxControllers);
safeParseValue(controllerConf, "allowDesktopConfig", controller.allowDesktopConfig);
safeParseValue(controllerConf, "emulateDS4", controller.emulateDS4);
}
safeParseValue(json, "extendedLogging", common.extendedLogging);
safeWStringParse(json, "name", common.name);
safeWStringParse(json, "icon", common.icon);
safeParseValue(json, "version", common.version);
safeWStringParse(json, "steamPath", common.steamPath);
safeWStringParse(json, "steamUserId", common.steamUserId);
safeWStringParse(json, "standaloneModeGameId", common.standaloneModeGameId);
safeParseValue(json, "standaloneUseGamepadUI", common.standaloneUseGamepadUI);
}
catch (const nlohmann::json::exception& e) {
spdlog::warn("Err parsing config: {}", e.what());
}
catch (const std::exception& e) {
spdlog::warn("Err parsing config: {}", e.what());
}
if (launch.launch) {
launch.isUWP = checkIsUwp(launch.launchPath);
}
}
inline void Parse(const std::vector<std::wstring>& args)
{
std::wstring configName;
for (const auto& arg : args) {
if (arg.empty()) {
continue;
}
if (arg == L"-disableuwpoverlay") {
common.no_uwp_overlay = true;
}
else if (arg == L"-disablewatchdog") {
common.disable_watchdog = true;
}
else if (arg == L"-ignorelauncher") {
launch.ignoreLauncher = true;
}
else if (arg == L"-window") {
window.windowMode = true;
}
else {
configName += L" " + std::wstring(arg.begin(), arg.end());
}
}
if (!configName.empty()) {
if (configName[0] == L' ') {
configName.erase(configName.begin());
}
if (!configName.ends_with(L".json")) {
configName += L".json";
}
}
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 (!configName.empty()) {
path /= "Targets";
path /= configName;
}
else {
spdlog::info("No config file specified, using default");
path /= "default.json";
}
std::ifstream json_file;
json_file.open(path);
if (!json_file.is_open()) {
spdlog::error(L"Couldn't open settings file {}", path.wstring());
spdlog::debug(L"Using sane defaults...");
return;
}
settings_path_ = path;
const auto& json = nlohmann::json::parse(json_file);
Parse(json);
spdlog::debug("Read config file \"{}\"; config: {}", path.string(), json.dump());
json_file.close();
}
inline nlohmann::json toJson()
{
nlohmann::json json;
json["version"] = 1;
json["launch"]["launch"] = launch.launch;
json["launch"]["launchPath"] = std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>>().to_bytes(launch.launchPath);
json["launch"]["launchAppArgs"] = std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>>().to_bytes(launch.launchAppArgs);
json["launch"]["closeOnExit"] = launch.closeOnExit;
json["launch"]["waitForChildProcs"] = launch.waitForChildProcs;
json["devices"]["hideDevices"] = devices.hideDevices;
json["devices"]["realDeviceIds"] = devices.realDeviceIds;
json["window"]["windowMode"] = window.windowMode;
json["window"]["maxFps"] = window.maxFps;
json["window"]["scale"] = window.scale;
json["window"]["disableOverlay"] = window.disableOverlay;
json["window"]["hideAltTab"] = window.hideAltTab;
json["controller"]["maxControllers"] = controller.maxControllers;
json["controller"]["allowDesktopConfig"] = controller.allowDesktopConfig;
json["controller"]["emulateDS4"] = controller.emulateDS4;
json["extendedLogging"] = common.extendedLogging;
json["name"] = std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>>().to_bytes(common.name);
json["icon"] = std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>>().to_bytes(common.icon);
json["version"] = common.version;
return json;
}
inline void StoreSettings()
{
const auto& json = toJson();
std::ofstream json_file;
json_file.open(settings_path_);
if (!json_file.is_open()) {
spdlog::error(L"Couldn't open settings file {}", settings_path_.wstring());
return;
}
json_file << json.dump(4);
json_file.close();
}
} // namespace Settings

@ -17,7 +17,7 @@ limitations under the License.
#include <spdlog/spdlog.h>
#include "Settings.h"
#include "..\common\Settings.h"
#ifdef _WIN32
#define NOMINMAX

@ -15,7 +15,7 @@ limitations under the License.
*/
#include "SteamTarget.h"
#include "Settings.h"
#include "..\common\Settings.h"
#include "steam_sf_keymap.h"
#include <SFML/Window/Keyboard.hpp>
@ -65,6 +65,7 @@ int SteamTarget::run()
auto closeBPM = false;
auto closeBPMTimer = sf::Clock{};
if (!SteamOverlayDetector::IsSteamInjected()) {
return 1;
spdlog::warn("GlosSI not launched via Steam.\nEnabling EXPERIMENTAL global controller and overlay...");
if (Settings::common.standaloneModeGameId == L"") {
spdlog::error("No game id set for standalone mode. Controller will use desktop-config!");

@ -21,7 +21,7 @@ limitations under the License.
#include "TargetWindow.h"
#ifdef _WIN32
#include "HidHide.h"
#include "../common/HidHide.h"
#include "InputRedirector.h"
#include <subhook.h>
#endif

@ -30,7 +30,7 @@ limitations under the License.
#include "ProcessPriority.h"
#include "Settings.h"
#include "..\common\Settings.h"
#if !defined(WM_DPICHANGED)
#define WM_DPICHANGED 0x02E0

@ -5,7 +5,6 @@
#include "DllInjector.h"
#include "Overlay.h"
#include "util.h"
namespace UWPOverlayEnabler {

@ -1,66 +0,0 @@
/*
Copyright 2021-2023 Peter Repukat - FlatspotSoftware
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#pragma once
#define NOMINMAX
#include <map>
#include <Windows.h>
#include <string>
#include <vector>
namespace UnhookUtil {
void UnPatchHook(const std::string& name, HMODULE module);
std::string ReadOriginalBytes(const std::string& name, const std::wstring& moduleName);
static inline const std::vector<uint8_t> JUMP_INSTR_OPCODES = {
0xE9,
0xE8,
0xEB,
0xEA,
0xFF};
// Valve Hooks various functions and hides Gaming devices like this.
// To be able to query them, unpatch the hook with the original bytes...
// Bytes here are just fallbacks; originalbytes will get read from GlosSIConfig and stored in %APPDATA%\GlosSI\unhook_bytes
// 22000 ^= Windows build number
static inline const std::map<std::string, std::string> UNHOOK_BYTES_ORIGINAL_22000 = {
{"SetupDiEnumDeviceInfo", "\x48\x89\x5C\x24\x08"},
{"SetupDiGetClassDevsW", "\x48\x89\x5C\x24\x08"},
{"HidD_GetPreparsedData", "\x48\x89\x5C\x24\x18"},
{"HidP_GetCaps", "\x4C\x8B\xD1\x48\x85\xC9"},
{"HidD_GetAttributes", "\x40\x53\x48\x83\xEC"},
{"HidD_GetProductString", "\x48\x83\xEC\x48\x48"},
{"HidP_GetUsages", "\x4C\x89\x4C\x24\x20"},
{"HidP_GetData", "\x4C\x89\x44\x24\x18"},
{"HidP_GetValueCaps", "\x48\x83\xEC\x48\x49"},
{"HidP_GetUsageValue", "\x40\x53\x55\x56\x48"},
{"HidP_GetButtonCaps", "\x48\x83\xEC\x48\x49"},
// Valve hooks "CreateProcess" to detect child-processes
{"CreateProcessW", "\x4C\x8B\xDC\x48\x83"},
};
// SetupApi.dll is different on Win10 than on Win11
static inline const std::map<std::string, std::string> UNHOOK_BYTES_ORIGINAL_WIN10 = {
{"SetupDiEnumDeviceInfo", "\x40\x53\x56\x57\x41\x54\x41\x55"},
{"SetupDiGetClassDevsW", "\x48\x8B\xC4\x48\x89\x58\x08"},
};
} // namespace UnhookUtil

@ -30,7 +30,7 @@ limitations under the License.
#include "SteamTarget.h"
#include "OverlayLogSink.h"
#include "Settings.h"
#include "..\common\Settings.h"
#include <iostream>
#include "../version.hpp"
@ -71,19 +71,7 @@ LONG Win32FaultHandler(struct _EXCEPTION_POINTERS* ExInfo)
MINIDUMP_EXCEPTION_INFORMATION M;
HANDLE hDump_File;
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))
std::filesystem::create_directories(path);
auto path = util::path::getDataDirPath();
path /= "glossitarget.dmp";
M.ThreadId = GetCurrentThreadId();
@ -127,19 +115,7 @@ int main(int argc, char* argv[])
const auto console_sink = std::make_shared<spdlog::sinks::stderr_color_sink_mt>();
console_sink->set_level(spdlog::level::trace);
#ifdef _WIN32
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))
std::filesystem::create_directories(path);
auto path = util::path::getDataDirPath();
path /= "glossitarget.log";
// For "path.wstring()" to be usable here, SPDLOG_WCHAR_FILENAMES must be defined.
const auto file_sink = std::make_shared<spdlog::sinks::basic_file_sink_mt>(path.wstring(), true);

@ -1,76 +0,0 @@
/*
Copyright 2021-2023 Peter Repukat - FlatspotSoftware
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#pragma once
#define WIN32_LEAN_AND_MEAN
#define NOMINMAX
#include <Windows.h>
#include <tlhelp32.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;
}
inline std::wstring GetProcName(DWORD pid)
{
PROCESSENTRY32 processInfo;
processInfo.dwSize = sizeof(processInfo);
const HANDLE processesSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL);
if (processesSnapshot == INVALID_HANDLE_VALUE) {
spdlog::trace("util::GetProcName: can't get a process snapshot");
return L"";
}
for (BOOL bok = Process32First(processesSnapshot, &processInfo);
bok;
bok = Process32Next(processesSnapshot, &processInfo)) {
if (pid == processInfo.th32ProcessID) {
CloseHandle(processesSnapshot);
return processInfo.szExeFile;
}
}
CloseHandle(processesSnapshot);
return L"";
}
inline bool KillProcess(DWORD pid)
{
auto res = true;
if (const auto proc = OpenProcess(PROCESS_TERMINATE, FALSE, pid)) {
spdlog::debug("Terminating process: {}", pid);
res = TerminateProcess(proc, 0);
if (!res) {
spdlog::error("Failed to terminate process: {}", pid);
}
CloseHandle(proc);
}
return res;
}
} // namespace glossi_util

@ -145,8 +145,8 @@
</CustomBuildStep>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\GlosSITarget\HidHide.cpp" />
<ClCompile Include="..\GlosSITarget\UnhookUtil.cpp" />
<ClCompile Include="..\common\HidHide.cpp" />
<ClCompile Include="..\common\UnhookUtil.cpp" />
<ClCompile Include="dllmain.cpp" />
</ItemGroup>
<ItemGroup>

@ -18,10 +18,10 @@
<ClCompile Include="dllmain.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\GlosSITarget\HidHide.cpp">
<ClCompile Include="..\common\HidHide.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\GlosSITarget\UnhookUtil.cpp">
<ClCompile Include="..\common\UnhookUtil.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>

@ -15,10 +15,9 @@ limitations under the License.
*/
#include <httplib.h>
#define WIN32_LEAN_AND_MEAN
#define NOMINMAX
#include <Windows.h>
#include <ShlObj.h>
#include "../common/util.h"
#include <filesystem>
@ -29,9 +28,8 @@ limitations under the License.
#include <nlohmann/json.hpp>
#include "../version.hpp"
#include "../GlosSITarget/Settings.h"
#include "../GlosSITarget/HidHide.h"
#include "../GlosSITarget/util.h"
#include "../common/Settings.h"
#include "../common/HidHide.h"
bool IsProcessRunning(DWORD pid)
{
@ -66,20 +64,7 @@ void fetchSettings(httplib::Client& http_client, int retried_count = 0) {
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";
if (!std::filesystem::exists(configDirPath))
std::filesystem::create_directories(configDirPath);
auto configDirPath = util::path::getDataDirPath();
auto logPath = configDirPath;
logPath /= "GlosSIWatchdog.log";
const auto file_sink = std::make_shared<spdlog::sinks::basic_file_sink_mt>(logPath.wstring(), true);
@ -143,7 +128,7 @@ DWORD WINAPI watchdog(HMODULE hModule)
}
if (IsProcessRunning(pid))
{
glossi_util::KillProcess(pid);
util::win::process::KillProcess(pid);
}
else
{

@ -3,7 +3,7 @@
!define APP_NAME "GlosSI"
!define COMP_NAME "Peter Repukat - Flatspotsoftware"
!define WEB_SITE "https://glossi.flatspot.pictures/"
!define VERSION "0.0.9.1-48-geb4ae9c"
!define VERSION "0.1.2.0-10-g43c9958"
!define COPYRIGHT "Peter Repukat - FlatspotSoftware © 2017-2022"
!define DESCRIPTION "SteamInput compatibility tool"
!define INSTALLER_NAME "GlosSI-Installer.exe"
@ -193,3 +193,42 @@ SectionEnd

@ -44,7 +44,8 @@ There are two (known to me, at time of writing) ways to get a working overlay fo
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include <ShlObj.h>
#include "../common/util.h"
#define SUBHOOK_STATIC
#include <atomic>
@ -141,22 +142,7 @@ BOOL APIENTRY DllMain( HMODULE hModule,
{
if (ul_reason_for_call == DLL_PROCESS_ATTACH)
{
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";
if (!std::filesystem::exists(configDirPath))
std::filesystem::create_directories(configDirPath);
auto configDirPath = util::path::getDataDirPath();
auto logPath = configDirPath;
logPath /= "UWPOverlayEnabler.log";
const auto file_sink = std::make_shared<spdlog::sinks::basic_file_sink_mt>(logPath.string(), true);

@ -21,6 +21,8 @@ limitations under the License.
#include "HidHide.h"
#include <numeric>
#define SPDLOG_WCHAR_TO_UTF8_SUPPORT
#define SPDLOG_WCHAR_FILENAMES
#include <spdlog/spdlog.h>
#include <vector>
@ -29,7 +31,7 @@ limitations under the License.
#include <cfgmgr32.h>
#ifndef WATCHDOG
#include "Overlay.h"
#include "../GlosSITarget/Overlay.h"
#endif
#include "Settings.h"
@ -41,7 +43,7 @@ limitations under the License.
#include <atlbase.h>
#include "UnhookUtil.h"
#include "../common/UnhookUtil.h"
#pragma comment(lib, "Setupapi.lib")
@ -52,7 +54,7 @@ DEFINE_GUID(GUID_DEVINTERFACE_XUSB, 0xEC87F1E3, 0xC13B, 0x4100, 0xB5, 0xF7, 0x8B
// {00000000-0000-0000-FFFF-FFFFFFFFFFFF} the system container id
DEFINE_GUID(GUID_CONTAINER_ID_SYSTEM, 0x00000000, 0x0000, 0x0000, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF);
HidHide::HidHide(){};
HidHide::HidHide() {};
void HidHide::openCtrlDevice()
{
@ -85,7 +87,7 @@ void HidHide::hideDevices(const std::filesystem::path& steam_path)
spdlog::info("Hiding devices is disabled; Not un-patching valve hooks, not looking for HidHide");
return;
}
spdlog::debug("Setting up device hiding...");
UnPatchValveHooks();
@ -112,12 +114,12 @@ void HidHide::hideDevices(const std::filesystem::path& steam_path)
for (const auto& exe : whitelist_executeables_) {
auto path = std::regex_replace(steam_path_string, std::wregex(L"(.:)(\\/|\\\\)"), dos_device + L"\\");
path = std::regex_replace(path, std::wregex(L"\\/"), L"\\") + L"\\" + std::wstring{exe};
path = std::regex_replace(path, std::wregex(L"\\/"), L"\\") + L"\\" + std::wstring{ exe };
if (std::ranges::none_of(whitelist, [&path](auto ep) { // make copy!
auto p = path; // non-const(!) copy of path
std::ranges::transform(path, p.begin(), tolower);
std::ranges::transform(ep, ep.begin(), tolower);
return p == ep;
auto p = path; // non-const(!) copy of path
std::ranges::transform(path, p.begin(), tolower);
std::ranges::transform(ep, ep.begin(), tolower);
return p == ep;
})) {
whitelist.push_back(path);
}
@ -125,7 +127,7 @@ void HidHide::hideDevices(const std::filesystem::path& steam_path)
if (Settings::common.extendedLogging) {
std::ranges::for_each(whitelist, [](const auto& exe) {
spdlog::trace(L"Whitelisted executable: {}", exe);
});
});
}
setAppWhiteList(whitelist);
@ -133,13 +135,13 @@ void HidHide::hideDevices(const std::filesystem::path& steam_path)
if (Settings::common.extendedLogging) {
std::ranges::for_each(avail_devices_, [](const auto& dev) {
spdlog::trace(L"AvailDevice device: {}", dev.name);
});
});
}
blacklisted_devices_ = getBlackListDevices();
for (const auto& dev : avail_devices_) {
if (std::ranges::none_of(blacklisted_devices_, [&dev](const auto& blackdev) {
return blackdev == dev.device_instance_path || blackdev == dev.base_container_device_instance_path;
return blackdev == dev.device_instance_path || blackdev == dev.base_container_device_instance_path;
})) {
// Valve emulated gamepad PID/VID; mirrord by ViGEm
if (!(dev.vendor_id == 0x28de && (dev.product_id == 0x11FF || dev.product_id == 0x028E))) {
@ -160,7 +162,7 @@ void HidHide::hideDevices(const std::filesystem::path& steam_path)
if (Settings::common.extendedLogging) {
std::ranges::for_each(blacklisted_devices_, [](const auto& dev) {
spdlog::trace(L"Blacklisted device: {}", dev);
});
});
}
}
closeCtrlDevice();
@ -199,80 +201,81 @@ void HidHide::enableOverlayElement()
{
Overlay::AddOverlayElem([this](bool window_has_focus, ImGuiID dockspace_id) {
ImGui::SetNextWindowDockID(dockspace_id, ImGuiCond_FirstUseEver);
if (ImGui::Begin("Hidden Devices")) {
if (device_hiding_setup_) {
if (window_has_focus && (overlay_elem_clock_.getElapsedTime().asSeconds() > OVERLAY_ELEM_REFRESH_INTERVAL_S_)) {
// UnPatchValveHooks();
openCtrlDevice();
bool hidehide_state_store = hidhide_active_;
if (Settings::common.extendedLogging) {
spdlog::debug("Refreshing HID devices");
}
if (hidhide_active_) {
setActive(false);
}
avail_devices_ = GetHidDeviceList();
if (Settings::common.extendedLogging) {
std::ranges::for_each(avail_devices_, [](const auto& dev) {
spdlog::trace(L"AvailDevice device: {}", dev.name);
if (ImGui::Begin("Hidden Devices")) {
if (device_hiding_setup_) {
if (window_has_focus && (overlay_elem_clock_.getElapsedTime().asSeconds() > OVERLAY_ELEM_REFRESH_INTERVAL_S_)) {
// UnPatchValveHooks();
openCtrlDevice();
bool hidehide_state_store = hidhide_active_;
if (Settings::common.extendedLogging) {
spdlog::debug("Refreshing HID devices");
}
if (hidhide_active_) {
setActive(false);
}
avail_devices_ = GetHidDeviceList();
if (Settings::common.extendedLogging) {
std::ranges::for_each(avail_devices_, [](const auto& dev) {
spdlog::trace(L"AvailDevice device: {}", dev.name);
});
}
blacklisted_devices_ = getBlackListDevices();
if (hidehide_state_store && Settings::devices.hideDevices) {
setActive(true);
}
closeCtrlDevice();
overlay_elem_clock_.restart();
}
ImGui::BeginChild("Inner", {0.f, ImGui::GetItemRectSize().y - 64}, true);
std::ranges::for_each(avail_devices_, [this](const auto& device) {
std::string label = (std::string(device.name.begin(), std::ranges::find(device.name, L'\0')) + "##" + std::string(device.device_instance_path.begin(), device.device_instance_path.end()));
const auto findDeviceFn = [&device](const auto& blackdev) {
return device.device_instance_path == blackdev || device.base_container_device_instance_path == blackdev;
};
bool hidden = std::ranges::find_if(blacklisted_devices_, findDeviceFn) != blacklisted_devices_.end();
if (ImGui::Checkbox(label.data(), &hidden)) {
openCtrlDevice();
if (hidden) {
if (std::ranges::none_of(blacklisted_devices_, findDeviceFn)) {
if (!device.device_instance_path.empty()) {
blacklisted_devices_.push_back(device.device_instance_path);
}
if (!device.device_instance_path.empty()) {
blacklisted_devices_.push_back(device.base_container_device_instance_path);
}
}
}
else {
blacklisted_devices_.erase(std::ranges::remove_if(blacklisted_devices_, findDeviceFn).begin(),
blacklisted_devices_.end());
blacklisted_devices_ = getBlackListDevices();
if (hidehide_state_store && Settings::devices.hideDevices) {
setActive(true);
}
closeCtrlDevice();
overlay_elem_clock_.restart();
}
ImGui::BeginChild("Inner", { 0.f, ImGui::GetItemRectSize().y - 64 }, true);
std::ranges::for_each(avail_devices_, [this](const auto& device) {
std::string label = (std::string(device.name.begin(), std::ranges::find(device.name, L'\0')) + "##" + std::string(device.device_instance_path.begin(), device.device_instance_path.end()));
const auto findDeviceFn = [&device](const auto& blackdev) {
return device.device_instance_path == blackdev || device.base_container_device_instance_path == blackdev;
};
bool hidden = std::ranges::find_if(blacklisted_devices_, findDeviceFn) != blacklisted_devices_.end();
if (ImGui::Checkbox(label.data(), &hidden)) {
openCtrlDevice();
if (hidden) {
if (std::ranges::none_of(blacklisted_devices_, findDeviceFn)) {
if (!device.device_instance_path.empty()) {
blacklisted_devices_.push_back(device.device_instance_path);
}
setBlacklistDevices(blacklisted_devices_);
if (Settings::common.extendedLogging) {
std::ranges::for_each(blacklisted_devices_, [](const auto& dev) {
spdlog::trace(L"Blacklisted device: {}", dev);
});
if (!device.device_instance_path.empty()) {
blacklisted_devices_.push_back(device.base_container_device_instance_path);
}
closeCtrlDevice();
}
});
ImGui::EndChild();
} else {
ImGui::Text("Enable \"Hide Devices\" to see a list of gaming-devices");
}
if (ImGui::Checkbox("Hide devices", &Settings::devices.hideDevices)) {
if (!device_hiding_setup_) {
hideDevices(steam_path_);
}
if (hidhide_active_ != Settings::devices.hideDevices) {
openCtrlDevice();
setActive(Settings::devices.hideDevices);
closeCtrlDevice();
else {
blacklisted_devices_.erase(std::ranges::remove_if(blacklisted_devices_, findDeviceFn).begin(),
blacklisted_devices_.end());
}
setBlacklistDevices(blacklisted_devices_);
if (Settings::common.extendedLogging) {
std::ranges::for_each(blacklisted_devices_, [](const auto& dev) {
spdlog::trace(L"Blacklisted device: {}", dev);
});
}
closeCtrlDevice();
}
});
ImGui::EndChild();
}
else {
ImGui::Text("Enable \"Hide Devices\" to see a list of gaming-devices");
}
if (ImGui::Checkbox("Hide devices", &Settings::devices.hideDevices)) {
if (!device_hiding_setup_) {
hideDevices(steam_path_);
}
if (hidhide_active_ != Settings::devices.hideDevices) {
openCtrlDevice();
setActive(Settings::devices.hideDevices);
closeCtrlDevice();
}
}
ImGui::End();
});
}
ImGui::End();
});
}
#endif
@ -280,7 +283,7 @@ std::wstring HidHide::DosDeviceForVolume(const std::wstring& volume)
{
std::vector<WCHAR> buffer(UNICODE_STRING_MAX_CHARS);
QueryDosDeviceW(volume.c_str(), buffer.data(), static_cast<DWORD>(buffer.size()));
return {buffer.data()};
return { buffer.data() };
}
std::vector<std::wstring> HidHide::getAppWhiteList() const
@ -291,7 +294,7 @@ std::vector<std::wstring> HidHide::getAppWhiteList() const
}
std::vector<WCHAR> buffer(bytes_needed);
if (!DeviceIoControl(
hidhide_handle, static_cast<DWORD>(IOCTL_TYPE::GET_WHITELIST), nullptr, 0, buffer.data(), static_cast<DWORD>(buffer.size() * sizeof(WCHAR)), &bytes_needed, nullptr)) {
hidhide_handle, static_cast<DWORD>(IOCTL_TYPE::GET_WHITELIST), nullptr, 0, buffer.data(), static_cast<DWORD>(buffer.size() * sizeof(WCHAR)), &bytes_needed, nullptr)) {
spdlog::error("Couldn't retrieve HidHide Whitelist");
return std::vector<std::wstring>{};
}
@ -306,7 +309,7 @@ std::vector<std::wstring> HidHide::getBlackListDevices() const
}
std::vector<WCHAR> buffer(bytes_needed);
if (!DeviceIoControl(
hidhide_handle, static_cast<DWORD>(IOCTL_TYPE::GET_BLACKLIST), nullptr, 0, buffer.data(), static_cast<DWORD>(buffer.size() * sizeof(WCHAR)), &bytes_needed, nullptr)) {
hidhide_handle, static_cast<DWORD>(IOCTL_TYPE::GET_BLACKLIST), nullptr, 0, buffer.data(), static_cast<DWORD>(buffer.size() * sizeof(WCHAR)), &bytes_needed, nullptr)) {
spdlog::error("Couldn't retrieve HidHide Blacklist");
return std::vector<std::wstring>{};
}
@ -318,7 +321,7 @@ bool HidHide::getActive()
DWORD bytes_needed;
BOOLEAN res;
if (!DeviceIoControl(
hidhide_handle, static_cast<DWORD>(IOCTL_TYPE::GET_ACTIVE), nullptr, 0, &res, sizeof(BOOLEAN), &bytes_needed, nullptr)) {
hidhide_handle, static_cast<DWORD>(IOCTL_TYPE::GET_ACTIVE), nullptr, 0, &res, sizeof(BOOLEAN), &bytes_needed, nullptr)) {
spdlog::error("Couldn't retrieve HidHide State");
return false;
}
@ -331,7 +334,7 @@ void HidHide::setAppWhiteList(const std::vector<std::wstring>& whitelist) const
DWORD bytes_needed;
auto buffer = StringListToMultiString(whitelist);
if (!DeviceIoControl(
hidhide_handle, static_cast<DWORD>(IOCTL_TYPE::SET_WHITELIST), buffer.data(), static_cast<DWORD>(buffer.size() * sizeof(WCHAR)), nullptr, 0, &bytes_needed, nullptr)) {
hidhide_handle, static_cast<DWORD>(IOCTL_TYPE::SET_WHITELIST), buffer.data(), static_cast<DWORD>(buffer.size() * sizeof(WCHAR)), nullptr, 0, &bytes_needed, nullptr)) {
spdlog::error("Couldn't set HidHide WhiteList");
}
}
@ -341,7 +344,7 @@ void HidHide::setBlacklistDevices(const std::vector<std::wstring>& blacklist) co
DWORD bytes_needed;
auto buffer = StringListToMultiString(blacklist);
if (!DeviceIoControl(
hidhide_handle, static_cast<DWORD>(IOCTL_TYPE::SET_BLACKLIST), buffer.data(), static_cast<DWORD>(buffer.size() * sizeof(WCHAR)), nullptr, 0, &bytes_needed, nullptr)) {
hidhide_handle, static_cast<DWORD>(IOCTL_TYPE::SET_BLACKLIST), buffer.data(), static_cast<DWORD>(buffer.size() * sizeof(WCHAR)), nullptr, 0, &bytes_needed, nullptr)) {
spdlog::error("Couldn't set HidHide BlackList");
}
}
@ -350,7 +353,7 @@ void HidHide::setActive(bool active)
{
DWORD bytes_needed;
if (!DeviceIoControl(
hidhide_handle, static_cast<DWORD>(IOCTL_TYPE::SET_ACTIVE), &active, sizeof(BOOLEAN), nullptr, 0, &bytes_needed, nullptr)) {
hidhide_handle, static_cast<DWORD>(IOCTL_TYPE::SET_ACTIVE), &active, sizeof(BOOLEAN), nullptr, 0, &bytes_needed, nullptr)) {
spdlog::error("Couldn't set HidHide State");
return;
}
@ -394,9 +397,9 @@ std::vector<WCHAR> HidHide::StringListToMultiString(const std::vector<std::wstri
{
auto res = std::accumulate(stringlist.begin(), stringlist.end(), std::vector<WCHAR>{}, [](auto acc, const auto& curr) {
acc.insert(acc.end(), curr.begin(), curr.end());
acc.push_back(L'\0');
return acc;
});
acc.push_back(L'\0');
return acc;
});
res.push_back(L'\0');
return res;
}
@ -426,7 +429,7 @@ std::vector<HidHide::SmallHidInfo> HidHide::GetHidDeviceList()
std::ranges::remove_if(
device_instance_paths,
[](const auto& dev) { return !DevicePresent(dev); })
.begin(),
.begin(),
device_instance_paths.end());
GUID hid_device_interface_guid{};
@ -443,7 +446,7 @@ std::vector<HidHide::SmallHidInfo> HidHide::GetHidDeviceList()
std::ranges::remove_if(
res,
[](const auto& dev) { return !dev.gaming_device; })
.begin(),
.begin(),
res.end());
return res;
@ -504,8 +507,8 @@ HidHide::SmallHidInfo HidHide::GetDeviceInfo(const DeviceInstancePath& instance_
std::wstring buffer;
buffer.resize(127 * sizeof WCHAR);
res.name = (HidD_GetProductString(device_object.get(), buffer.data(), static_cast<ULONG>(sizeof(WCHAR) * buffer.size()))
? buffer
: L"");
? buffer
: L"");
for (size_t i = 0; i < res.name.size(); ++i) {
if (res.name[i] == L'\0') {
res.name.resize(i + 1);
@ -566,13 +569,13 @@ std::filesystem::path HidHide::SymbolicLink(GUID const& interface_guid, DeviceIn
std::vector<BYTE> buffer(needed);
// Acquire the detailed data containing the symbolic link (aka. device path)
auto& [cbSize, DevicePath]{*reinterpret_cast<PSP_DEVICE_INTERFACE_DETAIL_DATA_W>(buffer.data())};
auto& [cbSize, DevicePath] {*reinterpret_cast<PSP_DEVICE_INTERFACE_DETAIL_DATA_W>(buffer.data())};
cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W);
if (!SetupDiGetDeviceInterfaceDetailW(handle.get(), &device_interface_data, reinterpret_cast<PSP_DEVICE_INTERFACE_DETAIL_DATA_W>(buffer.data()), static_cast<DWORD>(buffer.size()), nullptr, nullptr)) {
spdlog::error(L"Couldn't get Device interface details; device: {}", instance_path);
return {};
}
return {std::wstring(DevicePath)};
return { std::wstring(DevicePath) };
}
HidHide::DeviceInstancePath HidHide::BaseContainerDeviceInstancePath(DeviceInstancePath const& device_instance_path)
@ -580,7 +583,7 @@ HidHide::DeviceInstancePath HidHide::BaseContainerDeviceInstancePath(DeviceInsta
const GUID base_container_id(BaseContainerId(device_instance_path));
if ((GUID_NULL == base_container_id) || (GUID_CONTAINER_ID_SYSTEM == base_container_id))
return (std::wstring{});
for (auto it{device_instance_path};;) {
for (auto it{ device_instance_path };;) {
if (const auto device_instance_path_parent = DeviceInstancePathParent(it); (base_container_id == BaseContainerId(device_instance_path_parent)))
it = device_instance_path_parent;
else
@ -597,7 +600,7 @@ GUID HidHide::BaseContainerId(DeviceInstancePath const& device_instance_path)
DEVINST devInst{};
DEVPROPTYPE devPropType{};
GUID buffer{};
ULONG needed{sizeof(buffer)};
ULONG needed{ sizeof(buffer) };
if (const auto result = CM_Locate_DevNodeW(&devInst, const_cast<DEVINSTID_W>(device_instance_path.c_str()), CM_LOCATE_DEVNODE_PHANTOM); (CR_SUCCESS != result)) {
spdlog::error(L"Couldn't locate device DevNode; Device {}; Code: {}", device_instance_path, result);
return {};
@ -624,7 +627,7 @@ HidHide::DeviceInstancePath HidHide::DeviceInstancePathParent(DeviceInstancePath
DEVINST dev_inst_parent{};
std::wstring res;
res.resize(UNICODE_STRING_MAX_CHARS);
ULONG needed{static_cast<ULONG>(res.size())};
ULONG needed{ static_cast<ULONG>(res.size()) };
if (const auto result = CM_Locate_DevNodeW(&dev_inst, const_cast<DEVINSTID_W>(device_instance_path.c_str()), CM_LOCATE_DEVNODE_PHANTOM); (CR_SUCCESS != result)) {
spdlog::error(L"Couldn't locate device DevNode; Device {}; Code: {}", device_instance_path, result);
return {};

@ -34,7 +34,7 @@ limitations under the License.
#endif
class HidHide {
private:
private:
using DeviceInstancePath = std::wstring;
using SetupDiDestroyDeviceInfoListPtr = std::unique_ptr<std::remove_pointer_t<HDEVINFO>, decltype(&SetupDiDestroyDeviceInfoList)>;
using CloseHandlePtr = std::unique_ptr<std::remove_pointer_t<HANDLE>, decltype(&CloseHandle)>;
@ -62,7 +62,7 @@ class HidHide {
bool gaming_device = false;
};
public:
public:
HidHide();
void openCtrlDevice();
@ -72,7 +72,7 @@ class HidHide {
void disableHidHide();
// TODO: MAYBE: restore hidhide state/lists when app closes. not only disable device_hiding
private:
private:
HANDLE hidhide_handle = nullptr;
std::filesystem::path steam_path_;
@ -89,12 +89,12 @@ class HidHide {
std::vector<std::wstring> blacklisted_devices_;
std::vector<SmallHidInfo> avail_devices_;
bool hidhide_active_ = false;
static constexpr int OVERLAY_ELEM_REFRESH_INTERVAL_S_ = 5;
static constexpr int OVERLAY_ELEM_REFRESH_INTERVAL_S_ = 5;
static inline constexpr std::array<std::wstring_view, 3> whitelist_executeables_{
L"GameOverlayUI.exe",
L"steam.exe",
L"streaming_client.exe"};
L"streaming_client.exe" };
static [[nodiscard]] std::wstring DosDeviceForVolume(const std::wstring& volume);

@ -0,0 +1,300 @@
/*
Copyright 2021-2023 Peter Repukat - FlatspotSoftware
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#pragma once
#include <fstream>
#include <regex>
#include <string>
#include <nlohmann/json.hpp>
#include <spdlog/spdlog.h>
#ifdef WIN32
#define NOMINMAX
#include <Windows.h>
#endif
#include "../common/nlohmann_json_wstring.h"
#include "../common/util.h"
namespace Settings {
inline struct Launch {
bool launch = false;
std::wstring launchPath;
std::wstring launchAppArgs;
bool closeOnExit = true;
bool waitForChildProcs = true;
bool isUWP = false;
bool ignoreLauncher = true;
bool killLauncher = false;
std::vector<std::wstring> launcherProcesses{};
} launch;
inline struct Devices {
bool hideDevices = true;
bool realDeviceIds = false;
} devices;
inline struct Window {
bool windowMode = false;
int maxFps = 0;
float scale = 0.f;
bool disableOverlay = false;
bool hideAltTab = true;
bool disableGlosSIOverlay = false;
} window;
inline struct Controller {
int maxControllers = 1;
bool allowDesktopConfig = false;
bool emulateDS4 = false;
} controller;
inline struct Common {
bool no_uwp_overlay = false;
bool disable_watchdog = false;
bool extendedLogging = false;
std::wstring name;
std::wstring icon;
int version;
std::wstring steamPath;
std::wstring steamUserId;
std::wstring standaloneModeGameId; /* = L"12605636929694728192"; */
bool standaloneUseGamepadUI = false;
} common;
inline std::filesystem::path settings_path_ = "";
inline bool checkIsUwp(const std::wstring& launch_path)
{
if (launch_path.find(L"://") != std::wstring::npos) {
return false;
}
std::wsmatch m;
if (!std::regex_search(launch_path, m, std::wregex(L"^.{1,5}:"))) {
return true;
}
return false;
}
#ifdef WIN32
inline bool isWin10 = false;
inline void checkWinVer()
{
auto VN = util::win::GetRealOSVersion();
isWin10 = VN.dwBuildNumber < 22000;
if (isWin10) {
spdlog::info("Running on Windows 10; Winver: {}.{}.{}", VN.dwMajorVersion, VN.dwMinorVersion, VN.dwBuildNumber);
}
else {
spdlog::info("Running on Windows 11; Winver: {}.{}.{}", VN.dwMajorVersion, VN.dwMinorVersion, VN.dwBuildNumber);
}
}
#endif
inline void Parse(const nlohmann::basic_json<>& json)
{
constexpr auto safeParseValue = []<typename T>(const auto & object, const auto & key, T & value) {
try {
if (object.is_null() || object.empty() || object.at(key).empty() || object.at(key).is_null()) {
return;
}
if constexpr (std::is_same_v<T, std::wstring>) {
value = util::string::to_wstring(object[key].get<std::string>());
}
else {
value = object[key];
}
}
catch (const nlohmann::json::exception& e) {
e.id == 403
? spdlog::trace("Err parsing \"{}\"; {}", key, e.what())
: spdlog::warn("Err parsing \"{}\"; {}", key, e.what());
}
catch (const std::exception& e) {
spdlog::warn("Err parsing \"{}\"; {}", key, e.what());
}
};
int version;
safeParseValue(json, "version", version);
if (version != 1) { // TODO: versioning stuff
spdlog::warn("Config version doesn't match application version.");
}
// TODO: make this as much generic as fits in about the same amount of code if one would parse every value separately.
try {
if (auto launchconf = json["launch"]; !launchconf.is_null() && !launchconf.empty() && launchconf.is_object()) {
safeParseValue(launchconf, "launch", launch.launch);
safeParseValue(launchconf, "launchPath", launch.launchPath);
safeParseValue(launchconf, "launchAppArgs", launch.launchAppArgs);
safeParseValue(launchconf, "closeOnExit", launch.closeOnExit);
safeParseValue(launchconf, "waitForChildProcs", launch.waitForChildProcs);
safeParseValue(launchconf, "killLauncher", launch.killLauncher);
safeParseValue(launchconf, "ignoreLauncher", launch.ignoreLauncher);
if (auto launcherProcs = launchconf["launcherProcesses"];
!launcherProcs.is_null() && !launcherProcs.empty() && launcherProcs.is_array()) {
launch.launcherProcesses.clear();
launch.launcherProcesses.reserve(launcherProcs.size());
for (auto& proc : launcherProcs) {
launch.launcherProcesses.push_back(util::string::to_wstring(proc));
}
}
}
if (auto devconf = json["devices"]; !devconf.is_null() && !devconf.empty() && devconf.is_object()) {
safeParseValue(devconf, "hideDevices", devices.hideDevices);
safeParseValue(devconf, "realDeviceIds", devices.realDeviceIds);
}
if (auto winconf = json["window"]; !winconf.is_null() && !winconf.empty() && winconf.is_object()) {
safeParseValue(winconf, "windowMode", window.windowMode);
safeParseValue(winconf, "maxFps", window.maxFps);
safeParseValue(winconf, "scale", window.scale);
safeParseValue(winconf, "disableOverlay", window.disableOverlay);
safeParseValue(winconf, "hideAltTab", window.hideAltTab);
safeParseValue(winconf, "disableGlosSIOverlay", window.disableGlosSIOverlay);
}
if (auto controllerConf = json["controller"]; !controllerConf.is_null() && !controllerConf.empty() && controllerConf.is_object()) {
safeParseValue(controllerConf, "maxControllers", controller.maxControllers);
safeParseValue(controllerConf, "allowDesktopConfig", controller.allowDesktopConfig);
safeParseValue(controllerConf, "emulateDS4", controller.emulateDS4);
}
safeParseValue(json, "extendedLogging", common.extendedLogging);
safeParseValue(json, "name", common.name);
safeParseValue(json, "icon", common.icon);
safeParseValue(json, "version", common.version);
safeParseValue(json, "steamPath", common.steamPath);
safeParseValue(json, "steamUserId", common.steamUserId);
safeParseValue(json, "standaloneModeGameId", common.standaloneModeGameId);
safeParseValue(json, "standaloneUseGamepadUI", common.standaloneUseGamepadUI);
}
catch (const nlohmann::json::exception& e) {
spdlog::warn("Err parsing config: {}", e.what());
}
catch (const std::exception& e) {
spdlog::warn("Err parsing config: {}", e.what());
}
if (launch.launch) {
launch.isUWP = checkIsUwp(launch.launchPath);
}
}
inline void Parse(const std::vector<std::wstring>& args)
{
std::wstring configName;
for (const auto& arg : args) {
if (arg.empty()) {
continue;
}
if (arg == L"-disableuwpoverlay") {
common.no_uwp_overlay = true;
}
else if (arg == L"-disablewatchdog") {
common.disable_watchdog = true;
}
else if (arg == L"-ignorelauncher") {
launch.ignoreLauncher = true;
}
else if (arg == L"-window") {
window.windowMode = true;
}
else {
configName += L" " + std::wstring(arg.begin(), arg.end());
}
}
if (!configName.empty()) {
if (configName[0] == L' ') {
configName.erase(configName.begin());
}
if (!configName.ends_with(L".json")) {
configName += L".json";
}
}
auto path = util::path::getDataDirPath();
if (!configName.empty()) {
path /= "Targets";
path /= configName;
}
else {
spdlog::info("No config file specified, using default");
path /= "default.json";
}
std::ifstream json_file;
json_file.open(path);
if (!json_file.is_open()) {
spdlog::error(L"Couldn't open settings file {}", path.wstring());
spdlog::debug(L"Using sane defaults...");
return;
}
settings_path_ = path;
const auto& json = nlohmann::json::parse(json_file);
Parse(json);
spdlog::debug("Read config file \"{}\"; config: {}", path.string(), json.dump());
json_file.close();
}
inline nlohmann::json toJson()
{
nlohmann::json json;
json["version"] = 1;
json["launch"]["launch"] = launch.launch;
json["launch"]["launchPath"] = launch.launchPath;
json["launch"]["launchAppArgs"] = launch.launchAppArgs;
json["launch"]["closeOnExit"] = launch.closeOnExit;
json["launch"]["waitForChildProcs"] = launch.waitForChildProcs;
json["devices"]["hideDevices"] = devices.hideDevices;
json["devices"]["realDeviceIds"] = devices.realDeviceIds;
json["window"]["windowMode"] = window.windowMode;
json["window"]["maxFps"] = window.maxFps;
json["window"]["scale"] = window.scale;
json["window"]["disableOverlay"] = window.disableOverlay;
json["window"]["hideAltTab"] = window.hideAltTab;
json["controller"]["maxControllers"] = controller.maxControllers;
json["controller"]["allowDesktopConfig"] = controller.allowDesktopConfig;
json["controller"]["emulateDS4"] = controller.emulateDS4;
json["extendedLogging"] = common.extendedLogging;
json["name"] = common.name;
json["icon"] = common.icon;
json["version"] = common.version;
return json;
}
inline void StoreSettings()
{
const auto& json = toJson();
std::ofstream json_file;
json_file.open(settings_path_);
if (!json_file.is_open()) {
spdlog::error(L"Couldn't open settings file {}", settings_path_.wstring());
return;
}
json_file << json.dump(4);
json_file.close();
}
} // namespace Settings

@ -13,7 +13,9 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#include "UnhookUtil.h"
#include "../common/UnhookUtil.h"
#include "util.h"
#ifndef CONFIGAPP
#include <spdlog/spdlog.h>
@ -28,17 +30,7 @@ void UnhookUtil::UnPatchHook(const std::string& name, HMODULE module)
std::map<std::string, std::string> original_bytes_from_file;
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";
auto configDirPath = util::path::getDataDirPath();
if (std::filesystem::exists(configDirPath)) {
auto unhook_file_path = configDirPath / "unhook_bytes";
if (std::filesystem::exists(unhook_file_path)) {
@ -56,7 +48,8 @@ void UnhookUtil::UnPatchHook(const std::string& name, HMODULE module)
ifile.read(&buff, sizeof(char));
if (buff != ':') {
funcName.push_back(buff);
} else {
}
else {
char bytes[8];
ifile.read(bytes, sizeof(char) * 8);
ifile.read(&buff, sizeof(char)); // newline

@ -0,0 +1,66 @@
/*
Copyright 2021-2023 Peter Repukat - FlatspotSoftware
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#pragma once
#define NOMINMAX
#include <map>
#include <Windows.h>
#include <string>
#include <vector>
namespace UnhookUtil {
void UnPatchHook(const std::string& name, HMODULE module);
std::string ReadOriginalBytes(const std::string& name, const std::wstring& moduleName);
static inline const std::vector<uint8_t> JUMP_INSTR_OPCODES = {
0xE9,
0xE8,
0xEB,
0xEA,
0xFF };
// Valve Hooks various functions and hides Gaming devices like this.
// To be able to query them, unpatch the hook with the original bytes...
// Bytes here are just fallbacks; originalbytes will get read from GlosSIConfig and stored in %APPDATA%\GlosSI\unhook_bytes
// 22000 ^= Windows build number
static inline const std::map<std::string, std::string> UNHOOK_BYTES_ORIGINAL_22000 = {
{"SetupDiEnumDeviceInfo", "\x48\x89\x5C\x24\x08"},
{"SetupDiGetClassDevsW", "\x48\x89\x5C\x24\x08"},
{"HidD_GetPreparsedData", "\x48\x89\x5C\x24\x18"},
{"HidP_GetCaps", "\x4C\x8B\xD1\x48\x85\xC9"},
{"HidD_GetAttributes", "\x40\x53\x48\x83\xEC"},
{"HidD_GetProductString", "\x48\x83\xEC\x48\x48"},
{"HidP_GetUsages", "\x4C\x89\x4C\x24\x20"},
{"HidP_GetData", "\x4C\x89\x44\x24\x18"},
{"HidP_GetValueCaps", "\x48\x83\xEC\x48\x49"},
{"HidP_GetUsageValue", "\x40\x53\x55\x56\x48"},
{"HidP_GetButtonCaps", "\x48\x83\xEC\x48\x49"},
// Valve hooks "CreateProcess" to detect child-processes
{"CreateProcessW", "\x4C\x8B\xDC\x48\x83"},
};
// SetupApi.dll is different on Win10 than on Win11
static inline const std::map<std::string, std::string> UNHOOK_BYTES_ORIGINAL_WIN10 = {
{"SetupDiEnumDeviceInfo", "\x40\x53\x56\x57\x41\x54\x41\x55"},
{"SetupDiGetClassDevsW", "\x48\x8B\xC4\x48\x89\x58\x08"},
};
} // namespace UnhookUtil

@ -0,0 +1,151 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>16.0</VCProjectVersion>
<Keyword>Win32Proj</Keyword>
<ProjectGuid>{dfed4b7e-d04c-442b-bb48-5b6068a6b31b}</ProjectGuid>
<RootNamespace>common</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Utility</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Utility</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<IncludePath>..\deps\json\include;..\deps\spdlog\include;..\deps\SFML\include;..\deps\imgui;$(IncludePath)</IncludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<IncludePath>..\deps\json\include;..\deps\spdlog\include;..\deps\SFML\include;..\deps\imgui;$(IncludePath)</IncludePath>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpp20</LanguageStandard>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpp20</LanguageStandard>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="HidHide.h" />
<ClInclude Include="nlohmann_json_wstring.h" />
<ClInclude Include="Settings.h" />
<ClInclude Include="UnhookUtil.h" />
<ClInclude Include="util.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="HidHide.cpp" />
<ClCompile Include="UnhookUtil.cpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

@ -0,0 +1,42 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="nlohmann_json_wstring.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="util.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="UnhookUtil.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Settings.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="HidHide.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="UnhookUtil.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="HidHide.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>

@ -0,0 +1,36 @@
/*
Copyright 2021-2023 Peter Repukat - FlatspotSoftware
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#pragma once
#include <nlohmann/json.hpp>
#include "util.h"
namespace nlohmann {
template <>
struct adl_serializer<std::wstring> {
static void to_json(json& j, const std::wstring& str) {
j = util::string::to_string(str);
}
static void from_json(const json& j, std::wstring& str) {
str = util::string::to_wstring(j.get<std::string>());
}
};
}

@ -0,0 +1,163 @@
/*
Copyright 2021-2023 Peter Repukat - FlatspotSoftware
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#pragma once
#include <locale>
#include <codecvt>
#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN
#define NOMINMAX
#include <Windows.h>
#include <tlhelp32.h>
#include <ShlObj.h>
#include <KnownFolders.h>
#endif
#include <filesystem>
#ifdef SPDLOG_H
#include <spdlog/spdlog.h>
#endif
namespace util {
namespace string
{
template <typename T>
inline std::wstring to_wstring(const T& t)
{
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
return converter.from_bytes(t);
}
template <typename T>
inline std::string to_string(const T& t)
{
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
return converter.to_bytes(t);
}
}
namespace path
{
inline std::filesystem::path getDataDirPath()
{
wchar_t* localAppDataFolder;
std::filesystem::path path;
if (SHGetKnownFolderPath(FOLDERID_LocalAppData, KF_FLAG_CREATE, nullptr, &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))
std::filesystem::create_directories(path);
return path;
}
}
#ifdef _WIN32
namespace win
{
typedef LONG NTSTATUS, * PNTSTATUS;
#define STATUS_SUCCESS (0x00000000)
typedef NTSTATUS(WINAPI* RtlGetVersionPtr)(PRTL_OSVERSIONINFOW);
inline RTL_OSVERSIONINFOW GetRealOSVersion()
{
HMODULE hMod = ::GetModuleHandleW(L"ntdll.dll");
if (hMod) {
RtlGetVersionPtr fxPtr = (RtlGetVersionPtr)::GetProcAddress(hMod, "RtlGetVersion");
if (fxPtr != nullptr) {
RTL_OSVERSIONINFOW rovi = { 0 };
rovi.dwOSVersionInfoSize = sizeof(rovi);
if (STATUS_SUCCESS == fxPtr(&rovi)) {
return rovi;
}
}
}
RTL_OSVERSIONINFOW rovi = { 0 };
return rovi;
}
namespace process
{
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;
}
inline std::wstring GetProcName(DWORD pid)
{
PROCESSENTRY32 processInfo;
processInfo.dwSize = sizeof(processInfo);
const HANDLE processesSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL);
if (processesSnapshot == INVALID_HANDLE_VALUE) {
#ifdef SPDLOG_H
spdlog::trace("util::GetProcName: can't get a process snapshot");
#endif
return L"";
}
for (BOOL bok = Process32First(processesSnapshot, &processInfo);
bok;
bok = Process32Next(processesSnapshot, &processInfo)) {
if (pid == processInfo.th32ProcessID) {
CloseHandle(processesSnapshot);
return processInfo.szExeFile;
}
}
CloseHandle(processesSnapshot);
return L"";
}
inline bool KillProcess(DWORD pid)
{
auto res = true;
if (const auto proc = OpenProcess(PROCESS_TERMINATE, FALSE, pid)) {
#ifdef SPDLOG_H
spdlog::debug("Terminating process: {}", pid);
#endif
res = TerminateProcess(proc, 0);
if (!res) {
#ifdef SPDLOG_H
spdlog::error("Failed to terminate process: {}", pid);
#endif
}
CloseHandle(proc);
}
return res;
}
}
}
#endif
}
Loading…
Cancel
Save