mirror of
https://github.com/spice2x/spice2x.github.io.git
synced 2026-08-02 06:40:42 -07:00
utils: print out DLL metadata (#596)
## Link to GitHub Issue or related Pull Request, if one exists #592 ## Description of change * when custom DLLs are detected (`d3d9.dll`) print out some basic data from the PE header * for our own NVIDIA DLL stubs, add manifest files to identify ourselves * as a bonus, when DLL hooks are loaded from `-k`, print DLL info there as well This is mainly to detect when DXVK is in use.
This commit is contained in:
@@ -266,6 +266,7 @@ set_source_files_properties(cfg/manifest.rc PROPERTIES LANGUAGE RC)
|
||||
set_source_files_properties(cfg/icon.rc PROPERTIES LANGUAGE RC)
|
||||
set_source_files_properties(cfg/Win32D.rc PROPERTIES LANGUAGE RC)
|
||||
set_source_files_properties(build/manifest64.rc PROPERTIES LANGUAGE RC)
|
||||
set_source_files_properties(stubs/manifest.rc PROPERTIES LANGUAGE RC)
|
||||
|
||||
# sources
|
||||
#########
|
||||
@@ -813,7 +814,8 @@ endif()
|
||||
|
||||
# nvcuda.dll
|
||||
set(SOURCE_FILES stubs/nvcuda.cpp)
|
||||
add_library(spicetools_stubs_nvcuda SHARED ${SOURCE_FILES} stubs/nvcuda.def)
|
||||
set(RESOURCE_FILES stubs/manifest.rc)
|
||||
add_library(spicetools_stubs_nvcuda SHARED ${SOURCE_FILES} ${RESOURCE_FILES} stubs/nvcuda.def)
|
||||
set_target_properties(spicetools_stubs_nvcuda PROPERTIES PREFIX "")
|
||||
set_target_properties(spicetools_stubs_nvcuda PROPERTIES OUTPUT_NAME "nvcuda")
|
||||
|
||||
@@ -823,7 +825,8 @@ endif()
|
||||
|
||||
# nvcuvid.dll
|
||||
set(SOURCE_FILES stubs/nvcuvid.cpp)
|
||||
add_library(spicetools_stubs_nvcuvid SHARED ${SOURCE_FILES} stubs/nvcuvid.def)
|
||||
set(RESOURCE_FILES stubs/manifest.rc)
|
||||
add_library(spicetools_stubs_nvcuvid SHARED ${SOURCE_FILES} ${RESOURCE_FILES} stubs/nvcuvid.def)
|
||||
set_target_properties(spicetools_stubs_nvcuvid PROPERTIES PREFIX "")
|
||||
set_target_properties(spicetools_stubs_nvcuvid PROPERTIES OUTPUT_NAME "nvcuvid")
|
||||
|
||||
@@ -833,7 +836,8 @@ endif()
|
||||
|
||||
# nvEncodeAPI64.dll
|
||||
set(SOURCE_FILES stubs/nvEncodeAPI64.cpp)
|
||||
add_library(spicetools_stubs_nvEncodeAPI64 SHARED ${SOURCE_FILES} stubs/nvEncodeAPI64.def)
|
||||
set(RESOURCE_FILES stubs/manifest.rc)
|
||||
add_library(spicetools_stubs_nvEncodeAPI64 SHARED ${SOURCE_FILES} ${RESOURCE_FILES} stubs/nvEncodeAPI64.def)
|
||||
set_target_properties(spicetools_stubs_nvEncodeAPI64 PROPERTIES PREFIX "")
|
||||
set_target_properties(spicetools_stubs_nvEncodeAPI64 PROPERTIES OUTPUT_NAME "nvEncodeAPI64")
|
||||
|
||||
@@ -843,7 +847,8 @@ endif()
|
||||
|
||||
# cpusbxpkm.dll (32 bit)
|
||||
set(SOURCE_FILES stubs/cpusbxpkm.cpp)
|
||||
add_library(spicetools_stubs_cpusbxpkm SHARED ${SOURCE_FILES} stubs/cpusbxpkm.def)
|
||||
set(RESOURCE_FILES stubs/manifest.rc)
|
||||
add_library(spicetools_stubs_cpusbxpkm SHARED ${SOURCE_FILES} ${RESOURCE_FILES} stubs/cpusbxpkm.def)
|
||||
set_target_properties(spicetools_stubs_cpusbxpkm PROPERTIES PREFIX "")
|
||||
set_target_properties(spicetools_stubs_cpusbxpkm PROPERTIES OUTPUT_NAME "cpusbxpkm")
|
||||
|
||||
|
||||
@@ -2307,6 +2307,7 @@ int main_implementation(int argc, char *argv[]) {
|
||||
// load hooks
|
||||
for (auto &hook : game_hooks) {
|
||||
log_info("launcher", "loading hook DLL {}", hook);
|
||||
libutils::print_dll_info(hook);
|
||||
HMODULE module;
|
||||
if (!(module = libutils::try_library(hook))) {
|
||||
log_warning("launcher", "failed to load hook {}: {}", hook, get_last_error_string());
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
1 VERSIONINFO
|
||||
FILEVERSION 1,0,0,0
|
||||
PRODUCTVERSION 1,0,0,0
|
||||
BEGIN
|
||||
BLOCK "StringFileInfo"
|
||||
BEGIN
|
||||
BLOCK "040904E4"
|
||||
BEGIN
|
||||
VALUE "CompanyName", "SpiceTools"
|
||||
VALUE "FileDescription", "SpiceTools DLL Stub"
|
||||
VALUE "FileVersion", "1.0.0.0"
|
||||
VALUE "ProductName", "SpiceTools DLL Stub"
|
||||
VALUE "ProductVersion", "1.0.0.0"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
BEGIN
|
||||
VALUE "Translation", 0x0409, 1252
|
||||
END
|
||||
END
|
||||
@@ -9,6 +9,16 @@
|
||||
#include "peb.h"
|
||||
#include "util/fileutils.h"
|
||||
#include "util/dependencies.h"
|
||||
#include "util/unique_plain_ptr.h"
|
||||
|
||||
#define DEBUG_VERBOSE 0
|
||||
|
||||
#if DEBUG_VERBOSE
|
||||
#define log_debug(module, format_str, ...) logger::push( \
|
||||
LOG_FORMAT("M", module, format_str, ## __VA_ARGS__), logger::Style::GREY)
|
||||
#else
|
||||
#define log_debug(module, format_str, ...)
|
||||
#endif
|
||||
|
||||
std::filesystem::path libutils::module_file_name(HMODULE module) {
|
||||
std::wstring buf;
|
||||
@@ -361,11 +371,106 @@ void libutils::check_duplicate_dlls() {
|
||||
void libutils::warn_if_dll_exists(const std::string &file_name) {
|
||||
if (fileutils::file_exists(MODULE_PATH / file_name)) {
|
||||
log_info("libutils", "found user-supplied {} in modules directory", file_name);
|
||||
libutils::print_dll_info(MODULE_PATH / file_name);
|
||||
return;
|
||||
}
|
||||
const auto &spice_bin_path = libutils::module_file_name(nullptr).parent_path();
|
||||
if (fileutils::file_exists(spice_bin_path / file_name)) {
|
||||
log_info("libutils", "found user-supplied {} next to spice executable path", file_name);
|
||||
libutils::print_dll_info(spice_bin_path / file_name);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void libutils::print_dll_info(std::filesystem::path filename) {
|
||||
DWORD handle;
|
||||
const auto size = GetFileVersionInfoSizeA(filename.string().c_str(), &handle);
|
||||
if (size == 0) {
|
||||
log_debug(
|
||||
"libutils",
|
||||
"GetFileVersionInfoSizeA failed for {}: {}",
|
||||
filename.filename().string(),
|
||||
get_last_error_string());
|
||||
return;
|
||||
}
|
||||
|
||||
auto data = util::make_unique_plain<VOID>(size);
|
||||
if (!GetFileVersionInfoA(filename.string().c_str(), handle, size, data.get())) {
|
||||
log_debug(
|
||||
"libutils",
|
||||
"GetFileVersionInfoA failed for {}: {}",
|
||||
filename.filename().string(),
|
||||
get_last_error_string());
|
||||
return;
|
||||
}
|
||||
|
||||
struct LANGANDCODEPAGE {
|
||||
WORD wLanguage;
|
||||
WORD wCodePage;
|
||||
} *lpTranslate = nullptr;
|
||||
|
||||
UINT cbTranslate = 0;
|
||||
if (!VerQueryValueA(data.get(), "\\VarFileInfo\\Translation", (LPVOID*)&lpTranslate, &cbTranslate)) {
|
||||
log_debug(
|
||||
"libutils",
|
||||
"VerQueryValueA failed for {}: {}",
|
||||
filename.filename().string(),
|
||||
get_last_error_string());
|
||||
return;
|
||||
}
|
||||
if (cbTranslate == 0 || lpTranslate == nullptr) {
|
||||
log_debug(
|
||||
"libutils",
|
||||
"VerQueryValueA returned invalid results for {}",
|
||||
filename.filename().string());
|
||||
return;
|
||||
}
|
||||
|
||||
// pick language - prefer English
|
||||
WORD lang = 0, codepage = 0;
|
||||
for (UINT i = 0; i < cbTranslate / sizeof(*lpTranslate); i++) {
|
||||
if (lpTranslate[i].wLanguage == 0x0409) { // en-us
|
||||
lang = lpTranslate[i].wLanguage;
|
||||
codepage = lpTranslate[i].wCodePage;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (lang == 0) {
|
||||
lang = lpTranslate[0].wLanguage;
|
||||
codepage = lpTranslate[0].wCodePage;
|
||||
}
|
||||
|
||||
// StringFileInfo helper
|
||||
auto query_string = [&](const char* key) -> std::string {
|
||||
std::string subBlock = fmt::format(
|
||||
"\\StringFileInfo\\{:04x}{:04x}\\{}",
|
||||
lang, codepage, key
|
||||
);
|
||||
|
||||
char* value = nullptr;
|
||||
UINT size_out = 0;
|
||||
|
||||
if (VerQueryValueA(data.get(), subBlock.c_str(), (LPVOID*)&value, &size_out) && value) {
|
||||
return value;
|
||||
}
|
||||
log_debug(
|
||||
"libutils",
|
||||
"VerQueryValueA({}) failed for {}: {}",
|
||||
subBlock,
|
||||
filename.filename().string(),
|
||||
get_last_error_string());
|
||||
return "";
|
||||
};
|
||||
|
||||
const auto company_name = query_string("CompanyName");
|
||||
const auto product_name = query_string("ProductName");
|
||||
const auto version_str = query_string("FileVersion");
|
||||
|
||||
log_info(
|
||||
"libutils",
|
||||
"DLL info for {}: CompanyName = {}, ProductName = {}, Version = {}",
|
||||
filename.filename().string(),
|
||||
company_name.empty() ? "?" : company_name,
|
||||
product_name.empty() ? "?" : product_name,
|
||||
version_str.empty() ? "?" : version_str);
|
||||
}
|
||||
|
||||
@@ -77,4 +77,6 @@ namespace libutils {
|
||||
intptr_t rva2offset(const std::filesystem::path &path, intptr_t rva);
|
||||
intptr_t offset2rva(IMAGE_NT_HEADERS *nt_headers, intptr_t offset);
|
||||
intptr_t offset2rva(const std::filesystem::path &path, intptr_t offset);
|
||||
|
||||
void print_dll_info(std::filesystem::path filename);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user