From 6e4c5d780d38ecbea19b74361df7de5e96066ced Mon Sep 17 00:00:00 2001 From: spycrab Date: Wed, 25 Apr 2018 22:38:10 +0200 Subject: [PATCH] Updater: Implement UAC support --- Source/Core/Updater/Main.cpp | 35 +++++++++++++++++++++++++++++++---- 1 file changed, 31 insertions(+), 4 deletions(-) diff --git a/Source/Core/Updater/Main.cpp b/Source/Core/Updater/Main.cpp index d13019b8f6..4a5bcc7003 100644 --- a/Source/Core/Updater/Main.cpp +++ b/Source/Core/Updater/Main.cpp @@ -3,6 +3,7 @@ // Refer to the license.txt file included. #include +#include #include #include @@ -674,11 +675,18 @@ int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine return 1; Options opts = std::move(*maybe_opts); + bool need_admin = false; + if (opts.log_file) { log_fp = _wfopen(UTF8ToUTF16(*opts.log_file).c_str(), L"w"); if (!log_fp) + { log_fp = stderr; + // Failing to create the logfile for writing is a good indicator that we need administrator + // priviliges + need_admin = true; + } else atexit(FlushLog); } @@ -702,8 +710,25 @@ int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine fprintf(log_fp, "Completed! Proceeding with update.\n"); } - std::thread thread(UI::MessageLoop); - thread.detach(); + if (need_admin) + { + if (IsUserAnAdmin()) + { + FatalError("Failed to write to directory despite administrator priviliges."); + return 1; + } + + wchar_t path[MAX_PATH]; + if (GetModuleFileName(hInstance, path, sizeof(path)) == 0) + { + FatalError("Failed to get updater filename."); + return 1; + } + + // Relaunch the updater as administrator + ShellExecuteW(nullptr, L"runas", path, pCmdLine, NULL, SW_SHOW); + return 0; + } UI::SetDescription("Fetching and parsing manifests..."); @@ -754,8 +779,10 @@ int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine if (opts.binary_to_restart) { - ShellExecuteW(nullptr, L"open", UTF8ToUTF16(*opts.binary_to_restart).c_str(), L"", nullptr, - SW_SHOW); + // Hack: Launching the updater over the explorer ensures that admin priviliges are dropped. Why? + // Ask Microsoft. + ShellExecuteW(nullptr, nullptr, L"explorer.exe", UTF8ToUTF16(*opts.binary_to_restart).c_str(), + nullptr, SW_SHOW); } UI::Stop();