diff --git a/rpcs3/CMakeLists.txt b/rpcs3/CMakeLists.txt index a8675d945e..182d818f04 100644 --- a/rpcs3/CMakeLists.txt +++ b/rpcs3/CMakeLists.txt @@ -60,6 +60,7 @@ target_sources(rpcs3 headless_application.cpp main.cpp main_application.cpp + module_verifier.cpp rpcs3_version.cpp stb_image.cpp stdafx.cpp diff --git a/rpcs3/main.cpp b/rpcs3/main.cpp index cd685c4d40..3abec89104 100644 --- a/rpcs3/main.cpp +++ b/rpcs3/main.cpp @@ -491,9 +491,6 @@ int main(int argc, char** argv) report_fatal_error(error); } - // Before we proceed, run some sanity checks - run_platform_sanity_checks(); - const std::string lock_name = fs::get_cache_dir() + "RPCS3.buf"; static fs::file instance_lock; @@ -546,7 +543,7 @@ int main(int argc, char** argv) const int osx_ver_minor = Darwin_Version::getNSminorVersion(); if ((osx_ver_major == 14 && osx_ver_minor < 3) && (utils::get_cpu_brand().rfind("VirtualApple", 0) == 0)) { - int osx_ver_patch = Darwin_Version::getNSpatchVersion(); + const int osx_ver_patch = Darwin_Version::getNSpatchVersion(); report_fatal_error(fmt::format("RPCS3 requires macOS 14.3.0 or later.\nYou're currently using macOS %i.%i.%i.\nPlease update macOS from System Settings.\n\n", osx_ver_major, osx_ver_minor, osx_ver_patch)); } #endif @@ -612,6 +609,9 @@ int main(int argc, char** argv) } sys_log.notice("argc: %d, argv: %s", argc, argument_str); + // Before we proceed, run some sanity checks + run_platform_sanity_checks(); + #ifdef __linux__ struct ::rlimit rlim; rlim.rlim_cur = 4096; diff --git a/rpcs3/module_verifier.cpp b/rpcs3/module_verifier.cpp new file mode 100644 index 0000000000..fda0e21c07 --- /dev/null +++ b/rpcs3/module_verifier.cpp @@ -0,0 +1,96 @@ +#include "stdafx.h" +#include "module_verifier.hpp" + +#ifdef _WIN32 + +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif + +#include + +#include +#include +#include +#include + +LOG_CHANNEL(sys_log, "SYS"); + +[[noreturn]] void report_fatal_error(std::string_view text, bool is_html, bool include_help_text); + +void WIN32_module_verifier::run_module_verification() +{ + struct module_info_t + { + std::wstring_view name; + std::string_view package_name; + std::string_view dl_link; + }; + + const std::vector special_module_infos = { + { L"vulkan-1.dll", "Vulkan Runtime", "https://sdk.lunarg.com/sdk/download/latest/windows/vulkan-runtime.exe" }, + { L"msvcp140.dll", "Microsoft Visual C++ 2015-2019 Redistributable", "https://aka.ms/vs/16/release/VC_redist.x64.exe" }, + { L"vcruntime140.dll", "Microsoft Visual C++ 2015-2019 Redistributable", "https://aka.ms/vs/16/release/VC_redist.x64.exe" }, + { L"msvcp140_1.dll", "Microsoft Visual C++ 2015-2019 Redistributable", "https://aka.ms/vs/16/release/VC_redist.x64.exe" }, + { L"vcruntime140_1.dll", "Microsoft Visual C++ 2015-2019 Redistributable", "https://aka.ms/vs/16/release/VC_redist.x64.exe" } + }; + + WCHAR windir[MAX_PATH]; + if (!GetWindowsDirectory(windir, MAX_PATH)) + { + report_fatal_error(fmt::format("WIN32_module_verifier: Failed to query WindowsDirectory"), false, true); + } + + const std::wstring_view windir_wsv = windir; + + for (const auto& module : special_module_infos) + { + const HMODULE hModule = GetModuleHandle(module.name.data()); + if (hModule == NULL) + { + continue; + } + + WCHAR wpath[MAX_PATH]; + if (const auto len = GetModuleFileName(hModule, wpath, MAX_PATH)) + { + const std::wstring_view path_wsv = wpath; + if (path_wsv.find(windir_wsv) != 0) + { + const std::string path = wchar_to_utf8(wpath); + const std::string win_path = wchar_to_utf8(windir); + const std::string module_name = wchar_to_utf8(module.name); + const std::string error_message = fmt::format( + "

" + "The module %s was incorrectly installed at
" + "'%s'
" + "
" + "This module is part of the %s package.
" + "Install this package, then delete %s from rpcs3's installation directory.
" + "
" + "You can install this package from this URL:
" + "%s" + "

", + module_name, + path, + module.package_name, + module_name, + module.dl_link, + module.dl_link + ); + + sys_log.error("Found incorrectly installed module: '%s' (path='%s', windows='%s')", module_name, path, win_path); + + report_fatal_error(error_message, true, false); + } + } + } +} + +void WIN32_module_verifier::run() +{ + WIN32_module_verifier verifier{}; + verifier.run_module_verification(); +} + +#endif // _WIN32 diff --git a/rpcs3/module_verifier.hpp b/rpcs3/module_verifier.hpp index 0399d590c8..930288fb44 100644 --- a/rpcs3/module_verifier.hpp +++ b/rpcs3/module_verifier.hpp @@ -1,97 +1,18 @@ #pragma once #ifdef _WIN32 -#ifndef WIN32_LEAN_AND_MEAN -#define WIN32_LEAN_AND_MEAN -#endif - -#include - #include -#include -#include - -[[noreturn]] void report_fatal_error(std::string_view text, bool is_html, bool include_help_text); // Validates that system modules are properly installed // Only relevant for WIN32 class WIN32_module_verifier { - struct module_info_t - { - std::wstring_view name; - std::string_view package_name; - std::string_view dl_link; - }; - - const std::vector special_module_infos = { - { L"vulkan-1.dll", "Vulkan Runtime", "https://sdk.lunarg.com/sdk/download/latest/windows/vulkan-runtime.exe" }, - { L"msvcp140.dll", "Microsoft Visual C++ 2015-2019 Redistributable", "https://aka.ms/vs/16/release/VC_redist.x64.exe" }, - { L"vcruntime140.dll", "Microsoft Visual C++ 2015-2019 Redistributable", "https://aka.ms/vs/16/release/VC_redist.x64.exe" }, - { L"msvcp140_1.dll", "Microsoft Visual C++ 2015-2019 Redistributable", "https://aka.ms/vs/16/release/VC_redist.x64.exe" }, - { L"vcruntime140_1.dll", "Microsoft Visual C++ 2015-2019 Redistributable", "https://aka.ms/vs/16/release/VC_redist.x64.exe" } - }; - - // Inline impl. This class is only referenced once. - void run_module_verification() - { - WCHAR windir[MAX_PATH]; - if (!GetWindowsDirectory(windir, MAX_PATH)) - { - report_fatal_error(fmt::format("WIN32_module_verifier: Failed to query WindowsDirectory"), false, true); - } - - const std::wstring_view windir_wsv = windir; - - for (const auto& module : special_module_infos) - { - const HMODULE hModule = GetModuleHandle(module.name.data()); - if (hModule == NULL) - { - continue; - } - - WCHAR wpath[MAX_PATH]; - if (const auto len = GetModuleFileName(hModule, wpath, MAX_PATH)) - { - const std::wstring_view path_wsv = wpath; - if (path_wsv.find(windir_wsv) != 0) - { - const std::string path = wchar_to_utf8(wpath); - const std::string module_name = wchar_to_utf8(module.name); - const std::string error_message = fmt::format( - "

" - "The module %s was incorrectly installed at
" - "'%s'
" - "
" - "This module is part of the %s package.
" - "Install this package, then delete %s from rpcs3's installation directory.
" - "
" - "You can install this package from this URL:
" - "%s" - "

", - module_name, - path, - module.package_name, - module_name, - module.dl_link, - module.dl_link - ); - report_fatal_error(error_message, true, false); - } - } - } - } + void run_module_verification(); WIN32_module_verifier() = default; public: - - static void run() - { - WIN32_module_verifier verifier{}; - verifier.run_module_verification(); - } + static void run(); }; #endif // _WIN32 diff --git a/rpcs3/rpcs3.vcxproj b/rpcs3/rpcs3.vcxproj index fc644ae066..0e5f13a1cf 100644 --- a/rpcs3/rpcs3.vcxproj +++ b/rpcs3/rpcs3.vcxproj @@ -193,6 +193,7 @@ + true diff --git a/rpcs3/rpcs3.vcxproj.filters b/rpcs3/rpcs3.vcxproj.filters index af7dcf2223..b426e00787 100644 --- a/rpcs3/rpcs3.vcxproj.filters +++ b/rpcs3/rpcs3.vcxproj.filters @@ -1098,6 +1098,9 @@ Io\raw + + rpcs3 +