summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJMC47 <JMC4789@gmail.com>2022-10-21 13:55:51 -0400
committerGitHub <noreply@github.com>2022-10-21 13:55:51 -0400
commit00e23da6074b5b25a2ff4e4ff040986c07753e94 (patch)
tree2831c77c6a2aabb04c1d53c408df0b20dd6d0efe
parent9222956acdfb6a0526b6fdada4aeaa936de9fcd1 (diff)
parent717c36bc43c2a568b3fff04bd6d3ea2a81c0582d (diff)
Merge pull request #11051 from shuffle2/update-vcredist
WinUpdater: Check OS and VC++ Redist versions
-rw-r--r--CMake/FindPowerShell.cmake4
-rw-r--r--Source/Core/Common/CMakeLists.txt11
-rw-r--r--Source/Core/Common/build_info.txt.in24
-rw-r--r--Source/Core/DolphinLib.vcxproj34
-rw-r--r--Source/Core/MacUpdater/MacUI.mm19
-rw-r--r--Source/Core/UICommon/AutoUpdate.cpp4
-rw-r--r--Source/Core/UpdaterCommon/Platform.h100
-rw-r--r--Source/Core/UpdaterCommon/UpdaterCommon.cpp41
-rw-r--r--Source/Core/WinUpdater/CMakeLists.txt1
-rw-r--r--Source/Core/WinUpdater/Main.cpp8
-rw-r--r--Source/Core/WinUpdater/Platform.cpp187
-rw-r--r--Source/Core/WinUpdater/WinUI.cpp4
-rw-r--r--Source/Core/WinUpdater/WinUpdater.vcxproj6
13 files changed, 435 insertions, 8 deletions
diff --git a/CMake/FindPowerShell.cmake b/CMake/FindPowerShell.cmake
new file mode 100644
index 0000000000..c0e92a269e
--- /dev/null
+++ b/CMake/FindPowerShell.cmake
@@ -0,0 +1,4 @@
+find_program(POWERSHELL_EXE NAMES powershell)
+
+INCLUDE(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(PowerShell DEFAULT_MSG POWERSHELL_EXE)
diff --git a/Source/Core/Common/CMakeLists.txt b/Source/Core/Common/CMakeLists.txt
index 134d38062c..4dc764408d 100644
--- a/Source/Core/Common/CMakeLists.txt
+++ b/Source/Core/Common/CMakeLists.txt
@@ -324,6 +324,17 @@ if(UNIX)
target_link_libraries(traversal_server PRIVATE ${SYSTEMD_LIBRARIES})
endif()
elseif(WIN32)
+ find_package(PowerShell REQUIRED)
+ execute_process(
+ COMMAND ${POWERSHELL_EXE} -Command "[System.Diagnostics.FileVersionInfo]::GetVersionInfo('$ENV{VCToolsRedistDir}vc_redist.x64.exe').ProductVersion"
+ OUTPUT_VARIABLE VC_TOOLS_VERSION
+ OUTPUT_STRIP_TRAILING_WHITESPACE
+ )
+ configure_file(
+ "${CMAKE_CURRENT_SOURCE_DIR}/build_info.txt.in"
+ "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/build_info.txt"
+ )
+
target_link_libraries(common PRIVATE "-INCLUDE:enableCompatPatches")
endif()
diff --git a/Source/Core/Common/build_info.txt.in b/Source/Core/Common/build_info.txt.in
new file mode 100644
index 0000000000..3ae938cfc5
--- /dev/null
+++ b/Source/Core/Common/build_info.txt.in
@@ -0,0 +1,24 @@
+// Indicate the minimum OS version required for the binary to run properly.
+// Updater will fail the update if the user does not meet this requirement.
+OSMinimumVersionWin10=10.0.15063.0
+OSMinimumVersionWin11=10.0.22000.0
+OSMinimumVersionMacOS=10.14
+
+// This is the runtime which was compiled against - providing a way for Updater to detect if update
+// is needed before executing this binary. Note that, annoyingly, the version in environment
+// variables does not match the "real" version. Consider:
+// VersionInfo : File: C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools\VC\Redist\MSVC\14.32.31326\vc_redist.x64.exe
+// InternalName: setup
+// OriginalFilename: VC_redist.x64.exe
+// FileVersion: 14.32.31332.0
+// FileDescription: Microsoft Visual C++ 2015-2022 Redistributable (x64) - 14.32.31332
+// Product: Microsoft Visual C++ 2015-2022 Redistributable (x64) - 14.32.31332
+// ProductVersion: 14.32.31332.0
+// Whereas the environment variables look like:
+// VCToolsInstallDir=C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools\VC\Tools\MSVC\14.33.31629\
+// VCToolsRedistDir=C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools\VC\Redist\MSVC\14.32.31326\
+// VCToolsVersion=14.33.31629
+// We're really looking for "14.32.31332.0" (because that's what will appear in the registry once
+// installed), NOT the other values!
+VCToolsVersion=${VC_TOOLS_VERSION}
+VCToolsUpdateURL=https://aka.ms/vs/17/release/vc_redist.x64.exe
diff --git a/Source/Core/DolphinLib.vcxproj b/Source/Core/DolphinLib.vcxproj
index ae19db8c19..1aad7a65c3 100644
--- a/Source/Core/DolphinLib.vcxproj
+++ b/Source/Core/DolphinLib.vcxproj
@@ -60,4 +60,38 @@
<Import Project="$(ExternalsDir)zstd\exports.props" />
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets" />
+ <PropertyGroup>
+ <BuildInfoTemplate>Common\build_info.txt.in</BuildInfoTemplate>
+ <BuildInfoOutput>$(BinaryOutputDir)build_info.txt</BuildInfoOutput>
+ </PropertyGroup>
+ <ItemGroup>
+ <Text Include="$(BuildInfoTemplate)" />
+ </ItemGroup>
+ <UsingTask TaskName="GetProductVersion"
+ TaskFactory="CodeTaskFactory"
+ AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.Core.dll">
+ <ParameterGroup>
+ <Path ParameterType="System.String" Required="true" />
+ <ProductVersion ParameterType="System.String" Output="true" />
+ </ParameterGroup>
+ <Task>
+ <Using Namespace="System.Diagnostics"/>
+ <Code Type="Fragment" Language="cs">
+ <![CDATA[
+ ProductVersion = FileVersionInfo.GetVersionInfo(Path).ProductVersion;
+ ]]>
+ </Code>
+ </Task>
+ </UsingTask>
+ <Target Name="WriteBuildInfo" AfterTargets="Build" Inputs="$(BuildInfoTemplate)" Outputs="$(BuildInfoOutput)">
+ <GetProductVersion Path="$(VCToolsRedistInstallDir)vc_redist.x64.exe">
+ <Output PropertyName="VCToolsProductVersion" TaskParameter="ProductVersion" />
+ </GetProductVersion>
+ <Message Text="VCToolsProductVersion $(VCToolsProductVersion)" Importance="High" />
+ <WriteLinesToFile
+ File="$(BuildInfoOutput)"
+ Lines="$([System.IO.File]::ReadAllText($(BuildInfoTemplate)).Replace('${VC_TOOLS_VERSION}', $(VCToolsProductVersion)))"
+ Overwrite="true"
+ />
+ </Target>
</Project> \ No newline at end of file
diff --git a/Source/Core/MacUpdater/MacUI.mm b/Source/Core/MacUpdater/MacUI.mm
index a2ac4a4a83..0b2699b1dd 100644
--- a/Source/Core/MacUpdater/MacUI.mm
+++ b/Source/Core/MacUpdater/MacUI.mm
@@ -3,6 +3,7 @@
#include "MacUpdater/ViewController.h"
+#include "UpdaterCommon/Platform.h"
#include "UpdaterCommon/UI.h"
#include <Cocoa/Cocoa.h>
@@ -136,3 +137,21 @@ void UI::Stop()
void UI::Init()
{
}
+
+Platform::BuildInfo::BuildInfo(const std::string& content)
+{
+ map = {{"OSMinimumVersionMacOS", ""}};
+ Parse(content);
+}
+
+bool Platform::VersionCheck(const BuildInfo& this_build_info, const BuildInfo& next_build_info)
+{
+ // TODO implement OS Minimum Version check
+ // It should go something like this:
+ // auto target_version = next_build_info.GetVersion("OSMinimumVersionMacOS");
+ // if (!target_version.has_value() || current_version >= target_version)
+ // return true;
+ // show error
+ // return false;
+ return true;
+}
diff --git a/Source/Core/UICommon/AutoUpdate.cpp b/Source/Core/UICommon/AutoUpdate.cpp
index de8d426c7f..814f66c87b 100644
--- a/Source/Core/UICommon/AutoUpdate.cpp
+++ b/Source/Core/UICommon/AutoUpdate.cpp
@@ -246,11 +246,11 @@ void AutoUpdateChecker::TriggerUpdate(const AutoUpdateChecker::NewVersionInforma
#endif
// Run the updater!
- const std::string command_line = MakeUpdaterCommandLine(updater_flags);
+ std::string command_line = MakeUpdaterCommandLine(updater_flags);
INFO_LOG_FMT(COMMON, "Updater command line: {}", command_line);
#ifdef _WIN32
- STARTUPINFO sinfo = {sizeof(sinfo)};
+ STARTUPINFO sinfo{.cb = sizeof(sinfo)};
sinfo.dwFlags = STARTF_FORCEOFFFEEDBACK; // No hourglass cursor after starting the process.
PROCESS_INFORMATION pinfo;
if (CreateProcessW(UTF8ToWString(reloc_updater_path).c_str(), UTF8ToWString(command_line).data(),
diff --git a/Source/Core/UpdaterCommon/Platform.h b/Source/Core/UpdaterCommon/Platform.h
new file mode 100644
index 0000000000..9489ba9947
--- /dev/null
+++ b/Source/Core/UpdaterCommon/Platform.h
@@ -0,0 +1,100 @@
+// Copyright 2018 Dolphin Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include <map>
+#include <optional>
+#include <sstream>
+
+#include "Common/CommonTypes.h"
+#include "Common/StringUtil.h"
+
+namespace Platform
+{
+struct BuildVersion
+{
+ u32 major{};
+ u32 minor{};
+ u32 build{};
+ auto operator<=>(BuildVersion const& rhs) const = default;
+ static std::optional<BuildVersion> from_string(const std::string& str)
+ {
+ auto components = SplitString(str, '.');
+ // Allow variable number of components (truncating after "build"), but not
+ // empty.
+ if (components.size() == 0)
+ return {};
+ BuildVersion version;
+ if (!TryParse(components[0], &version.major, 10))
+ return {};
+ if (components.size() > 1 && !TryParse(components[1], &version.minor, 10))
+ return {};
+ if (components.size() > 2 && !TryParse(components[2], &version.build, 10))
+ return {};
+ return version;
+ }
+};
+
+enum class VersionCheckStatus
+{
+ NothingToDo,
+ UpdateOptional,
+ UpdateRequired,
+};
+
+struct VersionCheckResult
+{
+ VersionCheckStatus status{VersionCheckStatus::NothingToDo};
+ std::optional<BuildVersion> current_version{};
+ std::optional<BuildVersion> target_version{};
+};
+
+class BuildInfo
+{
+ using Map = std::map<std::string, std::string>;
+
+public:
+ BuildInfo() = default;
+ BuildInfo(const std::string& content);
+
+ std::optional<std::string> GetString(const std::string& name) const
+ {
+ auto it = map.find(name);
+ if (it == map.end() || it->second.size() == 0)
+ return {};
+ return it->second;
+ }
+
+ std::optional<BuildVersion> GetVersion(const std::string& name) const
+ {
+ auto str = GetString(name);
+ if (!str.has_value())
+ return {};
+ return BuildVersion::from_string(str.value());
+ }
+
+private:
+ void Parse(const std::string& content)
+ {
+ std::stringstream content_stream(content);
+ std::string line;
+ while (std::getline(content_stream, line))
+ {
+ if (line.starts_with("//"))
+ continue;
+ const size_t equals_index = line.find('=');
+ if (equals_index == line.npos)
+ continue;
+ auto key = line.substr(0, equals_index);
+ auto key_it = map.find(key);
+ if (key_it == map.end())
+ continue;
+ key_it->second = line.substr(equals_index + 1);
+ }
+ }
+ Map map;
+};
+
+bool VersionCheck(const BuildInfo& this_build_info, const BuildInfo& next_build_info);
+} // namespace Platform
diff --git a/Source/Core/UpdaterCommon/UpdaterCommon.cpp b/Source/Core/UpdaterCommon/UpdaterCommon.cpp
index fb9606ca49..dee55965bf 100644
--- a/Source/Core/UpdaterCommon/UpdaterCommon.cpp
+++ b/Source/Core/UpdaterCommon/UpdaterCommon.cpp
@@ -18,6 +18,7 @@
#include "Common/HttpRequest.h"
#include "Common/ScopeGuard.h"
#include "Common/StringUtil.h"
+#include "UpdaterCommon/Platform.h"
#include "UpdaterCommon/UI.h"
#ifndef _WIN32
@@ -278,6 +279,41 @@ bool DownloadContent(const std::vector<TodoList::DownloadOp>& to_download,
return true;
}
+bool PlatformVersionCheck(const std::vector<TodoList::UpdateOp>& to_update,
+ const std::string& install_base_path, const std::string& temp_dir)
+{
+ UI::SetDescription("Checking platform...");
+
+ const auto op_it = std::find_if(to_update.cbegin(), to_update.cend(),
+ [&](const auto& op) { return op.filename == "build_info.txt"; });
+ if (op_it == to_update.cend())
+ return true;
+
+ const auto op = *op_it;
+ std::string build_info_path =
+ temp_dir + DIR_SEP + HexEncode(op.new_hash.data(), op.new_hash.size());
+ std::string build_info_content;
+ if (!File::ReadFileToString(build_info_path, build_info_content) ||
+ op.new_hash != ComputeHash(build_info_content))
+ {
+ fprintf(log_fp, "Failed to read %s\n.", build_info_path.c_str());
+ return false;
+ }
+ auto next_build_info = Platform::BuildInfo(build_info_content);
+
+ build_info_path = install_base_path + DIR_SEP + "build_info.txt";
+ auto this_build_info = Platform::BuildInfo();
+ if (File::ReadFileToString(build_info_path, build_info_content))
+ {
+ if (op.old_hash != ComputeHash(build_info_content))
+ fprintf(log_fp, "Using modified existing BuildInfo %s.\n", build_info_path.c_str());
+ this_build_info = Platform::BuildInfo(build_info_content);
+ }
+
+ // The existing BuildInfo may have been modified. Be careful not to overly trust its contents!
+ return Platform::VersionCheck(this_build_info, next_build_info);
+}
+
TodoList ComputeActionsToDo(Manifest this_manifest, Manifest next_manifest)
{
TodoList todo;
@@ -474,6 +510,11 @@ bool PerformUpdate(const TodoList& todo, const std::string& install_base_path,
return false;
fprintf(log_fp, "Download step completed.\n");
+ fprintf(log_fp, "Starting platform version check step...\n");
+ if (!PlatformVersionCheck(todo.to_update, install_base_path, temp_path))
+ return false;
+ fprintf(log_fp, "Platform version check step completed.\n");
+
fprintf(log_fp, "Starting update step...\n");
if (!UpdateFiles(todo.to_update, install_base_path, temp_path))
return false;
diff --git a/Source/Core/WinUpdater/CMakeLists.txt b/Source/Core/WinUpdater/CMakeLists.txt
index a57d039209..23135d706f 100644
--- a/Source/Core/WinUpdater/CMakeLists.txt
+++ b/Source/Core/WinUpdater/CMakeLists.txt
@@ -2,6 +2,7 @@ set (MANIFEST_FILE Updater.exe.manifest)
add_executable(winupdater WIN32
Main.cpp
+ Platform.cpp
WinUI.cpp
${MANIFEST_FILE})
diff --git a/Source/Core/WinUpdater/Main.cpp b/Source/Core/WinUpdater/Main.cpp
index 71e67ecf1f..caa9f40958 100644
--- a/Source/Core/WinUpdater/Main.cpp
+++ b/Source/Core/WinUpdater/Main.cpp
@@ -21,10 +21,10 @@ int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine
{
if (lstrlenW(pCmdLine) == 0)
{
- MessageBox(nullptr,
- L"This updater is not meant to be launched directly. Configure Auto-Update in "
- "Dolphin's settings instead.",
- L"Error", MB_ICONERROR);
+ MessageBoxW(nullptr,
+ L"This updater is not meant to be launched directly. Configure Auto-Update in "
+ "Dolphin's settings instead.",
+ L"Error", MB_ICONERROR);
return 1;
}
diff --git a/Source/Core/WinUpdater/Platform.cpp b/Source/Core/WinUpdater/Platform.cpp
new file mode 100644
index 0000000000..8c79479560
--- /dev/null
+++ b/Source/Core/WinUpdater/Platform.cpp
@@ -0,0 +1,187 @@
+#include <Windows.h>
+
+#include <filesystem>
+#include <map>
+#include <optional>
+
+#include "Common/FileUtil.h"
+#include "Common/HttpRequest.h"
+#include "Common/IOFile.h"
+#include "Common/ScopeGuard.h"
+#include "Common/StringUtil.h"
+
+#include "UpdaterCommon/Platform.h"
+#include "UpdaterCommon/UI.h"
+
+namespace Platform
+{
+BuildInfo::BuildInfo(const std::string& content)
+{
+ map = {{"OSMinimumVersionWin10", ""},
+ {"OSMinimumVersionWin11", ""},
+ {"VCToolsVersion", ""},
+ {"VCToolsUpdateURL", ""}};
+ Parse(content);
+}
+
+// This default value should be kept in sync with the value of VCToolsUpdateURL in
+// build_info.txt.in
+static const char* VCToolsUpdateURLDefault = "https://aka.ms/vs/17/release/vc_redist.x64.exe";
+#define VC_RUNTIME_REGKEY R"(SOFTWARE\Microsoft\VisualStudio\14.0\VC\Runtimes\)"
+
+static const char* VCRuntimeRegistrySubkey()
+{
+ return VC_RUNTIME_REGKEY
+#ifdef _M_X86_64
+ "x64";
+#elif _M_ARM_64
+ "arm64";
+#else
+#error unsupported architecture
+#endif
+}
+
+static bool ReadVCRuntimeVersionField(u32* value, const char* name)
+{
+ DWORD value_len = sizeof(*value);
+ return RegGetValueA(HKEY_LOCAL_MACHINE, VCRuntimeRegistrySubkey(), name, RRF_RT_REG_DWORD,
+ nullptr, value, &value_len) == ERROR_SUCCESS;
+}
+
+static std::optional<BuildVersion> GetInstalledVCRuntimeVersion()
+{
+ u32 installed;
+ if (!ReadVCRuntimeVersionField(&installed, "Installed") || !installed)
+ return {};
+ BuildVersion version;
+ if (!ReadVCRuntimeVersionField(&version.major, "Major") ||
+ !ReadVCRuntimeVersionField(&version.minor, "Minor") ||
+ !ReadVCRuntimeVersionField(&version.build, "Bld"))
+ {
+ return {};
+ }
+ return version;
+}
+
+static VersionCheckResult VCRuntimeVersionCheck(const BuildInfo& this_build_info,
+ const BuildInfo& next_build_info)
+{
+ VersionCheckResult result;
+ result.current_version = GetInstalledVCRuntimeVersion();
+ result.target_version = next_build_info.GetVersion("VCToolsVersion");
+
+ auto existing_version = this_build_info.GetVersion("VCToolsVersion");
+
+ if (!result.target_version.has_value())
+ result.status = VersionCheckStatus::UpdateOptional;
+ else if (!result.current_version.has_value() || result.current_version < result.target_version)
+ result.status = VersionCheckStatus::UpdateRequired;
+
+ // See if the current build was already running on acceptable version of the runtime. This could
+ // happen if the user manually copied the redist DLLs and got Dolphin running that way.
+ if (existing_version.has_value() && existing_version >= result.target_version)
+ result.status = VersionCheckStatus::NothingToDo;
+
+ return result;
+}
+
+static bool VCRuntimeUpdate(const BuildInfo& build_info)
+{
+ UI::SetDescription("Updating VC++ Redist, please wait...");
+
+ Common::HttpRequest req;
+ req.FollowRedirects(10);
+ auto resp = req.Get(build_info.GetString("VCToolsUpdateURL").value_or(VCToolsUpdateURLDefault));
+ if (!resp)
+ return false;
+
+ // Write it to current working directory.
+ auto redist_path = std::filesystem::current_path() / L"vc_redist.x64.exe";
+ auto redist_path_u8 = WStringToUTF8(redist_path.wstring());
+ File::IOFile redist_file;
+ redist_file.Open(redist_path_u8, "wb");
+ if (!redist_file.WriteBytes(resp->data(), resp->size()))
+ return false;
+ redist_file.Close();
+
+ Common::ScopeGuard redist_deleter([&] { File::Delete(redist_path_u8); });
+
+ // The installer also supports /passive and /quiet. We pass neither to allow the user to see and
+ // interact with the installer.
+ std::wstring cmdline = redist_path.filename().wstring() + L" /install /norestart";
+ STARTUPINFOW startup_info{.cb = sizeof(startup_info)};
+ PROCESS_INFORMATION process_info;
+ if (!CreateProcessW(redist_path.c_str(), cmdline.data(), nullptr, nullptr, TRUE, 0, nullptr,
+ nullptr, &startup_info, &process_info))
+ {
+ return false;
+ }
+ CloseHandle(process_info.hThread);
+
+ // Wait for it to run
+ WaitForSingleObject(process_info.hProcess, INFINITE);
+ DWORD exit_code;
+ bool has_exit_code = GetExitCodeProcess(process_info.hProcess, &exit_code);
+ CloseHandle(process_info.hProcess);
+ // NOTE: Some nonzero exit codes can still be considered success (e.g. if installation was
+ // bypassed because the same version already installed).
+ return has_exit_code && exit_code == EXIT_SUCCESS;
+}
+
+static BuildVersion CurrentOSVersion()
+{
+ typedef DWORD(WINAPI * RtlGetVersion_t)(PRTL_OSVERSIONINFOW);
+ auto RtlGetVersion =
+ (RtlGetVersion_t)GetProcAddress(GetModuleHandle(TEXT("ntdll")), "RtlGetVersion");
+ RTL_OSVERSIONINFOW info{.dwOSVersionInfoSize = sizeof(info)};
+ RtlGetVersion(&info);
+ return {.major = info.dwMajorVersion, .minor = info.dwMinorVersion, .build = info.dwBuildNumber};
+}
+
+static VersionCheckResult OSVersionCheck(const BuildInfo& build_info)
+{
+ VersionCheckResult result;
+ result.current_version = CurrentOSVersion();
+
+ constexpr BuildVersion WIN11_BASE{10, 0, 22000};
+ const char* version_name =
+ (result.current_version >= WIN11_BASE) ? "OSMinimumVersionWin11" : "OSMinimumVersionWin10";
+ result.target_version = build_info.GetVersion(version_name);
+
+ if (!result.target_version.has_value() || result.current_version >= result.target_version)
+ result.status = VersionCheckStatus::NothingToDo;
+ else
+ result.status = VersionCheckStatus::UpdateRequired;
+ return result;
+}
+
+bool VersionCheck(const BuildInfo& this_build_info, const BuildInfo& next_build_info)
+{
+ // If the binary requires more recent OS, inform the user.
+ auto os_check = OSVersionCheck(next_build_info);
+ if (os_check.status == VersionCheckStatus::UpdateRequired)
+ {
+ UI::Error("Please update Windows in order to update Dolphin.");
+ return false;
+ }
+
+ // Check if application being launched needs more recent version of VC Redist. If so, download
+ // latest updater and execute it.
+ auto vc_check = VCRuntimeVersionCheck(this_build_info, next_build_info);
+ if (vc_check.status != VersionCheckStatus::NothingToDo)
+ {
+ // Don't bother checking status of the install itself, just check if we actually see the new
+ // version.
+ VCRuntimeUpdate(next_build_info);
+ vc_check = VCRuntimeVersionCheck(this_build_info, next_build_info);
+ if (vc_check.status == VersionCheckStatus::UpdateRequired)
+ {
+ // The update is required and the install failed for some reason.
+ UI::Error("Please update VC++ Runtime in order to update Dolphin.");
+ return false;
+ }
+ }
+
+ return true;
+}
+} // namespace Platform
diff --git a/Source/Core/WinUpdater/WinUI.cpp b/Source/Core/WinUpdater/WinUI.cpp
index 62b02eb0c0..1671f43457 100644
--- a/Source/Core/WinUpdater/WinUI.cpp
+++ b/Source/Core/WinUpdater/WinUI.cpp
@@ -253,8 +253,8 @@ void Stop()
void LaunchApplication(std::string path)
{
- // Hack: Launching the updater over the explorer ensures that admin priviliges are dropped. Why?
- // Ask Microsoft.
+ // Indirectly start the application via explorer. This effectively drops admin priviliges because
+ // explorer is running as current user.
ShellExecuteW(nullptr, nullptr, L"explorer.exe", UTF8ToWString(path).c_str(), nullptr, SW_SHOW);
}
diff --git a/Source/Core/WinUpdater/WinUpdater.vcxproj b/Source/Core/WinUpdater/WinUpdater.vcxproj
index 9ec5d4afb2..28ae61bb34 100644
--- a/Source/Core/WinUpdater/WinUpdater.vcxproj
+++ b/Source/Core/WinUpdater/WinUpdater.vcxproj
@@ -25,8 +25,14 @@
</ProjectReference>
</ItemGroup>
<ItemGroup>
+ <ClInclude Include="..\UpdaterCommon\Platform.h" />
+ <ClInclude Include="..\UpdaterCommon\UI.h" />
+ <ClInclude Include="..\UpdaterCommon\UpdaterCommon.h" />
+ </ItemGroup>
+ <ItemGroup>
<ClCompile Include="..\UpdaterCommon\UpdaterCommon.cpp" />
<ClCompile Include="Main.cpp" />
+ <ClCompile Include="Platform.cpp" />
<ClCompile Include="WinUI.cpp" />
</ItemGroup>
<Import Project="$(ExternalsDir)cpp-optparse\exports.props" />