diff --git a/Source/Core/DolphinQt/Updater.cpp b/Source/Core/DolphinQt/Updater.cpp index 788c5d8c0f..9783642ce0 100644 --- a/Source/Core/DolphinQt/Updater.cpp +++ b/Source/Core/DolphinQt/Updater.cpp @@ -95,6 +95,11 @@ void Updater::OnUpdateAvailable(const NewVersionInformation& info) AutoUpdateChecker::RestartMode::RESTART_AFTER_UPDATE); if (!later) - m_parent->close(); + { + RunOnObject(m_parent, [this] { + m_parent->close(); + return 0; + }); + } } } diff --git a/Source/Core/UICommon/AutoUpdate.cpp b/Source/Core/UICommon/AutoUpdate.cpp index 00256ee174..0cca98b4b2 100644 --- a/Source/Core/UICommon/AutoUpdate.cpp +++ b/Source/Core/UICommon/AutoUpdate.cpp @@ -234,12 +234,16 @@ void AutoUpdateChecker::TriggerUpdate(const AutoUpdateChecker::NewVersionInforma INFO_LOG(COMMON, "Updater command line: %s", command_line.c_str()); #ifdef _WIN32 - STARTUPINFO sinfo = {sizeof(info)}; + STARTUPINFO sinfo = {sizeof(sinfo)}; sinfo.dwFlags = STARTF_FORCEOFFFEEDBACK; // No hourglass cursor after starting the process. PROCESS_INFORMATION pinfo; - if (!CreateProcessW(UTF8ToUTF16(reloc_updater_path).c_str(), - const_cast(UTF8ToUTF16(command_line).c_str()), nullptr, nullptr, - FALSE, 0, nullptr, nullptr, &sinfo, &pinfo)) + if (CreateProcessW(UTF8ToUTF16(reloc_updater_path).c_str(), UTF8ToUTF16(command_line).data(), + nullptr, nullptr, FALSE, 0, nullptr, nullptr, &sinfo, &pinfo)) + { + CloseHandle(pinfo.hThread); + CloseHandle(pinfo.hProcess); + } + else { ERROR_LOG(COMMON, "Could not start updater process: error=%d", GetLastError()); } diff --git a/Source/Core/UpdaterCommon/UpdaterCommon.cpp b/Source/Core/UpdaterCommon/UpdaterCommon.cpp index 01c5149501..89a963609c 100644 --- a/Source/Core/UpdaterCommon/UpdaterCommon.cpp +++ b/Source/Core/UpdaterCommon/UpdaterCommon.cpp @@ -16,6 +16,7 @@ #include "Common/CommonPaths.h" #include "Common/FileUtil.h" #include "Common/HttpRequest.h" +#include "Common/ScopeGuard.h" #include "Common/StringUtil.h" #include "UpdaterCommon/UI.h" @@ -498,7 +499,6 @@ void FatalError(const std::string& message) UI::SetVisible(true); UI::Error(message); - UI::Stop(); } std::optional ParseManifest(const std::string& manifest) @@ -686,6 +686,7 @@ bool RunUpdater(std::vector args) UI::Init(); UI::SetVisible(false); + Common::ScopeGuard ui_guard{[] { UI::Stop(); }}; Options opts = std::move(*maybe_opts); if (opts.log_file) @@ -777,7 +778,5 @@ bool RunUpdater(std::vector args) UI::LaunchApplication(opts.binary_to_restart.value()); } - UI::Stop(); - return true; } diff --git a/Source/Core/WinUpdater/Main.cpp b/Source/Core/WinUpdater/Main.cpp index 0cb09cb966..9196805819 100644 --- a/Source/Core/WinUpdater/Main.cpp +++ b/Source/Core/WinUpdater/Main.cpp @@ -6,6 +6,7 @@ #include #include +#include #include #include @@ -32,6 +33,28 @@ std::vector CommandLineToUtf8Argv(PCWSTR command_line) LocalFree(tokenized); return argv; } + +std::optional GetModuleName(HINSTANCE hInstance) +{ + std::wstring name; + DWORD max_size = 50; // Start with space for 50 characters and grow if needed + name.resize(max_size); + + DWORD size; + while ((size = GetModuleFileNameW(hInstance, name.data(), max_size)) == max_size && + GetLastError() == ERROR_INSUFFICIENT_BUFFER) + { + max_size *= 2; + name.resize(max_size); + } + + if (size == 0) + { + return {}; + } + name.resize(size); + return name; +} }; // namespace int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine, int nCmdShow) @@ -64,15 +87,15 @@ int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine return 1; } - wchar_t path[MAX_PATH]; - if (GetModuleFileName(hInstance, path, sizeof(path)) == 0) + auto path = GetModuleName(hInstance); + if (!path) { MessageBox(nullptr, L"Failed to get updater filename.", L"Error", MB_ICONERROR); return 1; } // Relaunch the updater as administrator - ShellExecuteW(nullptr, L"runas", path, pCmdLine, NULL, SW_SHOW); + ShellExecuteW(nullptr, L"runas", path->c_str(), pCmdLine, NULL, SW_SHOW); return 0; } diff --git a/Source/Core/WinUpdater/WinUI.cpp b/Source/Core/WinUpdater/WinUI.cpp index 7f9a951bef..97f2da459b 100644 --- a/Source/Core/WinUpdater/WinUI.cpp +++ b/Source/Core/WinUpdater/WinUI.cpp @@ -12,7 +12,6 @@ #include #include -#include "Common/Flag.h" #include "Common/StringUtil.h" namespace @@ -23,8 +22,7 @@ HWND total_progressbar_handle = nullptr; HWND current_progressbar_handle = nullptr; ITaskbarList3* taskbar_list = nullptr; -Common::Flag running; -Common::Flag request_stop; +std::thread ui_thread; int GetWindowHeight(HWND hwnd) { @@ -33,6 +31,17 @@ int GetWindowHeight(HWND hwnd) return rect.bottom - rect.top; } + +LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + switch (uMsg) + { + case WM_DESTROY: + PostQuitMessage(0); + return 0; + } + return DefWindowProc(hwnd, uMsg, wParam, lParam); +} }; // namespace constexpr int PROGRESSBAR_FLAGS = WS_VISIBLE | WS_CHILD | PBS_SMOOTH | PBS_SMOOTHREVERSE; @@ -46,7 +55,7 @@ bool InitWindow() InitCommonControls(); WNDCLASS wndcl = {}; - wndcl.lpfnWndProc = DefWindowProcW; + wndcl.lpfnWndProc = WindowProc; wndcl.hbrBackground = GetSysColorBrush(COLOR_MENU); wndcl.lpszClassName = L"UPDATER"; @@ -124,14 +133,6 @@ bool InitWindow() return true; } -void Destroy() -{ - DestroyWindow(window_handle); - DestroyWindow(label_handle); - DestroyWindow(total_progressbar_handle); - DestroyWindow(current_progressbar_handle); -} - void SetTotalMarquee(bool marquee) { SetWindowLong(total_progressbar_handle, GWL_STYLE, @@ -199,49 +200,40 @@ void SetDescription(const std::string& text) void MessageLoop() { - request_stop.Clear(); - running.Set(); - if (!InitWindow()) { - running.Clear(); MessageBox(nullptr, L"Window init failed!", L"", MB_ICONERROR); + // Destroying the parent (if exists) destroys all children windows + if (window_handle) + { + DestroyWindow(window_handle); + window_handle = nullptr; + } + return; } SetTotalMarquee(true); SetCurrentMarquee(true); - while (!request_stop.IsSet()) + MSG msg; + while (GetMessage(&msg, nullptr, 0, 0)) { - MSG msg; - while (PeekMessage(&msg, window_handle, 0, 0, PM_REMOVE)) - { - TranslateMessage(&msg); - DispatchMessage(&msg); - } + TranslateMessage(&msg); + DispatchMessage(&msg); } - - running.Clear(); - - Destroy(); } void Init() { - std::thread thread(MessageLoop); - thread.detach(); + ui_thread = std::thread(MessageLoop); } void Stop() { - if (!running.IsSet()) - return; + if (window_handle) + PostMessage(window_handle, WM_CLOSE, 0, 0); - request_stop.Set(); - - while (running.IsSet()) - { - } + ui_thread.join(); } void LaunchApplication(std::string path) @@ -259,8 +251,11 @@ void Sleep(int sleep) void WaitForPID(u32 pid) { HANDLE parent_handle = OpenProcess(SYNCHRONIZE, FALSE, static_cast(pid)); - WaitForSingleObject(parent_handle, INFINITE); - CloseHandle(parent_handle); + if (parent_handle) + { + WaitForSingleObject(parent_handle, INFINITE); + CloseHandle(parent_handle); + } } void SetVisible(bool visible)