From 086084ef6617ffb4e8a6feb385d27ceead59676c Mon Sep 17 00:00:00 2001 From: Peter Repukat Date: Tue, 4 Jan 2022 15:38:28 +0100 Subject: [PATCH] Hopefully get rid of some UAC/Admin issues --- GlosSIConfig/GlosSIConfig.vcxproj | 3 +- GlosSIConfig/Resource.rc | 212 ++++++++++++++++++++++++++++- GlosSIConfig/UIModel.cpp | 83 ++++++++++- GlosSIConfig/UIModel.h | 14 +- GlosSIConfig/VDFParser.h | 24 ++++ GlosSIConfig/main.cpp | 17 +++ GlosSIConfig/manifest.xml | 22 --- GlosSIConfig/qml/ShortcutCards.qml | 4 +- 8 files changed, 340 insertions(+), 39 deletions(-) diff --git a/GlosSIConfig/GlosSIConfig.vcxproj b/GlosSIConfig/GlosSIConfig.vcxproj index 5d3a907..f29b5ae 100644 --- a/GlosSIConfig/GlosSIConfig.vcxproj +++ b/GlosSIConfig/GlosSIConfig.vcxproj @@ -76,7 +76,6 @@ true - RequireAdministrator powershell.exe $(SolutionDir)version_help.ps1 @@ -98,7 +97,7 @@ true - RequireAdministrator + AsInvoker powershell.exe $(SolutionDir)version_help.ps1 diff --git a/GlosSIConfig/Resource.rc b/GlosSIConfig/Resource.rc index b8c6f06..c3879cb 100644 --- a/GlosSIConfig/Resource.rc +++ b/GlosSIConfig/Resource.rc @@ -51,8 +51,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 0,0,3,101006047020 - PRODUCTVERSION 0,0,3,101006047020 + FILEVERSION 0,0,3,103000945081 + PRODUCTVERSION 0,0,3,103000945081 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -69,12 +69,12 @@ BEGIN BEGIN VALUE "CompanyName", "Peter Repukat - FlatspotSoftware" VALUE "FileDescription", "GlosSI - Config" - VALUE "FileVersion", "0.0.3.1-1-g6f47020" + VALUE "FileVersion", "0.0.3.1-3-ge945c81" VALUE "InternalName", "GlosSIConfig" VALUE "LegalCopyright", "Copyright (C) 2021 Peter Repukat - FlatspotSoftware" VALUE "OriginalFilename", "GlosSIConfig.exe" VALUE "ProductName", "GlosSi" - VALUE "ProductVersion", "0.0.3.1-1-g6f47020" + VALUE "ProductVersion", "0.0.3.1-3-ge945c81" END END BLOCK "VarFileInfo" @@ -326,6 +326,210 @@ END + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/GlosSIConfig/UIModel.cpp b/GlosSIConfig/UIModel.cpp index 9f3d29c..a882683 100644 --- a/GlosSIConfig/UIModel.cpp +++ b/GlosSIConfig/UIModel.cpp @@ -23,6 +23,7 @@ limitations under the License. #ifdef _WIN32 #include "UWPFetch.h" +#include #endif UIModel::UIModel() : QObject(nullptr) @@ -146,7 +147,7 @@ bool UIModel::isInSteam(QVariant shortcut) return false; } -bool UIModel::addToSteam(QVariant shortcut) +bool UIModel::addToSteam(QVariant shortcut, const QString& shortcutspath, bool from_cmd) { QDir appDir = QGuiApplication::applicationDirPath(); const auto map = shortcut.toMap(); @@ -203,11 +204,25 @@ bool UIModel::addToSteam(QVariant shortcut) shortcuts_vdf_.shortcuts.push_back(vdfshortcut); - const std::filesystem::path config_path = std::wstring(getSteamPath()) + user_data_path_.toStdWString() + getSteamUserId() + shortcutsfile_.toStdWString(); - return VDFParser::Parser::writeShortcuts(config_path, shortcuts_vdf_); + return writeShortcutsVDF(L"add", name.toStdWString(), shortcutspath.toStdWString(), from_cmd); +} +bool UIModel::addToSteam(const QString& name, const QString& shortcutspath, bool from_cmd) +{ + qDebug() << "trying to add " << name << " to steam"; + const auto target = std::find_if(targets_.begin(), targets_.end(), [&name](const auto& target) { + const auto map = target.toMap(); + const auto target_name = map["name"].toString(); + return name == target_name; + }); + if (target != targets_.end()) { + return addToSteam(*target, shortcutspath, from_cmd); + } + qDebug() << name << " not found!"; + return false; } -bool UIModel::removeFromSteam(const QString& name) +bool UIModel::removeFromSteam(const QString& name, const QString& shortcutspath, bool from_cmd) { + qDebug() << "trying to remove " << name << " from steam"; auto& scuts = shortcuts_vdf_.shortcuts; scuts.erase(std::remove_if(scuts.begin(), scuts.end(), [&name](const auto& shortcut) { return shortcut.appName.value == name.toStdString(); @@ -218,8 +233,7 @@ bool UIModel::removeFromSteam(const QString& name) scuts[i].idx = i; } } - const std::filesystem::path config_path = std::wstring(getSteamPath()) + user_data_path_.toStdWString() + getSteamUserId() + shortcutsfile_.toStdWString(); - return VDFParser::Parser::writeShortcuts(config_path, shortcuts_vdf_); + return writeShortcutsVDF(L"remove", name.toStdWString(), shortcutspath.toStdWString(), from_cmd); } #ifdef _WIN32 @@ -229,6 +243,60 @@ QVariantList UIModel::uwpApps() } #endif +bool UIModel::writeShortcutsVDF(const std::wstring& mode, const std::wstring& name, const std::wstring& shortcutspath, bool is_admin_try) const +{ +#ifdef _WIN32 + const std::filesystem::path config_path = is_admin_try + ? shortcutspath + : std::wstring(getSteamPath()) + user_data_path_.toStdWString() + getSteamUserId() + shortcutsfile_.toStdWString(); + + qDebug() << "Steam config Path: " << config_path; + qDebug() << "Trying to write config as admin: " << is_admin_try; + + + auto write_res = VDFParser::Parser::writeShortcuts(config_path, shortcuts_vdf_); + + if (!write_res && !is_admin_try) { + wchar_t szPath[MAX_PATH]; + if (GetModuleFileName(NULL, szPath, ARRAYSIZE(szPath))) { + // Launch itself as admin + SHELLEXECUTEINFO sei = {sizeof(sei)}; + sei.lpVerb = L"runas"; + qDebug() << QString("exepath: %1").arg(szPath); + sei.lpFile = szPath; + const std::wstring paramstr = mode + L" " + name + L" \"" + config_path.wstring() + L"\""; + sei.lpParameters = paramstr.c_str(); + sei.hwnd = NULL; + sei.nShow = SW_NORMAL; + sei.fMask = SEE_MASK_NOCLOSEPROCESS; + if (!ShellExecuteEx(&sei)) { + DWORD dwError = GetLastError(); + if (dwError == ERROR_CANCELLED) { + qDebug() << "User cancelled UAC Prompt"; + return false; + } + } + else { + qDebug() << QString("HProc: %1").arg((int)sei.hProcess); + + if (sei.hProcess && WAIT_OBJECT_0 == WaitForSingleObject(sei.hProcess, INFINITE)) { + DWORD exitcode = 1; + GetExitCodeProcess(sei.hProcess, &exitcode); + qDebug() << QString("Exitcode: %1").arg((int)exitcode); + if (exitcode == 0) { + return true; + } + } + return false; + } + } + } + return write_res; +#else + return VDFParser::Parser::writeShortcuts(config_path, shortcuts_vdf_); +#endif +} + bool UIModel::getIsWindows() const { return is_windows_; @@ -302,6 +370,9 @@ std::wstring UIModel::getSteamUserId() const // steam should always be open and have written reg values... winreg::RegKey key{HKEY_CURRENT_USER, L"SOFTWARE\\Valve\\Steam\\ActiveProcess"}; const auto res = std::to_wstring(key.GetDwordValue(L"ActiveUser")); + if (res == L"0") { + qDebug() << "Steam not open?"; + } return res; #else return L""; // TODO LINUX diff --git a/GlosSIConfig/UIModel.h b/GlosSIConfig/UIModel.h index f706d45..22b4758 100644 --- a/GlosSIConfig/UIModel.h +++ b/GlosSIConfig/UIModel.h @@ -37,12 +37,20 @@ class UIModel : public QObject { Q_INVOKABLE void updateTarget(int index, QVariant shortcut); Q_INVOKABLE void deleteTarget(int index); Q_INVOKABLE bool isInSteam(QVariant shortcut); - Q_INVOKABLE bool addToSteam(QVariant shortcut); - Q_INVOKABLE bool removeFromSteam(const QString& name); + Q_INVOKABLE bool addToSteam(QVariant shortcut, const QString& shortcutspath, bool from_cmd = false); + bool addToSteam(const QString& name, const QString& shortcutspath, bool from_cmd = false); + Q_INVOKABLE bool removeFromSteam(const QString& name, const QString& shortcutspath, bool from_cmd = false); #ifdef _WIN32 Q_INVOKABLE QVariantList uwpApps(); #endif + [[nodiscard]] bool writeShortcutsVDF( + const std::wstring& mode, + const std::wstring& name, + const std::wstring& shortcutspath, + bool is_admin_try = false + ) const; + bool getIsWindows() const; [[nodiscard]] bool hasAcrylicEffect() const; void setAcrylicEffect(bool has_acrylic_affect); @@ -54,7 +62,7 @@ class UIModel : public QObject { private: std::filesystem::path config_path_; QString config_dir_name_; - + void writeTarget(const QJsonObject& json, const QString& name); std::filesystem::path getSteamPath() const; diff --git a/GlosSIConfig/VDFParser.h b/GlosSIConfig/VDFParser.h index ec16169..22ebead 100644 --- a/GlosSIConfig/VDFParser.h +++ b/GlosSIConfig/VDFParser.h @@ -226,6 +226,21 @@ struct Shortcut { tags = other.tags; return *this; } + //std::wstring to_json() + //{ + // std::wstring res = L"{"; + // res += L"idx: " + std::to_wstring(idx.operator int()) + L",\n"; + // res += L"appId: " + std::to_wstring(appId.value) + L",\n"; + // res += L"appName: " + std::filesystem::path(appName.value).wstring() + L",\n"; + // res += L"StartDir: " + std::filesystem::path(StartDir.value).wstring() + L",\n"; + // res += L"ShortcutPath: " + std::filesystem::path(ShortcutPath.value).wstring() + L",\n"; + // res += L"LaunchOptions: " + std::filesystem::path(LaunchOptions.value).wstring() + L",\n"; + // res += L"IsHidden: " + (IsHidden.value ? L"true" : L"false") + L",\n"; + // res += L"AllowDesktopConfig: " + (AllowDesktopConfig.value ? L"true" : L"false") + L",\n"; + // res += L"idx: " + std::to_wstring(appId.value) + L",\n"; + // res += L"}"; + // return res; + //} }; struct VDFFile { @@ -252,6 +267,15 @@ struct VDFFile { shortcuts = std::move(other.shortcuts); return *this; } + //std::wstring to_json() + //{ + // std::wstring res = L"["; + + + + // res += L"]"; + // return res; + //} }; class Parser { diff --git a/GlosSIConfig/main.cpp b/GlosSIConfig/main.cpp index ae55d9a..ed1e9fc 100644 --- a/GlosSIConfig/main.cpp +++ b/GlosSIConfig/main.cpp @@ -116,6 +116,23 @@ int main(int argc, char* argv[]) QQmlApplicationEngine engine; UIModel uimodel; + if (argc >= 4) { + if (QString::fromStdString(argv[1]) == "remove") { + const auto write_res = uimodel.removeFromSteam( + QString::fromStdString(argv[2]), QString::fromStdString(argv[3]), true); + if (write_res) { + return 0; + } + return 1; + } else if (QString::fromStdString(argv[1]) == "add") { + const auto write_res = uimodel.addToSteam( + QString::fromStdString(argv[2]), QString::fromStdString(argv[3]), true); + if (write_res) { + return 0; + } + return 1; + } + } #ifdef _WIN32 engine.addImageProvider(QLatin1String("exe"), new ExeImageProvider()); #endif diff --git a/GlosSIConfig/manifest.xml b/GlosSIConfig/manifest.xml index e58f8ee..c4924ac 100644 --- a/GlosSIConfig/manifest.xml +++ b/GlosSIConfig/manifest.xml @@ -5,28 +5,6 @@ - - - - - - - - - - - - - - \ No newline at end of file diff --git a/GlosSIConfig/qml/ShortcutCards.qml b/GlosSIConfig/qml/ShortcutCards.qml index 4fdb9dd..1d7238c 100644 --- a/GlosSIConfig/qml/ShortcutCards.qml +++ b/GlosSIConfig/qml/ShortcutCards.qml @@ -178,12 +178,12 @@ GridView { steamChangedDialog.open(); } if (delegateRoot.isInSteam) { - if (!uiModel.removeFromSteam(modelData.name)) { + if (!uiModel.removeFromSteam(modelData.name, "")) { writeErrorDialog.open(); return; } } else { - if (!uiModel.addToSteam(modelData)) { + if (!uiModel.addToSteam(modelData, "")) { writeErrorDialog.open(); return; }