Merge branch 'develop'

pull/212/head 0.1.2.0
Peter Repukat 1 year ago
commit a4d2bd81ad

8
.gitmodules vendored

@ -27,13 +27,13 @@
url = https://github.com/nlohmann/json
[submodule "deps/traypp"]
path = deps/traypp
url = https://github.com/Soundux/traypp.git
url = https://github.com/Soundux/traypp
[submodule "deps/fifo_map"]
path = deps/fifo_map
url = git@github.com:nlohmann/fifo_map.git
url = https://github.com/nlohmann/fifo_map
[submodule "deps/Shortcuts_VDF"]
path = deps/Shortcuts_VDF
url = git@github.com:Alia5/Shortcuts_VDF.git
url = https://github.com/Alia5/Shortcuts_VDF
[submodule "deps/cpp-httplib"]
path = deps/cpp-httplib
url = git@github.com:yhirose/cpp-httplib.git
url = https://github.com/yhirose/cpp-httplib

@ -69,7 +69,7 @@
<AdditionalUsingDirectories>%(AdditionalUsingDirectories)</AdditionalUsingDirectories>
<AdditionalOptions>/Zc:__cplusplus /Zc:twoPhase- %(AdditionalOptions)</AdditionalOptions>
<CompileAsWinRT>false</CompileAsWinRT>
<PreprocessorDefinitions>NOMINMAX;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>NOMINMAX;CONFIGAPP;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>..\deps\WinReg;..\deps\fifo_map\src;..\deps\Shortcuts_VDF\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Manifest>
@ -92,7 +92,7 @@
<AdditionalUsingDirectories>%(AdditionalUsingDirectories)</AdditionalUsingDirectories>
<AdditionalOptions>/Zc:__cplusplus /Zc:zwoPhase- /permissive- %(AdditionalOptions)</AdditionalOptions>
<CompileAsWinRT>false</CompileAsWinRT>
<PreprocessorDefinitions>NOMINMAX;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>NOMINMAX;CONFIGAPP;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>..\deps\WinReg;..\deps\fifo_map\src;..\deps\Shortcuts_VDF\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Manifest>
@ -136,6 +136,7 @@
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\GlosSITarget\UnhookUtil.cpp" />
<ClCompile Include="ExeImageProvider.cpp" />
<ClCompile Include="main.cpp" />
<ClCompile Include="UIModel.cpp" />

@ -37,6 +37,9 @@
<ClCompile Include="ExeImageProvider.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\GlosSITarget\UnhookUtil.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="qml\main.qml">

@ -51,8 +51,8 @@ END
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 0,1,1,101000823500
PRODUCTVERSION 0,1,1,101000823500
FILEVERSION 0,1,1,2012005004400
PRODUCTVERSION 0,1,1,2012005004400
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.1-1-ga8235ca"
VALUE "FileVersion", "0.1.1.2-12-g5fe44d0"
VALUE "InternalName", "GlosSIConfig"
VALUE "LegalCopyright", "Copyright (C) 2021 Peter Repukat - FlatspotSoftware"
VALUE "OriginalFilename", "GlosSIConfig.exe"
VALUE "ProductName", "GlosSI"
VALUE "ProductVersion", "0.1.1.1-1-ga8235ca"
VALUE "ProductVersion", "0.1.1.2-12-g5fe44d0"
END
END
BLOCK "VarFileInfo"
@ -1400,6 +1400,106 @@ IDI_ICON1 ICON "..\GlosSI_Icon.ico"

@ -1,5 +1,5 @@
/*
Copyright 2021-2022 Peter Repukat - FlatspotSoftware
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.
@ -22,6 +22,8 @@ limitations under the License.
#include <QJsonArray>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QMetaType>
#include <WinReg/WinReg.hpp>
@ -36,6 +38,9 @@ limitations under the License.
#include "ExeImageProvider.h"
#include "../version.hpp"
#include "../../GlosSITarget/UnhookUtil.h"
UIModel::UIModel() : QObject(nullptr)
{
wchar_t* localAppDataFolder;
@ -60,9 +65,13 @@ UIModel::UIModel() : QObject(nullptr)
if (!std::filesystem::exists(path))
std::filesystem::create_directories(path);
auto defaultConf = getDefaultConf();
saveDefaultConf(defaultConf);
parseShortcutVDF();
readTargetConfigs();
updateCheck();
readUnhookBytes();
auto font = QGuiApplication::font();
font.setPointSize(11);
@ -115,6 +124,8 @@ bool UIModel::updateTarget(int index, QVariant shortcut)
const auto map = shortcut.toMap();
const auto json = QJsonObject::fromVariantMap(map);
const auto was_in_steam_ = isInSteam(shortcut);
auto oldSteamName = targets_[index].toMap()["name"].toString();
auto oldName =
targets_[index].toMap()["name"].toString().replace(QRegularExpression("[\\\\/:*?\"<>|]"), "") + ".json";
@ -132,15 +143,19 @@ bool UIModel::updateTarget(int index, QVariant shortcut)
path /= config_dir_name_.toStdString();
path /= (map["name"].toString()).toStdString();
if (removeFromSteam(oldSteamName, QString::fromStdWString(path.wstring()))) {
if (!addToSteam(shortcut, QString::fromStdWString(path.wstring()))) {
qDebug() << "Couldn't add shortcut \"" << (map["name"].toString()) << "\" to Steam when updating";
return false;
if (was_in_steam_) {
if (removeFromSteam(oldSteamName, QString::fromStdWString(path.wstring()))) {
if (!addToSteam(shortcut, QString::fromStdWString(path.wstring()))) {
qDebug() << "Couldn't add shortcut \"" << (map["name"].toString()) << "\" to Steam when updating";
return false;
}
return true;
}
qDebug() << "Couldn't remove shortcut \"" << oldName << "\" from Steam when updating";
return false;
} else {
return true;
}
qDebug() << "Couldn't remove shortcut \"" << oldName << "\" from Steam when updating";
return false;
}
void UIModel::deleteTarget(int index)
@ -159,7 +174,9 @@ bool UIModel::isInSteam(QVariant shortcut) const
{
const auto map = shortcut.toMap();
for (auto& steam_shortcut : shortcuts_vdf_) {
if (map["name"].toString() == QString::fromStdString(steam_shortcut.appname)) {
if (
map["name"].toString() == QString::fromStdString(steam_shortcut.appname) ||
map["oldName"].toString() == QString::fromStdString(steam_shortcut.appname)) {
if (QString::fromStdString(steam_shortcut.exe).toLower().contains("glossitarget.exe")) {
return true;
}
@ -383,6 +400,10 @@ QVariantMap UIModel::getDefaultConf() const
{"extendedLogging", false},
{"snapshotNotify", false},
{"steamgridApiKey", QJsonValue::Null},
{"steamPath",
QJsonValue::fromVariant(QString::fromStdWString(getSteamPath(false).wstring()))},
{"steamUserId",
QJsonValue::fromVariant(QString::fromStdWString(getSteamUserId(false)))},
{"controller", QJsonObject{{"maxControllers", 1}, {"emulateDS4", false}, {"allowDesktopConfig", false}}},
{"devices",
QJsonObject{
@ -403,9 +424,11 @@ QVariantMap UIModel::getDefaultConf() const
{"window",
QJsonObject{
{"disableOverlay", false},
{"hideAltTab", false},
{"maxFps", QJsonValue::Null},
{"scale", QJsonValue::Null},
{"windowMode", false},
{"disableGlosSIOverlay", false},
}},
};
@ -719,20 +742,33 @@ QString UIModel::getVersionString() const { return QString(version::VERSION_STR)
QString UIModel::getNewVersionName() const { return new_version_name_; }
std::filesystem::path UIModel::getSteamPath() const
std::filesystem::path UIModel::getSteamPath(bool tryConfig) const
{
QVariantMap defaultConf;
if (tryConfig) {
defaultConf = getDefaultConf();
}
try {
#ifdef _WIN32
// TODO: check if keys/value exist
// steam should always be open and have written reg values...
winreg::RegKey key{HKEY_CURRENT_USER, L"SOFTWARE\\Valve\\Steam"};
if (!key.IsValid()) {
if (defaultConf.contains("steamPath") &&
QMetaType::canConvert(defaultConf["steamPath"].metaType(), QMetaType(QMetaType::QString))) {
return defaultConf["steamPath"].toString().toStdWString();
}
return "";
}
const auto res = key.GetStringValue(L"SteamPath");
return res;
}
catch (...) {
if (defaultConf.contains("steamPath") &&
QMetaType::canConvert(defaultConf["steamPath"].metaType(), QMetaType(QMetaType::QString))) {
return defaultConf["steamPath"].toString().toStdWString();
}
return "";
}
#else
@ -740,23 +776,39 @@ std::filesystem::path UIModel::getSteamPath() const
#endif
}
std::wstring UIModel::getSteamUserId() const
std::wstring UIModel::getSteamUserId(bool tryConfig) const
{
QVariantMap defaultConf;
if (tryConfig) {
defaultConf = getDefaultConf();
}
#ifdef _WIN32
try {
// TODO: check if keys/value exist
// steam should always be open and have written reg values...
winreg::RegKey key{HKEY_CURRENT_USER, L"SOFTWARE\\Valve\\Steam\\ActiveProcess"};
if (!key.IsValid()) {
if (defaultConf.contains("steamUserId") &&
QMetaType::canConvert(defaultConf["steamUserId"].metaType(), QMetaType(QMetaType::QString))) {
return defaultConf["steamUserId"].toString().toStdWString();
}
return L"0";
}
const auto res = std::to_wstring(key.GetDwordValue(L"ActiveUser"));
if (res == L"0") {
qDebug() << "Steam not open?";
if (defaultConf.contains("steamUserId") &&
QMetaType::canConvert(defaultConf["steamUserId"].metaType(), QMetaType(QMetaType::QString))) {
return defaultConf["steamUserId"].toString().toStdWString();
}
}
return res;
}
catch (...) {
if (defaultConf.contains("steamUserId") &&
QMetaType::canConvert(defaultConf["steamUserId"].metaType(), QMetaType(QMetaType::QString))) {
return defaultConf["steamUserId"].toString().toStdWString();
}
return L"0";
}
#else
@ -830,3 +882,35 @@ bool UIModel::isSteamInputXboxSupportEnabled() const
}
return true;
}
void UIModel::readUnhookBytes() const
{
std::map<std::string, std::string> unhook_bytes;
for (const auto& name : UnhookUtil::UNHOOK_BYTES_ORIGINAL_22000 | std::views::keys) {
auto bytes = UnhookUtil::ReadOriginalBytes(
name,
name.starts_with("Hid")
? L"hid.dll"
: name.starts_with("Setup")
? L"setupapi.dll"
: L"Kernel32.dll"
);
unhook_bytes[name] = bytes;
}
auto path = config_path_;
path /= "unhook_bytes";
QFile file(path);
if (!file.open(QIODevice::Truncate | QIODevice::ReadWrite)) {
qDebug() << "Couldn't open file for writing: " << path;
return;
}
for (const auto& [name, bytes] : unhook_bytes) {
file.write(
QString::fromStdString(name + ":").toStdString().data()
);
file.write(bytes.data(), bytes.size());
file.write("\n");
}
file.close();
}

@ -1,5 +1,5 @@
/*
Copyright 2021-2022 Peter Repukat - FlatspotSoftware
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.
@ -125,10 +125,12 @@ class UIModel : public QObject {
QString getVersionString() const;
QString getNewVersionName() const;
std::filesystem::path getSteamPath() const;
std::wstring getSteamUserId() const;
std::filesystem::path getSteamPath(bool tryConfig = true) const;
std::wstring getSteamUserId(bool tryConfig = true) const;
bool foundSteam() const;
void parseShortcutVDF();
bool isSteamInputXboxSupportEnabled() const;
void readUnhookBytes() const;
};

@ -1,5 +1,5 @@
/*
Copyright 2021-2022 Peter Repukat - FlatspotSoftware
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.

@ -1,5 +1,5 @@
/*
Copyright 2021-2022 Peter Repukat - FlatspotSoftware
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.

@ -1,5 +1,5 @@
/*
Copyright 2021-2022 Peter Repukat - FlatspotSoftware
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.

@ -1,5 +1,5 @@
/*
Copyright 2021-2022 Peter Repukat - FlatspotSoftware
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.
@ -140,7 +140,7 @@ CollapsiblePane {
RPane {
width: parent.width / 2 - 8
height: 248
height: 324
radius: 4
Material.elevation: 32
bgOpacity: 0.97
@ -290,7 +290,7 @@ CollapsiblePane {
}
RPane {
width: parent.width / 2 - 8
height: 248
height: 324
radius: 4
Material.elevation: 32
bgOpacity: 0.97
@ -359,6 +359,76 @@ CollapsiblePane {
height: 24
}
}
}
Item {
width: 1
height: 4
}
Row {
CheckBox {
id: hideAltTabCheckbox
text: qsTr("Hide GlosSI from Windowlist (Alt+Tab)")
checked: shortcutInfo.window.hideAltTab
onCheckedChanged: shortcutInfo.window.hideAltTab = checked
}
RoundButton {
onClicked: () => {
helpInfoDialog.titleText = qsTr("Hide GlosSI from Windowlist (Alt+Tab)")
helpInfoDialog.text =
qsTr("Hides GlosSI from the Windowlist (Alt+Tab)")
+ "\n"
+ qsTr("You can close the GlosSI-Window via the system-tray")
+ "\n"
+ "\n"
+ qsTr("Might help with Steam remote play.")
helpInfoDialog.open()
}
width: 48
height: 48
Material.elevation: 0
anchors.topMargin: 16
Image {
anchors.centerIn: parent
source: "qrc:/svg/help_outline_white_24dp.svg"
width: 24
height: 24
}
}
}
Item {
width: 1
height: 4
}
Row {
CheckBox {
id: disableGlosSIOverlayCheckbox
text: qsTr("Disable GlosSI overlay")
checked: shortcutInfo.window.disableGlosSIOverlay
onCheckedChanged: shortcutInfo.window.disableGlosSIOverlay = checked
}
RoundButton {
onClicked: () => {
helpInfoDialog.titleText = qsTr("Disable GlosSI overlay")
helpInfoDialog.text =
qsTr("Disables the additional GlosSI overlay")
+ "\n"
+ qsTr("but keeps the Steam overlay");
helpInfoDialog.open()
}
width: 48
height: 48
Material.elevation: 0
anchors.topMargin: 16
Image {
anchors.centerIn: parent
source: "qrc:/svg/help_outline_white_24dp.svg"
width: 24
height: 24
}
}
}
Item {
width: 1

@ -1,5 +1,5 @@
/*
Copyright 2021-2022 Peter Repukat - FlatspotSoftware
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.

@ -1,5 +1,5 @@
/*
Copyright 2021-2022 Peter Repukat - FlatspotSoftware
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.
@ -189,7 +189,7 @@ Dialog {
anchors.verticalCenter: parent.verticalCenter
spacing: 2
Label {
text: modelData.InstallLocation.split('/').pop().split('\\').pop()
text: modelData.InstallLocation.split('/').pop().split('\\').pop().replace(/([a-z])([A-Z])/g, '$1 $2')
font.pixelSize: 18
font.bold: true
}

@ -1,5 +1,5 @@
/*
Copyright 2021-2022 Peter Repukat - FlatspotSoftware
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.

@ -1,5 +1,5 @@
/*
Copyright 2021-2022 Peter Repukat - FlatspotSoftware
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.

@ -1,5 +1,5 @@
/*
Copyright 2021-2022 Peter Repukat - FlatspotSoftware
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.

@ -1,5 +1,5 @@
/*
Copyright 2021-2022 Peter Repukat - FlatspotSoftware
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.

@ -1,5 +1,5 @@
/*
Copyright 2021-2022 Peter Repukat - FlatspotSoftware
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.

@ -1,5 +1,5 @@
/*
Copyright 2021-2022 Peter Repukat - FlatspotSoftware
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.
@ -136,7 +136,11 @@ Item {
id: nameInput
placeholderText: qsTr("...")
text: shortcutInfo.name
onTextChanged: shortcutInfo.name = text
onTextChanged: function() {
shortcutInfo.oldName = shortcutInfo.oldName || shortcutInfo.name
shortcutInfo.name = nameInput.text
shortcutInfo = shortcutInfo
}
validator: RegularExpressionValidator { regularExpression: /([0-z]|\s|.)+/gm }
}
}
@ -374,7 +378,7 @@ Item {
id: egsSelectDialog
onConfirmed: function(modelData) {
if (nameInput.text == "") {
nameInput.text = modelData.InstallLocation.split('/').pop().split('\\').pop()
nameInput.text = modelData.InstallLocation.split('/').pop().split('\\').pop().replace(/([a-z])([A-Z])/g, '$1 $2')
}
pathInput.text = "com.epicgames.launcher://apps/"
+ modelData.NamespaceId

@ -1,5 +1,5 @@
/*
Copyright 2021-2022 Peter Repukat - FlatspotSoftware
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.

@ -1,5 +1,5 @@
/*
Copyright 2021-2022 Peter Repukat - FlatspotSoftware
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.

@ -1,5 +1,5 @@
/*
Copyright 2021-2022 Peter Repukat - FlatspotSoftware
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.

@ -1,5 +1,5 @@
/*
Copyright 2021-2022 Peter Repukat - FlatspotSoftware
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.

@ -1,5 +1,5 @@
/*
Copyright 2021-2022 Peter Repukat - FlatspotSoftware
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.
@ -492,12 +492,12 @@ Window {
if (windowContent.editedIndex < 0) {
uiModel.addTarget(shortcut)
} else {
if (uiModel.isInSteam(shortcut)) {
if (uiModel.updateTarget(windowContent.editedIndex, shortcut)) {
if (steamShortcutsChanged == false) {
steamChangedDialog.open();
}
} else {
if (uiModel.updateTarget(windowContent.editedIndex, shortcut)) {
if (uiModel.isInSteam(shortcut) && steamShortcutsChanged == false) {
steamChangedDialog.open();
}
} else {
if (uiModel.isInSteam(shortcut)) {
manualInfo = uiModel.manualProps(shortcut);
writeErrorDialog.open();
}

@ -1,5 +1,5 @@
/*
Copyright 2021-2022 Peter Repukat - FlatspotSoftware
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.

@ -1,5 +1,5 @@
/*
Copyright 2021-2022 Peter Repukat - FlatspotSoftware
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.

@ -1,5 +1,5 @@
/*
Copyright 2021-2022 Peter Repukat - FlatspotSoftware
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.

@ -1,5 +1,5 @@
/*
Copyright 2021-2022 Peter Repukat - FlatspotSoftware
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.

@ -1,5 +1,5 @@
/*
Copyright 2021-2022 Peter Repukat - FlatspotSoftware
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.
@ -21,7 +21,7 @@ limitations under the License.
#include "AppLauncher.h"
#include "Settings.h"
HttpServer::HttpServer(AppLauncher& app_launcher) : app_launcher_(app_launcher)
HttpServer::HttpServer(AppLauncher& app_launcher, std::function<void()> close) : app_launcher_(app_launcher), close_(close)
{
}
@ -62,6 +62,10 @@ void HttpServer::run()
res.set_content(j.dump(), "text/json");
});
server_.Post("/quit", [this](const httplib::Request& req, httplib::Response& res) {
close_();
});
server_.Get("/settings", [this](const httplib::Request& req, httplib::Response& res) {
res.set_content(Settings::toJson().dump(), "text/json");
});

@ -1,5 +1,5 @@
/*
Copyright 2021-2022 Peter Repukat - FlatspotSoftware
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.
@ -23,7 +23,7 @@ class AppLauncher;
class HttpServer {
public:
explicit HttpServer(AppLauncher& app_launcher);
explicit HttpServer(AppLauncher& app_launcher, std::function<void()> close);
void run();
void stop();
@ -34,4 +34,5 @@ class HttpServer {
uint16_t port_ = 8756;
AppLauncher& app_launcher_;
std::function<void()> close_;
};

@ -1,5 +1,5 @@
/*
Copyright 2021-2022 Peter Repukat - FlatspotSoftware
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.

@ -1,5 +1,5 @@
/*
Copyright 2021-2022 Peter Repukat - FlatspotSoftware
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.

@ -1,5 +1,5 @@
/*
Copyright 2021-2022 Peter Repukat - FlatspotSoftware
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.
@ -182,6 +182,11 @@ void Overlay::update()
}
}
if (Settings::window.disableGlosSIOverlay) {
ImGui::SFML::Render(window_);
return;
}
showLogs(0);
if (enabled_ || force_enable_) {

@ -1,5 +1,5 @@
/*
Copyright 2021-2022 Peter Repukat - FlatspotSoftware
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.

@ -1,5 +1,5 @@
/*
Copyright 2021-2022 Peter Repukat - FlatspotSoftware
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.
@ -54,6 +54,8 @@ inline struct Window {
int maxFps = 0;
float scale = 0.f;
bool disableOverlay = false;
bool hideAltTab = false;
bool disableGlosSIOverlay = false;
} window;
inline struct Controller {
@ -69,6 +71,8 @@ inline struct Common {
std::wstring name;
std::wstring icon;
int version;
std::wstring steamPath;
std::wstring steamUserId;
} common;
inline std::filesystem::path settings_path_ = "";
@ -189,6 +193,8 @@ inline void Parse(const nlohmann::basic_json<>& json)
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()) {
@ -200,6 +206,9 @@ inline void Parse(const nlohmann::basic_json<>& json)
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);
}
catch (const nlohmann::json::exception& e) {
spdlog::warn("Err parsing config: {}", e.what());
@ -293,6 +302,7 @@ inline nlohmann::json toJson()
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;

@ -1,5 +1,5 @@
/*
Copyright 2021-2022 Peter Repukat - FlatspotSoftware
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.

@ -1,5 +1,5 @@
/*
Copyright 2021-2022 Peter Repukat - FlatspotSoftware
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.

@ -1,5 +1,5 @@
/*
Copyright 2021-2022 Peter Repukat - FlatspotSoftware
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.
@ -46,7 +46,7 @@ SteamTarget::SteamTarget()
delayed_shutdown_ = true;
delay_shutdown_clock_.restart();
}),
server_(launcher_)
server_(launcher_, [this] { run_ = false; })
{
target_window_handle_ = window_.getSystemHandle();
#ifdef _WIN32
@ -180,6 +180,9 @@ void SteamTarget::onOverlayChanged(bool overlay_open)
void SteamTarget::toggleGlossiOverlay()
{
if (Settings::window.disableGlosSIOverlay) {
return;
}
if (overlay_.expired()) {
return;
}
@ -253,7 +256,7 @@ std::filesystem::path SteamTarget::getSteamPath() const
catch (const winreg::RegException& e) {
spdlog::error("Couldn't get Steam path from Registry; {}", e.what());
}
return L"";
return Settings::common.steamPath;
#else
return L""; // TODO
#endif
@ -273,7 +276,7 @@ std::wstring SteamTarget::getSteamUserId() const
catch (const winreg::RegException& e) {
spdlog::error("Couldn't get Steam path from Registry; {}", e.what());
}
return L"";
return Settings::common.steamUserId;
#else
return L""; // TODO
#endif

@ -1,5 +1,5 @@
/*
Copyright 2021-2022 Peter Repukat - FlatspotSoftware
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.

@ -1,5 +1,5 @@
/*
Copyright 2021-2022 Peter Repukat - FlatspotSoftware
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.
@ -56,6 +56,11 @@ TargetWindow::TargetWindow(
if (ImGui::Checkbox("Window mode", &Settings::window.windowMode)) {
toggle_window_mode_after_frame_ = true;
}
#ifdef _WIN32
if (ImGui::Checkbox("Hide from Alt+Tab", &Settings::window.hideAltTab)) {
toggle_hidealttab_after_frame_ = true;
}
#endif
ImGui::Text("Max. FPS");
ImGui::SameLine();
int max_fps_copy = Settings::window.maxFps;
@ -116,13 +121,30 @@ void TargetWindow::setClickThrough(bool click_through)
}
#ifdef _WIN32
HWND hwnd = window_.getSystemHandle();
if (click_through) {
SetWindowLong(hwnd, GWL_EXSTYLE, WS_EX_LAYERED | WS_EX_TRANSPARENT | WS_EX_TOPMOST | WS_EX_COMPOSITED);
SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
// hiding GlosSI from Alt-Tab list
// https://learn.microsoft.com/en-us/windows/win32/winmsg/extended-window-styles
if (Settings::window.hideAltTab) {
toggle_hidealttab_after_frame_ = false;
if (click_through) {
SetWindowLong(hwnd, GWL_EXSTYLE, WS_EX_LAYERED | WS_EX_TRANSPARENT | WS_EX_TOPMOST | WS_EX_COMPOSITED | WS_EX_TOOLWINDOW);
SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
}
else {
SetWindowLong(hwnd, GWL_EXSTYLE, WS_EX_LAYERED | WS_EX_COMPOSITED | WS_EX_TOOLWINDOW);
SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
}
}
else {
SetWindowLong(hwnd, GWL_EXSTYLE, WS_EX_LAYERED | WS_EX_COMPOSITED);
SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
if (click_through) {
SetWindowLong(hwnd, GWL_EXSTYLE, WS_EX_LAYERED | WS_EX_TRANSPARENT | WS_EX_TOPMOST | WS_EX_COMPOSITED);
SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
}
else {
SetWindowLong(hwnd, GWL_EXSTYLE, WS_EX_LAYERED | WS_EX_COMPOSITED);
SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
}
}
#endif
}
@ -142,9 +164,15 @@ void TargetWindow::update()
screenShotWorkaround();
overlay_->update();
window_.display();
#ifdef _WIN32
if (toggle_hidealttab_after_frame_) {
toggle_hidealttab_after_frame_ = false;
}
#endif
if (toggle_window_mode_after_frame_) {
createWindow();
}
// As SFML screws us out of most windows-events, just poll resolution every once in a while
// If changed, recreate window.
// Fixes Blackscreen issues when user does funky stuff and still uses GlosSI in non windowed mod...
@ -335,6 +363,7 @@ void TargetWindow::createWindow()
style &= ~WS_OVERLAPPED;
style |= WS_POPUP;
SetWindowLong(hwnd, GWL_STYLE, style);
MARGINS margins;
margins.cxLeftWidth = -1;

@ -1,5 +1,5 @@
/*
Copyright 2021-2022 Peter Repukat - FlatspotSoftware
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.
@ -82,4 +82,5 @@ class TargetWindow {
void createWindow();
bool toggle_window_mode_after_frame_ = false;
bool toggle_hidealttab_after_frame_ = false;
};

@ -1,5 +1,5 @@
/*
Copyright 2021-2022 Peter Repukat - FlatspotSoftware
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.
@ -15,12 +15,63 @@ limitations under the License.
*/
#include "UnhookUtil.h"
#ifndef CONFIGAPP
#include <spdlog/spdlog.h>
#include "Settings.h"
#endif
void UnhookUtil::UnPatchHook(const std::string& name, HMODULE module)
{
#ifndef CONFIGAPP
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";
if (std::filesystem::exists(configDirPath)) {
auto unhook_file_path = configDirPath / "unhook_bytes";
if (std::filesystem::exists(unhook_file_path)) {
std::ifstream ifile;
ifile.open(unhook_file_path, std::ios::binary | std::ios::in);
if (ifile.is_open()) {
std::string funcName;
char buff;
do {
if (ifile.eof()) {
break;
}
ifile.read(&buff, sizeof(char));
if (buff != ':') {
funcName.push_back(buff);
} else {
char bytes[8];
ifile.read(bytes, sizeof(char) * 8);
ifile.read(&buff, sizeof(char)); // newline
original_bytes_from_file[funcName] = std::string(bytes, 8);
funcName = "";
}
} while (!ifile.eof());
ifile.close();
}
}
}
spdlog::trace("Patching \"{}\"...", name);
BYTE* address = reinterpret_cast<BYTE*>(GetProcAddress(module, name.c_str()));
@ -28,11 +79,19 @@ void UnhookUtil::UnPatchHook(const std::string& name, HMODULE module)
spdlog::error("failed to unpatch \"{}\"", name);
}
std::string bytes;
if (Settings::isWin10 && UNHOOK_BYTES_ORIGINAL_WIN10.contains(name)) {
bytes = UNHOOK_BYTES_ORIGINAL_WIN10.at(name);
if (original_bytes_from_file.contains(name)) {
bytes = original_bytes_from_file.at(name);
spdlog::trace("Using originalBytes from file for {}", name);
}
else {
bytes = UNHOOK_BYTES_ORIGINAL_22000.at(name);
if (Settings::isWin10 && UNHOOK_BYTES_ORIGINAL_WIN10.contains(name)) {
bytes = UNHOOK_BYTES_ORIGINAL_WIN10.at(name);
}
else {
bytes = UNHOOK_BYTES_ORIGINAL_22000.at(name);
}
spdlog::trace("Using fallback originalBytes for {}", name);
}
DWORD dw_old_protect, dw_bkup;
const auto len = bytes.size();
@ -52,4 +111,18 @@ void UnhookUtil::UnPatchHook(const std::string& name, HMODULE module)
spdlog::trace("Unpatched \"{}\"", name);
}
VirtualProtect(address, len, dw_old_protect, &dw_bkup); // Revert permission change...
#endif
}
std::string UnhookUtil::ReadOriginalBytes(const std::string& name, const std::wstring& moduleName)
{
auto module = LoadLibraryW(moduleName.c_str());
auto address = reinterpret_cast<BYTE*>(GetProcAddress(module, name.c_str()));
std::string res;
res.resize(8);
for (int i = 0; i < 8; i++) {
res[i] = static_cast<char>(*(address + i));
}
return res;
}

@ -1,5 +1,5 @@
/*
Copyright 2021-2022 Peter Repukat - FlatspotSoftware
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.
@ -25,6 +25,8 @@ limitations under the License.
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,
@ -34,6 +36,9 @@ static inline const std::vector<uint8_t> JUMP_INSTR_OPCODES = {
// 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"},

@ -1,5 +1,5 @@
/*
Copyright 2021-2022 Peter Repukat - FlatspotSoftware
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.
@ -168,8 +168,9 @@ int main(int argc, char* argv[])
auto existingwindow = FindWindowA(nullptr, "GlosSITarget");
if (existingwindow) {
spdlog::error("GlosSITarget is already running!");
return 1;
spdlog::error("GlosSITarget is already running! Closing old process...");
httplib::Client client("http://localhost:8756");
client.Post("/quit");
}
int numArgs;

@ -1,5 +1,5 @@
/*
Copyright 2021-2022 Peter Repukat - FlatspotSoftware
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.

@ -1,5 +1,5 @@
/*
Copyright 2021-2022 Peter Repukat - FlatspotSoftware
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.

@ -1,5 +1,5 @@
/*
Copyright 2021-2022 Peter Repukat - FlatspotSoftware
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.

@ -67,7 +67,7 @@ For Building instructions refer to [BUILDING.md](./docs/BUILDING.md)
## License
```license
Copyright 2017-2022 Peter Repukat - FlatspotSoftware
Copyright 2017-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.

@ -1,5 +1,5 @@
/*
Copyright 2021-2022 Peter Repukat - FlatspotSoftware
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.

Loading…
Cancel
Save