From 1e40a930a91a8775ec8a4f11a6154e904f7e0d2d Mon Sep 17 00:00:00 2001 From: Aireil <33433913+Aireil@users.noreply.github.com> Date: Wed, 17 Aug 2022 22:13:31 +0200 Subject: [PATCH 1/4] fix: plugin config deletion context menu (#955) --- .../PluginInstaller/PluginInstallerWindow.cs | 4 ++-- Dalamud/Plugin/Internal/PluginManager.cs | 14 +++++++++----- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/Dalamud/Interface/Internal/Windows/PluginInstaller/PluginInstallerWindow.cs b/Dalamud/Interface/Internal/Windows/PluginInstaller/PluginInstallerWindow.cs index b658d3304..003c26105 100644 --- a/Dalamud/Interface/Internal/Windows/PluginInstaller/PluginInstallerWindow.cs +++ b/Dalamud/Interface/Internal/Windows/PluginInstaller/PluginInstallerWindow.cs @@ -2631,9 +2631,9 @@ namespace Dalamud.Interface.Internal.Windows.PluginInstaller public static string PluginContext_HidePlugin => Loc.Localize("InstallerHidePlugin", "Hide from installer"); - public static string PluginContext_DeletePluginConfig => Loc.Localize("InstallerDeletePluginConfig", "Reset plugin"); + public static string PluginContext_DeletePluginConfig => Loc.Localize("InstallerDeletePluginConfig", "Reset plugin configuration"); - public static string PluginContext_DeletePluginConfigReload => Loc.Localize("InstallerDeletePluginConfigReload", "Reset plugin settings & reload"); + public static string PluginContext_DeletePluginConfigReload => Loc.Localize("InstallerDeletePluginConfigReload", "Reset plugin configuration and reload"); #endregion diff --git a/Dalamud/Plugin/Internal/PluginManager.cs b/Dalamud/Plugin/Internal/PluginManager.cs index 8051cc081..2634cbd30 100644 --- a/Dalamud/Plugin/Internal/PluginManager.cs +++ b/Dalamud/Plugin/Internal/PluginManager.cs @@ -1128,17 +1128,18 @@ internal partial class PluginManager : IDisposable, IServiceType } /// - /// Unload the plugin, delete its configuration, and reload it. + /// Delete the plugin configuration, unload/reload it if loaded. /// /// The plugin. /// Throws if the plugin is still loading/unloading. /// The task. public async Task DeleteConfigurationAsync(LocalPlugin plugin) { - if (plugin.State == PluginState.Loading || plugin.State == PluginState.Unloaded) + if (plugin.State is PluginState.Loading or PluginState.Unloading) throw new Exception("Cannot delete configuration for a loading/unloading plugin"); - if (plugin.IsLoaded) + var isReloading = plugin.IsLoaded; + if (isReloading) await plugin.UnloadAsync(); for (var waitUntil = Environment.TickCount64 + 1000; Environment.TickCount64 < waitUntil;) @@ -1154,8 +1155,11 @@ internal partial class PluginManager : IDisposable, IServiceType } } - // Let's indicate "installer" here since this is supposed to be a fresh install - await plugin.LoadAsync(PluginLoadReason.Installer); + if (isReloading) + { + // Let's indicate "installer" here since this is supposed to be a fresh install + await plugin.LoadAsync(PluginLoadReason.Installer); + } } /// From 38e3a8e7f5b7551641b80ffb32c51aac279ff6a2 Mon Sep 17 00:00:00 2001 From: Chivalrik <77893938+fitzchivalrik@users.noreply.github.com> Date: Wed, 17 Aug 2022 22:17:59 +0200 Subject: [PATCH 2/4] fix: Change GamepadState interface version for consistency (#880) Co-authored-by: goat --- Dalamud/Game/ClientState/GamePad/GamepadState.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dalamud/Game/ClientState/GamePad/GamepadState.cs b/Dalamud/Game/ClientState/GamePad/GamepadState.cs index 597818975..bd4cadbc8 100644 --- a/Dalamud/Game/ClientState/GamePad/GamepadState.cs +++ b/Dalamud/Game/ClientState/GamePad/GamepadState.cs @@ -14,7 +14,7 @@ namespace Dalamud.Game.ClientState.GamePad /// Will block game's gamepad input if is set. /// [PluginInterface] - [InterfaceVersion("1.0.0")] + [InterfaceVersion("1.0")] [ServiceManager.BlockingEarlyLoadedService] public unsafe class GamepadState : IDisposable, IServiceType { From e9147387c7862fdb488aef743302564549e402d4 Mon Sep 17 00:00:00 2001 From: kizer Date: Thu, 18 Aug 2022 15:47:38 +0900 Subject: [PATCH 3/4] Fix error message on import hook fail (#957) --- Dalamud.Boot/utils.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dalamud.Boot/utils.cpp b/Dalamud.Boot/utils.cpp index e06e812ef..b487f398b 100644 --- a/Dalamud.Boot/utils.cpp +++ b/Dalamud.Boot/utils.cpp @@ -140,7 +140,7 @@ void* utils::loaded_module::get_imported_function_pointer(const char* pcszDllNam if (void* ppImportTableItem{}; find_imported_function_pointer(pcszDllName, pcszFunctionName, hintOrOrdinal, ppImportTableItem)) return ppImportTableItem; - throw std::runtime_error("Failed to find import for kernel32!OpenProcess."); + throw std::runtime_error(std::format("Failed to find import for {}!{} ({}).", pcszDllName, pcszFunctionName ? pcszFunctionName : "", hintOrOrdinal)); } utils::loaded_module utils::loaded_module::current_process() { From 1f1f0aaa20fb0e0f56fff5ba422ceb12b2aeba14 Mon Sep 17 00:00:00 2001 From: kizer Date: Fri, 19 Aug 2022 04:20:45 +0900 Subject: [PATCH 4/4] Show DLL description and version into xivfixes dll load list (#958) --- Dalamud.Boot/hooks.cpp | 19 ++++++++- Dalamud.Boot/utils.cpp | 83 +++++++++++++++++++++++++++++++++++++++ Dalamud.Boot/utils.h | 6 +++ Dalamud.Boot/xivfixes.cpp | 15 ++++++- 4 files changed, 120 insertions(+), 3 deletions(-) diff --git a/Dalamud.Boot/hooks.cpp b/Dalamud.Boot/hooks.cpp index 2619ffa72..7cf489195 100644 --- a/Dalamud.Boot/hooks.cpp +++ b/Dalamud.Boot/hooks.cpp @@ -103,8 +103,23 @@ void hooks::getprocaddress_singleton_import_hook::initialize() { LdrRegisterDllNotification(0, [](ULONG notiReason, const LDR_DLL_NOTIFICATION_DATA* pData, void* context) { if (notiReason == LDR_DLL_NOTIFICATION_REASON_LOADED) { const auto dllName = unicode::convert(pData->Loaded.FullDllName->Buffer); - logging::I(R"({} "{}" has been loaded at 0x{:X} ~ 0x{:X} (0x{:X}); finding import table items to hook.)", - LogTag, dllName, + + utils::loaded_module mod(pData->Loaded.DllBase); + std::wstring version, description; + try { + version = utils::format_file_version(mod.get_file_version()); + } catch (...) { + version = L""; + } + + try { + description = mod.get_description(); + } catch (...) { + description = L""; + } + + logging::I(R"({} "{}" ("{}" ver {}) has been loaded at 0x{:X} ~ 0x{:X} (0x{:X}); finding import table items to hook.)", + LogTag, dllName, description, version, reinterpret_cast(pData->Loaded.DllBase), reinterpret_cast(pData->Loaded.DllBase) + pData->Loaded.SizeOfImage, pData->Loaded.SizeOfImage); diff --git a/Dalamud.Boot/utils.cpp b/Dalamud.Boot/utils.cpp index b487f398b..62b436aa2 100644 --- a/Dalamud.Boot/utils.cpp +++ b/Dalamud.Boot/utils.cpp @@ -143,6 +143,69 @@ void* utils::loaded_module::get_imported_function_pointer(const char* pcszDllNam throw std::runtime_error(std::format("Failed to find import for {}!{} ({}).", pcszDllName, pcszFunctionName ? pcszFunctionName : "", hintOrOrdinal)); } +std::unique_ptr, decltype(&FreeResource)> utils::loaded_module::get_resource(LPCWSTR lpName, LPCWSTR lpType) const { + const auto hres = FindResourceW(m_hModule, lpName, lpType); + if (!hres) + throw std::runtime_error("No such resource"); + + const auto hRes = LoadResource(m_hModule, hres); + if (!hRes) + throw std::runtime_error("LoadResource failure"); + + return {hRes, &FreeResource}; +} + +std::wstring utils::loaded_module::get_description() const { + const auto rsrc = get_resource(MAKEINTRESOURCE(VS_VERSION_INFO), RT_VERSION); + const auto pBlock = LockResource(rsrc.get()); + + struct LANGANDCODEPAGE { + WORD wLanguage; + WORD wCodePage; + } * lpTranslate; + UINT cbTranslate; + if (!VerQueryValueW(pBlock, + TEXT("\\VarFileInfo\\Translation"), + reinterpret_cast(&lpTranslate), + &cbTranslate)) { + throw std::runtime_error("Invalid version information (1)"); + } + + for (size_t i = 0; i < (cbTranslate / sizeof(LANGANDCODEPAGE)); i++) { + wchar_t* buf = nullptr; + UINT size = 0; + if (!VerQueryValueW(pBlock, + std::format(L"\\StringFileInfo\\{:04x}{:04x}\\FileDescription", + lpTranslate[i].wLanguage, + lpTranslate[i].wCodePage).c_str(), + reinterpret_cast(&buf), + &size)) { + continue; + } + auto currName = std::wstring_view(buf, size); + while (!currName.empty() && currName.back() == L'\0') + currName = currName.substr(0, currName.size() - 1); + if (currName.empty()) + continue; + return std::wstring(currName); + } + + throw std::runtime_error("Invalid version information (2)"); +} + +VS_FIXEDFILEINFO utils::loaded_module::get_file_version() const { + const auto rsrc = get_resource(MAKEINTRESOURCE(VS_VERSION_INFO), RT_VERSION); + const auto pBlock = LockResource(rsrc.get()); + UINT size = 0; + LPVOID lpBuffer = nullptr; + if (!VerQueryValueW(pBlock, L"\\", &lpBuffer, &size)) + throw std::runtime_error("Failed to query version information."); + const VS_FIXEDFILEINFO& versionInfo = *static_cast(lpBuffer); + if (versionInfo.dwSignature != 0xfeef04bd) + throw std::runtime_error("Invalid version info found."); + return versionInfo; +} + utils::loaded_module utils::loaded_module::current_process() { return { GetModuleHandleW(nullptr) }; } @@ -163,6 +226,26 @@ std::vector utils::loaded_module::all_modules() { return modules; } +std::wstring utils::format_file_version(const VS_FIXEDFILEINFO& v) { + if (v.dwFileVersionMS == v.dwProductVersionMS && v.dwFileVersionLS == v.dwProductVersionLS) { + return std::format(L"{}.{}.{}.{}", + (v.dwProductVersionMS >> 16) & 0xFFFF, + (v.dwProductVersionMS >> 0) & 0xFFFF, + (v.dwProductVersionLS >> 16) & 0xFFFF, + (v.dwProductVersionLS >> 0) & 0xFFFF); + } else { + return std::format(L"file={}.{}.{}.{} prod={}.{}.{}.{}", + (v.dwFileVersionMS >> 16) & 0xFFFF, + (v.dwFileVersionMS >> 0) & 0xFFFF, + (v.dwFileVersionLS >> 16) & 0xFFFF, + (v.dwFileVersionLS >> 0) & 0xFFFF, + (v.dwProductVersionMS >> 16) & 0xFFFF, + (v.dwProductVersionMS >> 0) & 0xFFFF, + (v.dwProductVersionLS >> 16) & 0xFFFF, + (v.dwProductVersionLS >> 0) & 0xFFFF); + } +} + utils::signature_finder& utils::signature_finder::look_in(const void* pFirst, size_t length) { if (length) m_ranges.emplace_back(std::span(reinterpret_cast(pFirst), length)); diff --git a/Dalamud.Boot/utils.h b/Dalamud.Boot/utils.h index ca350674a..1e29493b7 100644 --- a/Dalamud.Boot/utils.h +++ b/Dalamud.Boot/utils.h @@ -58,10 +58,16 @@ namespace utils { void* get_imported_function_pointer(const char* pcszDllName, const char* pcszFunctionName, uint32_t hintOrOrdinal) const; template TFn** get_imported_function_pointer(const char* pcszDllName, const char* pcszFunctionName, uint32_t hintOrOrdinal) { return reinterpret_cast(get_imported_function_pointer(pcszDllName, pcszFunctionName, hintOrOrdinal)); } + [[nodiscard]] std::unique_ptr, decltype(&FreeResource)> get_resource(LPCWSTR lpName, LPCWSTR lpType) const; + [[nodiscard]] std::wstring get_description() const; + [[nodiscard]] VS_FIXEDFILEINFO get_file_version() const; + static loaded_module current_process(); static std::vector all_modules(); }; + std::wstring format_file_version(const VS_FIXEDFILEINFO& v); + class signature_finder { std::vector> m_ranges; std::vector m_patterns; diff --git a/Dalamud.Boot/xivfixes.cpp b/Dalamud.Boot/xivfixes.cpp index 338938fc1..c5cde28d3 100644 --- a/Dalamud.Boot/xivfixes.cpp +++ b/Dalamud.Boot/xivfixes.cpp @@ -26,7 +26,20 @@ void xivfixes::unhook_dll(bool bApply) { std::filesystem::path path; try { path = mod.path(); - logging::I("{} [{}/{}] Module 0x{:X} ~ 0x{:X} (0x{:X}): \"{}\"", LogTagW, i + 1, mods.size(), mod.address_int(), mod.address_int() + mod.image_size(), mod.image_size(), path.wstring()); + std::wstring version, description; + try { + version = utils::format_file_version(mod.get_file_version()); + } catch (...) { + version = L""; + } + + try { + description = mod.get_description(); + } catch (...) { + description = L""; + } + + logging::I(R"({} [{}/{}] Module 0x{:X} ~ 0x{:X} (0x{:X}): "{}" ("{}" ver {}))", LogTagW, i + 1, mods.size(), mod.address_int(), mod.address_int() + mod.image_size(), mod.image_size(), path.wstring(), description, version); } catch (const std::exception& e) { logging::W("{} [{}/{}] Module 0x{:X}: Failed to resolve path: {}", LogTag, i + 1, mods.size(), mod.address_int(), e.what()); return;