mirror of
https://github.com/goatcorp/Dalamud.git
synced 2025-12-12 10:17:22 +01:00
Check if CRT version is at least 14.40.33816.0 (#2361)
* Check if CRT version is at least 14.40.33816.0 * Fix ULD path * Remove debugging code
This commit is contained in:
parent
4413634508
commit
8fcf633f02
5 changed files with 91 additions and 11 deletions
|
|
@ -13,9 +13,86 @@
|
||||||
HMODULE g_hModule;
|
HMODULE g_hModule;
|
||||||
HINSTANCE g_hGameInstance = GetModuleHandleW(nullptr);
|
HINSTANCE g_hGameInstance = GetModuleHandleW(nullptr);
|
||||||
|
|
||||||
|
void CheckMsvcrtVersion() {
|
||||||
|
constexpr WORD RequiredMsvcrtVersionComponents[] = {14, 40, 33816, 0};
|
||||||
|
constexpr auto RequiredMsvcrtVersion = 0ULL
|
||||||
|
| (static_cast<uint64_t>(RequiredMsvcrtVersionComponents[0]) << 48)
|
||||||
|
| (static_cast<uint64_t>(RequiredMsvcrtVersionComponents[1]) << 32)
|
||||||
|
| (static_cast<uint64_t>(RequiredMsvcrtVersionComponents[2]) << 16)
|
||||||
|
| (static_cast<uint64_t>(RequiredMsvcrtVersionComponents[3]) << 0);
|
||||||
|
|
||||||
|
#ifdef _DEBUG
|
||||||
|
constexpr const wchar_t* RuntimeDllNames[] = {
|
||||||
|
L"msvcp140d.dll",
|
||||||
|
L"vcruntime140d.dll",
|
||||||
|
L"vcruntime140_1d.dll",
|
||||||
|
};
|
||||||
|
#else
|
||||||
|
constexpr const wchar_t* RuntimeDllNames[] = {
|
||||||
|
L"msvcp140.dll",
|
||||||
|
L"vcruntime140.dll",
|
||||||
|
L"vcruntime140_1.dll",
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
uint64_t lowestVersion = 0;
|
||||||
|
for (const auto& runtimeDllName : RuntimeDllNames) {
|
||||||
|
const utils::loaded_module mod(GetModuleHandleW(runtimeDllName));
|
||||||
|
if (!mod) {
|
||||||
|
logging::E("Runtime DLL not found: {}", runtimeDllName);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto& versionFull = mod.get_file_version();
|
||||||
|
logging::I("Runtime DLL {} has version {}.", runtimeDllName, utils::format_file_version(versionFull));
|
||||||
|
|
||||||
|
const auto version = (static_cast<uint64_t>(versionFull.dwFileVersionMS) << 32) |
|
||||||
|
static_cast<uint64_t>(versionFull.dwFileVersionLS);
|
||||||
|
|
||||||
|
// Commit introducing inline mutex ctor: tagged vs-2022-17.14 (2024-06-18)
|
||||||
|
// - https://github.com/microsoft/STL/commit/22a88260db4d754bbc067e2002430144d6ec5391
|
||||||
|
// MSVC Redist versions:
|
||||||
|
// - https://github.com/abbodi1406/vcredist/blob/master/source_links/README.md
|
||||||
|
// - 14.40.33810.0 dsig 2024-04-28
|
||||||
|
// - 14.40.33816.0 dsig 2024-09-11
|
||||||
|
|
||||||
|
if (version < RequiredMsvcrtVersion && (lowestVersion == 0 || lowestVersion > version))
|
||||||
|
lowestVersion = version;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lowestVersion) {
|
||||||
|
switch (MessageBoxW(
|
||||||
|
nullptr,
|
||||||
|
L"Microsoft Visual C++ Redistributable should be updated, or Dalamud may not work as expected."
|
||||||
|
L" Do you want to download and install the latest version from Microsoft?"
|
||||||
|
L"\n"
|
||||||
|
L"\n* Clicking \"Yes\" will exit the game and open the download page from Microsoft."
|
||||||
|
L"\n* Clicking \"No\" will continue loading the game with Dalamud. This may fail."
|
||||||
|
L"\n"
|
||||||
|
L"\nClick \"X64\" from the table in the download page, regardless of what CPU you have.",
|
||||||
|
L"Dalamud",
|
||||||
|
MB_YESNO | MB_ICONWARNING)) {
|
||||||
|
case IDYES:
|
||||||
|
ShellExecuteW(
|
||||||
|
nullptr,
|
||||||
|
L"open",
|
||||||
|
L"https://learn.microsoft.com/en-us/cpp/windows/latest-supported-vc-redist?view=msvc-170#latest-microsoft-visual-c-redistributable-version",
|
||||||
|
nullptr,
|
||||||
|
nullptr,
|
||||||
|
SW_SHOW);
|
||||||
|
ExitProcess(0);
|
||||||
|
break;
|
||||||
|
case IDNO:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
HRESULT WINAPI InitializeImpl(LPVOID lpParam, HANDLE hMainThreadContinue) {
|
HRESULT WINAPI InitializeImpl(LPVOID lpParam, HANDLE hMainThreadContinue) {
|
||||||
g_startInfo.from_envvars();
|
g_startInfo.from_envvars();
|
||||||
|
|
||||||
|
CheckMsvcrtVersion();
|
||||||
|
|
||||||
std::string jsonParseError;
|
std::string jsonParseError;
|
||||||
try {
|
try {
|
||||||
from_json(nlohmann::json::parse(std::string_view(static_cast<char*>(lpParam))), g_startInfo);
|
from_json(nlohmann::json::parse(std::string_view(static_cast<char*>(lpParam))), g_startInfo);
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,9 @@
|
||||||
#define WIN32_LEAN_AND_MEAN
|
#define WIN32_LEAN_AND_MEAN
|
||||||
#define NOMINMAX
|
#define NOMINMAX
|
||||||
|
|
||||||
|
// https://developercommunity.visualstudio.com/t/Access-violation-with-std::mutex::lock-a/10664660
|
||||||
|
#define _DISABLE_CONSTEXPR_MUTEX_CONSTRUCTOR
|
||||||
|
|
||||||
// Windows Header Files (1)
|
// Windows Header Files (1)
|
||||||
#include <Windows.h>
|
#include <Windows.h>
|
||||||
|
|
||||||
|
|
@ -21,6 +24,7 @@
|
||||||
#include <iphlpapi.h>
|
#include <iphlpapi.h>
|
||||||
#include <PathCch.h>
|
#include <PathCch.h>
|
||||||
#include <Psapi.h>
|
#include <Psapi.h>
|
||||||
|
#include <shellapi.h>
|
||||||
#include <ShlObj.h>
|
#include <ShlObj.h>
|
||||||
#include <Shlwapi.h>
|
#include <Shlwapi.h>
|
||||||
#include <SubAuth.h>
|
#include <SubAuth.h>
|
||||||
|
|
|
||||||
|
|
@ -148,7 +148,7 @@ std::unique_ptr<std::remove_pointer_t<HGLOBAL>, decltype(&FreeResource)> utils::
|
||||||
const auto hres = FindResourceW(m_hModule, lpName, lpType);
|
const auto hres = FindResourceW(m_hModule, lpName, lpType);
|
||||||
if (!hres)
|
if (!hres)
|
||||||
throw std::runtime_error("No such resource");
|
throw std::runtime_error("No such resource");
|
||||||
|
|
||||||
const auto hRes = LoadResource(m_hModule, hres);
|
const auto hRes = LoadResource(m_hModule, hres);
|
||||||
if (!hRes)
|
if (!hRes)
|
||||||
throw std::runtime_error("LoadResource failure");
|
throw std::runtime_error("LoadResource failure");
|
||||||
|
|
@ -159,7 +159,7 @@ std::unique_ptr<std::remove_pointer_t<HGLOBAL>, decltype(&FreeResource)> utils::
|
||||||
std::wstring utils::loaded_module::get_description() const {
|
std::wstring utils::loaded_module::get_description() const {
|
||||||
const auto rsrc = get_resource(MAKEINTRESOURCE(VS_VERSION_INFO), RT_VERSION);
|
const auto rsrc = get_resource(MAKEINTRESOURCE(VS_VERSION_INFO), RT_VERSION);
|
||||||
const auto pBlock = LockResource(rsrc.get());
|
const auto pBlock = LockResource(rsrc.get());
|
||||||
|
|
||||||
struct LANGANDCODEPAGE {
|
struct LANGANDCODEPAGE {
|
||||||
WORD wLanguage;
|
WORD wLanguage;
|
||||||
WORD wCodePage;
|
WORD wCodePage;
|
||||||
|
|
@ -190,11 +190,11 @@ std::wstring utils::loaded_module::get_description() const {
|
||||||
continue;
|
continue;
|
||||||
return std::wstring(currName);
|
return std::wstring(currName);
|
||||||
}
|
}
|
||||||
|
|
||||||
throw std::runtime_error("Invalid version information (2)");
|
throw std::runtime_error("Invalid version information (2)");
|
||||||
}
|
}
|
||||||
|
|
||||||
VS_FIXEDFILEINFO utils::loaded_module::get_file_version() const {
|
const VS_FIXEDFILEINFO& utils::loaded_module::get_file_version() const {
|
||||||
const auto rsrc = get_resource(MAKEINTRESOURCE(VS_VERSION_INFO), RT_VERSION);
|
const auto rsrc = get_resource(MAKEINTRESOURCE(VS_VERSION_INFO), RT_VERSION);
|
||||||
const auto pBlock = LockResource(rsrc.get());
|
const auto pBlock = LockResource(rsrc.get());
|
||||||
UINT size = 0;
|
UINT size = 0;
|
||||||
|
|
@ -353,7 +353,7 @@ const char* utils::signature_finder::result::resolve_jump_target(size_t instruct
|
||||||
nmd_x86_instruction instruction{};
|
nmd_x86_instruction instruction{};
|
||||||
if (!nmd_x86_decode(&Match[instructionOffset], NMD_X86_MAXIMUM_INSTRUCTION_LENGTH, &instruction, NMD_X86_MODE_64, NMD_X86_DECODER_FLAGS_ALL))
|
if (!nmd_x86_decode(&Match[instructionOffset], NMD_X86_MAXIMUM_INSTRUCTION_LENGTH, &instruction, NMD_X86_MODE_64, NMD_X86_DECODER_FLAGS_ALL))
|
||||||
throw std::runtime_error("Matched address does not have a valid assembly instruction");
|
throw std::runtime_error("Matched address does not have a valid assembly instruction");
|
||||||
|
|
||||||
size_t numExplicitOperands = 0;
|
size_t numExplicitOperands = 0;
|
||||||
for (size_t i = 0; i < instruction.num_operands; i++)
|
for (size_t i = 0; i < instruction.num_operands; i++)
|
||||||
numExplicitOperands += instruction.operands[i].is_implicit ? 0 : 1;
|
numExplicitOperands += instruction.operands[i].is_implicit ? 0 : 1;
|
||||||
|
|
@ -625,7 +625,7 @@ void utils::wait_for_game_window() {
|
||||||
|
|
||||||
std::wstring utils::escape_shell_arg(const std::wstring& arg) {
|
std::wstring utils::escape_shell_arg(const std::wstring& arg) {
|
||||||
// https://docs.microsoft.com/en-us/archive/blogs/twistylittlepassagesallalike/everyone-quotes-command-line-arguments-the-wrong-way
|
// https://docs.microsoft.com/en-us/archive/blogs/twistylittlepassagesallalike/everyone-quotes-command-line-arguments-the-wrong-way
|
||||||
|
|
||||||
std::wstring res;
|
std::wstring res;
|
||||||
if (!arg.empty() && arg.find_first_of(L" \t\n\v\"") == std::wstring::npos) {
|
if (!arg.empty() && arg.find_first_of(L" \t\n\v\"") == std::wstring::npos) {
|
||||||
res.append(arg);
|
res.append(arg);
|
||||||
|
|
|
||||||
|
|
@ -23,9 +23,8 @@ namespace utils {
|
||||||
bool is_current_process() const { return m_hModule == GetModuleHandleW(nullptr); }
|
bool is_current_process() const { return m_hModule == GetModuleHandleW(nullptr); }
|
||||||
bool owns_address(const void* pAddress) const;
|
bool owns_address(const void* pAddress) const;
|
||||||
|
|
||||||
operator HMODULE() const {
|
operator HMODULE() const { return m_hModule; }
|
||||||
return m_hModule;
|
operator bool() const { return m_hModule; }
|
||||||
}
|
|
||||||
|
|
||||||
size_t address_int() const { return reinterpret_cast<size_t>(m_hModule); }
|
size_t address_int() const { return reinterpret_cast<size_t>(m_hModule); }
|
||||||
size_t image_size() const { return is_pe64() ? nt_header64().OptionalHeader.SizeOfImage : nt_header32().OptionalHeader.SizeOfImage; }
|
size_t image_size() const { return is_pe64() ? nt_header64().OptionalHeader.SizeOfImage : nt_header32().OptionalHeader.SizeOfImage; }
|
||||||
|
|
@ -60,7 +59,7 @@ namespace utils {
|
||||||
|
|
||||||
[[nodiscard]] std::unique_ptr<std::remove_pointer_t<HGLOBAL>, decltype(&FreeResource)> get_resource(LPCWSTR lpName, LPCWSTR lpType) const;
|
[[nodiscard]] std::unique_ptr<std::remove_pointer_t<HGLOBAL>, decltype(&FreeResource)> get_resource(LPCWSTR lpName, LPCWSTR lpType) const;
|
||||||
[[nodiscard]] std::wstring get_description() const;
|
[[nodiscard]] std::wstring get_description() const;
|
||||||
[[nodiscard]] VS_FIXEDFILEINFO get_file_version() const;
|
[[nodiscard]] const VS_FIXEDFILEINFO& get_file_version() const;
|
||||||
|
|
||||||
static loaded_module current_process();
|
static loaded_module current_process();
|
||||||
static std::vector<loaded_module> all_modules();
|
static std::vector<loaded_module> all_modules();
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ internal class UldWidget : IDataWindowWidget
|
||||||
{
|
{
|
||||||
// ULD styles can be hardcoded for now as they don't add new ones regularly. Can later try and find where to load these from in the game EXE.
|
// ULD styles can be hardcoded for now as they don't add new ones regularly. Can later try and find where to load these from in the game EXE.
|
||||||
private static readonly string[] ThemeDisplayNames = ["Dark", "Light", "Classic FF", "Clear Blue"];
|
private static readonly string[] ThemeDisplayNames = ["Dark", "Light", "Classic FF", "Clear Blue"];
|
||||||
private static readonly string[] ThemeBasePaths = ["ui/uld/", "ui/uld/light/", "ui/uld/third/", "ui/uld/fourth/"];
|
private static readonly string[] ThemeBasePaths = ["ui/uld/", "ui/uld/img01/", "ui/uld/img02/", "ui/uld/img03/"];
|
||||||
|
|
||||||
// 48 8D 15 ?? ?? ?? ?? is the part of the signatures that contain the string location offset
|
// 48 8D 15 ?? ?? ?? ?? is the part of the signatures that contain the string location offset
|
||||||
// 48 = 64 bit register prefix
|
// 48 = 64 bit register prefix
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue