diff --git a/CHANGES.md b/CHANGES.md index 191bff9..859a062 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -74,11 +74,3 @@ The change was made for two reasons: * Doorstop does not need to pass any arguments anymore. Instead, Doorstop passes all the information via environment variables. * CoreCLR does not support easy method searching using wildcards yet. - -## *Possibly* breaking: `target_assembly` directory is now always added to mono search path - -In UnityDoorstop 3.x, the tool only loaded the `target_assembly` and left any other assembly resolving to the target assembly code. -**Starting Doorstop 4, `target_assembly`'s parent directory is set to mono DLL search path.** - -This means that any additional assemblies that are placed into the same directory as `target_assembly` will receive priority during assembly resolving. -Note that this option for now only affects UnityMono as there is no similar search path priority available via current CoreCLR C hosting API. \ No newline at end of file diff --git a/assets/nix/run.sh b/assets/nix/run.sh index 257fb00..ab24a52 100755 --- a/assets/nix/run.sh +++ b/assets/nix/run.sh @@ -36,6 +36,7 @@ ignore_disable_switch="0" # (e.g. mscorlib is stripped in original game) # This option causes Mono to seek mscorlib and core libraries from a different folder before Managed # Original Managed folder is added as a secondary folder in the search path +# To specify multiple paths, separate them with colons (:) dll_search_path_override="" # If 1, Mono debugger server will be enabled diff --git a/assets/windows/doorstop_config.ini b/assets/windows/doorstop_config.ini index 4c2a493..4803878 100644 --- a/assets/windows/doorstop_config.ini +++ b/assets/windows/doorstop_config.ini @@ -24,6 +24,7 @@ ignore_disable_switch=false # (e.g. mscorlib is stripped in original game) # This option causes Mono to seek mscorlib and core libraries from a different folder before Managed # Original Managed folder is added as a secondary folder in the search path +# To specify multiple paths, separate them with semicolons (;) dll_search_path_override= # If true, Mono debugger server will be enabled diff --git a/src/bootstrap.c b/src/bootstrap.c index 6cc60e4..c38790b 100644 --- a/src/bootstrap.c +++ b/src/bootstrap.c @@ -134,27 +134,65 @@ void *init_mono(const char *root_domain_name, const char *runtime_version) { LOG("Overriding mono DLL search path"); size_t mono_search_path_len = strlen(root_dir) + 1; - char_t *target_path_full = get_full_path(config.target_assembly); - char_t *target_path_folder = get_folder_name(target_path_full); - mono_search_path_len += strlen(target_path_folder) + 1; - LOG("Adding %s to mono search path", target_path_folder); char_t *override_dir_full = NULL; - bool_t has_override = config.mono_dll_search_path_override && - strlen(config.mono_dll_search_path_override); + char_t *config_path_value = config.mono_dll_search_path_override; + bool_t has_override = config_path_value && strlen(config_path_value); if (has_override) { - override_dir_full = get_full_path(config.mono_dll_search_path_override); + size_t path_start = 0; + override_dir_full = calloc(MAX_PATH, sizeof(char_t)); + memset(override_dir_full, 0, MAX_PATH * sizeof(char_t)); + + bool_t found_path = FALSE; + for (size_t i = 0; i <= strlen(config_path_value); i++) { + char_t current_char = config_path_value[i]; + if (current_char == *PATH_SEP || current_char == 0) { + if (i <= path_start) { + path_start++; + continue; + } + + size_t path_len = i - path_start; + char_t *path = calloc(path_len + 1, sizeof(char_t)); + strncpy(path, config_path_value + path_start, path_len); + path[path_len] = 0; + + char_t *full_path = get_full_path(path); + + if (strlen(override_dir_full) + strlen(full_path) + 2 > + MAX_PATH) { + LOG("Ignoring this root path because its absolute version " + "is too long: %s", + full_path); + free(path); + free(full_path); + path_start = i + 1; + continue; + } + + if (found_path) { + strcat(override_dir_full, PATH_SEP); + } + + strcat(override_dir_full, full_path); + LOG("Adding root path: %s", full_path); + + free(path); + free(full_path); + + found_path = TRUE; + path_start = i + 1; + } + } + mono_search_path_len += strlen(override_dir_full) + 1; - LOG("Adding root path: %s", override_dir_full); } char_t *mono_search_path = calloc(mono_search_path_len + 1, sizeof(char_t)); - if (has_override) { + if (override_dir_full && strlen(override_dir_full)) { strcat(mono_search_path, override_dir_full); strcat(mono_search_path, PATH_SEP); } - strcat(mono_search_path, target_path_folder); - strcat(mono_search_path, PATH_SEP); strcat(mono_search_path, root_dir); LOG("Mono search path: %s", mono_search_path); @@ -166,8 +204,6 @@ void *init_mono(const char *root_domain_name, const char *runtime_version) { if (override_dir_full) { free(override_dir_full); } - free(target_path_full); - free(target_path_folder); hook_mono_jit_parse_options(0, NULL); diff --git a/src/nix/config.c b/src/nix/config.c index f6d0444..afd8b8e 100644 --- a/src/nix/config.c +++ b/src/nix/config.c @@ -37,8 +37,8 @@ void load_config() { try_get_env("DOORSTOP_MONO_DEBUG_ADDRESS", TEXT("127.0.0.1:10000"), &config.mono_debug_address); get_env_path("DOORSTOP_TARGET_ASSEMBLY", &config.target_assembly); - get_env_path("DOORSTOP_MONO_DLL_SEARCH_PATH_OVERRIDE", - &config.mono_dll_search_path_override); + try_get_env("DOORSTOP_MONO_DLL_SEARCH_PATH_OVERRIDE", TEXT(""), + &config.mono_dll_search_path_override); get_env_path("DOORSTOP_CLR_RUNTIME_CORECLR_PATH", &config.clr_runtime_coreclr_path); get_env_path("DOORSTOP_CLR_CORLIB_DIR", &config.clr_corlib_dir); diff --git a/src/windows/config.c b/src/windows/config.c index 4babb9d..493230d 100644 --- a/src/windows/config.c +++ b/src/windows/config.c @@ -72,9 +72,9 @@ static inline void init_config_file() { load_path_file(config_path, TEXT("General"), TEXT("target_assembly"), DEFAULT_TARGET_ASSEMBLY, &config.target_assembly); - load_path_file(config_path, TEXT("UnityMono"), - TEXT("dll_search_path_override"), NULL, - &config.mono_dll_search_path_override); + load_str_file(config_path, TEXT("UnityMono"), + TEXT("dll_search_path_override"), TEXT(""), + &config.mono_dll_search_path_override); load_bool_file(config_path, TEXT("UnityMono"), TEXT("debug_enabled"), TEXT("false"), &config.mono_debug_enabled); load_bool_file(config_path, TEXT("UnityMono"), TEXT("debug_suspend"),