From bf9074a76eebe496399c51fe9f240bd7c51fbaf9 Mon Sep 17 00:00:00 2001 From: bicarus-dev <202771338+bicarus-dev@users.noreply.github.com> Date: Thu, 24 Apr 2025 10:35:34 -0700 Subject: [PATCH] launcher: complain when duplicate DLLs are detected (#306) ## Link to GitHub Issue, if one exists #304 ## Description of change Complain loudly about DLL conflicts. Show warnings for each DLL that exists in both modules directory and the root. This is not based on LoadLibrary hooks, just enumerating DLLs via filesystem access. Deliberately not using `log_fatal` since these are not necessarily going to crash the game. Some people just love to have messy installs and if the game booted fine before, it should continue to boot. ## Testing Tested with/without `-modules`, with/without duplicate DLLs. --- src/spice2x/launcher/launcher.cpp | 3 +++ src/spice2x/util/libutils.cpp | 33 +++++++++++++++++++++++++++++++ src/spice2x/util/libutils.h | 2 ++ 3 files changed, 38 insertions(+) diff --git a/src/spice2x/launcher/launcher.cpp b/src/spice2x/launcher/launcher.cpp index 7f5da40..94c922d 100644 --- a/src/spice2x/launcher/launcher.cpp +++ b/src/spice2x/launcher/launcher.cpp @@ -1806,6 +1806,9 @@ int main_implementation(int argc, char *argv[]) { exit(spicecfg_run(sextet_devices)); } + // complain loudly & early about dll load ordering issue + libutils::check_duplicate_dlls(); + // print cpu features if (!cfg::CONFIGURATOR_STANDALONE && dump_sysinfo) { cpuutils::print_cpu_features(); diff --git a/src/spice2x/util/libutils.cpp b/src/spice2x/util/libutils.cpp index fc76c5b..11509b5 100644 --- a/src/spice2x/util/libutils.cpp +++ b/src/spice2x/util/libutils.cpp @@ -7,6 +7,7 @@ #include "logging.h" #include "utils.h" #include "peb.h" +#include "util/fileutils.h" std::filesystem::path libutils::module_file_name(HMODULE module) { std::wstring buf; @@ -323,3 +324,35 @@ intptr_t libutils::offset2rva(const std::filesystem::path &path, intptr_t offset return rva; } + +void libutils::check_duplicate_dlls() { + const auto &spice_bin_path = libutils::module_file_name(nullptr).parent_path(); + if (MODULE_PATH == spice_bin_path) { + return; + } + + for (const auto &file : std::filesystem::directory_iterator(MODULE_PATH)) { + const auto &filename = file.path().filename(); + const auto extension = strtolower(filename.extension().string()); + + if (extension == ".dll" && + fileutils::file_exists(spice_bin_path / filename)) { + log_warning( + "libutils", + "DLL CONFLICT WARNING\n\n\n" + "-------------------------------------------------------------------\n" + "WARNING - WARNING - WARNING - WARNING - WARNING - WARNING - WARNING\n" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n" + "{} exists in BOTH of these directories:\n\n" + " 1. {}\n" + " 2. {}\n\n" + "due to Windows DLL load order rules, #1 will load instead of #2.\n" + "this has unintended consequences and may crash your game!\n" + "resolve the conflict by deleting the stale copy of the DLL\n" + "-------------------------------------------------------------------\n\n\n", + filename.string(), + (spice_bin_path / filename).string(), + (MODULE_PATH / filename).string()); + } + } +} \ No newline at end of file diff --git a/src/spice2x/util/libutils.h b/src/spice2x/util/libutils.h index e3cf06a..d5123ca 100644 --- a/src/spice2x/util/libutils.h +++ b/src/spice2x/util/libutils.h @@ -24,6 +24,8 @@ namespace libutils { return try_library(module_name.c_str()); } + void check_duplicate_dlls(); + // get module handle helpers HMODULE get_module(const char *module_name); HMODULE try_module(const char *module_name);