From 3062a35eb1297067446156c43e9d0df2f684edff Mon Sep 17 00:00:00 2001
From: boludoz <francomaro@gmail.com>
Date: Sun, 15 Oct 2023 02:02:22 -0300
Subject: [PATCH 01/24] Improved shortcut: add games in applist for Windows,
 question for start game at fullscreen & better unicode support for some
 Windows path funcs.

---
 src/common/fs/fs_util.cpp   |  59 +++++
 src/common/fs/fs_util.h     |  22 +-
 src/common/fs/path_util.cpp |  87 ++++++-
 src/common/fs/path_util.h   |  15 +-
 src/yuzu/game_list.cpp      |   4 -
 src/yuzu/main.cpp           | 504 ++++++++++++++++++++++--------------
 src/yuzu/main.h             |  22 +-
 src/yuzu/util/util.cpp      |  17 +-
 src/yuzu/util/util.h        |  14 +-
 9 files changed, 522 insertions(+), 222 deletions(-)

diff --git a/src/common/fs/fs_util.cpp b/src/common/fs/fs_util.cpp
index 813a713c3b..442f637281 100644
--- a/src/common/fs/fs_util.cpp
+++ b/src/common/fs/fs_util.cpp
@@ -36,4 +36,63 @@ std::string PathToUTF8String(const std::filesystem::path& path) {
     return ToUTF8String(path.u8string());
 }
 
+std::u8string U8FilenameSantizer(const std::u8string_view u8filename) {
+    std::u8string u8path_santized{u8filename.begin(), u8filename.end()};
+    size_t eSizeSanitized = u8path_santized.size();
+
+    // Special case for ":", for example: 'Pepe: La secuela' --> 'Pepe - La
+    // secuela' or 'Pepe : La secuela' --> 'Pepe - La secuela'
+    for (size_t i = 0; i < eSizeSanitized; i++) {
+        switch (u8path_santized[i]) {
+        case u8':':
+            if (i == 0 || i == eSizeSanitized - 1) {
+                u8path_santized.replace(i, 1, u8"_");
+            } else if (u8path_santized[i - 1] == u8' ') {
+                u8path_santized.replace(i, 1, u8"-");
+            } else {
+                u8path_santized.replace(i, 1, u8" -");
+                eSizeSanitized++;
+            }
+            break;
+        case u8'\\':
+        case u8'/':
+        case u8'*':
+        case u8'?':
+        case u8'\"':
+        case u8'<':
+        case u8'>':
+        case u8'|':
+        case u8'\0':
+            u8path_santized.replace(i, 1, u8"_");
+            break;
+        default:
+            break;
+        }
+    }
+
+    // Delete duplicated spaces || Delete duplicated dots (MacOS i think)
+    for (size_t i = 0; i < eSizeSanitized - 1; i++) {
+        if ((u8path_santized[i] == u8' ' && u8path_santized[i + 1] == u8' ') ||
+            (u8path_santized[i] == u8'.' && u8path_santized[i + 1] == u8'.')) {
+            u8path_santized.erase(i, 1);
+            i--;
+        }
+    }
+
+    // Delete all spaces and dots at the end (Windows almost)
+    while (u8path_santized.back() == u8' ' || u8path_santized.back() == u8'.') {
+        u8path_santized.pop_back();
+    }
+
+    if (u8path_santized.empty()) {
+        return u8"";
+    }
+
+    return u8path_santized;
+}
+
+std::string UTF8FilenameSantizer(const std::string_view filename) {
+    return ToUTF8String(U8FilenameSantizer(ToU8String(filename)));
+}
+
 } // namespace Common::FS
diff --git a/src/common/fs/fs_util.h b/src/common/fs/fs_util.h
index 2492a9f942..dbb4f5a9a1 100644
--- a/src/common/fs/fs_util.h
+++ b/src/common/fs/fs_util.h
@@ -82,4 +82,24 @@ concept IsChar = std::same_as<T, char>;
  */
 [[nodiscard]] std::string PathToUTF8String(const std::filesystem::path& path);
 
-} // namespace Common::FS
+/**
+ * Fix filename (remove invalid characters)
+ *
+ * @param u8_string dirty encoded filename string
+ *
+ * @returns utf8_string santized filename string
+ *
+ */
+[[nodiscard]] std::u8string U8FilenameSantizer(const std::u8string_view u8filename);
+
+/**
+ * Fix filename (remove invalid characters)
+ *
+ * @param utf8_string dirty encoded filename string
+ *
+ * @returns utf8_string santized filename string
+ *
+ */
+[[nodiscard]] std::string UTF8FilenameSantizer(const std::string_view filename);
+
+} // namespace Common::FS
\ No newline at end of file
diff --git a/src/common/fs/path_util.cpp b/src/common/fs/path_util.cpp
index 0abd81a45e..a461161ede 100644
--- a/src/common/fs/path_util.cpp
+++ b/src/common/fs/path_util.cpp
@@ -6,6 +6,7 @@
 #include <unordered_map>
 
 #include "common/fs/fs.h"
+#include "common/string_util.h"
 #ifdef ANDROID
 #include "common/fs/fs_android.h"
 #endif
@@ -14,7 +15,7 @@
 #include "common/logging/log.h"
 
 #ifdef _WIN32
-#include <shlobj.h> // Used in GetExeDirectory()
+#include <shlobj.h> // Used in GetExeDirectory() and GetWindowsDesktop()
 #else
 #include <cstdlib>     // Used in Get(Home/Data)Directory()
 #include <pwd.h>       // Used in GetHomeDirectory()
@@ -250,30 +251,39 @@ void SetYuzuPath(YuzuPath yuzu_path, const fs::path& new_path) {
 #ifdef _WIN32
 
 fs::path GetExeDirectory() {
-    wchar_t exe_path[MAX_PATH];
+    WCHAR exe_path[MAX_PATH];
 
-    if (GetModuleFileNameW(nullptr, exe_path, MAX_PATH) == 0) {
+    if (SUCCEEDED(GetModuleFileNameW(nullptr, exe_path, MAX_PATH))) {
+        std::wstring wideExePath(exe_path);
+
+        // UTF-16 filesystem lib to UTF-8 is broken, so we need to convert to UTF-8 with the with
+        // the Windows library (Filesystem converts the strings literally).
+        return fs::path{Common::UTF16ToUTF8(wideExePath)}.parent_path();
+    } else {
         LOG_ERROR(Common_Filesystem,
-                  "Failed to get the path to the executable of the current process");
+                  "[GetExeDirectory] Failed to get the path to the executable of the current "
+                  "process");
     }
 
-    return fs::path{exe_path}.parent_path();
+    return fs::path{};
 }
 
 fs::path GetAppDataRoamingDirectory() {
     PWSTR appdata_roaming_path = nullptr;
 
-    SHGetKnownFolderPath(FOLDERID_RoamingAppData, 0, nullptr, &appdata_roaming_path);
+    if (SUCCEEDED(SHGetKnownFolderPath(FOLDERID_RoamingAppData, 0, NULL, &appdata_roaming_path))) {
+        std::wstring wideAppdataRoamingPath(appdata_roaming_path);
+        CoTaskMemFree(appdata_roaming_path);
 
-    auto fs_appdata_roaming_path = fs::path{appdata_roaming_path};
-
-    CoTaskMemFree(appdata_roaming_path);
-
-    if (fs_appdata_roaming_path.empty()) {
-        LOG_ERROR(Common_Filesystem, "Failed to get the path to the %APPDATA% directory");
+        // UTF-16 filesystem lib to UTF-8 is broken, so we need to convert to UTF-8 with the with
+        // the Windows library (Filesystem converts the strings literally).
+        return fs::path{Common::UTF16ToUTF8(wideAppdataRoamingPath)};
+    } else {
+        LOG_ERROR(Common_Filesystem,
+                  "[GetAppDataRoamingDirectory] Failed to get the path to the %APPDATA% directory");
     }
 
-    return fs_appdata_roaming_path;
+    return fs::path{};
 }
 
 #else
@@ -338,6 +348,57 @@ fs::path GetBundleDirectory() {
 
 #endif
 
+fs::path GetDesktopPath() {
+#if defined(_WIN32)
+    PWSTR DesktopPath = nullptr;
+
+    if (SUCCEEDED(SHGetKnownFolderPath(FOLDERID_Desktop, 0, NULL, &DesktopPath))) {
+        std::wstring wideDesktopPath(DesktopPath);
+        CoTaskMemFree(DesktopPath);
+
+        // UTF-16 filesystem lib to UTF-8 is broken, so we need to convert to UTF-8 with the with
+        // the Windows library (Filesystem converts the strings literally).
+        return fs::path{Common::UTF16ToUTF8(wideDesktopPath)};
+    } else {
+        LOG_ERROR(Common_Filesystem,
+                  "[GetDesktopPath] Failed to get the path to the desktop directory");
+    }
+#else
+    fs::path shortcut_path = GetHomeDirectory() / "Desktop";
+    if (fs::exists(shortcut_path)) {
+        return shortcut_path;
+    }
+#endif
+    return fs::path{};
+}
+
+fs::path GetAppsShortcutsPath() {
+#if defined(_WIN32)
+    PWSTR AppShortcutsPath = nullptr;
+
+    if (SUCCEEDED(SHGetKnownFolderPath(FOLDERID_CommonPrograms, 0, NULL, &AppShortcutsPath))) {
+        std::wstring wideAppShortcutsPath(AppShortcutsPath);
+        CoTaskMemFree(AppShortcutsPath);
+
+        // UTF-16 filesystem lib to UTF-8 is broken, so we need to convert to UTF-8 with the with
+        // the Windows library (Filesystem converts the strings literally).
+        return fs::path{Common::UTF16ToUTF8(wideAppShortcutsPath)};
+    } else {
+        LOG_ERROR(Common_Filesystem,
+                  "[GetAppsShortcutsPath] Failed to get the path to the App Shortcuts directory");
+    }
+#else
+    fs::path shortcut_path = GetHomeDirectory() / ".local/share/applications";
+    if (!fs::exists(shortcut_path)) {
+        shortcut_path = std::filesystem::path("/usr/share/applications");
+        return shortcut_path;
+    } else {
+        return shortcut_path;
+    }
+#endif
+    return fs::path{};
+}
+
 // vvvvvvvvvv Deprecated vvvvvvvvvv //
 
 std::string_view RemoveTrailingSlash(std::string_view path) {
diff --git a/src/common/fs/path_util.h b/src/common/fs/path_util.h
index 63801c924b..b88a388d19 100644
--- a/src/common/fs/path_util.h
+++ b/src/common/fs/path_util.h
@@ -244,7 +244,6 @@ void SetYuzuPath(YuzuPath yuzu_path, const Path& new_path) {
  * @returns The path of the current user's %APPDATA% directory.
  */
 [[nodiscard]] std::filesystem::path GetAppDataRoamingDirectory();
-
 #else
 
 /**
@@ -275,6 +274,20 @@ void SetYuzuPath(YuzuPath yuzu_path, const Path& new_path) {
 
 #endif
 
+/**
+ * Gets the path of the current user's desktop directory.
+ *
+ * @returns The path of the current user's desktop directory.
+ */
+[[nodiscard]] std::filesystem::path GetDesktopPath();
+
+/**
+ * Gets the path of the current user's apps directory.
+ *
+ * @returns The path of the current user's apps directory.
+ */
+[[nodiscard]] std::filesystem::path GetAppsShortcutsPath();
+
 // vvvvvvvvvv Deprecated vvvvvvvvvv //
 
 // Removes the final '/' or '\' if one exists
diff --git a/src/yuzu/game_list.cpp b/src/yuzu/game_list.cpp
index 2bb1a0239b..fbe0996612 100644
--- a/src/yuzu/game_list.cpp
+++ b/src/yuzu/game_list.cpp
@@ -566,10 +566,8 @@ void GameList::AddGamePopup(QMenu& context_menu, u64 program_id, const std::stri
     QAction* navigate_to_gamedb_entry = context_menu.addAction(tr("Navigate to GameDB entry"));
     QMenu* shortcut_menu = context_menu.addMenu(tr("Create Shortcut"));
     QAction* create_desktop_shortcut = shortcut_menu->addAction(tr("Add to Desktop"));
-#ifndef WIN32
     QAction* create_applications_menu_shortcut =
         shortcut_menu->addAction(tr("Add to Applications Menu"));
-#endif
     context_menu.addSeparator();
     QAction* properties = context_menu.addAction(tr("Properties"));
 
@@ -647,11 +645,9 @@ void GameList::AddGamePopup(QMenu& context_menu, u64 program_id, const std::stri
     connect(create_desktop_shortcut, &QAction::triggered, [this, program_id, path]() {
         emit CreateShortcut(program_id, path, GameListShortcutTarget::Desktop);
     });
-#ifndef WIN32
     connect(create_applications_menu_shortcut, &QAction::triggered, [this, program_id, path]() {
         emit CreateShortcut(program_id, path, GameListShortcutTarget::Applications);
     });
-#endif
     connect(properties, &QAction::triggered,
             [this, path]() { emit OpenPerGameGeneralRequested(path); });
 };
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index 1431cf2fee..e4dc717ed3 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -2840,8 +2840,236 @@ void GMainWindow::OnGameListNavigateToGamedbEntry(u64 program_id,
     QDesktopServices::openUrl(QUrl(QStringLiteral("https://yuzu-emu.org/game/") + directory));
 }
 
+bool GMainWindow::CreateShortcutLink(const std::filesystem::path& shortcut_path,
+                                     const std::string& comment,
+                                     const std::filesystem::path& icon_path,
+                                     const std::filesystem::path& command,
+                                     const std::string& arguments, const std::string& categories,
+                                     const std::string& keywords, const std::string& name) {
+
+    bool shortcut_succeeded = false;
+
+    // Replace characters that are illegal in Windows filenames
+    std::filesystem::path shortcut_path_full =
+        shortcut_path / Common::FS::UTF8FilenameSantizer(name);
+
+#if defined(__linux__) || defined(__FreeBSD__)
+    shortcut_path_full += ".desktop";
+#elif defined(_WIN32)
+    shortcut_path_full += ".lnk";
+#endif
+
+    LOG_INFO(Common, "[GMainWindow::CreateShortcutLink] Create shortcut path: {}",
+             shortcut_path_full.string());
+
+#if defined(__linux__) || defined(__FreeBSD__)
+    // This desktop file template was writing referencing
+    // https://specifications.freedesktop.org/desktop-entry-spec/desktop-entry-spec-1.0.html
+    try {
+
+        // Plus 'Type' is required
+        if (name.empty()) {
+            LOG_ERROR(Common, "[GMainWindow::CreateShortcutLink] Name is empty");
+            shortcut_succeeded = false;
+            return shortcut_succeeded;
+        }
+        std::ofstream shortcut_stream(shortcut_path_full, std::ios::binary | std::ios::trunc);
+
+        if (shortcut_stream.is_open()) {
+
+            fmt::print(shortcut_stream, "[Desktop Entry]\n");
+            fmt::print(shortcut_stream, "Type=Application\n");
+            fmt::print(shortcut_stream, "Version=1.0\n");
+            fmt::print(shortcut_stream, "Name={}\n", name);
+
+            if (!comment.empty()) {
+                fmt::print(shortcut_stream, "Comment={}\n", comment);
+            }
+
+            if (std::filesystem::is_regular_file(icon_path)) {
+                fmt::print(shortcut_stream, "Icon={}\n", icon_path.string());
+            }
+
+            fmt::print(shortcut_stream, "TryExec={}\n", command.string());
+            fmt::print(shortcut_stream, "Exec={}", command.string());
+
+            if (!arguments.empty()) {
+                fmt::print(shortcut_stream, " {}", arguments);
+            }
+
+            fmt::print(shortcut_stream, "\n");
+
+            if (!categories.empty()) {
+                fmt::print(shortcut_stream, "Categories={}\n", categories);
+            }
+
+            if (!keywords.empty()) {
+                fmt::print(shortcut_stream, "Keywords={}\n", keywords);
+            }
+
+            shortcut_stream.close();
+            return true;
+
+        } else {
+            LOG_ERROR(Common, "[GMainWindow::CreateShortcutLink] Failed to create shortcut");
+            return false;
+        }
+
+        shortcut_stream.close();
+    } catch (const std::exception& e) {
+        LOG_ERROR(Common, "[GMainWindow::CreateShortcutLink] Failed to create shortcut: {}",
+                  e.what());
+    }
+#elif defined(_WIN32)
+    // Initialize COM
+    auto hr = CoInitialize(NULL);
+    if (FAILED(hr)) {
+        return shortcut_succeeded;
+    }
+
+    IShellLinkW* ps1;
+
+    auto hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLinkW,
+                                 (void**)&ps1);
+
+    // The UTF-16 / UTF-8 conversion is broken in C++, it is necessary to perform these steps and
+    // resort to the native Windows function.
+    std::wstring wshortcut_path_full = Common::UTF8ToUTF16W(shortcut_path_full.string());
+    std::wstring wicon_path = Common::UTF8ToUTF16W(icon_path.string());
+    std::wstring wcommand = Common::UTF8ToUTF16W(command.string());
+    std::wstring warguments = Common::UTF8ToUTF16W(arguments);
+    std::wstring wcomment = Common::UTF8ToUTF16W(comment);
+
+    if (SUCCEEDED(hres)) {
+        if (std::filesystem::is_regular_file(command))
+            hres = ps1->SetPath(wcommand.data());
+
+        if (SUCCEEDED(hres) && !arguments.empty())
+            hres = ps1->SetArguments(warguments.data());
+
+        if (SUCCEEDED(hres) && !comment.empty())
+            hres = ps1->SetDescription(wcomment.data());
+
+        if (SUCCEEDED(hres) && std::filesystem::is_regular_file(icon_path))
+            hres = ps1->SetIconLocation(wicon_path.data(), 0);
+
+        IPersistFile* pPersistFile = nullptr;
+
+        if (SUCCEEDED(hres)) {
+            hres = ps1->QueryInterface(IID_IPersistFile, (void**)&pPersistFile);
+
+            if (SUCCEEDED(hres) && pPersistFile != nullptr) {
+                hres = pPersistFile->Save(wshortcut_path_full.data(), TRUE);
+                if (SUCCEEDED(hres)) {
+                    shortcut_succeeded = true;
+                }
+            }
+        }
+
+        if (pPersistFile != nullptr) {
+            pPersistFile->Release();
+        }
+    } else {
+        LOG_ERROR(Common, "[GMainWindow::CreateShortcutLink] Failed to create IShellLinkWinstance");
+    }
+
+    ps1->Release();
+    CoUninitialize();
+#endif
+
+    if (shortcut_succeeded && std::filesystem::is_regular_file(shortcut_path_full)) {
+        LOG_INFO(Common, "[GMainWindow::CreateShortcutLink] Shortcut created");
+    } else {
+        LOG_ERROR(Common, "[GMainWindow::CreateShortcutLink] Shortcut error, failed to create it");
+        shortcut_succeeded = false;
+    }
+
+    return shortcut_succeeded;
+}
+
+// Messages in pre-defined message boxes for less code spaghetti
+bool GMainWindow::CreateShortcutMessagesGUI(QWidget* parent, const int& imsg,
+                                            const std::string title) {
+    QMessageBox::StandardButtons buttons;
+    int result = 0;
+
+    switch (imsg) {
+
+    case GMainWindow::CREATE_SHORTCUT_MSGBOX_FULLSCREEN_YES:
+        buttons = QMessageBox::Yes | QMessageBox::No;
+
+        result =
+            QMessageBox::information(parent, tr("Create Shortcut"),
+                                     tr("Do you want to launch the game in fullscreen?"), buttons);
+
+        LOG_INFO(Frontend, "Shortcut will launch in fullscreen");
+        return (result == QMessageBox::No) ? false : true;
+
+    case GMainWindow::CREATE_SHORTCUT_MSGBOX_SUCCESS:
+        QMessageBox::information(
+            parent, tr("Create Shortcut"),
+            tr("Successfully created a shortcut to %1").arg(QString::fromStdString(title)));
+        LOG_INFO(Frontend, "Successfully created a shortcut to {}", title);
+        return true;
+
+    case GMainWindow::CREATE_SHORTCUT_MSGBOX_APPVOLATILE_WARNING:
+        result = QMessageBox::warning(
+            this, tr("Create Shortcut"),
+            tr("This will create a shortcut to the current AppImage. This may "
+               "not work well if you update. Continue?"),
+            QMessageBox::StandardButton::Ok | QMessageBox::StandardButton::Cancel);
+        return (result == QMessageBox::StandardButton::Cancel) ? true : false;
+    case GMainWindow::CREATE_SHORTCUT_MSGBOX_ADMIN:
+        buttons = QMessageBox::Ok;
+        QMessageBox::critical(parent, tr("Create Shortcut"),
+                              tr("Cannot create shortcut in Apps. Restart yuzu as administrator."),
+                              buttons);
+        LOG_ERROR(Frontend, "Cannot create shortcut in Apps. Restart yuzu as administrator.");
+        return true;
+    default:
+        buttons = QMessageBox::Ok;
+        QMessageBox::critical(
+            parent, tr("Create Shortcut"),
+            tr("Failed to create a shortcut to %1").arg(QString::fromStdString(title)), buttons);
+        LOG_ERROR(Frontend, "Failed to create a shortcut to {}", title);
+        return true;
+    }
+
+    return true;
+}
+
+bool GMainWindow::MakeShortcutIcoPath(const u64 program_id, const std::string_view game_file_name,
+                                      std::filesystem::path& icons_path) {
+
+    // Get path to Yuzu icons directory & icon extension
+    std::string ico_extension = "png";
+#if defined(_WIN32)
+    icons_path = Common::FS::GetYuzuPath(Common::FS::YuzuPath::ConfigDir) / "icons";
+    ico_extension = "ico";
+#elif defined(__linux__) || defined(__FreeBSD__)
+    icons_path = GetDataDirectory("XDG_DATA_HOME") / "icons/hicolor/256x256";
+#endif
+
+    // Create icons directory if it doesn't exist
+    if (!Common::FS::CreateDirs(icons_path)) {
+        QMessageBox::critical(
+            this, tr("Create Icon"),
+            tr("Cannot create icon file. Path \"%1\" does not exist and cannot be created.")
+                .arg(QString::fromStdString(icons_path.string())),
+            QMessageBox::StandardButton::Ok);
+        icons_path = ""; // Reset path
+        return false;
+    }
+
+    // Create icon file path
+    icons_path /= (program_id == 0 ? fmt::format("yuzu-{}.{}", game_file_name, ico_extension)
+                                   : fmt::format("yuzu-{:016X}.{}", program_id, ico_extension));
+    return true;
+}
+
 void GMainWindow::OnGameListCreateShortcut(u64 program_id, const std::string& game_path,
                                            GameListShortcutTarget target) {
+
     // Get path to yuzu executable
     const QStringList args = QApplication::arguments();
     std::filesystem::path yuzu_command = args[0].toStdString();
@@ -2851,159 +3079,111 @@ void GMainWindow::OnGameListCreateShortcut(u64 program_id, const std::string& ga
         yuzu_command = Common::FS::GetCurrentDir() / yuzu_command;
     }
 
+    // Shortcut path
+    std::filesystem::path shortcut_path{};
+    if (target == GameListShortcutTarget::Desktop) {
+        shortcut_path = Common::FS::GetDesktopPath();
+        if (!std::filesystem::exists(shortcut_path)) {
+            shortcut_path =
+                QStandardPaths::writableLocation(QStandardPaths::DesktopLocation).toStdString();
+        }
+    } else if (target == GameListShortcutTarget::Applications) {
+
+#if defined(_WIN32)
+        HANDLE hProcess = GetCurrentProcess();
+        if (!IsUserAnAdmin()) {
+            GMainWindow::CreateShortcutMessagesGUI(this, GMainWindow::CREATE_SHORTCUT_MSGBOX_ADMIN,
+                                                   "");
+            return;
+        }
+        CloseHandle(hProcess);
+#endif // _WIN32
+
+        shortcut_path = Common::FS::GetAppsShortcutsPath();
+        if (!std::filesystem::exists(shortcut_path)) {
+            shortcut_path = QStandardPaths::writableLocation(QStandardPaths::ApplicationsLocation)
+                                .toStdString();
+        }
+    }
+
+    // Icon path and title
+    std::string title;
+    std::filesystem::path icons_path;
+    if (std::filesystem::exists(shortcut_path)) {
+
+        // Get title from game file
+        const FileSys::PatchManager pm{program_id, system->GetFileSystemController(),
+                                       system->GetContentProvider()};
+        const auto control = pm.GetControlMetadata();
+        const auto loader =
+            Loader::GetLoader(*system, vfs->OpenFile(game_path, FileSys::Mode::Read));
+
+        title = fmt::format("{:016X}", program_id);
+
+        if (control.first != nullptr) {
+            title = control.first->GetApplicationName();
+        } else {
+            loader->ReadTitle(title);
+        }
+
+        // Get icon from game file
+        std::vector<u8> icon_image_file{};
+        if (control.second != nullptr) {
+            icon_image_file = control.second->ReadAllBytes();
+        } else if (loader->ReadIcon(icon_image_file) != Loader::ResultStatus::Success) {
+            LOG_WARNING(Frontend, "Could not read icon from {:s}", game_path);
+        }
+
+        QImage icon_data =
+            QImage::fromData(icon_image_file.data(), static_cast<int>(icon_image_file.size()));
+
+        if (GMainWindow::MakeShortcutIcoPath(program_id, title, icons_path)) {
+            if (!SaveIconToFile(icon_data, icons_path)) {
+                LOG_ERROR(Frontend, "Could not write icon to file");
+            }
+        }
+
+    } else {
+        GMainWindow::CreateShortcutMessagesGUI(this, GMainWindow::CREATE_SHORTCUT_MSGBOX_ERROR,
+                                               title);
+        LOG_ERROR(Frontend, "[GMainWindow::OnGameListCreateShortcut] Invalid shortcut target");
+        return;
+    }
+
+// Special case for AppImages
 #if defined(__linux__)
     // Warn once if we are making a shortcut to a volatile AppImage
     const std::string appimage_ending =
         std::string(Common::g_scm_rev).substr(0, 9).append(".AppImage");
     if (yuzu_command.string().ends_with(appimage_ending) &&
         !UISettings::values.shortcut_already_warned) {
-        if (QMessageBox::warning(this, tr("Create Shortcut"),
-                                 tr("This will create a shortcut to the current AppImage. This may "
-                                    "not work well if you update. Continue?"),
-                                 QMessageBox::StandardButton::Ok |
-                                     QMessageBox::StandardButton::Cancel) ==
-            QMessageBox::StandardButton::Cancel) {
+        if (GMainWindow::CreateShortcutMessagesGUI(
+                this, GMainWindow::CREATE_SHORTCUT_MSGBOX_APPVOLATILE_WARNING, title)) {
             return;
         }
         UISettings::values.shortcut_already_warned = true;
     }
 #endif // __linux__
 
-    std::filesystem::path target_directory{};
-
-    switch (target) {
-    case GameListShortcutTarget::Desktop: {
-        const QString desktop_path =
-            QStandardPaths::writableLocation(QStandardPaths::DesktopLocation);
-        target_directory = desktop_path.toUtf8().toStdString();
-        break;
+    // Create shortcut
+    std::string arguments = fmt::format("-g \"{:s}\"", game_path);
+    if (GMainWindow::CreateShortcutMessagesGUI(
+            this, GMainWindow::CREATE_SHORTCUT_MSGBOX_FULLSCREEN_YES, title)) {
+        arguments = "-f " + arguments;
     }
-    case GameListShortcutTarget::Applications: {
-        const QString applications_path =
-            QStandardPaths::writableLocation(QStandardPaths::ApplicationsLocation);
-        if (applications_path.isEmpty()) {
-            const char* home = std::getenv("HOME");
-            if (home != nullptr) {
-                target_directory = std::filesystem::path(home) / ".local/share/applications";
-            }
-        } else {
-            target_directory = applications_path.toUtf8().toStdString();
-        }
-        break;
-    }
-    default:
-        return;
-    }
-
-    const QDir dir(QString::fromStdString(target_directory.generic_string()));
-    if (!dir.exists()) {
-        QMessageBox::critical(this, tr("Create Shortcut"),
-                              tr("Cannot create shortcut. Path \"%1\" does not exist.")
-                                  .arg(QString::fromStdString(target_directory.generic_string())),
-                              QMessageBox::StandardButton::Ok);
-        return;
-    }
-
-    const std::string game_file_name = std::filesystem::path(game_path).filename().string();
-    // Determine full paths for icon and shortcut
-#if defined(__linux__) || defined(__FreeBSD__)
-    const char* home = std::getenv("HOME");
-    const std::filesystem::path home_path = (home == nullptr ? "~" : home);
-    const char* xdg_data_home = std::getenv("XDG_DATA_HOME");
-
-    std::filesystem::path system_icons_path =
-        (xdg_data_home == nullptr ? home_path / ".local/share/"
-                                  : std::filesystem::path(xdg_data_home)) /
-        "icons/hicolor/256x256";
-    if (!Common::FS::CreateDirs(system_icons_path)) {
-        QMessageBox::critical(
-            this, tr("Create Icon"),
-            tr("Cannot create icon file. Path \"%1\" does not exist and cannot be created.")
-                .arg(QString::fromStdString(system_icons_path)),
-            QMessageBox::StandardButton::Ok);
-        return;
-    }
-    std::filesystem::path icon_path =
-        system_icons_path / (program_id == 0 ? fmt::format("yuzu-{}.png", game_file_name)
-                                             : fmt::format("yuzu-{:016X}.png", program_id));
-    const std::filesystem::path shortcut_path =
-        target_directory / (program_id == 0 ? fmt::format("yuzu-{}.desktop", game_file_name)
-                                            : fmt::format("yuzu-{:016X}.desktop", program_id));
-#elif defined(WIN32)
-    std::filesystem::path icons_path =
-        Common::FS::GetYuzuPathString(Common::FS::YuzuPath::IconsDir);
-    std::filesystem::path icon_path =
-        icons_path / ((program_id == 0 ? fmt::format("yuzu-{}.ico", game_file_name)
-                                       : fmt::format("yuzu-{:016X}.ico", program_id)));
-#else
-    std::string icon_extension;
-#endif
-
-    // Get title from game file
-    const FileSys::PatchManager pm{program_id, system->GetFileSystemController(),
-                                   system->GetContentProvider()};
-    const auto control = pm.GetControlMetadata();
-    const auto loader = Loader::GetLoader(*system, vfs->OpenFile(game_path, FileSys::Mode::Read));
-
-    std::string title{fmt::format("{:016X}", program_id)};
-
-    if (control.first != nullptr) {
-        title = control.first->GetApplicationName();
-    } else {
-        loader->ReadTitle(title);
-    }
-
-    // Get icon from game file
-    std::vector<u8> icon_image_file{};
-    if (control.second != nullptr) {
-        icon_image_file = control.second->ReadAllBytes();
-    } else if (loader->ReadIcon(icon_image_file) != Loader::ResultStatus::Success) {
-        LOG_WARNING(Frontend, "Could not read icon from {:s}", game_path);
-    }
-
-    QImage icon_data =
-        QImage::fromData(icon_image_file.data(), static_cast<int>(icon_image_file.size()));
-#if defined(__linux__) || defined(__FreeBSD__)
-    // Convert and write the icon as a PNG
-    if (!icon_data.save(QString::fromStdString(icon_path.string()))) {
-        LOG_ERROR(Frontend, "Could not write icon as PNG to file");
-    } else {
-        LOG_INFO(Frontend, "Wrote an icon to {}", icon_path.string());
-    }
-#elif defined(WIN32)
-    if (!SaveIconToFile(icon_path.string(), icon_data)) {
-        LOG_ERROR(Frontend, "Could not write icon to file");
-        return;
-    }
-#endif // __linux__
-
-#ifdef _WIN32
-    // Replace characters that are illegal in Windows filenames by a dash
-    const std::string illegal_chars = "<>:\"/\\|?*";
-    for (char c : illegal_chars) {
-        std::replace(title.begin(), title.end(), c, '_');
-    }
-    const std::filesystem::path shortcut_path = target_directory / (title + ".lnk").c_str();
-#endif
-
     const std::string comment =
         tr("Start %1 with the yuzu Emulator").arg(QString::fromStdString(title)).toStdString();
-    const std::string arguments = fmt::format("-g \"{:s}\"", game_path);
     const std::string categories = "Game;Emulator;Qt;";
     const std::string keywords = "Switch;Nintendo;";
 
-    if (!CreateShortcut(shortcut_path.string(), title, comment, icon_path.string(),
-                        yuzu_command.string(), arguments, categories, keywords)) {
-        QMessageBox::critical(this, tr("Create Shortcut"),
-                              tr("Failed to create a shortcut at %1")
-                                  .arg(QString::fromStdString(shortcut_path.string())));
+    if (GMainWindow::CreateShortcutLink(shortcut_path, comment, icons_path, yuzu_command, arguments,
+                                        categories, keywords, title)) {
+        GMainWindow::CreateShortcutMessagesGUI(this, GMainWindow::CREATE_SHORTCUT_MSGBOX_SUCCESS,
+                                               title);
         return;
     }
 
-    LOG_INFO(Frontend, "Wrote a shortcut to {}", shortcut_path.string());
-    QMessageBox::information(
-        this, tr("Create Shortcut"),
-        tr("Successfully created a shortcut to %1").arg(QString::fromStdString(title)));
+    GMainWindow::CreateShortcutMessagesGUI(this, GMainWindow::CREATE_SHORTCUT_MSGBOX_ERROR, title);
 }
 
 void GMainWindow::OnGameListOpenDirectory(const QString& directory) {
@@ -3998,66 +4178,6 @@ void GMainWindow::OpenPerGameConfiguration(u64 title_id, const std::string& file
     }
 }
 
-bool GMainWindow::CreateShortcut(const std::string& shortcut_path, const std::string& title,
-                                 const std::string& comment, const std::string& icon_path,
-                                 const std::string& command, const std::string& arguments,
-                                 const std::string& categories, const std::string& keywords) {
-#if defined(__linux__) || defined(__FreeBSD__)
-    // This desktop file template was writing referencing
-    // https://specifications.freedesktop.org/desktop-entry-spec/desktop-entry-spec-1.0.html
-    std::string shortcut_contents{};
-    shortcut_contents.append("[Desktop Entry]\n");
-    shortcut_contents.append("Type=Application\n");
-    shortcut_contents.append("Version=1.0\n");
-    shortcut_contents.append(fmt::format("Name={:s}\n", title));
-    shortcut_contents.append(fmt::format("Comment={:s}\n", comment));
-    shortcut_contents.append(fmt::format("Icon={:s}\n", icon_path));
-    shortcut_contents.append(fmt::format("TryExec={:s}\n", command));
-    shortcut_contents.append(fmt::format("Exec={:s} {:s}\n", command, arguments));
-    shortcut_contents.append(fmt::format("Categories={:s}\n", categories));
-    shortcut_contents.append(fmt::format("Keywords={:s}\n", keywords));
-
-    std::ofstream shortcut_stream(shortcut_path);
-    if (!shortcut_stream.is_open()) {
-        LOG_WARNING(Common, "Failed to create file {:s}", shortcut_path);
-        return false;
-    }
-    shortcut_stream << shortcut_contents;
-    shortcut_stream.close();
-
-    return true;
-#elif defined(WIN32)
-    IShellLinkW* shell_link;
-    auto hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLinkW,
-                                 (void**)&shell_link);
-    if (FAILED(hres)) {
-        return false;
-    }
-    shell_link->SetPath(
-        Common::UTF8ToUTF16W(command).data()); // Path to the object we are referring to
-    shell_link->SetArguments(Common::UTF8ToUTF16W(arguments).data());
-    shell_link->SetDescription(Common::UTF8ToUTF16W(comment).data());
-    shell_link->SetIconLocation(Common::UTF8ToUTF16W(icon_path).data(), 0);
-
-    IPersistFile* persist_file;
-    hres = shell_link->QueryInterface(IID_IPersistFile, (void**)&persist_file);
-    if (FAILED(hres)) {
-        return false;
-    }
-
-    hres = persist_file->Save(Common::UTF8ToUTF16W(shortcut_path).data(), TRUE);
-    if (FAILED(hres)) {
-        return false;
-    }
-
-    persist_file->Release();
-    shell_link->Release();
-
-    return true;
-#endif
-    return false;
-}
-
 void GMainWindow::OnLoadAmiibo() {
     if (emu_thread == nullptr || !emu_thread->IsRunning()) {
         return;
diff --git a/src/yuzu/main.h b/src/yuzu/main.h
index 270a40c5f9..bf6756b486 100644
--- a/src/yuzu/main.h
+++ b/src/yuzu/main.h
@@ -6,6 +6,7 @@
 #include <memory>
 #include <optional>
 
+#include <filesystem>
 #include <QMainWindow>
 #include <QMessageBox>
 #include <QTimer>
@@ -151,6 +152,14 @@ class GMainWindow : public QMainWindow {
         UI_EMU_STOPPING,
     };
 
+    const enum {
+        CREATE_SHORTCUT_MSGBOX_FULLSCREEN_YES,
+        CREATE_SHORTCUT_MSGBOX_SUCCESS,
+        CREATE_SHORTCUT_MSGBOX_ERROR,
+        CREATE_SHORTCUT_MSGBOX_APPVOLATILE_WARNING,
+        CREATE_SHORTCUT_MSGBOX_ADMIN,
+    };
+
 public:
     void filterBarSetChecked(bool state);
     void UpdateUITheme();
@@ -433,11 +442,14 @@ private:
     bool ConfirmShutdownGame();
 
     QString GetTasStateDescription() const;
-    bool CreateShortcut(const std::string& shortcut_path, const std::string& title,
-                        const std::string& comment, const std::string& icon_path,
-                        const std::string& command, const std::string& arguments,
-                        const std::string& categories, const std::string& keywords);
-
+    bool CreateShortcutMessagesGUI(QWidget* parent, const int& imsg, const std::string title);
+    bool MakeShortcutIcoPath(const u64 program_id, const std::string_view game_file_name,
+                             std::filesystem::path& icons_path);
+    bool CreateShortcutLink(const std::filesystem::path& shortcut_path, const std::string& comment,
+                            const std::filesystem::path& icon_path,
+                            const std::filesystem::path& command, const std::string& arguments,
+                            const std::string& categories, const std::string& keywords,
+                            const std::string& name);
     /**
      * Mimic the behavior of QMessageBox::question but link controller navigation to the dialog
      * The only difference is that it returns a boolean.
diff --git a/src/yuzu/util/util.cpp b/src/yuzu/util/util.cpp
index f2854c8ec3..4d199ebd16 100644
--- a/src/yuzu/util/util.cpp
+++ b/src/yuzu/util/util.cpp
@@ -42,7 +42,7 @@ QPixmap CreateCirclePixmapFromColor(const QColor& color) {
     return circle_pixmap;
 }
 
-bool SaveIconToFile(const std::string_view path, const QImage& image) {
+bool SaveIconToFile(const QImage& image, const std::filesystem::path& icon_path) {
 #if defined(WIN32)
 #pragma pack(push, 2)
     struct IconDir {
@@ -73,7 +73,7 @@ bool SaveIconToFile(const std::string_view path, const QImage& image) {
         .id_count = static_cast<WORD>(scale_sizes.size()),
     };
 
-    Common::FS::IOFile icon_file(path, Common::FS::FileAccessMode::Write,
+    Common::FS::IOFile icon_file(icon_path.string(), Common::FS::FileAccessMode::Write,
                                  Common::FS::FileType::BinaryFile);
     if (!icon_file.IsOpen()) {
         return false;
@@ -135,7 +135,16 @@ bool SaveIconToFile(const std::string_view path, const QImage& image) {
     icon_file.Close();
 
     return true;
-#else
-    return false;
+#elif defined(__linux__) || defined(__FreeBSD__)
+    // Convert and write the icon as a PNG
+    if (!image.save(QString::fromStdString(icon_path.string()))) {
+        LOG_ERROR(Frontend, "Could not write icon as PNG to file");
+    } else {
+        LOG_INFO(Frontend, "Wrote an icon to {}", icon_path.string());
+    }
+
+    return true;
 #endif
+
+    return false;
 }
diff --git a/src/yuzu/util/util.h b/src/yuzu/util/util.h
index 09c14ce3fc..8839e160ae 100644
--- a/src/yuzu/util/util.h
+++ b/src/yuzu/util/util.h
@@ -3,26 +3,36 @@
 
 #pragma once
 
+#include <filesystem>
 #include <QFont>
 #include <QString>
 
 /// Returns a QFont object appropriate to use as a monospace font for debugging widgets, etc.
+
 [[nodiscard]] QFont GetMonospaceFont();
 
 /// Convert a size in bytes into a readable format (KiB, MiB, etc.)
+
 [[nodiscard]] QString ReadableByteSize(qulonglong size);
 
 /**
  * Creates a circle pixmap from a specified color
+ *
  * @param color The color the pixmap shall have
+ *
  * @return QPixmap circle pixmap
  */
+
 [[nodiscard]] QPixmap CreateCirclePixmapFromColor(const QColor& color);
 
 /**
  * Saves a windows icon to a file
- * @param path The icons path
+ *
  * @param image The image to save
+ *
+ * @param path The icons path
+ *
  * @return bool If the operation succeeded
  */
-[[nodiscard]] bool SaveIconToFile(const std::string_view path, const QImage& image);
+
+[[nodiscard]] bool SaveIconToFile(const QImage& image, const std::filesystem::path& icon_path);

From 0a75519ab590e250c94dc04b3f6072a69ef7e96b Mon Sep 17 00:00:00 2001
From: boludoz <francomaro@gmail.com>
Date: Sun, 15 Oct 2023 03:16:29 -0300
Subject: [PATCH 02/24] Fixes and improvements

---
 src/common/fs/path_util.cpp | 39 +++++++++++++++++++++++++++----------
 src/yuzu/main.h             |  2 +-
 src/yuzu/util/util.cpp      |  4 ++--
 3 files changed, 32 insertions(+), 13 deletions(-)

diff --git a/src/common/fs/path_util.cpp b/src/common/fs/path_util.cpp
index a461161ede..f030939ce0 100644
--- a/src/common/fs/path_util.cpp
+++ b/src/common/fs/path_util.cpp
@@ -363,13 +363,28 @@ fs::path GetDesktopPath() {
         LOG_ERROR(Common_Filesystem,
                   "[GetDesktopPath] Failed to get the path to the desktop directory");
     }
-#else
-    fs::path shortcut_path = GetHomeDirectory() / "Desktop";
-    if (fs::exists(shortcut_path)) {
-        return shortcut_path;
-    }
-#endif
     return fs::path{};
+#else
+    fs::path shortcut_path{};
+
+    // Array of possible desktop
+    std::vector<std::string> desktop_paths = {
+        "Desktop",      "Escritorio", "Bureau",       "Skrivebord", "Plocha",
+        "Skrivbord",    "Desktop",    "Рабочий стол", "Pulpit",     "Área de Trabalho",
+        "Робочий стіл", "Bureaublad", "デスクトップ", "桌面",       "Pöytä",
+        "바탕 화면",    "바탕 화면",  "سطح المكتب",   "دسکتاپ",     "שולחן עבודה"};
+
+    for (auto& path : desktop_paths) {
+        if (fs::exists(GetHomeDirectory() / path)) {
+            return path;
+        }
+    }
+
+    LOG_ERROR(Common_Filesystem,
+              "[GetDesktopPath] Failed to get the path to the desktop directory");
+
+    return shortcut_path;
+#endif
 }
 
 fs::path GetAppsShortcutsPath() {
@@ -387,16 +402,20 @@ fs::path GetAppsShortcutsPath() {
         LOG_ERROR(Common_Filesystem,
                   "[GetAppsShortcutsPath] Failed to get the path to the App Shortcuts directory");
     }
+
+    return fs::path{};
 #else
     fs::path shortcut_path = GetHomeDirectory() / ".local/share/applications";
     if (!fs::exists(shortcut_path)) {
         shortcut_path = std::filesystem::path("/usr/share/applications");
-        return shortcut_path;
-    } else {
-        return shortcut_path;
+        if (!fs::exists(shortcut_path)) {
+            LOG_ERROR(Common_Filesystem,
+                      "[GetAppsShortcutsPath] Failed to get the path to the App Shortcuts "
+                      "directory");
+        }
     }
-#endif
     return fs::path{};
+#endif
 }
 
 // vvvvvvvvvv Deprecated vvvvvvvvvv //
diff --git a/src/yuzu/main.h b/src/yuzu/main.h
index bf6756b486..d7426607f7 100644
--- a/src/yuzu/main.h
+++ b/src/yuzu/main.h
@@ -152,7 +152,7 @@ class GMainWindow : public QMainWindow {
         UI_EMU_STOPPING,
     };
 
-    const enum {
+    enum {
         CREATE_SHORTCUT_MSGBOX_FULLSCREEN_YES,
         CREATE_SHORTCUT_MSGBOX_SUCCESS,
         CREATE_SHORTCUT_MSGBOX_ERROR,
diff --git a/src/yuzu/util/util.cpp b/src/yuzu/util/util.cpp
index 4d199ebd16..9755004ad7 100644
--- a/src/yuzu/util/util.cpp
+++ b/src/yuzu/util/util.cpp
@@ -144,7 +144,7 @@ bool SaveIconToFile(const QImage& image, const std::filesystem::path& icon_path)
     }
 
     return true;
-#endif
-
+#else
     return false;
+#endif
 }

From 4d4fe69223bd6cd053cbd2088e5925fb653a12d3 Mon Sep 17 00:00:00 2001
From: boludoz <francomaro@gmail.com>
Date: Sun, 15 Oct 2023 14:44:23 -0300
Subject: [PATCH 03/24] Unnecessary feature removed

---
 src/common/fs/path_util.cpp | 70 -------------------------------------
 src/common/fs/path_util.h   | 15 +-------
 src/yuzu/main.cpp           | 16 +++------
 src/yuzu/util/util.h        |  3 --
 4 files changed, 5 insertions(+), 99 deletions(-)

diff --git a/src/common/fs/path_util.cpp b/src/common/fs/path_util.cpp
index f030939ce0..bccf953e41 100644
--- a/src/common/fs/path_util.cpp
+++ b/src/common/fs/path_util.cpp
@@ -348,76 +348,6 @@ fs::path GetBundleDirectory() {
 
 #endif
 
-fs::path GetDesktopPath() {
-#if defined(_WIN32)
-    PWSTR DesktopPath = nullptr;
-
-    if (SUCCEEDED(SHGetKnownFolderPath(FOLDERID_Desktop, 0, NULL, &DesktopPath))) {
-        std::wstring wideDesktopPath(DesktopPath);
-        CoTaskMemFree(DesktopPath);
-
-        // UTF-16 filesystem lib to UTF-8 is broken, so we need to convert to UTF-8 with the with
-        // the Windows library (Filesystem converts the strings literally).
-        return fs::path{Common::UTF16ToUTF8(wideDesktopPath)};
-    } else {
-        LOG_ERROR(Common_Filesystem,
-                  "[GetDesktopPath] Failed to get the path to the desktop directory");
-    }
-    return fs::path{};
-#else
-    fs::path shortcut_path{};
-
-    // Array of possible desktop
-    std::vector<std::string> desktop_paths = {
-        "Desktop",      "Escritorio", "Bureau",       "Skrivebord", "Plocha",
-        "Skrivbord",    "Desktop",    "Рабочий стол", "Pulpit",     "Área de Trabalho",
-        "Робочий стіл", "Bureaublad", "デスクトップ", "桌面",       "Pöytä",
-        "바탕 화면",    "바탕 화면",  "سطح المكتب",   "دسکتاپ",     "שולחן עבודה"};
-
-    for (auto& path : desktop_paths) {
-        if (fs::exists(GetHomeDirectory() / path)) {
-            return path;
-        }
-    }
-
-    LOG_ERROR(Common_Filesystem,
-              "[GetDesktopPath] Failed to get the path to the desktop directory");
-
-    return shortcut_path;
-#endif
-}
-
-fs::path GetAppsShortcutsPath() {
-#if defined(_WIN32)
-    PWSTR AppShortcutsPath = nullptr;
-
-    if (SUCCEEDED(SHGetKnownFolderPath(FOLDERID_CommonPrograms, 0, NULL, &AppShortcutsPath))) {
-        std::wstring wideAppShortcutsPath(AppShortcutsPath);
-        CoTaskMemFree(AppShortcutsPath);
-
-        // UTF-16 filesystem lib to UTF-8 is broken, so we need to convert to UTF-8 with the with
-        // the Windows library (Filesystem converts the strings literally).
-        return fs::path{Common::UTF16ToUTF8(wideAppShortcutsPath)};
-    } else {
-        LOG_ERROR(Common_Filesystem,
-                  "[GetAppsShortcutsPath] Failed to get the path to the App Shortcuts directory");
-    }
-
-    return fs::path{};
-#else
-    fs::path shortcut_path = GetHomeDirectory() / ".local/share/applications";
-    if (!fs::exists(shortcut_path)) {
-        shortcut_path = std::filesystem::path("/usr/share/applications");
-        if (!fs::exists(shortcut_path)) {
-            LOG_ERROR(Common_Filesystem,
-                      "[GetAppsShortcutsPath] Failed to get the path to the App Shortcuts "
-                      "directory");
-        }
-    }
-    return fs::path{};
-#endif
-}
-
 // vvvvvvvvvv Deprecated vvvvvvvvvv //
 
 std::string_view RemoveTrailingSlash(std::string_view path) {
diff --git a/src/common/fs/path_util.h b/src/common/fs/path_util.h
index b88a388d19..63801c924b 100644
--- a/src/common/fs/path_util.h
+++ b/src/common/fs/path_util.h
@@ -244,6 +244,7 @@ void SetYuzuPath(YuzuPath yuzu_path, const Path& new_path) {
  * @returns The path of the current user's %APPDATA% directory.
  */
 [[nodiscard]] std::filesystem::path GetAppDataRoamingDirectory();
+
 #else
 
 /**
@@ -274,20 +275,6 @@ void SetYuzuPath(YuzuPath yuzu_path, const Path& new_path) {
 
 #endif
 
-/**
- * Gets the path of the current user's desktop directory.
- *
- * @returns The path of the current user's desktop directory.
- */
-[[nodiscard]] std::filesystem::path GetDesktopPath();
-
-/**
- * Gets the path of the current user's apps directory.
- *
- * @returns The path of the current user's apps directory.
- */
-[[nodiscard]] std::filesystem::path GetAppsShortcutsPath();
-
 // vvvvvvvvvv Deprecated vvvvvvvvvv //
 
 // Removes the final '/' or '\' if one exists
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index e4dc717ed3..fd68ac9b64 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -3082,13 +3082,9 @@ void GMainWindow::OnGameListCreateShortcut(u64 program_id, const std::string& ga
     // Shortcut path
     std::filesystem::path shortcut_path{};
     if (target == GameListShortcutTarget::Desktop) {
-        shortcut_path = Common::FS::GetDesktopPath();
-        if (!std::filesystem::exists(shortcut_path)) {
-            shortcut_path =
-                QStandardPaths::writableLocation(QStandardPaths::DesktopLocation).toStdString();
-        }
+        shortcut_path =
+            QStandardPaths::writableLocation(QStandardPaths::DesktopLocation).toStdString();
     } else if (target == GameListShortcutTarget::Applications) {
-
 #if defined(_WIN32)
         HANDLE hProcess = GetCurrentProcess();
         if (!IsUserAnAdmin()) {
@@ -3098,12 +3094,8 @@ void GMainWindow::OnGameListCreateShortcut(u64 program_id, const std::string& ga
         }
         CloseHandle(hProcess);
 #endif // _WIN32
-
-        shortcut_path = Common::FS::GetAppsShortcutsPath();
-        if (!std::filesystem::exists(shortcut_path)) {
-            shortcut_path = QStandardPaths::writableLocation(QStandardPaths::ApplicationsLocation)
-                                .toStdString();
-        }
+        shortcut_path =
+            QStandardPaths::writableLocation(QStandardPaths::ApplicationsLocation).toStdString();
     }
 
     // Icon path and title
diff --git a/src/yuzu/util/util.h b/src/yuzu/util/util.h
index 8839e160ae..31e82ff67d 100644
--- a/src/yuzu/util/util.h
+++ b/src/yuzu/util/util.h
@@ -8,11 +8,9 @@
 #include <QString>
 
 /// Returns a QFont object appropriate to use as a monospace font for debugging widgets, etc.
-
 [[nodiscard]] QFont GetMonospaceFont();
 
 /// Convert a size in bytes into a readable format (KiB, MiB, etc.)
-
 [[nodiscard]] QString ReadableByteSize(qulonglong size);
 
 /**
@@ -34,5 +32,4 @@
  *
  * @return bool If the operation succeeded
  */
-
 [[nodiscard]] bool SaveIconToFile(const QImage& image, const std::filesystem::path& icon_path);

From 9ffa1801c75073afb851351ecdd1a8b40e33cc5c Mon Sep 17 00:00:00 2001
From: boludoz <francomaro@gmail.com>
Date: Sun, 15 Oct 2023 20:57:06 -0300
Subject: [PATCH 04/24] Typing and formatting errors fixed.

---
 src/common/fs/fs_util.cpp   | 44 ++++++++++++++++++-------------------
 src/common/fs/fs_util.h     |  8 +++----
 src/common/fs/path_util.cpp |  8 +++----
 src/yuzu/main.cpp           | 24 ++++++++++----------
 src/yuzu/util/util.cpp      |  3 +--
 src/yuzu/util/util.h        | 10 ++-------
 6 files changed, 43 insertions(+), 54 deletions(-)

diff --git a/src/common/fs/fs_util.cpp b/src/common/fs/fs_util.cpp
index 442f637281..e77958224b 100644
--- a/src/common/fs/fs_util.cpp
+++ b/src/common/fs/fs_util.cpp
@@ -36,21 +36,21 @@ std::string PathToUTF8String(const std::filesystem::path& path) {
     return ToUTF8String(path.u8string());
 }
 
-std::u8string U8FilenameSantizer(const std::u8string_view u8filename) {
-    std::u8string u8path_santized{u8filename.begin(), u8filename.end()};
-    size_t eSizeSanitized = u8path_santized.size();
+std::u8string U8FilenameSanitizer(const std::u8string_view u8filename) {
+    std::u8string u8path_sanitized{u8filename.begin(), u8filename.end()};
+    size_t eSizeSanitized = u8path_sanitized.size();
 
-    // Special case for ":", for example: 'Pepe: La secuela' --> 'Pepe - La
-    // secuela' or 'Pepe : La secuela' --> 'Pepe - La secuela'
+    // The name is improved to make it look more beautiful and prohibited characters and shapes are
+    // removed. Switch is used since it is better with many conditions.
     for (size_t i = 0; i < eSizeSanitized; i++) {
-        switch (u8path_santized[i]) {
+        switch (u8path_sanitized[i]) {
         case u8':':
             if (i == 0 || i == eSizeSanitized - 1) {
-                u8path_santized.replace(i, 1, u8"_");
-            } else if (u8path_santized[i - 1] == u8' ') {
-                u8path_santized.replace(i, 1, u8"-");
+                u8path_sanitized.replace(i, 1, u8"_");
+            } else if (u8path_sanitized[i - 1] == u8' ') {
+                u8path_sanitized.replace(i, 1, u8"-");
             } else {
-                u8path_santized.replace(i, 1, u8" -");
+                u8path_sanitized.replace(i, 1, u8" -");
                 eSizeSanitized++;
             }
             break;
@@ -63,36 +63,36 @@ std::u8string U8FilenameSantizer(const std::u8string_view u8filename) {
         case u8'>':
         case u8'|':
         case u8'\0':
-            u8path_santized.replace(i, 1, u8"_");
+            u8path_sanitized.replace(i, 1, u8"_");
             break;
         default:
             break;
         }
     }
 
-    // Delete duplicated spaces || Delete duplicated dots (MacOS i think)
+    // Delete duplicated spaces and dots
     for (size_t i = 0; i < eSizeSanitized - 1; i++) {
-        if ((u8path_santized[i] == u8' ' && u8path_santized[i + 1] == u8' ') ||
-            (u8path_santized[i] == u8'.' && u8path_santized[i + 1] == u8'.')) {
-            u8path_santized.erase(i, 1);
+        if ((u8path_sanitized[i] == u8' ' && u8path_sanitized[i + 1] == u8' ') ||
+            (u8path_sanitized[i] == u8'.' && u8path_sanitized[i + 1] == u8'.')) {
+            u8path_sanitized.erase(i, 1);
             i--;
         }
     }
 
-    // Delete all spaces and dots at the end (Windows almost)
-    while (u8path_santized.back() == u8' ' || u8path_santized.back() == u8'.') {
-        u8path_santized.pop_back();
+    // Delete all spaces and dots at the end of the name
+    while (u8path_sanitized.back() == u8' ' || u8path_sanitized.back() == u8'.') {
+        u8path_sanitized.pop_back();
     }
 
-    if (u8path_santized.empty()) {
+    if (u8path_sanitized.empty()) {
         return u8"";
     }
 
-    return u8path_santized;
+    return u8path_sanitized;
 }
 
-std::string UTF8FilenameSantizer(const std::string_view filename) {
-    return ToUTF8String(U8FilenameSantizer(ToU8String(filename)));
+std::string UTF8FilenameSanitizer(const std::string_view filename) {
+    return ToUTF8String(U8FilenameSanitizer(ToU8String(filename)));
 }
 
 } // namespace Common::FS
diff --git a/src/common/fs/fs_util.h b/src/common/fs/fs_util.h
index dbb4f5a9a1..daec1f8cbc 100644
--- a/src/common/fs/fs_util.h
+++ b/src/common/fs/fs_util.h
@@ -87,19 +87,19 @@ concept IsChar = std::same_as<T, char>;
  *
  * @param u8_string dirty encoded filename string
  *
- * @returns utf8_string santized filename string
+ * @returns utf8_string sanitized filename string
  *
  */
-[[nodiscard]] std::u8string U8FilenameSantizer(const std::u8string_view u8filename);
+[[nodiscard]] std::u8string U8FilenameSanitizer(const std::u8string_view u8filename);
 
 /**
  * Fix filename (remove invalid characters)
  *
  * @param utf8_string dirty encoded filename string
  *
- * @returns utf8_string santized filename string
+ * @returns utf8_string sanitized filename string
  *
  */
-[[nodiscard]] std::string UTF8FilenameSantizer(const std::string_view filename);
+[[nodiscard]] std::string UTF8FilenameSanitizer(const std::string_view filename);
 
 } // namespace Common::FS
\ No newline at end of file
diff --git a/src/common/fs/path_util.cpp b/src/common/fs/path_util.cpp
index bccf953e41..3d88fcf4fc 100644
--- a/src/common/fs/path_util.cpp
+++ b/src/common/fs/path_util.cpp
@@ -260,9 +260,8 @@ fs::path GetExeDirectory() {
         // the Windows library (Filesystem converts the strings literally).
         return fs::path{Common::UTF16ToUTF8(wideExePath)}.parent_path();
     } else {
-        LOG_ERROR(Common_Filesystem,
-                  "[GetExeDirectory] Failed to get the path to the executable of the current "
-                  "process");
+        LOG_ERROR(Common_Filesystem, "Failed to get the path to the executable of the current "
+                                     "process");
     }
 
     return fs::path{};
@@ -279,8 +278,7 @@ fs::path GetAppDataRoamingDirectory() {
         // the Windows library (Filesystem converts the strings literally).
         return fs::path{Common::UTF16ToUTF8(wideAppdataRoamingPath)};
     } else {
-        LOG_ERROR(Common_Filesystem,
-                  "[GetAppDataRoamingDirectory] Failed to get the path to the %APPDATA% directory");
+        LOG_ERROR(Common_Filesystem, "Failed to get the path to the %APPDATA% directory");
     }
 
     return fs::path{};
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index fd68ac9b64..c3c12eeec4 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -2851,7 +2851,7 @@ bool GMainWindow::CreateShortcutLink(const std::filesystem::path& shortcut_path,
 
     // Replace characters that are illegal in Windows filenames
     std::filesystem::path shortcut_path_full =
-        shortcut_path / Common::FS::UTF8FilenameSantizer(name);
+        shortcut_path / Common::FS::UTF8FilenameSanitizer(name);
 
 #if defined(__linux__) || defined(__FreeBSD__)
     shortcut_path_full += ".desktop";
@@ -2859,8 +2859,7 @@ bool GMainWindow::CreateShortcutLink(const std::filesystem::path& shortcut_path,
     shortcut_path_full += ".lnk";
 #endif
 
-    LOG_INFO(Common, "[GMainWindow::CreateShortcutLink] Create shortcut path: {}",
-             shortcut_path_full.string());
+    LOG_ERROR(Frontend, "Create shortcut path: {}", shortcut_path_full.string());
 
 #if defined(__linux__) || defined(__FreeBSD__)
     // This desktop file template was writing referencing
@@ -2869,7 +2868,7 @@ bool GMainWindow::CreateShortcutLink(const std::filesystem::path& shortcut_path,
 
         // Plus 'Type' is required
         if (name.empty()) {
-            LOG_ERROR(Common, "[GMainWindow::CreateShortcutLink] Name is empty");
+            LOG_ERROR(Frontend, "Name is empty");
             shortcut_succeeded = false;
             return shortcut_succeeded;
         }
@@ -2911,14 +2910,13 @@ bool GMainWindow::CreateShortcutLink(const std::filesystem::path& shortcut_path,
             return true;
 
         } else {
-            LOG_ERROR(Common, "[GMainWindow::CreateShortcutLink] Failed to create shortcut");
+            LOG_ERROR(Frontend, "Failed to create shortcut");
             return false;
         }
 
         shortcut_stream.close();
     } catch (const std::exception& e) {
-        LOG_ERROR(Common, "[GMainWindow::CreateShortcutLink] Failed to create shortcut: {}",
-                  e.what());
+        LOG_ERROR(Frontend, "Failed to create shortcut: {}", e.what());
     }
 #elif defined(_WIN32)
     // Initialize COM
@@ -2970,7 +2968,7 @@ bool GMainWindow::CreateShortcutLink(const std::filesystem::path& shortcut_path,
             pPersistFile->Release();
         }
     } else {
-        LOG_ERROR(Common, "[GMainWindow::CreateShortcutLink] Failed to create IShellLinkWinstance");
+        LOG_ERROR(Frontend, "Failed to create IShellLinkWinstance");
     }
 
     ps1->Release();
@@ -2978,9 +2976,9 @@ bool GMainWindow::CreateShortcutLink(const std::filesystem::path& shortcut_path,
 #endif
 
     if (shortcut_succeeded && std::filesystem::is_regular_file(shortcut_path_full)) {
-        LOG_INFO(Common, "[GMainWindow::CreateShortcutLink] Shortcut created");
+        LOG_ERROR(Frontend, "Shortcut created");
     } else {
-        LOG_ERROR(Common, "[GMainWindow::CreateShortcutLink] Shortcut error, failed to create it");
+        LOG_ERROR(Frontend, "Shortcut error, failed to create it");
         shortcut_succeeded = false;
     }
 
@@ -3047,7 +3045,7 @@ bool GMainWindow::MakeShortcutIcoPath(const u64 program_id, const std::string_vi
     icons_path = Common::FS::GetYuzuPath(Common::FS::YuzuPath::ConfigDir) / "icons";
     ico_extension = "ico";
 #elif defined(__linux__) || defined(__FreeBSD__)
-    icons_path = GetDataDirectory("XDG_DATA_HOME") / "icons/hicolor/256x256";
+    icons_path = Common::FS::GetDataDirectory("XDG_DATA_HOME") / "icons/hicolor/256x256";
 #endif
 
     // Create icons directory if it doesn't exist
@@ -3130,7 +3128,7 @@ void GMainWindow::OnGameListCreateShortcut(u64 program_id, const std::string& ga
             QImage::fromData(icon_image_file.data(), static_cast<int>(icon_image_file.size()));
 
         if (GMainWindow::MakeShortcutIcoPath(program_id, title, icons_path)) {
-            if (!SaveIconToFile(icon_data, icons_path)) {
+            if (!SaveIconToFile(icons_path, icon_data)) {
                 LOG_ERROR(Frontend, "Could not write icon to file");
             }
         }
@@ -3138,7 +3136,7 @@ void GMainWindow::OnGameListCreateShortcut(u64 program_id, const std::string& ga
     } else {
         GMainWindow::CreateShortcutMessagesGUI(this, GMainWindow::CREATE_SHORTCUT_MSGBOX_ERROR,
                                                title);
-        LOG_ERROR(Frontend, "[GMainWindow::OnGameListCreateShortcut] Invalid shortcut target");
+        LOG_ERROR(Frontend, "Invalid shortcut target");
         return;
     }
 
diff --git a/src/yuzu/util/util.cpp b/src/yuzu/util/util.cpp
index 9755004ad7..7b2a474966 100644
--- a/src/yuzu/util/util.cpp
+++ b/src/yuzu/util/util.cpp
@@ -42,7 +42,7 @@ QPixmap CreateCirclePixmapFromColor(const QColor& color) {
     return circle_pixmap;
 }
 
-bool SaveIconToFile(const QImage& image, const std::filesystem::path& icon_path) {
+bool SaveIconToFile(const std::filesystem::path& icon_path, const QImage& image) {
 #if defined(WIN32)
 #pragma pack(push, 2)
     struct IconDir {
@@ -142,7 +142,6 @@ bool SaveIconToFile(const QImage& image, const std::filesystem::path& icon_path)
     } else {
         LOG_INFO(Frontend, "Wrote an icon to {}", icon_path.string());
     }
-
     return true;
 #else
     return false;
diff --git a/src/yuzu/util/util.h b/src/yuzu/util/util.h
index 31e82ff67d..4094cf6c2b 100644
--- a/src/yuzu/util/util.h
+++ b/src/yuzu/util/util.h
@@ -15,21 +15,15 @@
 
 /**
  * Creates a circle pixmap from a specified color
- *
  * @param color The color the pixmap shall have
- *
  * @return QPixmap circle pixmap
  */
-
 [[nodiscard]] QPixmap CreateCirclePixmapFromColor(const QColor& color);
 
 /**
  * Saves a windows icon to a file
- *
- * @param image The image to save
- *
  * @param path The icons path
- *
+ * @param image The image to save
  * @return bool If the operation succeeded
  */
-[[nodiscard]] bool SaveIconToFile(const QImage& image, const std::filesystem::path& icon_path);
+[[nodiscard]] bool SaveIconToFile(const std::filesystem::path& icon_path, const QImage& image);

From 74961d4dfb394c098da494f6beacdd994c089566 Mon Sep 17 00:00:00 2001
From: boludoz <francomaro@gmail.com>
Date: Sun, 15 Oct 2023 21:40:10 -0300
Subject: [PATCH 05/24] Less code, simpler, better.

---
 src/common/fs/fs_util.cpp | 59 ---------------------------------------
 src/common/fs/fs_util.h   | 22 +--------------
 src/yuzu/main.cpp         | 16 +++++++++--
 3 files changed, 15 insertions(+), 82 deletions(-)

diff --git a/src/common/fs/fs_util.cpp b/src/common/fs/fs_util.cpp
index e77958224b..813a713c3b 100644
--- a/src/common/fs/fs_util.cpp
+++ b/src/common/fs/fs_util.cpp
@@ -36,63 +36,4 @@ std::string PathToUTF8String(const std::filesystem::path& path) {
     return ToUTF8String(path.u8string());
 }
 
-std::u8string U8FilenameSanitizer(const std::u8string_view u8filename) {
-    std::u8string u8path_sanitized{u8filename.begin(), u8filename.end()};
-    size_t eSizeSanitized = u8path_sanitized.size();
-
-    // The name is improved to make it look more beautiful and prohibited characters and shapes are
-    // removed. Switch is used since it is better with many conditions.
-    for (size_t i = 0; i < eSizeSanitized; i++) {
-        switch (u8path_sanitized[i]) {
-        case u8':':
-            if (i == 0 || i == eSizeSanitized - 1) {
-                u8path_sanitized.replace(i, 1, u8"_");
-            } else if (u8path_sanitized[i - 1] == u8' ') {
-                u8path_sanitized.replace(i, 1, u8"-");
-            } else {
-                u8path_sanitized.replace(i, 1, u8" -");
-                eSizeSanitized++;
-            }
-            break;
-        case u8'\\':
-        case u8'/':
-        case u8'*':
-        case u8'?':
-        case u8'\"':
-        case u8'<':
-        case u8'>':
-        case u8'|':
-        case u8'\0':
-            u8path_sanitized.replace(i, 1, u8"_");
-            break;
-        default:
-            break;
-        }
-    }
-
-    // Delete duplicated spaces and dots
-    for (size_t i = 0; i < eSizeSanitized - 1; i++) {
-        if ((u8path_sanitized[i] == u8' ' && u8path_sanitized[i + 1] == u8' ') ||
-            (u8path_sanitized[i] == u8'.' && u8path_sanitized[i + 1] == u8'.')) {
-            u8path_sanitized.erase(i, 1);
-            i--;
-        }
-    }
-
-    // Delete all spaces and dots at the end of the name
-    while (u8path_sanitized.back() == u8' ' || u8path_sanitized.back() == u8'.') {
-        u8path_sanitized.pop_back();
-    }
-
-    if (u8path_sanitized.empty()) {
-        return u8"";
-    }
-
-    return u8path_sanitized;
-}
-
-std::string UTF8FilenameSanitizer(const std::string_view filename) {
-    return ToUTF8String(U8FilenameSanitizer(ToU8String(filename)));
-}
-
 } // namespace Common::FS
diff --git a/src/common/fs/fs_util.h b/src/common/fs/fs_util.h
index daec1f8cbc..2492a9f942 100644
--- a/src/common/fs/fs_util.h
+++ b/src/common/fs/fs_util.h
@@ -82,24 +82,4 @@ concept IsChar = std::same_as<T, char>;
  */
 [[nodiscard]] std::string PathToUTF8String(const std::filesystem::path& path);
 
-/**
- * Fix filename (remove invalid characters)
- *
- * @param u8_string dirty encoded filename string
- *
- * @returns utf8_string sanitized filename string
- *
- */
-[[nodiscard]] std::u8string U8FilenameSanitizer(const std::u8string_view u8filename);
-
-/**
- * Fix filename (remove invalid characters)
- *
- * @param utf8_string dirty encoded filename string
- *
- * @returns utf8_string sanitized filename string
- *
- */
-[[nodiscard]] std::string UTF8FilenameSanitizer(const std::string_view filename);
-
-} // namespace Common::FS
\ No newline at end of file
+} // namespace Common::FS
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index c3c12eeec4..f2b91a7f35 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -2849,9 +2849,21 @@ bool GMainWindow::CreateShortcutLink(const std::filesystem::path& shortcut_path,
 
     bool shortcut_succeeded = false;
 
+    // Copy characters if they are not illegal in Windows filenames
+    std::string filename = "";
+    const std::string illegal_chars = "<>:\"/\\|?*";
+    filename.reserve(name.size());
+    std::copy_if(name.begin(), name.end(), std::back_inserter(filename),
+                 [&illegal_chars](char c) { return illegal_chars.find(c) == std::string::npos; });
+
+    if (filename.empty()) {
+        LOG_ERROR(Frontend, "Filename is empty");
+        shortcut_succeeded = false;
+        return shortcut_succeeded;
+    }
+
     // Replace characters that are illegal in Windows filenames
-    std::filesystem::path shortcut_path_full =
-        shortcut_path / Common::FS::UTF8FilenameSanitizer(name);
+    std::filesystem::path shortcut_path_full = shortcut_path / filename;
 
 #if defined(__linux__) || defined(__FreeBSD__)
     shortcut_path_full += ".desktop";

From 26417da5d36ea5aae4410a5c35405e27f39661d2 Mon Sep 17 00:00:00 2001
From: boludoz <francomaro@gmail.com>
Date: Mon, 16 Oct 2023 03:26:40 -0300
Subject: [PATCH 06/24] Some improvements (suggestions)

---
 src/common/fs/path_util.cpp |  10 +--
 src/yuzu/main.cpp           | 162 +++++++++++++++++-------------------
 src/yuzu/main.h             |   2 +-
 3 files changed, 81 insertions(+), 93 deletions(-)

diff --git a/src/common/fs/path_util.cpp b/src/common/fs/path_util.cpp
index 3d88fcf4fc..bcd64156e9 100644
--- a/src/common/fs/path_util.cpp
+++ b/src/common/fs/path_util.cpp
@@ -254,11 +254,8 @@ fs::path GetExeDirectory() {
     WCHAR exe_path[MAX_PATH];
 
     if (SUCCEEDED(GetModuleFileNameW(nullptr, exe_path, MAX_PATH))) {
-        std::wstring wideExePath(exe_path);
-
-        // UTF-16 filesystem lib to UTF-8 is broken, so we need to convert to UTF-8 with the with
-        // the Windows library (Filesystem converts the strings literally).
-        return fs::path{Common::UTF16ToUTF8(wideExePath)}.parent_path();
+        std::wstring wide_exe_path(exe_path);
+        return fs::path{Common::UTF16ToUTF8(wide_exe_path)}.parent_path();
     } else {
         LOG_ERROR(Common_Filesystem, "Failed to get the path to the executable of the current "
                                      "process");
@@ -273,9 +270,6 @@ fs::path GetAppDataRoamingDirectory() {
     if (SUCCEEDED(SHGetKnownFolderPath(FOLDERID_RoamingAppData, 0, NULL, &appdata_roaming_path))) {
         std::wstring wideAppdataRoamingPath(appdata_roaming_path);
         CoTaskMemFree(appdata_roaming_path);
-
-        // UTF-16 filesystem lib to UTF-8 is broken, so we need to convert to UTF-8 with the with
-        // the Windows library (Filesystem converts the strings literally).
         return fs::path{Common::UTF16ToUTF8(wideAppdataRoamingPath)};
     } else {
         LOG_ERROR(Common_Filesystem, "Failed to get the path to the %APPDATA% directory");
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index f2b91a7f35..36f9551a13 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -2847,8 +2847,6 @@ bool GMainWindow::CreateShortcutLink(const std::filesystem::path& shortcut_path,
                                      const std::string& arguments, const std::string& categories,
                                      const std::string& keywords, const std::string& name) {
 
-    bool shortcut_succeeded = false;
-
     // Copy characters if they are not illegal in Windows filenames
     std::string filename = "";
     const std::string illegal_chars = "<>:\"/\\|?*";
@@ -2858,22 +2856,13 @@ bool GMainWindow::CreateShortcutLink(const std::filesystem::path& shortcut_path,
 
     if (filename.empty()) {
         LOG_ERROR(Frontend, "Filename is empty");
-        shortcut_succeeded = false;
-        return shortcut_succeeded;
+        return false;
     }
 
-    // Replace characters that are illegal in Windows filenames
+    // Append .desktop or .lnk extension
     std::filesystem::path shortcut_path_full = shortcut_path / filename;
 
-#if defined(__linux__) || defined(__FreeBSD__)
-    shortcut_path_full += ".desktop";
-#elif defined(_WIN32)
-    shortcut_path_full += ".lnk";
-#endif
-
-    LOG_ERROR(Frontend, "Create shortcut path: {}", shortcut_path_full.string());
-
-#if defined(__linux__) || defined(__FreeBSD__)
+#if defined(__linux__) || defined(__FreeBSD__) // Linux and FreeBSD
     // This desktop file template was writing referencing
     // https://specifications.freedesktop.org/desktop-entry-spec/desktop-entry-spec-1.0.html
     try {
@@ -2881,9 +2870,13 @@ bool GMainWindow::CreateShortcutLink(const std::filesystem::path& shortcut_path,
         // Plus 'Type' is required
         if (name.empty()) {
             LOG_ERROR(Frontend, "Name is empty");
-            shortcut_succeeded = false;
-            return shortcut_succeeded;
+            return false;
         }
+
+        // Append .desktop extension
+        shortcut_path_full += ".desktop";
+
+        // Create shortcut file
         std::ofstream shortcut_stream(shortcut_path_full, std::ios::binary | std::ios::trunc);
 
         if (shortcut_stream.is_open()) {
@@ -2923,78 +2916,82 @@ bool GMainWindow::CreateShortcutLink(const std::filesystem::path& shortcut_path,
 
         } else {
             LOG_ERROR(Frontend, "Failed to create shortcut");
-            return false;
         }
 
         shortcut_stream.close();
     } catch (const std::exception& e) {
         LOG_ERROR(Frontend, "Failed to create shortcut: {}", e.what());
     }
-#elif defined(_WIN32)
-    // Initialize COM
-    auto hr = CoInitialize(NULL);
-    if (FAILED(hr)) {
-        return shortcut_succeeded;
-    }
+    return false;
+#elif defined(_WIN32) // Windows
+    HRESULT hr = CoInitialize(NULL);
+    if (SUCCEEDED(hr)) {
 
-    IShellLinkW* ps1;
+        IShellLinkW* ps1 = nullptr;
+        IPersistFile* persist_file = nullptr;
 
-    auto hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLinkW,
-                                 (void**)&ps1);
+        SCOPE_EXIT({
+            if (persist_file != nullptr) {
+                persist_file->Release();
+            }
+            if (ps1 != nullptr) {
+                ps1->Release();
+            }
 
-    // The UTF-16 / UTF-8 conversion is broken in C++, it is necessary to perform these steps and
-    // resort to the native Windows function.
-    std::wstring wshortcut_path_full = Common::UTF8ToUTF16W(shortcut_path_full.string());
-    std::wstring wicon_path = Common::UTF8ToUTF16W(icon_path.string());
-    std::wstring wcommand = Common::UTF8ToUTF16W(command.string());
-    std::wstring warguments = Common::UTF8ToUTF16W(arguments);
-    std::wstring wcomment = Common::UTF8ToUTF16W(comment);
+            CoUninitialize();
+        });
 
-    if (SUCCEEDED(hres)) {
-        if (std::filesystem::is_regular_file(command))
-            hres = ps1->SetPath(wcommand.data());
+        HRESULT hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
+                                        IID_IShellLinkW, (void**)&ps1);
 
-        if (SUCCEEDED(hres) && !arguments.empty())
-            hres = ps1->SetArguments(warguments.data());
-
-        if (SUCCEEDED(hres) && !comment.empty())
-            hres = ps1->SetDescription(wcomment.data());
-
-        if (SUCCEEDED(hres) && std::filesystem::is_regular_file(icon_path))
-            hres = ps1->SetIconLocation(wicon_path.data(), 0);
-
-        IPersistFile* pPersistFile = nullptr;
+        std::wstring wshortcut_path_full = Common::UTF8ToUTF16W(shortcut_path_full.string());
+        std::wstring wicon_path = Common::UTF8ToUTF16W(icon_path.string());
+        std::wstring wcommand = Common::UTF8ToUTF16W(command.string());
+        std::wstring warguments = Common::UTF8ToUTF16W(arguments);
+        std::wstring wcomment = Common::UTF8ToUTF16W(comment);
 
         if (SUCCEEDED(hres)) {
-            hres = ps1->QueryInterface(IID_IPersistFile, (void**)&pPersistFile);
+            if (std::filesystem::is_regular_file(command)) {
+                hres = ps1->SetPath(wcommand.data());
+            } else {
+                LOG_ERROR(Frontend, "Command is not a regular file");
+                return false;
+            }
 
-            if (SUCCEEDED(hres) && pPersistFile != nullptr) {
-                hres = pPersistFile->Save(wshortcut_path_full.data(), TRUE);
+            if (SUCCEEDED(hres) && !arguments.empty()) {
+                hres = ps1->SetArguments(warguments.data());
+            }
+
+            if (SUCCEEDED(hres) && !comment.empty()) {
+                hres = ps1->SetDescription(wcomment.data());
+            }
+
+            if (SUCCEEDED(hres) && std::filesystem::is_regular_file(icon_path)) {
+                hres = ps1->SetIconLocation(wicon_path.data(), 0);
+            }
+
+            if (SUCCEEDED(hres)) {
+                hres = ps1->QueryInterface(IID_IPersistFile, (void**)&persist_file);
+            }
+
+            if (SUCCEEDED(hres) && persist_file != nullptr) {
+                // Append .lnk extension and save shortcut
+                shortcut_path_full += ".lnk";
+                hres = persist_file->Save(wshortcut_path_full.data(), TRUE);
                 if (SUCCEEDED(hres)) {
-                    shortcut_succeeded = true;
+                    return true;
+                } else {
+                    LOG_ERROR(Frontend, "Failed to create shortcut");
                 }
             }
+        } else {
+            LOG_ERROR(Frontend, "Failed to create CoCreateInstance");
         }
-
-        if (pPersistFile != nullptr) {
-            pPersistFile->Release();
-        }
-    } else {
-        LOG_ERROR(Frontend, "Failed to create IShellLinkWinstance");
     }
-
-    ps1->Release();
-    CoUninitialize();
+    return false;
+#else                 // Unsupported platform
+    return false;
 #endif
-
-    if (shortcut_succeeded && std::filesystem::is_regular_file(shortcut_path_full)) {
-        LOG_ERROR(Frontend, "Shortcut created");
-    } else {
-        LOG_ERROR(Frontend, "Shortcut error, failed to create it");
-        shortcut_succeeded = false;
-    }
-
-    return shortcut_succeeded;
 }
 
 // Messages in pre-defined message boxes for less code spaghetti
@@ -3049,31 +3046,31 @@ bool GMainWindow::CreateShortcutMessagesGUI(QWidget* parent, const int& imsg,
 }
 
 bool GMainWindow::MakeShortcutIcoPath(const u64 program_id, const std::string_view game_file_name,
-                                      std::filesystem::path& icons_path) {
+                                      std::filesystem::path& out_icon_path) {
 
     // Get path to Yuzu icons directory & icon extension
     std::string ico_extension = "png";
 #if defined(_WIN32)
-    icons_path = Common::FS::GetYuzuPath(Common::FS::YuzuPath::ConfigDir) / "icons";
+    out_icon_path = Common::FS::GetYuzuPath(Common::FS::YuzuPath::ConfigDir) / "icons";
     ico_extension = "ico";
 #elif defined(__linux__) || defined(__FreeBSD__)
-    icons_path = Common::FS::GetDataDirectory("XDG_DATA_HOME") / "icons/hicolor/256x256";
+    out_icon_path = Common::FS::GetDataDirectory("XDG_DATA_HOME") / "icons/hicolor/256x256";
 #endif
 
     // Create icons directory if it doesn't exist
-    if (!Common::FS::CreateDirs(icons_path)) {
+    if (!Common::FS::CreateDirs(out_icon_path)) {
         QMessageBox::critical(
             this, tr("Create Icon"),
             tr("Cannot create icon file. Path \"%1\" does not exist and cannot be created.")
-                .arg(QString::fromStdString(icons_path.string())),
+                .arg(QString::fromStdString(out_icon_path.string())),
             QMessageBox::StandardButton::Ok);
-        icons_path = ""; // Reset path
+        out_icon_path = ""; // Reset path
         return false;
     }
 
     // Create icon file path
-    icons_path /= (program_id == 0 ? fmt::format("yuzu-{}.{}", game_file_name, ico_extension)
-                                   : fmt::format("yuzu-{:016X}.{}", program_id, ico_extension));
+    out_icon_path /= (program_id == 0 ? fmt::format("yuzu-{}.{}", game_file_name, ico_extension)
+                                      : fmt::format("yuzu-{:016X}.{}", program_id, ico_extension));
     return true;
 }
 
@@ -3096,13 +3093,11 @@ void GMainWindow::OnGameListCreateShortcut(u64 program_id, const std::string& ga
             QStandardPaths::writableLocation(QStandardPaths::DesktopLocation).toStdString();
     } else if (target == GameListShortcutTarget::Applications) {
 #if defined(_WIN32)
-        HANDLE hProcess = GetCurrentProcess();
         if (!IsUserAnAdmin()) {
             GMainWindow::CreateShortcutMessagesGUI(this, GMainWindow::CREATE_SHORTCUT_MSGBOX_ADMIN,
                                                    "");
             return;
         }
-        CloseHandle(hProcess);
 #endif // _WIN32
         shortcut_path =
             QStandardPaths::writableLocation(QStandardPaths::ApplicationsLocation).toStdString();
@@ -3110,9 +3105,8 @@ void GMainWindow::OnGameListCreateShortcut(u64 program_id, const std::string& ga
 
     // Icon path and title
     std::string title;
-    std::filesystem::path icons_path;
+    std::filesystem::path out_icon_path;
     if (std::filesystem::exists(shortcut_path)) {
-
         // Get title from game file
         const FileSys::PatchManager pm{program_id, system->GetFileSystemController(),
                                        system->GetContentProvider()};
@@ -3139,8 +3133,8 @@ void GMainWindow::OnGameListCreateShortcut(u64 program_id, const std::string& ga
         QImage icon_data =
             QImage::fromData(icon_image_file.data(), static_cast<int>(icon_image_file.size()));
 
-        if (GMainWindow::MakeShortcutIcoPath(program_id, title, icons_path)) {
-            if (!SaveIconToFile(icons_path, icon_data)) {
+        if (GMainWindow::MakeShortcutIcoPath(program_id, title, out_icon_path)) {
+            if (!SaveIconToFile(out_icon_path, icon_data)) {
                 LOG_ERROR(Frontend, "Could not write icon to file");
             }
         }
@@ -3178,8 +3172,8 @@ void GMainWindow::OnGameListCreateShortcut(u64 program_id, const std::string& ga
     const std::string categories = "Game;Emulator;Qt;";
     const std::string keywords = "Switch;Nintendo;";
 
-    if (GMainWindow::CreateShortcutLink(shortcut_path, comment, icons_path, yuzu_command, arguments,
-                                        categories, keywords, title)) {
+    if (GMainWindow::CreateShortcutLink(shortcut_path, comment, out_icon_path, yuzu_command,
+                                        arguments, categories, keywords, title)) {
         GMainWindow::CreateShortcutMessagesGUI(this, GMainWindow::CREATE_SHORTCUT_MSGBOX_SUCCESS,
                                                title);
         return;
diff --git a/src/yuzu/main.h b/src/yuzu/main.h
index d7426607f7..d3a1bf5b98 100644
--- a/src/yuzu/main.h
+++ b/src/yuzu/main.h
@@ -444,7 +444,7 @@ private:
     QString GetTasStateDescription() const;
     bool CreateShortcutMessagesGUI(QWidget* parent, const int& imsg, const std::string title);
     bool MakeShortcutIcoPath(const u64 program_id, const std::string_view game_file_name,
-                             std::filesystem::path& icons_path);
+                             std::filesystem::path& out_icon_path);
     bool CreateShortcutLink(const std::filesystem::path& shortcut_path, const std::string& comment,
                             const std::filesystem::path& icon_path,
                             const std::filesystem::path& command, const std::string& arguments,

From 89d3e81be8b923711a548b0973276353392449a6 Mon Sep 17 00:00:00 2001
From: boludoz <francomaro@gmail.com>
Date: Mon, 16 Oct 2023 16:01:46 -0300
Subject: [PATCH 07/24] Sugestions and fixes.

---
 src/common/fs/path_util.cpp |   4 +-
 src/yuzu/main.cpp           | 104 ++++++++++++++++++------------------
 src/yuzu/main.h             |   2 +-
 3 files changed, 56 insertions(+), 54 deletions(-)

diff --git a/src/common/fs/path_util.cpp b/src/common/fs/path_util.cpp
index bcd64156e9..60c5e477e3 100644
--- a/src/common/fs/path_util.cpp
+++ b/src/common/fs/path_util.cpp
@@ -268,9 +268,9 @@ fs::path GetAppDataRoamingDirectory() {
     PWSTR appdata_roaming_path = nullptr;
 
     if (SUCCEEDED(SHGetKnownFolderPath(FOLDERID_RoamingAppData, 0, NULL, &appdata_roaming_path))) {
-        std::wstring wideAppdataRoamingPath(appdata_roaming_path);
+        std::wstring wide_appdata_roaming_path(appdata_roaming_path);
         CoTaskMemFree(appdata_roaming_path);
-        return fs::path{Common::UTF16ToUTF8(wideAppdataRoamingPath)};
+        return fs::path{Common::UTF16ToUTF8(wide_appdata_roaming_path)};
     } else {
         LOG_ERROR(Common_Filesystem, "Failed to get the path to the %APPDATA% directory");
     }
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index 36f9551a13..feb455763d 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -2859,11 +2859,15 @@ bool GMainWindow::CreateShortcutLink(const std::filesystem::path& shortcut_path,
         return false;
     }
 
-    // Append .desktop or .lnk extension
+    if (!std::filesystem::is_regular_file(command)) {
+        LOG_ERROR(Frontend, "Command is not a regular file");
+        return false;
+    }
+
     std::filesystem::path shortcut_path_full = shortcut_path / filename;
 
 #if defined(__linux__) || defined(__FreeBSD__) // Linux and FreeBSD
-    // This desktop file template was writing referencing
+    // Reference for the desktop file template:
     // https://specifications.freedesktop.org/desktop-entry-spec/desktop-entry-spec-1.0.html
     try {
 
@@ -2911,17 +2915,17 @@ bool GMainWindow::CreateShortcutLink(const std::filesystem::path& shortcut_path,
                 fmt::print(shortcut_stream, "Keywords={}\n", keywords);
             }
 
+            // Flush and close file
+            shortcut_stream.flush();
             shortcut_stream.close();
             return true;
-
         } else {
             LOG_ERROR(Frontend, "Failed to create shortcut");
         }
-
-        shortcut_stream.close();
     } catch (const std::exception& e) {
         LOG_ERROR(Frontend, "Failed to create shortcut: {}", e.what());
     }
+    shortcut_stream.close();
     return false;
 #elif defined(_WIN32) // Windows
     HRESULT hr = CoInitialize(NULL);
@@ -2944,19 +2948,15 @@ bool GMainWindow::CreateShortcutLink(const std::filesystem::path& shortcut_path,
         HRESULT hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
                                         IID_IShellLinkW, (void**)&ps1);
 
-        std::wstring wshortcut_path_full = Common::UTF8ToUTF16W(shortcut_path_full.string());
+        std::wstring wshortcut_path_full =
+            Common::UTF8ToUTF16W((shortcut_path_full).string() + ".lnk");
         std::wstring wicon_path = Common::UTF8ToUTF16W(icon_path.string());
         std::wstring wcommand = Common::UTF8ToUTF16W(command.string());
         std::wstring warguments = Common::UTF8ToUTF16W(arguments);
         std::wstring wcomment = Common::UTF8ToUTF16W(comment);
 
         if (SUCCEEDED(hres)) {
-            if (std::filesystem::is_regular_file(command)) {
-                hres = ps1->SetPath(wcommand.data());
-            } else {
-                LOG_ERROR(Frontend, "Command is not a regular file");
-                return false;
-            }
+            hres = ps1->SetPath(wcommand.data());
 
             if (SUCCEEDED(hres) && !arguments.empty()) {
                 hres = ps1->SetArguments(warguments.data());
@@ -2975,8 +2975,6 @@ bool GMainWindow::CreateShortcutLink(const std::filesystem::path& shortcut_path,
             }
 
             if (SUCCEEDED(hres) && persist_file != nullptr) {
-                // Append .lnk extension and save shortcut
-                shortcut_path_full += ".lnk";
                 hres = persist_file->Save(wshortcut_path_full.data(), TRUE);
                 if (SUCCEEDED(hres)) {
                     return true;
@@ -2995,9 +2993,10 @@ bool GMainWindow::CreateShortcutLink(const std::filesystem::path& shortcut_path,
 }
 
 // Messages in pre-defined message boxes for less code spaghetti
-bool GMainWindow::CreateShortcutMessagesGUI(QWidget* parent, const int& imsg,
-                                            const std::string title) {
+bool GMainWindow::CreateShortcutMessagesGUI(QWidget* parent, int imsg, const QString& game_title) {
     QMessageBox::StandardButtons buttons;
+    std::string_view game_title_sv = game_title.toStdString();
+
     int result = 0;
 
     switch (imsg) {
@@ -3013,18 +3012,18 @@ bool GMainWindow::CreateShortcutMessagesGUI(QWidget* parent, const int& imsg,
         return (result == QMessageBox::No) ? false : true;
 
     case GMainWindow::CREATE_SHORTCUT_MSGBOX_SUCCESS:
-        QMessageBox::information(
-            parent, tr("Create Shortcut"),
-            tr("Successfully created a shortcut to %1").arg(QString::fromStdString(title)));
-        LOG_INFO(Frontend, "Successfully created a shortcut to {}", title);
+        QMessageBox::information(parent, tr("Create Shortcut"),
+                                 tr("Successfully created a shortcut to %1").arg(game_title));
+        LOG_INFO(Frontend, "Successfully created a shortcut to {}", game_title_sv);
         return true;
 
     case GMainWindow::CREATE_SHORTCUT_MSGBOX_APPVOLATILE_WARNING:
-        result = QMessageBox::warning(
-            this, tr("Create Shortcut"),
-            tr("This will create a shortcut to the current AppImage. This may "
-               "not work well if you update. Continue?"),
-            QMessageBox::StandardButton::Ok | QMessageBox::StandardButton::Cancel);
+        buttons = QMessageBox::StandardButton::Ok | QMessageBox::StandardButton::Cancel;
+        result =
+            QMessageBox::warning(this, tr("Create Shortcut"),
+                                 tr("This will create a shortcut to the current AppImage. This may "
+                                    "not work well if you update. Continue?"),
+                                 buttons);
         return (result == QMessageBox::StandardButton::Cancel) ? true : false;
     case GMainWindow::CREATE_SHORTCUT_MSGBOX_ADMIN:
         buttons = QMessageBox::Ok;
@@ -3035,10 +3034,9 @@ bool GMainWindow::CreateShortcutMessagesGUI(QWidget* parent, const int& imsg,
         return true;
     default:
         buttons = QMessageBox::Ok;
-        QMessageBox::critical(
-            parent, tr("Create Shortcut"),
-            tr("Failed to create a shortcut to %1").arg(QString::fromStdString(title)), buttons);
-        LOG_ERROR(Frontend, "Failed to create a shortcut to {}", title);
+        QMessageBox::critical(parent, tr("Create Shortcut"),
+                              tr("Failed to create a shortcut to %1").arg(game_title), buttons);
+        LOG_ERROR(Frontend, "Failed to create a shortcut to {}", game_title_sv);
         return true;
     }
 
@@ -3077,6 +3075,10 @@ bool GMainWindow::MakeShortcutIcoPath(const u64 program_id, const std::string_vi
 void GMainWindow::OnGameListCreateShortcut(u64 program_id, const std::string& game_path,
                                            GameListShortcutTarget target) {
 
+    std::string game_title;
+    QString qt_game_title;
+    std::filesystem::path out_icon_path;
+
     // Get path to yuzu executable
     const QStringList args = QApplication::arguments();
     std::filesystem::path yuzu_command = args[0].toStdString();
@@ -3092,20 +3094,11 @@ void GMainWindow::OnGameListCreateShortcut(u64 program_id, const std::string& ga
         shortcut_path =
             QStandardPaths::writableLocation(QStandardPaths::DesktopLocation).toStdString();
     } else if (target == GameListShortcutTarget::Applications) {
-#if defined(_WIN32)
-        if (!IsUserAnAdmin()) {
-            GMainWindow::CreateShortcutMessagesGUI(this, GMainWindow::CREATE_SHORTCUT_MSGBOX_ADMIN,
-                                                   "");
-            return;
-        }
-#endif // _WIN32
         shortcut_path =
             QStandardPaths::writableLocation(QStandardPaths::ApplicationsLocation).toStdString();
     }
 
     // Icon path and title
-    std::string title;
-    std::filesystem::path out_icon_path;
     if (std::filesystem::exists(shortcut_path)) {
         // Get title from game file
         const FileSys::PatchManager pm{program_id, system->GetFileSystemController(),
@@ -3114,14 +3107,16 @@ void GMainWindow::OnGameListCreateShortcut(u64 program_id, const std::string& ga
         const auto loader =
             Loader::GetLoader(*system, vfs->OpenFile(game_path, FileSys::Mode::Read));
 
-        title = fmt::format("{:016X}", program_id);
+        game_title = fmt::format("{:016X}", program_id);
 
         if (control.first != nullptr) {
-            title = control.first->GetApplicationName();
+            game_title = control.first->GetApplicationName();
         } else {
-            loader->ReadTitle(title);
+            loader->ReadTitle(game_title);
         }
 
+        qt_game_title = QString::fromStdString(game_title);
+
         // Get icon from game file
         std::vector<u8> icon_image_file{};
         if (control.second != nullptr) {
@@ -3133,7 +3128,7 @@ void GMainWindow::OnGameListCreateShortcut(u64 program_id, const std::string& ga
         QImage icon_data =
             QImage::fromData(icon_image_file.data(), static_cast<int>(icon_image_file.size()));
 
-        if (GMainWindow::MakeShortcutIcoPath(program_id, title, out_icon_path)) {
+        if (GMainWindow::MakeShortcutIcoPath(program_id, game_title, out_icon_path)) {
             if (!SaveIconToFile(out_icon_path, icon_data)) {
                 LOG_ERROR(Frontend, "Could not write icon to file");
             }
@@ -3141,20 +3136,26 @@ void GMainWindow::OnGameListCreateShortcut(u64 program_id, const std::string& ga
 
     } else {
         GMainWindow::CreateShortcutMessagesGUI(this, GMainWindow::CREATE_SHORTCUT_MSGBOX_ERROR,
-                                               title);
+                                               qt_game_title);
         LOG_ERROR(Frontend, "Invalid shortcut target");
         return;
     }
 
-// Special case for AppImages
-#if defined(__linux__)
+#if defined(_WIN32)
+    if (!IsUserAnAdmin() && target == GameListShortcutTarget::Applications) {
+        GMainWindow::CreateShortcutMessagesGUI(this, GMainWindow::CREATE_SHORTCUT_MSGBOX_ADMIN,
+                                               qt_game_title);
+        return;
+    }
+#elif defined(__linux__)
+    // Special case for AppImages
     // Warn once if we are making a shortcut to a volatile AppImage
     const std::string appimage_ending =
         std::string(Common::g_scm_rev).substr(0, 9).append(".AppImage");
     if (yuzu_command.string().ends_with(appimage_ending) &&
         !UISettings::values.shortcut_already_warned) {
         if (GMainWindow::CreateShortcutMessagesGUI(
-                this, GMainWindow::CREATE_SHORTCUT_MSGBOX_APPVOLATILE_WARNING, title)) {
+                this, GMainWindow::CREATE_SHORTCUT_MSGBOX_APPVOLATILE_WARNING, qt_game_title)) {
             return;
         }
         UISettings::values.shortcut_already_warned = true;
@@ -3164,22 +3165,23 @@ void GMainWindow::OnGameListCreateShortcut(u64 program_id, const std::string& ga
     // Create shortcut
     std::string arguments = fmt::format("-g \"{:s}\"", game_path);
     if (GMainWindow::CreateShortcutMessagesGUI(
-            this, GMainWindow::CREATE_SHORTCUT_MSGBOX_FULLSCREEN_YES, title)) {
+            this, GMainWindow::CREATE_SHORTCUT_MSGBOX_FULLSCREEN_YES, qt_game_title)) {
         arguments = "-f " + arguments;
     }
     const std::string comment =
-        tr("Start %1 with the yuzu Emulator").arg(QString::fromStdString(title)).toStdString();
+        tr("Start %1 with the yuzu Emulator").arg(QString::fromStdString(game_title)).toStdString();
     const std::string categories = "Game;Emulator;Qt;";
     const std::string keywords = "Switch;Nintendo;";
 
     if (GMainWindow::CreateShortcutLink(shortcut_path, comment, out_icon_path, yuzu_command,
-                                        arguments, categories, keywords, title)) {
+                                        arguments, categories, keywords, game_title)) {
         GMainWindow::CreateShortcutMessagesGUI(this, GMainWindow::CREATE_SHORTCUT_MSGBOX_SUCCESS,
-                                               title);
+                                               qt_game_title);
         return;
     }
 
-    GMainWindow::CreateShortcutMessagesGUI(this, GMainWindow::CREATE_SHORTCUT_MSGBOX_ERROR, title);
+    GMainWindow::CreateShortcutMessagesGUI(this, GMainWindow::CREATE_SHORTCUT_MSGBOX_ERROR,
+                                           qt_game_title);
 }
 
 void GMainWindow::OnGameListOpenDirectory(const QString& directory) {
diff --git a/src/yuzu/main.h b/src/yuzu/main.h
index d3a1bf5b98..41902cc8da 100644
--- a/src/yuzu/main.h
+++ b/src/yuzu/main.h
@@ -442,7 +442,7 @@ private:
     bool ConfirmShutdownGame();
 
     QString GetTasStateDescription() const;
-    bool CreateShortcutMessagesGUI(QWidget* parent, const int& imsg, const std::string title);
+    bool CreateShortcutMessagesGUI(QWidget* parent, int imsg, const QString& game_title);
     bool MakeShortcutIcoPath(const u64 program_id, const std::string_view game_file_name,
                              std::filesystem::path& out_icon_path);
     bool CreateShortcutLink(const std::filesystem::path& shortcut_path, const std::string& comment,

From d759de9f96faa8f530b3724b79ccc04ab0d01a09 Mon Sep 17 00:00:00 2001
From: boludoz <francomaro@gmail.com>
Date: Mon, 16 Oct 2023 16:11:24 -0300
Subject: [PATCH 08/24] More missed suggestions

---
 src/yuzu/main.cpp | 8 ++------
 1 file changed, 2 insertions(+), 6 deletions(-)

diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index feb455763d..90bb61c152 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -2995,12 +2995,10 @@ bool GMainWindow::CreateShortcutLink(const std::filesystem::path& shortcut_path,
 // Messages in pre-defined message boxes for less code spaghetti
 bool GMainWindow::CreateShortcutMessagesGUI(QWidget* parent, int imsg, const QString& game_title) {
     QMessageBox::StandardButtons buttons;
-    std::string_view game_title_sv = game_title.toStdString();
 
     int result = 0;
 
     switch (imsg) {
-
     case GMainWindow::CREATE_SHORTCUT_MSGBOX_FULLSCREEN_YES:
         buttons = QMessageBox::Yes | QMessageBox::No;
 
@@ -3009,12 +3007,11 @@ bool GMainWindow::CreateShortcutMessagesGUI(QWidget* parent, int imsg, const QSt
                                      tr("Do you want to launch the game in fullscreen?"), buttons);
 
         LOG_INFO(Frontend, "Shortcut will launch in fullscreen");
-        return (result == QMessageBox::No) ? false : true;
+        return result == QMessageBox::Yes;
 
     case GMainWindow::CREATE_SHORTCUT_MSGBOX_SUCCESS:
         QMessageBox::information(parent, tr("Create Shortcut"),
                                  tr("Successfully created a shortcut to %1").arg(game_title));
-        LOG_INFO(Frontend, "Successfully created a shortcut to {}", game_title_sv);
         return true;
 
     case GMainWindow::CREATE_SHORTCUT_MSGBOX_APPVOLATILE_WARNING:
@@ -3024,7 +3021,7 @@ bool GMainWindow::CreateShortcutMessagesGUI(QWidget* parent, int imsg, const QSt
                                  tr("This will create a shortcut to the current AppImage. This may "
                                     "not work well if you update. Continue?"),
                                  buttons);
-        return (result == QMessageBox::StandardButton::Cancel) ? true : false;
+        return result == QMessageBox::StandardButton::Ok;
     case GMainWindow::CREATE_SHORTCUT_MSGBOX_ADMIN:
         buttons = QMessageBox::Ok;
         QMessageBox::critical(parent, tr("Create Shortcut"),
@@ -3036,7 +3033,6 @@ bool GMainWindow::CreateShortcutMessagesGUI(QWidget* parent, int imsg, const QSt
         buttons = QMessageBox::Ok;
         QMessageBox::critical(parent, tr("Create Shortcut"),
                               tr("Failed to create a shortcut to %1").arg(game_title), buttons);
-        LOG_ERROR(Frontend, "Failed to create a shortcut to {}", game_title_sv);
         return true;
     }
 

From ae88d01d8dfc9c39206d3fb37938e44a3480c70f Mon Sep 17 00:00:00 2001
From: boludoz <francomaro@gmail.com>
Date: Mon, 16 Oct 2023 16:47:21 -0300
Subject: [PATCH 09/24] .clear() instead = ""; and switch improved.

---
 src/yuzu/main.cpp | 24 ++++++++----------------
 1 file changed, 8 insertions(+), 16 deletions(-)

diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index 90bb61c152..82b38fc07b 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -2997,23 +2997,17 @@ bool GMainWindow::CreateShortcutMessagesGUI(QWidget* parent, int imsg, const QSt
     QMessageBox::StandardButtons buttons;
 
     int result = 0;
-
     switch (imsg) {
     case GMainWindow::CREATE_SHORTCUT_MSGBOX_FULLSCREEN_YES:
         buttons = QMessageBox::Yes | QMessageBox::No;
-
         result =
             QMessageBox::information(parent, tr("Create Shortcut"),
                                      tr("Do you want to launch the game in fullscreen?"), buttons);
-
-        LOG_INFO(Frontend, "Shortcut will launch in fullscreen");
-        return result == QMessageBox::Yes;
-
+        return (result == QMessageBox::Yes);
     case GMainWindow::CREATE_SHORTCUT_MSGBOX_SUCCESS:
         QMessageBox::information(parent, tr("Create Shortcut"),
                                  tr("Successfully created a shortcut to %1").arg(game_title));
-        return true;
-
+        break;
     case GMainWindow::CREATE_SHORTCUT_MSGBOX_APPVOLATILE_WARNING:
         buttons = QMessageBox::StandardButton::Ok | QMessageBox::StandardButton::Cancel;
         result =
@@ -3021,22 +3015,20 @@ bool GMainWindow::CreateShortcutMessagesGUI(QWidget* parent, int imsg, const QSt
                                  tr("This will create a shortcut to the current AppImage. This may "
                                     "not work well if you update. Continue?"),
                                  buttons);
-        return result == QMessageBox::StandardButton::Ok;
+        return (result == QMessageBox::Ok);
     case GMainWindow::CREATE_SHORTCUT_MSGBOX_ADMIN:
         buttons = QMessageBox::Ok;
         QMessageBox::critical(parent, tr("Create Shortcut"),
                               tr("Cannot create shortcut in Apps. Restart yuzu as administrator."),
                               buttons);
-        LOG_ERROR(Frontend, "Cannot create shortcut in Apps. Restart yuzu as administrator.");
-        return true;
+        break;
     default:
         buttons = QMessageBox::Ok;
         QMessageBox::critical(parent, tr("Create Shortcut"),
                               tr("Failed to create a shortcut to %1").arg(game_title), buttons);
-        return true;
+        break;
     }
-
-    return true;
+    return false;
 }
 
 bool GMainWindow::MakeShortcutIcoPath(const u64 program_id, const std::string_view game_file_name,
@@ -3058,7 +3050,7 @@ bool GMainWindow::MakeShortcutIcoPath(const u64 program_id, const std::string_vi
             tr("Cannot create icon file. Path \"%1\" does not exist and cannot be created.")
                 .arg(QString::fromStdString(out_icon_path.string())),
             QMessageBox::StandardButton::Ok);
-        out_icon_path = ""; // Reset path
+        out_icon_path.clear();
         return false;
     }
 
@@ -3165,7 +3157,7 @@ void GMainWindow::OnGameListCreateShortcut(u64 program_id, const std::string& ga
         arguments = "-f " + arguments;
     }
     const std::string comment =
-        tr("Start %1 with the yuzu Emulator").arg(QString::fromStdString(game_title)).toStdString();
+        tr("Start %1 with the yuzu Emulator").arg(qt_game_title).toStdString();
     const std::string categories = "Game;Emulator;Qt;";
     const std::string keywords = "Switch;Nintendo;";
 

From de0b35b97456313498785facccad5980cea737f7 Mon Sep 17 00:00:00 2001
From: boludoz <francomaro@gmail.com>
Date: Mon, 16 Oct 2023 16:54:51 -0300
Subject: [PATCH 10/24] Comment using fmt instead qt.

---
 src/yuzu/main.cpp | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index 82b38fc07b..54b36552d4 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -3156,8 +3156,7 @@ void GMainWindow::OnGameListCreateShortcut(u64 program_id, const std::string& ga
             this, GMainWindow::CREATE_SHORTCUT_MSGBOX_FULLSCREEN_YES, qt_game_title)) {
         arguments = "-f " + arguments;
     }
-    const std::string comment =
-        tr("Start %1 with the yuzu Emulator").arg(qt_game_title).toStdString();
+    const std::string comment = fmt::format("Start {:s} with the yuzu Emulator", game_title);
     const std::string categories = "Game;Emulator;Qt;";
     const std::string keywords = "Switch;Nintendo;";
 

From 1ae0f0f3f64446b3128da0f1b1151d95739c9a6e Mon Sep 17 00:00:00 2001
From: boludoz <francomaro@gmail.com>
Date: Mon, 16 Oct 2023 18:59:21 -0300
Subject: [PATCH 11/24] shortcut_stream.close(); fixed

---
 src/yuzu/main.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index 54b36552d4..e49de921cf 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -2922,10 +2922,10 @@ bool GMainWindow::CreateShortcutLink(const std::filesystem::path& shortcut_path,
         } else {
             LOG_ERROR(Frontend, "Failed to create shortcut");
         }
+        shortcut_stream.close();
     } catch (const std::exception& e) {
         LOG_ERROR(Frontend, "Failed to create shortcut: {}", e.what());
     }
-    shortcut_stream.close();
     return false;
 #elif defined(_WIN32) // Windows
     HRESULT hr = CoInitialize(NULL);

From 1afe6d51eed4a420bb7289955333a2bb10c06b99 Mon Sep 17 00:00:00 2001
From: boludoz <francomaro@gmail.com>
Date: Mon, 16 Oct 2023 23:42:45 -0300
Subject: [PATCH 12/24] More @liamwhite suggestions applied.

---
 src/common/fs/path_util.cpp |  12 +-
 src/yuzu/main.cpp           | 216 ++++++++++++++++--------------------
 2 files changed, 98 insertions(+), 130 deletions(-)

diff --git a/src/common/fs/path_util.cpp b/src/common/fs/path_util.cpp
index 60c5e477e3..732c1559fa 100644
--- a/src/common/fs/path_util.cpp
+++ b/src/common/fs/path_util.cpp
@@ -252,29 +252,23 @@ void SetYuzuPath(YuzuPath yuzu_path, const fs::path& new_path) {
 
 fs::path GetExeDirectory() {
     WCHAR exe_path[MAX_PATH];
-
     if (SUCCEEDED(GetModuleFileNameW(nullptr, exe_path, MAX_PATH))) {
         std::wstring wide_exe_path(exe_path);
         return fs::path{Common::UTF16ToUTF8(wide_exe_path)}.parent_path();
-    } else {
-        LOG_ERROR(Common_Filesystem, "Failed to get the path to the executable of the current "
-                                     "process");
     }
-
+    LOG_ERROR(Common_Filesystem, "Failed to get the path to the executable of the current "
+                                 "process");
     return fs::path{};
 }
 
 fs::path GetAppDataRoamingDirectory() {
     PWSTR appdata_roaming_path = nullptr;
-
     if (SUCCEEDED(SHGetKnownFolderPath(FOLDERID_RoamingAppData, 0, NULL, &appdata_roaming_path))) {
         std::wstring wide_appdata_roaming_path(appdata_roaming_path);
         CoTaskMemFree(appdata_roaming_path);
         return fs::path{Common::UTF16ToUTF8(wide_appdata_roaming_path)};
-    } else {
-        LOG_ERROR(Common_Filesystem, "Failed to get the path to the %APPDATA% directory");
     }
-
+    LOG_ERROR(Common_Filesystem, "Failed to get the path to the %APPDATA% directory");
     return fs::path{};
 }
 
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index e49de921cf..75fbd042ae 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -2845,7 +2845,7 @@ bool GMainWindow::CreateShortcutLink(const std::filesystem::path& shortcut_path,
                                      const std::filesystem::path& icon_path,
                                      const std::filesystem::path& command,
                                      const std::string& arguments, const std::string& categories,
-                                     const std::string& keywords, const std::string& name) {
+                                     const std::string& keywords, const std::string& name) try {
 
     // Copy characters if they are not illegal in Windows filenames
     std::string filename = "";
@@ -2869,145 +2869,120 @@ bool GMainWindow::CreateShortcutLink(const std::filesystem::path& shortcut_path,
 #if defined(__linux__) || defined(__FreeBSD__) // Linux and FreeBSD
     // Reference for the desktop file template:
     // https://specifications.freedesktop.org/desktop-entry-spec/desktop-entry-spec-1.0.html
-    try {
 
-        // Plus 'Type' is required
-        if (name.empty()) {
-            LOG_ERROR(Frontend, "Name is empty");
-            return false;
-        }
-
-        // Append .desktop extension
-        shortcut_path_full += ".desktop";
-
-        // Create shortcut file
-        std::ofstream shortcut_stream(shortcut_path_full, std::ios::binary | std::ios::trunc);
-
-        if (shortcut_stream.is_open()) {
-
-            fmt::print(shortcut_stream, "[Desktop Entry]\n");
-            fmt::print(shortcut_stream, "Type=Application\n");
-            fmt::print(shortcut_stream, "Version=1.0\n");
-            fmt::print(shortcut_stream, "Name={}\n", name);
-
-            if (!comment.empty()) {
-                fmt::print(shortcut_stream, "Comment={}\n", comment);
-            }
-
-            if (std::filesystem::is_regular_file(icon_path)) {
-                fmt::print(shortcut_stream, "Icon={}\n", icon_path.string());
-            }
-
-            fmt::print(shortcut_stream, "TryExec={}\n", command.string());
-            fmt::print(shortcut_stream, "Exec={}", command.string());
-
-            if (!arguments.empty()) {
-                fmt::print(shortcut_stream, " {}", arguments);
-            }
-
-            fmt::print(shortcut_stream, "\n");
-
-            if (!categories.empty()) {
-                fmt::print(shortcut_stream, "Categories={}\n", categories);
-            }
-
-            if (!keywords.empty()) {
-                fmt::print(shortcut_stream, "Keywords={}\n", keywords);
-            }
-
-            // Flush and close file
-            shortcut_stream.flush();
-            shortcut_stream.close();
-            return true;
-        } else {
-            LOG_ERROR(Frontend, "Failed to create shortcut");
-        }
-        shortcut_stream.close();
-    } catch (const std::exception& e) {
-        LOG_ERROR(Frontend, "Failed to create shortcut: {}", e.what());
+    // Plus 'Type' is required
+    if (name.empty()) {
+        LOG_ERROR(Frontend, "Name is empty");
+        return false;
     }
-    return false;
+
+    // Append .desktop extension
+    shortcut_path_full += ".desktop";
+
+    // Create shortcut file
+    std::ofstream shortcut_stream(shortcut_path_full, std::ios::binary | std::ios::trunc);
+    if (!shortcut_stream.is_open()) {
+        LOG_ERROR(Frontend, "Failed to create shortcut");
+        return false;
+    }
+
+    fmt::print(shortcut_stream, "[Desktop Entry]\n");
+    fmt::print(shortcut_stream, "Type=Application\n");
+    fmt::print(shortcut_stream, "Version=1.0\n");
+    fmt::print(shortcut_stream, "Name={}\n", name);
+    if (!comment.empty()) {
+        fmt::print(shortcut_stream, "Comment={}\n", comment);
+    }
+    if (std::filesystem::is_regular_file(icon_path)) {
+        fmt::print(shortcut_stream, "Icon={}\n", icon_path.string());
+    }
+    fmt::print(shortcut_stream, "TryExec={}\n", command.string());
+    fmt::print(shortcut_stream, "Exec={}", command.string());
+    if (!arguments.empty()) {
+        fmt::print(shortcut_stream, " {}", arguments);
+    }
+    fmt::print(shortcut_stream, "\n");
+    if (!categories.empty()) {
+        fmt::print(shortcut_stream, "Categories={}\n", categories);
+    }
+    if (!keywords.empty()) {
+        fmt::print(shortcut_stream, "Keywords={}\n", keywords);
+    }
+    return true;
 #elif defined(_WIN32) // Windows
     HRESULT hr = CoInitialize(NULL);
-    if (SUCCEEDED(hr)) {
-
-        IShellLinkW* ps1 = nullptr;
-        IPersistFile* persist_file = nullptr;
-
-        SCOPE_EXIT({
-            if (persist_file != nullptr) {
-                persist_file->Release();
-            }
-            if (ps1 != nullptr) {
-                ps1->Release();
-            }
-
-            CoUninitialize();
-        });
-
-        HRESULT hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
-                                        IID_IShellLinkW, (void**)&ps1);
-
-        std::wstring wshortcut_path_full =
-            Common::UTF8ToUTF16W((shortcut_path_full).string() + ".lnk");
-        std::wstring wicon_path = Common::UTF8ToUTF16W(icon_path.string());
-        std::wstring wcommand = Common::UTF8ToUTF16W(command.string());
-        std::wstring warguments = Common::UTF8ToUTF16W(arguments);
-        std::wstring wcomment = Common::UTF8ToUTF16W(comment);
-
-        if (SUCCEEDED(hres)) {
-            hres = ps1->SetPath(wcommand.data());
-
-            if (SUCCEEDED(hres) && !arguments.empty()) {
-                hres = ps1->SetArguments(warguments.data());
-            }
-
-            if (SUCCEEDED(hres) && !comment.empty()) {
-                hres = ps1->SetDescription(wcomment.data());
-            }
-
-            if (SUCCEEDED(hres) && std::filesystem::is_regular_file(icon_path)) {
-                hres = ps1->SetIconLocation(wicon_path.data(), 0);
-            }
-
-            if (SUCCEEDED(hres)) {
-                hres = ps1->QueryInterface(IID_IPersistFile, (void**)&persist_file);
-            }
-
-            if (SUCCEEDED(hres) && persist_file != nullptr) {
-                hres = persist_file->Save(wshortcut_path_full.data(), TRUE);
-                if (SUCCEEDED(hres)) {
-                    return true;
-                } else {
-                    LOG_ERROR(Frontend, "Failed to create shortcut");
-                }
-            }
-        } else {
-            LOG_ERROR(Frontend, "Failed to create CoCreateInstance");
-        }
+    if (FAILED(hr)) {
+        LOG_ERROR(Frontend, "CoInitialize failed");
+        return false;
     }
+
+    IShellLinkW* ps1 = nullptr;
+    IPersistFile* persist_file = nullptr;
+
+    SCOPE_EXIT({
+        if (persist_file != nullptr) {
+            persist_file->Release();
+        }
+        if (ps1 != nullptr) {
+            ps1->Release();
+        }
+
+        CoUninitialize();
+    });
+
+    HRESULT hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLinkW,
+                                    (void**)&ps1);
+
+    if (SUCCEEDED(hres)) {
+        hres = ps1->SetPath(Common::UTF8ToUTF16W(command.string()).data());
+    } else {
+        LOG_ERROR(Frontend, "Failed to create CoCreateInstance");
+        return false;
+    }
+    if (SUCCEEDED(hres) && !arguments.empty()) {
+        hres = ps1->SetArguments(Common::UTF8ToUTF16W(arguments).data());
+    }
+    if (SUCCEEDED(hres) && !comment.empty()) {
+        hres = ps1->SetDescription(Common::UTF8ToUTF16W(comment).data());
+    }
+    if (SUCCEEDED(hres) && std::filesystem::is_regular_file(icon_path)) {
+        hres = ps1->SetIconLocation(Common::UTF8ToUTF16W(icon_path.string()).data(), 0);
+    }
+    if (SUCCEEDED(hres)) {
+        hres = ps1->QueryInterface(IID_IPersistFile, (void**)&persist_file);
+    }
+    if (SUCCEEDED(hres) && persist_file != nullptr) {
+        hres = persist_file->Save(
+            Common::UTF8ToUTF16W((shortcut_path_full).string() + ".lnk").data(), TRUE);
+    }
+    if (SUCCEEDED(hres)) {
+        return true;
+    }
+    LOG_ERROR(Frontend, "Failed to create shortcut");
     return false;
 #else                 // Unsupported platform
     return false;
 #endif
+} catch (const std::exception& e) {
+    LOG_ERROR(Frontend, "Failed to create shortcut: {}", e.what());
+    return false;
 }
 
 // Messages in pre-defined message boxes for less code spaghetti
 bool GMainWindow::CreateShortcutMessagesGUI(QWidget* parent, int imsg, const QString& game_title) {
-    QMessageBox::StandardButtons buttons;
-
     int result = 0;
+    QMessageBox::StandardButtons buttons;
     switch (imsg) {
     case GMainWindow::CREATE_SHORTCUT_MSGBOX_FULLSCREEN_YES:
         buttons = QMessageBox::Yes | QMessageBox::No;
         result =
             QMessageBox::information(parent, tr("Create Shortcut"),
                                      tr("Do you want to launch the game in fullscreen?"), buttons);
-        return (result == QMessageBox::Yes);
+        return result == QMessageBox::Yes;
     case GMainWindow::CREATE_SHORTCUT_MSGBOX_SUCCESS:
         QMessageBox::information(parent, tr("Create Shortcut"),
                                  tr("Successfully created a shortcut to %1").arg(game_title));
-        break;
+        return false;
     case GMainWindow::CREATE_SHORTCUT_MSGBOX_APPVOLATILE_WARNING:
         buttons = QMessageBox::StandardButton::Ok | QMessageBox::StandardButton::Cancel;
         result =
@@ -3015,20 +2990,19 @@ bool GMainWindow::CreateShortcutMessagesGUI(QWidget* parent, int imsg, const QSt
                                  tr("This will create a shortcut to the current AppImage. This may "
                                     "not work well if you update. Continue?"),
                                  buttons);
-        return (result == QMessageBox::Ok);
+        return result == QMessageBox::Ok;
     case GMainWindow::CREATE_SHORTCUT_MSGBOX_ADMIN:
         buttons = QMessageBox::Ok;
         QMessageBox::critical(parent, tr("Create Shortcut"),
                               tr("Cannot create shortcut in Apps. Restart yuzu as administrator."),
                               buttons);
-        break;
+        return false;
     default:
         buttons = QMessageBox::Ok;
         QMessageBox::critical(parent, tr("Create Shortcut"),
                               tr("Failed to create a shortcut to %1").arg(game_title), buttons);
-        break;
+        return false;
     }
-    return false;
 }
 
 bool GMainWindow::MakeShortcutIcoPath(const u64 program_id, const std::string_view game_file_name,

From fc4b45ebd344a3e3d571b8516e73cd9afe824a9b Mon Sep 17 00:00:00 2001
From: boludoz <francomaro@gmail.com>
Date: Mon, 16 Oct 2023 23:50:09 -0300
Subject: [PATCH 13/24] Moved check.

---
 src/yuzu/main.cpp | 14 ++++++++------
 1 file changed, 8 insertions(+), 6 deletions(-)

diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index 75fbd042ae..0e0d7ef0eb 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -2847,6 +2847,13 @@ bool GMainWindow::CreateShortcutLink(const std::filesystem::path& shortcut_path,
                                      const std::string& arguments, const std::string& categories,
                                      const std::string& keywords, const std::string& name) try {
 
+#if defined(__linux__) || defined(__FreeBSD__) || defined(_WIN32) // Linux, FreeBSD and Windows
+    // Plus 'name' is required
+    if (name.empty()) {
+        LOG_ERROR(Frontend, "Name is empty");
+        return false;
+    }
+
     // Copy characters if they are not illegal in Windows filenames
     std::string filename = "";
     const std::string illegal_chars = "<>:\"/\\|?*";
@@ -2865,17 +2872,12 @@ bool GMainWindow::CreateShortcutLink(const std::filesystem::path& shortcut_path,
     }
 
     std::filesystem::path shortcut_path_full = shortcut_path / filename;
+#endif
 
 #if defined(__linux__) || defined(__FreeBSD__) // Linux and FreeBSD
     // Reference for the desktop file template:
     // https://specifications.freedesktop.org/desktop-entry-spec/desktop-entry-spec-1.0.html
 
-    // Plus 'Type' is required
-    if (name.empty()) {
-        LOG_ERROR(Frontend, "Name is empty");
-        return false;
-    }
-
     // Append .desktop extension
     shortcut_path_full += ".desktop";
 

From 9908434c14d68faa7fde933258aafd7da15b3b3b Mon Sep 17 00:00:00 2001
From: boludoz <francomaro@gmail.com>
Date: Tue, 17 Oct 2023 02:57:35 -0300
Subject: [PATCH 14/24] Final refactorization

---
 src/yuzu/main.cpp | 131 ++++++++++++++++------------------------------
 1 file changed, 45 insertions(+), 86 deletions(-)

diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index 0e0d7ef0eb..01b64e1654 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -2846,48 +2846,13 @@ bool GMainWindow::CreateShortcutLink(const std::filesystem::path& shortcut_path,
                                      const std::filesystem::path& command,
                                      const std::string& arguments, const std::string& categories,
                                      const std::string& keywords, const std::string& name) try {
-
-#if defined(__linux__) || defined(__FreeBSD__) || defined(_WIN32) // Linux, FreeBSD and Windows
-    // Plus 'name' is required
-    if (name.empty()) {
-        LOG_ERROR(Frontend, "Name is empty");
-        return false;
-    }
-
-    // Copy characters if they are not illegal in Windows filenames
-    std::string filename = "";
-    const std::string illegal_chars = "<>:\"/\\|?*";
-    filename.reserve(name.size());
-    std::copy_if(name.begin(), name.end(), std::back_inserter(filename),
-                 [&illegal_chars](char c) { return illegal_chars.find(c) == std::string::npos; });
-
-    if (filename.empty()) {
-        LOG_ERROR(Frontend, "Filename is empty");
-        return false;
-    }
-
-    if (!std::filesystem::is_regular_file(command)) {
-        LOG_ERROR(Frontend, "Command is not a regular file");
-        return false;
-    }
-
-    std::filesystem::path shortcut_path_full = shortcut_path / filename;
-#endif
-
 #if defined(__linux__) || defined(__FreeBSD__) // Linux and FreeBSD
-    // Reference for the desktop file template:
-    // https://specifications.freedesktop.org/desktop-entry-spec/desktop-entry-spec-1.0.html
-
-    // Append .desktop extension
-    shortcut_path_full += ".desktop";
-
-    // Create shortcut file
+    std::filesystem::path shortcut_path_full = shortcut_path / (name + ".desktop");
     std::ofstream shortcut_stream(shortcut_path_full, std::ios::binary | std::ios::trunc);
     if (!shortcut_stream.is_open()) {
         LOG_ERROR(Frontend, "Failed to create shortcut");
         return false;
     }
-
     fmt::print(shortcut_stream, "[Desktop Entry]\n");
     fmt::print(shortcut_stream, "Type=Application\n");
     fmt::print(shortcut_stream, "Version=1.0\n");
@@ -2899,11 +2864,7 @@ bool GMainWindow::CreateShortcutLink(const std::filesystem::path& shortcut_path,
         fmt::print(shortcut_stream, "Icon={}\n", icon_path.string());
     }
     fmt::print(shortcut_stream, "TryExec={}\n", command.string());
-    fmt::print(shortcut_stream, "Exec={}", command.string());
-    if (!arguments.empty()) {
-        fmt::print(shortcut_stream, " {}", arguments);
-    }
-    fmt::print(shortcut_stream, "\n");
+    fmt::print(shortcut_stream, "Exec={} {}\n", command.string(), arguments);
     if (!categories.empty()) {
         fmt::print(shortcut_stream, "Categories={}\n", categories);
     }
@@ -2912,15 +2873,14 @@ bool GMainWindow::CreateShortcutLink(const std::filesystem::path& shortcut_path,
     }
     return true;
 #elif defined(_WIN32) // Windows
-    HRESULT hr = CoInitialize(NULL);
+    HRESULT hr = CoInitialize(nullptr);
     if (FAILED(hr)) {
         LOG_ERROR(Frontend, "CoInitialize failed");
         return false;
     }
-
+    SCOPE_EXIT({ CoUninitialize(); });
     IShellLinkW* ps1 = nullptr;
     IPersistFile* persist_file = nullptr;
-
     SCOPE_EXIT({
         if (persist_file != nullptr) {
             persist_file->Release();
@@ -2928,40 +2888,50 @@ bool GMainWindow::CreateShortcutLink(const std::filesystem::path& shortcut_path,
         if (ps1 != nullptr) {
             ps1->Release();
         }
-
-        CoUninitialize();
     });
-
-    HRESULT hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLinkW,
-                                    (void**)&ps1);
-
-    if (SUCCEEDED(hres)) {
-        hres = ps1->SetPath(Common::UTF8ToUTF16W(command.string()).data());
-    } else {
-        LOG_ERROR(Frontend, "Failed to create CoCreateInstance");
+    HRESULT hres = CoCreateInstance(CLSID_ShellLink, nullptr, CLSCTX_INPROC_SERVER, IID_IShellLinkW,
+                                    reinterpret_cast<void**>(&ps1));
+    if (FAILED(hres)) {
+        LOG_ERROR(Frontend, "Failed to create IShellLinkW instance");
         return false;
     }
-    if (SUCCEEDED(hres) && !arguments.empty()) {
+    hres = ps1->SetPath(command.c_str());
+    if (FAILED(hres)) {
+        LOG_ERROR(Frontend, "Failed to set path");
+        return false;
+    }
+    if (!arguments.empty()) {
         hres = ps1->SetArguments(Common::UTF8ToUTF16W(arguments).data());
+        if (FAILED(hres)) {
+            LOG_ERROR(Frontend, "Failed to set arguments");
+            return false;
+        }
     }
-    if (SUCCEEDED(hres) && !comment.empty()) {
+    if (!comment.empty()) {
         hres = ps1->SetDescription(Common::UTF8ToUTF16W(comment).data());
+        if (FAILED(hres)) {
+            LOG_ERROR(Frontend, "Failed to set description");
+            return false;
+        }
     }
-    if (SUCCEEDED(hres) && std::filesystem::is_regular_file(icon_path)) {
-        hres = ps1->SetIconLocation(Common::UTF8ToUTF16W(icon_path.string()).data(), 0);
+    if (std::filesystem::is_regular_file(icon_path)) {
+        hres = ps1->SetIconLocation(icon_path.c_str(), 0);
+        if (FAILED(hres)) {
+            LOG_ERROR(Frontend, "Failed to set icon location");
+            return false;
+        }
     }
-    if (SUCCEEDED(hres)) {
-        hres = ps1->QueryInterface(IID_IPersistFile, (void**)&persist_file);
+    hres = ps1->QueryInterface(IID_IPersistFile, reinterpret_cast<void**>(&persist_file));
+    if (FAILED(hres)) {
+        LOG_ERROR(Frontend, "Failed to get IPersistFile interface");
+        return false;
     }
-    if (SUCCEEDED(hres) && persist_file != nullptr) {
-        hres = persist_file->Save(
-            Common::UTF8ToUTF16W((shortcut_path_full).string() + ".lnk").data(), TRUE);
+    hres = persist_file->Save(std::filesystem::path{shortcut_path / (name + ".lnk")}.c_str(), TRUE);
+    if (FAILED(hres)) {
+        LOG_ERROR(Frontend, "Failed to save shortcut");
+        return false;
     }
-    if (SUCCEEDED(hres)) {
-        return true;
-    }
-    LOG_ERROR(Frontend, "Failed to create shortcut");
-    return false;
+    return true;
 #else                 // Unsupported platform
     return false;
 #endif
@@ -2969,7 +2939,6 @@ bool GMainWindow::CreateShortcutLink(const std::filesystem::path& shortcut_path,
     LOG_ERROR(Frontend, "Failed to create shortcut: {}", e.what());
     return false;
 }
-
 // Messages in pre-defined message boxes for less code spaghetti
 bool GMainWindow::CreateShortcutMessagesGUI(QWidget* parent, int imsg, const QString& game_title) {
     int result = 0;
@@ -3009,7 +2978,6 @@ bool GMainWindow::CreateShortcutMessagesGUI(QWidget* parent, int imsg, const QSt
 
 bool GMainWindow::MakeShortcutIcoPath(const u64 program_id, const std::string_view game_file_name,
                                       std::filesystem::path& out_icon_path) {
-
     // Get path to Yuzu icons directory & icon extension
     std::string ico_extension = "png";
 #if defined(_WIN32)
@@ -3038,20 +3006,16 @@ bool GMainWindow::MakeShortcutIcoPath(const u64 program_id, const std::string_vi
 
 void GMainWindow::OnGameListCreateShortcut(u64 program_id, const std::string& game_path,
                                            GameListShortcutTarget target) {
-
     std::string game_title;
     QString qt_game_title;
     std::filesystem::path out_icon_path;
-
     // Get path to yuzu executable
     const QStringList args = QApplication::arguments();
     std::filesystem::path yuzu_command = args[0].toStdString();
-
     // If relative path, make it an absolute path
     if (yuzu_command.c_str()[0] == '.') {
         yuzu_command = Common::FS::GetCurrentDir() / yuzu_command;
     }
-
     // Shortcut path
     std::filesystem::path shortcut_path{};
     if (target == GameListShortcutTarget::Desktop) {
@@ -3061,7 +3025,6 @@ void GMainWindow::OnGameListCreateShortcut(u64 program_id, const std::string& ga
         shortcut_path =
             QStandardPaths::writableLocation(QStandardPaths::ApplicationsLocation).toStdString();
     }
-
     // Icon path and title
     if (std::filesystem::exists(shortcut_path)) {
         // Get title from game file
@@ -3070,17 +3033,20 @@ void GMainWindow::OnGameListCreateShortcut(u64 program_id, const std::string& ga
         const auto control = pm.GetControlMetadata();
         const auto loader =
             Loader::GetLoader(*system, vfs->OpenFile(game_path, FileSys::Mode::Read));
-
         game_title = fmt::format("{:016X}", program_id);
-
         if (control.first != nullptr) {
             game_title = control.first->GetApplicationName();
         } else {
             loader->ReadTitle(game_title);
         }
-
+        // Delete illegal characters from title
+        const std::string illegal_chars = "<>:\"/\\|?*.";
+        for (auto it = game_title.rbegin(); it != game_title.rend(); ++it) {
+            if (illegal_chars.find(*it) != std::string::npos) {
+                game_title.erase(it.base() - 1);
+            }
+        }
         qt_game_title = QString::fromStdString(game_title);
-
         // Get icon from game file
         std::vector<u8> icon_image_file{};
         if (control.second != nullptr) {
@@ -3088,23 +3054,19 @@ void GMainWindow::OnGameListCreateShortcut(u64 program_id, const std::string& ga
         } else if (loader->ReadIcon(icon_image_file) != Loader::ResultStatus::Success) {
             LOG_WARNING(Frontend, "Could not read icon from {:s}", game_path);
         }
-
         QImage icon_data =
             QImage::fromData(icon_image_file.data(), static_cast<int>(icon_image_file.size()));
-
         if (GMainWindow::MakeShortcutIcoPath(program_id, game_title, out_icon_path)) {
             if (!SaveIconToFile(out_icon_path, icon_data)) {
                 LOG_ERROR(Frontend, "Could not write icon to file");
             }
         }
-
     } else {
         GMainWindow::CreateShortcutMessagesGUI(this, GMainWindow::CREATE_SHORTCUT_MSGBOX_ERROR,
                                                qt_game_title);
         LOG_ERROR(Frontend, "Invalid shortcut target");
         return;
     }
-
 #if defined(_WIN32)
     if (!IsUserAnAdmin() && target == GameListShortcutTarget::Applications) {
         GMainWindow::CreateShortcutMessagesGUI(this, GMainWindow::CREATE_SHORTCUT_MSGBOX_ADMIN,
@@ -3125,7 +3087,6 @@ void GMainWindow::OnGameListCreateShortcut(u64 program_id, const std::string& ga
         UISettings::values.shortcut_already_warned = true;
     }
 #endif // __linux__
-
     // Create shortcut
     std::string arguments = fmt::format("-g \"{:s}\"", game_path);
     if (GMainWindow::CreateShortcutMessagesGUI(
@@ -3142,7 +3103,6 @@ void GMainWindow::OnGameListCreateShortcut(u64 program_id, const std::string& ga
                                                qt_game_title);
         return;
     }
-
     GMainWindow::CreateShortcutMessagesGUI(this, GMainWindow::CREATE_SHORTCUT_MSGBOX_ERROR,
                                            qt_game_title);
 }
@@ -4177,7 +4137,6 @@ void GMainWindow::OnLoadAmiibo() {
 bool GMainWindow::question(QWidget* parent, const QString& title, const QString& text,
                            QMessageBox::StandardButtons buttons,
                            QMessageBox::StandardButton defaultButton) {
-
     QMessageBox* box_dialog = new QMessageBox(parent);
     box_dialog->setWindowTitle(title);
     box_dialog->setText(text);

From 2a7edda70ac7bfcce6a830c814a6b8cd559b8c03 Mon Sep 17 00:00:00 2001
From: boludoz <francomaro@gmail.com>
Date: Wed, 18 Oct 2023 01:20:46 -0300
Subject: [PATCH 15/24] Deleted admin requisite (maybe it was another mistake).

---
 src/yuzu/main.cpp | 8 +-------
 1 file changed, 1 insertion(+), 7 deletions(-)

diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index 01b64e1654..37f1c0bc4d 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -3067,13 +3067,7 @@ void GMainWindow::OnGameListCreateShortcut(u64 program_id, const std::string& ga
         LOG_ERROR(Frontend, "Invalid shortcut target");
         return;
     }
-#if defined(_WIN32)
-    if (!IsUserAnAdmin() && target == GameListShortcutTarget::Applications) {
-        GMainWindow::CreateShortcutMessagesGUI(this, GMainWindow::CREATE_SHORTCUT_MSGBOX_ADMIN,
-                                               qt_game_title);
-        return;
-    }
-#elif defined(__linux__)
+#if defined(__linux__)
     // Special case for AppImages
     // Warn once if we are making a shortcut to a volatile AppImage
     const std::string appimage_ending =

From 4051bbbed7f0160a6565212affbbb24553a9b510 Mon Sep 17 00:00:00 2001
From: boludoz <francomaro@gmail.com>
Date: Wed, 18 Oct 2023 01:26:50 -0300
Subject: [PATCH 16/24] Useless code removed related to admin privileges, if it
 is not an error we can add it later, that is what git is for.

---
 src/yuzu/main.cpp | 6 ------
 src/yuzu/main.h   | 1 -
 2 files changed, 7 deletions(-)

diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index 37f1c0bc4d..73cd064782 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -2962,12 +2962,6 @@ bool GMainWindow::CreateShortcutMessagesGUI(QWidget* parent, int imsg, const QSt
                                     "not work well if you update. Continue?"),
                                  buttons);
         return result == QMessageBox::Ok;
-    case GMainWindow::CREATE_SHORTCUT_MSGBOX_ADMIN:
-        buttons = QMessageBox::Ok;
-        QMessageBox::critical(parent, tr("Create Shortcut"),
-                              tr("Cannot create shortcut in Apps. Restart yuzu as administrator."),
-                              buttons);
-        return false;
     default:
         buttons = QMessageBox::Ok;
         QMessageBox::critical(parent, tr("Create Shortcut"),
diff --git a/src/yuzu/main.h b/src/yuzu/main.h
index 41902cc8da..d203e5301c 100644
--- a/src/yuzu/main.h
+++ b/src/yuzu/main.h
@@ -157,7 +157,6 @@ class GMainWindow : public QMainWindow {
         CREATE_SHORTCUT_MSGBOX_SUCCESS,
         CREATE_SHORTCUT_MSGBOX_ERROR,
         CREATE_SHORTCUT_MSGBOX_APPVOLATILE_WARNING,
-        CREATE_SHORTCUT_MSGBOX_ADMIN,
     };
 
 public:

From ac6290bea76e9719ef7806dab7f92ab53fdd27d0 Mon Sep 17 00:00:00 2001
From: boludoz <francomaro@gmail.com>
Date: Wed, 18 Oct 2023 02:35:23 -0300
Subject: [PATCH 17/24] TODO: Implement shortcut creation for Apple.

---
 src/yuzu/game_list.cpp | 6 ++++++
 src/yuzu/main.cpp      | 8 ++++++--
 src/yuzu/main.h        | 3 +++
 3 files changed, 15 insertions(+), 2 deletions(-)

diff --git a/src/yuzu/game_list.cpp b/src/yuzu/game_list.cpp
index fbe0996612..90433e2454 100644
--- a/src/yuzu/game_list.cpp
+++ b/src/yuzu/game_list.cpp
@@ -564,10 +564,13 @@ void GameList::AddGamePopup(QMenu& context_menu, u64 program_id, const std::stri
     QAction* verify_integrity = context_menu.addAction(tr("Verify Integrity"));
     QAction* copy_tid = context_menu.addAction(tr("Copy Title ID to Clipboard"));
     QAction* navigate_to_gamedb_entry = context_menu.addAction(tr("Navigate to GameDB entry"));
+// TODO: Implement shortcut creation for macOS
+#if !defined(__APPLE__)
     QMenu* shortcut_menu = context_menu.addMenu(tr("Create Shortcut"));
     QAction* create_desktop_shortcut = shortcut_menu->addAction(tr("Add to Desktop"));
     QAction* create_applications_menu_shortcut =
         shortcut_menu->addAction(tr("Add to Applications Menu"));
+#endif
     context_menu.addSeparator();
     QAction* properties = context_menu.addAction(tr("Properties"));
 
@@ -642,12 +645,15 @@ void GameList::AddGamePopup(QMenu& context_menu, u64 program_id, const std::stri
     connect(navigate_to_gamedb_entry, &QAction::triggered, [this, program_id]() {
         emit NavigateToGamedbEntryRequested(program_id, compatibility_list);
     });
+// TODO: Implement shortcut creation for macOS
+#if !defined(__APPLE__)
     connect(create_desktop_shortcut, &QAction::triggered, [this, program_id, path]() {
         emit CreateShortcut(program_id, path, GameListShortcutTarget::Desktop);
     });
     connect(create_applications_menu_shortcut, &QAction::triggered, [this, program_id, path]() {
         emit CreateShortcut(program_id, path, GameListShortcutTarget::Applications);
     });
+#endif
     connect(properties, &QAction::triggered,
             [this, path]() { emit OpenPerGameGeneralRequested(path); });
 };
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index 73cd064782..ec3eb7536b 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -2839,7 +2839,8 @@ void GMainWindow::OnGameListNavigateToGamedbEntry(u64 program_id,
 
     QDesktopServices::openUrl(QUrl(QStringLiteral("https://yuzu-emu.org/game/") + directory));
 }
-
+// TODO: Implement shortcut creation for macOS
+#if !defined(__APPLE__)
 bool GMainWindow::CreateShortcutLink(const std::filesystem::path& shortcut_path,
                                      const std::string& comment,
                                      const std::filesystem::path& icon_path,
@@ -2997,9 +2998,11 @@ bool GMainWindow::MakeShortcutIcoPath(const u64 program_id, const std::string_vi
                                       : fmt::format("yuzu-{:016X}.{}", program_id, ico_extension));
     return true;
 }
-
+#endif // !defined(__APPLE__)
 void GMainWindow::OnGameListCreateShortcut(u64 program_id, const std::string& game_path,
                                            GameListShortcutTarget target) {
+// TODO: Implement shortcut creation for macOS
+#if !defined(__APPLE__)
     std::string game_title;
     QString qt_game_title;
     std::filesystem::path out_icon_path;
@@ -3093,6 +3096,7 @@ void GMainWindow::OnGameListCreateShortcut(u64 program_id, const std::string& ga
     }
     GMainWindow::CreateShortcutMessagesGUI(this, GMainWindow::CREATE_SHORTCUT_MSGBOX_ERROR,
                                            qt_game_title);
+#endif
 }
 
 void GMainWindow::OnGameListOpenDirectory(const QString& directory) {
diff --git a/src/yuzu/main.h b/src/yuzu/main.h
index d203e5301c..7a1a97f33a 100644
--- a/src/yuzu/main.h
+++ b/src/yuzu/main.h
@@ -441,6 +441,8 @@ private:
     bool ConfirmShutdownGame();
 
     QString GetTasStateDescription() const;
+// TODO: Implement shortcut creation for macOS
+#if !defined(__APPLE__)
     bool CreateShortcutMessagesGUI(QWidget* parent, int imsg, const QString& game_title);
     bool MakeShortcutIcoPath(const u64 program_id, const std::string_view game_file_name,
                              std::filesystem::path& out_icon_path);
@@ -449,6 +451,7 @@ private:
                             const std::filesystem::path& command, const std::string& arguments,
                             const std::string& categories, const std::string& keywords,
                             const std::string& name);
+#endif
     /**
      * Mimic the behavior of QMessageBox::question but link controller navigation to the dialog
      * The only difference is that it returns a boolean.

From ae2130470effa72c3ea1ffc045e9b6b2a77b23d3 Mon Sep 17 00:00:00 2001
From: boludoz <francomaro@gmail.com>
Date: Wed, 18 Oct 2023 19:30:21 -0300
Subject: [PATCH 18/24] Reverted dirty code in main.

---
 src/yuzu/main.cpp | 8 ++------
 src/yuzu/main.h   | 3 ---
 2 files changed, 2 insertions(+), 9 deletions(-)

diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index ec3eb7536b..73cd064782 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -2839,8 +2839,7 @@ void GMainWindow::OnGameListNavigateToGamedbEntry(u64 program_id,
 
     QDesktopServices::openUrl(QUrl(QStringLiteral("https://yuzu-emu.org/game/") + directory));
 }
-// TODO: Implement shortcut creation for macOS
-#if !defined(__APPLE__)
+
 bool GMainWindow::CreateShortcutLink(const std::filesystem::path& shortcut_path,
                                      const std::string& comment,
                                      const std::filesystem::path& icon_path,
@@ -2998,11 +2997,9 @@ bool GMainWindow::MakeShortcutIcoPath(const u64 program_id, const std::string_vi
                                       : fmt::format("yuzu-{:016X}.{}", program_id, ico_extension));
     return true;
 }
-#endif // !defined(__APPLE__)
+
 void GMainWindow::OnGameListCreateShortcut(u64 program_id, const std::string& game_path,
                                            GameListShortcutTarget target) {
-// TODO: Implement shortcut creation for macOS
-#if !defined(__APPLE__)
     std::string game_title;
     QString qt_game_title;
     std::filesystem::path out_icon_path;
@@ -3096,7 +3093,6 @@ void GMainWindow::OnGameListCreateShortcut(u64 program_id, const std::string& ga
     }
     GMainWindow::CreateShortcutMessagesGUI(this, GMainWindow::CREATE_SHORTCUT_MSGBOX_ERROR,
                                            qt_game_title);
-#endif
 }
 
 void GMainWindow::OnGameListOpenDirectory(const QString& directory) {
diff --git a/src/yuzu/main.h b/src/yuzu/main.h
index 7a1a97f33a..d203e5301c 100644
--- a/src/yuzu/main.h
+++ b/src/yuzu/main.h
@@ -441,8 +441,6 @@ private:
     bool ConfirmShutdownGame();
 
     QString GetTasStateDescription() const;
-// TODO: Implement shortcut creation for macOS
-#if !defined(__APPLE__)
     bool CreateShortcutMessagesGUI(QWidget* parent, int imsg, const QString& game_title);
     bool MakeShortcutIcoPath(const u64 program_id, const std::string_view game_file_name,
                              std::filesystem::path& out_icon_path);
@@ -451,7 +449,6 @@ private:
                             const std::filesystem::path& command, const std::string& arguments,
                             const std::string& categories, const std::string& keywords,
                             const std::string& name);
-#endif
     /**
      * Mimic the behavior of QMessageBox::question but link controller navigation to the dialog
      * The only difference is that it returns a boolean.

From 7f62a48ab507d3874378c10944662d5b841c6c2e Mon Sep 17 00:00:00 2001
From: boludoz <francomaro@gmail.com>
Date: Fri, 27 Oct 2023 00:30:35 -0300
Subject: [PATCH 19/24] We dont need that

---
 src/common/fs/path_util.cpp | 34 +++++++++++++++++++---------------
 1 file changed, 19 insertions(+), 15 deletions(-)

diff --git a/src/common/fs/path_util.cpp b/src/common/fs/path_util.cpp
index 732c1559fa..0abd81a45e 100644
--- a/src/common/fs/path_util.cpp
+++ b/src/common/fs/path_util.cpp
@@ -6,7 +6,6 @@
 #include <unordered_map>
 
 #include "common/fs/fs.h"
-#include "common/string_util.h"
 #ifdef ANDROID
 #include "common/fs/fs_android.h"
 #endif
@@ -15,7 +14,7 @@
 #include "common/logging/log.h"
 
 #ifdef _WIN32
-#include <shlobj.h> // Used in GetExeDirectory() and GetWindowsDesktop()
+#include <shlobj.h> // Used in GetExeDirectory()
 #else
 #include <cstdlib>     // Used in Get(Home/Data)Directory()
 #include <pwd.h>       // Used in GetHomeDirectory()
@@ -251,25 +250,30 @@ void SetYuzuPath(YuzuPath yuzu_path, const fs::path& new_path) {
 #ifdef _WIN32
 
 fs::path GetExeDirectory() {
-    WCHAR exe_path[MAX_PATH];
-    if (SUCCEEDED(GetModuleFileNameW(nullptr, exe_path, MAX_PATH))) {
-        std::wstring wide_exe_path(exe_path);
-        return fs::path{Common::UTF16ToUTF8(wide_exe_path)}.parent_path();
+    wchar_t exe_path[MAX_PATH];
+
+    if (GetModuleFileNameW(nullptr, exe_path, MAX_PATH) == 0) {
+        LOG_ERROR(Common_Filesystem,
+                  "Failed to get the path to the executable of the current process");
     }
-    LOG_ERROR(Common_Filesystem, "Failed to get the path to the executable of the current "
-                                 "process");
-    return fs::path{};
+
+    return fs::path{exe_path}.parent_path();
 }
 
 fs::path GetAppDataRoamingDirectory() {
     PWSTR appdata_roaming_path = nullptr;
-    if (SUCCEEDED(SHGetKnownFolderPath(FOLDERID_RoamingAppData, 0, NULL, &appdata_roaming_path))) {
-        std::wstring wide_appdata_roaming_path(appdata_roaming_path);
-        CoTaskMemFree(appdata_roaming_path);
-        return fs::path{Common::UTF16ToUTF8(wide_appdata_roaming_path)};
+
+    SHGetKnownFolderPath(FOLDERID_RoamingAppData, 0, nullptr, &appdata_roaming_path);
+
+    auto fs_appdata_roaming_path = fs::path{appdata_roaming_path};
+
+    CoTaskMemFree(appdata_roaming_path);
+
+    if (fs_appdata_roaming_path.empty()) {
+        LOG_ERROR(Common_Filesystem, "Failed to get the path to the %APPDATA% directory");
     }
-    LOG_ERROR(Common_Filesystem, "Failed to get the path to the %APPDATA% directory");
-    return fs::path{};
+
+    return fs_appdata_roaming_path;
 }
 
 #else

From 4b8b223db2ed0f79ce81083128fe8085786877cc Mon Sep 17 00:00:00 2001
From: Franco M <francomaro@gmail.com>
Date: Sun, 5 Nov 2023 00:39:43 +0000
Subject: [PATCH 20/24] 	modified:   src/yuzu/main.cpp

---
 src/yuzu/main.cpp | 73 +++++------------------------------------------
 1 file changed, 7 insertions(+), 66 deletions(-)

diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index c8efd19178..6b6feb1e6c 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -8,6 +8,7 @@
 #include <iostream>
 #include <memory>
 #include <thread>
+#include <format>
 #include "core/loader/nca.h"
 #include "core/tools/renderdoc.h"
 #ifdef __APPLE__
@@ -2856,6 +2857,7 @@ bool GMainWindow::CreateShortcutLink(const std::filesystem::path& shortcut_path,
         LOG_ERROR(Frontend, "Failed to create shortcut");
         return false;
     }
+    // TODO: Migrate fmt::print to std::print in futures STD C++ 23.
     fmt::print(shortcut_stream, "[Desktop Entry]\n");
     fmt::print(shortcut_stream, "Type=Application\n");
     fmt::print(shortcut_stream, "Version=1.0\n");
@@ -2983,7 +2985,6 @@ bool GMainWindow::MakeShortcutIcoPath(const u64 program_id, const std::string_vi
 #elif defined(__linux__) || defined(__FreeBSD__)
     out_icon_path = Common::FS::GetDataDirectory("XDG_DATA_HOME") / "icons/hicolor/256x256";
 #endif
-  
     // Create icons directory if it doesn't exist
     if (!Common::FS::CreateDirs(out_icon_path)) {
         QMessageBox::critical(
@@ -2996,8 +2997,8 @@ bool GMainWindow::MakeShortcutIcoPath(const u64 program_id, const std::string_vi
     }
 
     // Create icon file path
-    out_icon_path /= (program_id == 0 ? fmt::format("yuzu-{}.{}", game_file_name, ico_extension)
-                                      : fmt::format("yuzu-{:016X}.{}", program_id, ico_extension));
+    out_icon_path /= (program_id == 0 ? std::format("yuzu-{}.{}", game_file_name, ico_extension)
+                                      : std::format("yuzu-{:016X}.{}", program_id, ico_extension));
     return true;
 }
 
@@ -3030,7 +3031,7 @@ void GMainWindow::OnGameListCreateShortcut(u64 program_id, const std::string& ga
         const auto control = pm.GetControlMetadata();
         const auto loader =
             Loader::GetLoader(*system, vfs->OpenFile(game_path, FileSys::Mode::Read));
-        game_title = fmt::format("{:016X}", program_id);
+        game_title = std::format("{:016X}", program_id);
         if (control.first != nullptr) {
             game_title = control.first->GetApplicationName();
         } else {
@@ -3079,12 +3080,12 @@ void GMainWindow::OnGameListCreateShortcut(u64 program_id, const std::string& ga
     }
 #endif // __linux__
     // Create shortcut
-    std::string arguments = fmt::format("-g \"{:s}\"", game_path);
+    std::string arguments = std::format("-g \"{:s}\"", game_path);
     if (GMainWindow::CreateShortcutMessagesGUI(
             this, GMainWindow::CREATE_SHORTCUT_MSGBOX_FULLSCREEN_YES, qt_game_title)) {
         arguments = "-f " + arguments;
     }
-    const std::string comment = fmt::format("Start {:s} with the yuzu Emulator", game_title);
+    const std::string comment = std::format("Start {:s} with the yuzu Emulator", game_title);
     const std::string categories = "Game;Emulator;Qt;";
     const std::string keywords = "Switch;Nintendo;";
 
@@ -4090,66 +4091,6 @@ void GMainWindow::OpenPerGameConfiguration(u64 title_id, const std::string& file
     }
 }
 
-bool GMainWindow::CreateShortcut(const std::string& shortcut_path, const std::string& title,
-                                 const std::string& comment, const std::string& icon_path,
-                                 const std::string& command, const std::string& arguments,
-                                 const std::string& categories, const std::string& keywords) {
-#if defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__)
-    // This desktop file template was writing referencing
-    // https://specifications.freedesktop.org/desktop-entry-spec/desktop-entry-spec-1.0.html
-    std::string shortcut_contents{};
-    shortcut_contents.append("[Desktop Entry]\n");
-    shortcut_contents.append("Type=Application\n");
-    shortcut_contents.append("Version=1.0\n");
-    shortcut_contents.append(fmt::format("Name={:s}\n", title));
-    shortcut_contents.append(fmt::format("Comment={:s}\n", comment));
-    shortcut_contents.append(fmt::format("Icon={:s}\n", icon_path));
-    shortcut_contents.append(fmt::format("TryExec={:s}\n", command));
-    shortcut_contents.append(fmt::format("Exec={:s} {:s}\n", command, arguments));
-    shortcut_contents.append(fmt::format("Categories={:s}\n", categories));
-    shortcut_contents.append(fmt::format("Keywords={:s}\n", keywords));
-
-    std::ofstream shortcut_stream(shortcut_path);
-    if (!shortcut_stream.is_open()) {
-        LOG_WARNING(Common, "Failed to create file {:s}", shortcut_path);
-        return false;
-    }
-    shortcut_stream << shortcut_contents;
-    shortcut_stream.close();
-
-    return true;
-#elif defined(WIN32)
-    IShellLinkW* shell_link;
-    auto hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLinkW,
-                                 (void**)&shell_link);
-    if (FAILED(hres)) {
-        return false;
-    }
-    shell_link->SetPath(
-        Common::UTF8ToUTF16W(command).data()); // Path to the object we are referring to
-    shell_link->SetArguments(Common::UTF8ToUTF16W(arguments).data());
-    shell_link->SetDescription(Common::UTF8ToUTF16W(comment).data());
-    shell_link->SetIconLocation(Common::UTF8ToUTF16W(icon_path).data(), 0);
-
-    IPersistFile* persist_file;
-    hres = shell_link->QueryInterface(IID_IPersistFile, (void**)&persist_file);
-    if (FAILED(hres)) {
-        return false;
-    }
-
-    hres = persist_file->Save(Common::UTF8ToUTF16W(shortcut_path).data(), TRUE);
-    if (FAILED(hres)) {
-        return false;
-    }
-
-    persist_file->Release();
-    shell_link->Release();
-
-    return true;
-#endif
-    return false;
-}
-
 void GMainWindow::OnLoadAmiibo() {
     if (emu_thread == nullptr || !emu_thread->IsRunning()) {
         return;

From 8d0d0e1c7a95858dc5eaffe0eb0484815b491d9d Mon Sep 17 00:00:00 2001
From: Franco M <francomaro@gmail.com>
Date: Tue, 7 Nov 2023 02:32:19 +0000
Subject: [PATCH 21/24] Fixed clang

---
 src/yuzu/main.cpp | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index 6b6feb1e6c..2402ea6f58 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -4,13 +4,14 @@
 #include <cinttypes>
 #include <clocale>
 #include <cmath>
+#include <format>
 #include <fstream>
 #include <iostream>
 #include <memory>
 #include <thread>
-#include <format>
 #include "core/loader/nca.h"
 #include "core/tools/renderdoc.h"
+
 #ifdef __APPLE__
 #include <unistd.h> // for chdir
 #endif
@@ -5331,4 +5332,4 @@ int main(int argc, char* argv[]) {
     int result = app.exec();
     detached_tasks.WaitForAllTasks();
     return result;
-}
+}
\ No newline at end of file

From c7b31d24b979c36e2a9e59e7ae6876ffbc82a81e Mon Sep 17 00:00:00 2001
From: Franco M <francomaro@gmail.com>
Date: Wed, 8 Nov 2023 21:04:30 +0000
Subject: [PATCH 22/24] Final change, i think

---
 src/yuzu/main.cpp | 11 +++++------
 1 file changed, 5 insertions(+), 6 deletions(-)

diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index 2402ea6f58..442408280f 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -4,7 +4,6 @@
 #include <cinttypes>
 #include <clocale>
 #include <cmath>
-#include <format>
 #include <fstream>
 #include <iostream>
 #include <memory>
@@ -2998,8 +2997,8 @@ bool GMainWindow::MakeShortcutIcoPath(const u64 program_id, const std::string_vi
     }
 
     // Create icon file path
-    out_icon_path /= (program_id == 0 ? std::format("yuzu-{}.{}", game_file_name, ico_extension)
-                                      : std::format("yuzu-{:016X}.{}", program_id, ico_extension));
+    out_icon_path /= (program_id == 0 ? fmt::format("yuzu-{}.{}", game_file_name, ico_extension)
+                                      : fmt::format("yuzu-{:016X}.{}", program_id, ico_extension));
     return true;
 }
 
@@ -3032,7 +3031,7 @@ void GMainWindow::OnGameListCreateShortcut(u64 program_id, const std::string& ga
         const auto control = pm.GetControlMetadata();
         const auto loader =
             Loader::GetLoader(*system, vfs->OpenFile(game_path, FileSys::Mode::Read));
-        game_title = std::format("{:016X}", program_id);
+        game_title = fmt::format("{:016X}", program_id);
         if (control.first != nullptr) {
             game_title = control.first->GetApplicationName();
         } else {
@@ -3081,12 +3080,12 @@ void GMainWindow::OnGameListCreateShortcut(u64 program_id, const std::string& ga
     }
 #endif // __linux__
     // Create shortcut
-    std::string arguments = std::format("-g \"{:s}\"", game_path);
+    std::string arguments = fmt::format("-g \"{:s}\"", game_path);
     if (GMainWindow::CreateShortcutMessagesGUI(
             this, GMainWindow::CREATE_SHORTCUT_MSGBOX_FULLSCREEN_YES, qt_game_title)) {
         arguments = "-f " + arguments;
     }
-    const std::string comment = std::format("Start {:s} with the yuzu Emulator", game_title);
+    const std::string comment = fmt::format("Start {:s} with the yuzu Emulator", game_title);
     const std::string categories = "Game;Emulator;Qt;";
     const std::string keywords = "Switch;Nintendo;";
 

From f3053920bf75858b702b13a2d80589a386c397b9 Mon Sep 17 00:00:00 2001
From: Franco M <francomaro@gmail.com>
Date: Thu, 9 Nov 2023 03:37:06 +0000
Subject: [PATCH 23/24] Minor changes

---
 src/yuzu/main.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index 442408280f..a4ad9d8a80 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -2980,7 +2980,7 @@ bool GMainWindow::MakeShortcutIcoPath(const u64 program_id, const std::string_vi
     // Get path to Yuzu icons directory & icon extension
     std::string ico_extension = "png";
 #if defined(_WIN32)
-    out_icon_path = Common::FS::GetYuzuPath(Common::FS::YuzuPath::ConfigDir) / "icons";
+    out_icon_path = Common::FS::YuzuPath::IconsDir;
     ico_extension = "ico";
 #elif defined(__linux__) || defined(__FreeBSD__)
     out_icon_path = Common::FS::GetDataDirectory("XDG_DATA_HOME") / "icons/hicolor/256x256";
@@ -5331,4 +5331,4 @@ int main(int argc, char* argv[]) {
     int result = app.exec();
     detached_tasks.WaitForAllTasks();
     return result;
-}
\ No newline at end of file
+}

From c9038af29e05458bd2f647158cc2903132c4c560 Mon Sep 17 00:00:00 2001
From: Franco M <francomaro@gmail.com>
Date: Thu, 9 Nov 2023 04:53:10 +0000
Subject: [PATCH 24/24] Fix out_icon_path =
 Common::FS::GetYuzuPath(Common::FS::YuzuPath::IconsDir);

---
 src/yuzu/main.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index a4ad9d8a80..e0a656a5ed 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -2980,7 +2980,7 @@ bool GMainWindow::MakeShortcutIcoPath(const u64 program_id, const std::string_vi
     // Get path to Yuzu icons directory & icon extension
     std::string ico_extension = "png";
 #if defined(_WIN32)
-    out_icon_path = Common::FS::YuzuPath::IconsDir;
+    out_icon_path = Common::FS::GetYuzuPath(Common::FS::YuzuPath::IconsDir);
     ico_extension = "ico";
 #elif defined(__linux__) || defined(__FreeBSD__)
     out_icon_path = Common::FS::GetDataDirectory("XDG_DATA_HOME") / "icons/hicolor/256x256";