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.
This commit is contained in:
bicarus-dev
2025-04-24 10:35:34 -07:00
committed by GitHub
parent 44e1edb50c
commit bf9074a76e
3 changed files with 38 additions and 0 deletions
+3
View File
@@ -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();
+33
View File
@@ -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());
}
}
}
+2
View File
@@ -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);