mirror of
https://github.com/goatcorp/Dalamud.git
synced 2025-12-12 18:27:23 +01:00
Show DLL description and version into xivfixes dll load list (#958)
This commit is contained in:
parent
e9147387c7
commit
1f1f0aaa20
4 changed files with 120 additions and 3 deletions
|
|
@ -103,8 +103,23 @@ void hooks::getprocaddress_singleton_import_hook::initialize() {
|
||||||
LdrRegisterDllNotification(0, [](ULONG notiReason, const LDR_DLL_NOTIFICATION_DATA* pData, void* context) {
|
LdrRegisterDllNotification(0, [](ULONG notiReason, const LDR_DLL_NOTIFICATION_DATA* pData, void* context) {
|
||||||
if (notiReason == LDR_DLL_NOTIFICATION_REASON_LOADED) {
|
if (notiReason == LDR_DLL_NOTIFICATION_REASON_LOADED) {
|
||||||
const auto dllName = unicode::convert<std::string>(pData->Loaded.FullDllName->Buffer);
|
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),
|
||||||
reinterpret_cast<size_t>(pData->Loaded.DllBase) + pData->Loaded.SizeOfImage,
|
reinterpret_cast<size_t>(pData->Loaded.DllBase) + pData->Loaded.SizeOfImage,
|
||||||
pData->Loaded.SizeOfImage);
|
pData->Loaded.SizeOfImage);
|
||||||
|
|
|
||||||
|
|
@ -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 : "<unnamed>", hintOrOrdinal));
|
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() {
|
utils::loaded_module utils::loaded_module::current_process() {
|
||||||
return { GetModuleHandleW(nullptr) };
|
return { GetModuleHandleW(nullptr) };
|
||||||
}
|
}
|
||||||
|
|
@ -163,6 +226,26 @@ std::vector<utils::loaded_module> utils::loaded_module::all_modules() {
|
||||||
return 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) {
|
utils::signature_finder& utils::signature_finder::look_in(const void* pFirst, size_t length) {
|
||||||
if (length)
|
if (length)
|
||||||
m_ranges.emplace_back(std::span(reinterpret_cast<const char*>(pFirst), length));
|
m_ranges.emplace_back(std::span(reinterpret_cast<const char*>(pFirst), length));
|
||||||
|
|
|
||||||
|
|
@ -58,10 +58,16 @@ namespace utils {
|
||||||
void* get_imported_function_pointer(const char* pcszDllName, const char* pcszFunctionName, uint32_t hintOrOrdinal) const;
|
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)); }
|
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 loaded_module current_process();
|
||||||
static std::vector<loaded_module> all_modules();
|
static std::vector<loaded_module> all_modules();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
std::wstring format_file_version(const VS_FIXEDFILEINFO& v);
|
||||||
|
|
||||||
class signature_finder {
|
class signature_finder {
|
||||||
std::vector<std::span<const char>> m_ranges;
|
std::vector<std::span<const char>> m_ranges;
|
||||||
std::vector<srell::regex> m_patterns;
|
std::vector<srell::regex> m_patterns;
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,20 @@ void xivfixes::unhook_dll(bool bApply) {
|
||||||
std::filesystem::path path;
|
std::filesystem::path path;
|
||||||
try {
|
try {
|
||||||
path = mod.path();
|
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) {
|
} catch (const std::exception& e) {
|
||||||
logging::W("{} [{}/{}] Module 0x{:X}: Failed to resolve path: {}", LogTag, i + 1, mods.size(), mod.address_int(), e.what());
|
logging::W("{} [{}/{}] Module 0x{:X}: Failed to resolve path: {}", LogTag, i + 1, mods.size(), mod.address_int(), e.what());
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue