Merge branch 'net5' of github.com:goatcorp/Dalamud into net5

This commit is contained in:
goat 2022-08-20 19:02:46 +02:00
commit 7e4f51bee1
No known key found for this signature in database
GPG key ID: 49E2AA8C6A76498B
7 changed files with 133 additions and 12 deletions

View file

@ -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<std::string>(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"<unknown>";
}
try {
description = mod.get_description();
} catch (...) {
description = L"<unknown>";
}
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<size_t>(pData->Loaded.DllBase),
reinterpret_cast<size_t>(pData->Loaded.DllBase) + pData->Loaded.SizeOfImage,
pData->Loaded.SizeOfImage);

View file

@ -140,7 +140,70 @@ 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 : "<unnamed>", hintOrOrdinal));
}
std::unique_ptr<std::remove_pointer_t<HGLOBAL>, 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<LPVOID*>(&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<LPVOID*>(&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<const VS_FIXEDFILEINFO*>(lpBuffer);
if (versionInfo.dwSignature != 0xfeef04bd)
throw std::runtime_error("Invalid version info found.");
return versionInfo;
}
utils::loaded_module utils::loaded_module::current_process() {
@ -163,6 +226,26 @@ std::vector<utils::loaded_module> 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<const char*>(pFirst), length));

View file

@ -58,10 +58,16 @@ namespace utils {
void* get_imported_function_pointer(const char* pcszDllName, const char* pcszFunctionName, uint32_t hintOrOrdinal) const;
template<typename TFn> TFn** get_imported_function_pointer(const char* pcszDllName, const char* pcszFunctionName, uint32_t hintOrOrdinal) { return reinterpret_cast<TFn**>(get_imported_function_pointer(pcszDllName, pcszFunctionName, hintOrOrdinal)); }
[[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]] VS_FIXEDFILEINFO get_file_version() const;
static loaded_module current_process();
static std::vector<loaded_module> all_modules();
};
std::wstring format_file_version(const VS_FIXEDFILEINFO& v);
class signature_finder {
std::vector<std::span<const char>> m_ranges;
std::vector<srell::regex> m_patterns;

View file

@ -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"<unknown>";
}
try {
description = mod.get_description();
} catch (...) {
description = L"<unknown>";
}
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;

View file

@ -14,7 +14,7 @@ namespace Dalamud.Game.ClientState.GamePad
/// Will block game's gamepad input if <see cref="ImGuiConfigFlags.NavEnableGamepad"/> is set.
/// </summary>
[PluginInterface]
[InterfaceVersion("1.0.0")]
[InterfaceVersion("1.0")]
[ServiceManager.BlockingEarlyLoadedService]
public unsafe class GamepadState : IDisposable, IServiceType
{

View file

@ -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

View file

@ -1128,17 +1128,18 @@ internal partial class PluginManager : IDisposable, IServiceType
}
/// <summary>
/// Unload the plugin, delete its configuration, and reload it.
/// Delete the plugin configuration, unload/reload it if loaded.
/// </summary>
/// <param name="plugin">The plugin.</param>
/// <exception cref="Exception">Throws if the plugin is still loading/unloading.</exception>
/// <returns>The task.</returns>
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);
}
}
/// <summary>