Use DOORSTOP_DLL_SEARCH_DIRS for preloader patching and typeloading

This commit is contained in:
ghorsington committed 2021-02-14 17:37:55 +02:00
1 parent 9ca5720cd1
commit b920999686
7 files changed
+45 -8

No files matched your search

+1 -1
View File
@@ -45,7 +45,7 @@ namespace BepInEx.Preloader
string bepinPath = Utility.ParentDirectory(Path.GetFullPath(EnvVars.DOORSTOP_INVOKE_DLL_PATH), 2);
Paths.SetExecutablePath(EnvVars.DOORSTOP_PROCESS_PATH, bepinPath, EnvVars.DOORSTOP_MANAGED_FOLDER_DIR);
Paths.SetExecutablePath(EnvVars.DOORSTOP_PROCESS_PATH, bepinPath, EnvVars.DOORSTOP_MANAGED_FOLDER_DIR, EnvVars.DOORSTOP_DLL_SEARCH_DIRS);
LoadCriticalAssemblies();
AppDomain.CurrentDomain.AssemblyResolve += LocalResolve;
+7
View File
@@ -1,4 +1,5 @@
using System;
using System.IO;
namespace BepInEx.Preloader
{
@@ -22,12 +23,18 @@ namespace BepInEx.Preloader
/// Full path to the game executable currently running.
/// </summary>
public static string DOORSTOP_PROCESS_PATH { get; private set; }
/// <summary>
/// Array of paths where Mono searches DLLs from before assembly resolvers are invoked.
/// </summary>
public static string[] DOORSTOP_DLL_SEARCH_DIRS { get; private set; }
internal static void LoadVars()
{
DOORSTOP_INVOKE_DLL_PATH = Environment.GetEnvironmentVariable("DOORSTOP_INVOKE_DLL_PATH");
DOORSTOP_MANAGED_FOLDER_DIR = Environment.GetEnvironmentVariable("DOORSTOP_MANAGED_FOLDER_DIR");
DOORSTOP_PROCESS_PATH = Environment.GetEnvironmentVariable("DOORSTOP_PROCESS_PATH");
DOORSTOP_DLL_SEARCH_DIRS = Environment.GetEnvironmentVariable("DOORSTOP_DLL_SEARCH_DIRS")?.Split(Path.PathSeparator) ?? new string[0];
}
}
}
@@ -203,14 +203,14 @@ namespace BepInEx.Preloader.Patching
/// <summary>
/// Applies patchers to all assemblies in the given directory and loads patched assemblies into memory.
/// </summary>
/// <param name="directory">Directory to load CLR assemblies from.</param>
public static void PatchAndLoad(string directory)
/// <param name="directories">Directories to load CLR assemblies from in their search order.</param>
public static void PatchAndLoad(params string[] directories)
{
// First, load patchable assemblies into Cecil
// Ignore case for keys (dll filenames) to account for running on *nix
var assemblies = new Dictionary<string, AssemblyDefinition>(StringComparer.InvariantCultureIgnoreCase);
foreach (string assemblyPath in Directory.GetFiles(directory, "*.dll"))
foreach (string assemblyPath in Utility.GetUniqueFilesInDirectories(directories, "*.dll"))
{
AssemblyDefinition assembly;
+1 -1
View File
@@ -87,7 +87,7 @@ namespace BepInEx.Preloader
Logger.LogInfo($"{AssemblyPatcher.PatcherPlugins.Count} patcher plugin{(AssemblyPatcher.PatcherPlugins.Count == 1 ? "" : "s")} loaded");
AssemblyPatcher.PatchAndLoad(Paths.ManagedPath);
AssemblyPatcher.PatchAndLoad(Paths.DllSearchPaths);
AssemblyPatcher.DisposePatchers();
Logger.LogMessage("Preloader finished");
+5 -2
View File
@@ -70,10 +70,13 @@ namespace BepInEx.Bootstrap
{
if (Utility.TryParseAssemblyName(reference.FullName, out var name) &&
(Utility.TryResolveDllAssembly(name, Paths.BepInExAssemblyDirectory, ReaderParameters, out var assembly) ||
Utility.TryResolveDllAssembly(name, Paths.PluginPath, ReaderParameters, out assembly) ||
Utility.TryResolveDllAssembly(name, Paths.ManagedPath, ReaderParameters, out assembly)))
Utility.TryResolveDllAssembly(name, Paths.PluginPath, ReaderParameters, out assembly)))
return assembly;
foreach (string dllSearchPath in Paths.DllSearchPaths)
if (Utility.TryResolveDllAssembly(name, dllSearchPath, ReaderParameters, out assembly))
return assembly;
return AssemblyResolve?.Invoke(sender, reference);
};
}
+8 -1
View File
@@ -1,4 +1,5 @@
using System.IO;
using System.Linq;
using System.Reflection;
using MonoMod.Utils;
@@ -9,7 +10,7 @@ namespace BepInEx
/// </summary>
public static class Paths
{
internal static void SetExecutablePath(string executablePath, string bepinRootPath = null, string managedPath = null)
internal static void SetExecutablePath(string executablePath, string bepinRootPath = null, string managedPath = null, string[] dllSearchPath = null)
{
ExecutablePath = executablePath;
ProcessName = Path.GetFileNameWithoutExtension(executablePath);
@@ -27,6 +28,7 @@ namespace BepInEx
BepInExAssemblyDirectory = Path.Combine(BepInExRootPath, "core");
BepInExAssemblyPath = Path.Combine(BepInExAssemblyDirectory, $"{Assembly.GetExecutingAssembly().GetName().Name}.dll");
CachePath = Path.Combine(BepInExRootPath, "cache");
DllSearchPaths = (dllSearchPath ?? new string[0]).Concat(new[] { ManagedPath }).Distinct().ToArray();
}
internal static void SetManagedPath(string managedPath)
@@ -41,6 +43,11 @@ namespace BepInEx
PluginPath = Utility.CombinePaths(BepInExRootPath, pluginPath);
}
/// <summary>
/// List of directories from where Mono will search assemblies before assembly resolving is invoked.
/// </summary>
public static string[] DllSearchPaths { get; private set; }
/// <summary>
/// The directory that the core BepInEx DLLs reside in.
/// </summary>
+20
View File
@@ -293,5 +293,25 @@ namespace BepInEx
return false;
}
}
/// <summary>
/// Gets unique files in all given directories. If the file with the same name exists in multiple directories,
/// only the first occurrence is returned.
/// </summary>
/// <param name="directories">Directories to search from.</param>
/// <param name="pattern">File pattern to search.</param>
/// <returns>Collection of all files in the directories.</returns>
public static IEnumerable<string> GetUniqueFilesInDirectories(IEnumerable<string> directories, string pattern = "*")
{
var result = new Dictionary<string, string>(StringComparer.InvariantCultureIgnoreCase);
foreach (string directory in directories)
foreach (string file in Directory.GetFiles(directory, pattern))
{
string fileName = Path.GetFileName(file);
if (!result.ContainsKey(fileName))
result[fileName] = file;
}
return result.Values;
}
}
}