mirror of
https://github.com/BepInEx/BepInEx.git
synced 2026-10-19 15:51:45 +00:00
Fix MonoAssemblyHelper not working on Unity 5 and older
In older Unity (ones that embed UnityPlayer into the EXE), __Internal will map to the EXE which causes wrong DllImport resolving. Instead, use Doorstop's env var to resolve correct functions
This commit is contained in:
1 parent
5ef040f96d
commit
f27cfd7215
2 files changed
+42
-15
No files matched your search
@@ -30,11 +30,17 @@ public static class EnvVars
|
||||
/// </summary>
|
||||
public static string[] DOORSTOP_DLL_SEARCH_DIRS { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Path of the DLL that contains mono imports.
|
||||
/// </summary>
|
||||
public static string DOORSTOP_MONO_LIB_PATH { 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_MONO_LIB_PATH = Environment.GetEnvironmentVariable("DOORSTOP_MONO_LIB_PATH");
|
||||
DOORSTOP_DLL_SEARCH_DIRS =
|
||||
Environment.GetEnvironmentVariable("DOORSTOP_DLL_SEARCH_DIRS")?.Split(Path.PathSeparator) ??
|
||||
new string[0];
|
||||
|
||||
@@ -3,25 +3,32 @@ using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
using BepInEx.Preloader.Core;
|
||||
using Mono.Cecil;
|
||||
using MonoMod.Utils;
|
||||
|
||||
namespace BepInEx.Preloader.UnityMono.Utils;
|
||||
|
||||
internal static class MonoAssemblyHelper
|
||||
{
|
||||
[DllImport("__Internal", CallingConvention = CallingConvention.Cdecl)]
|
||||
private static extern nint mono_image_open_from_data_with_name(nint data,
|
||||
uint dataLength,
|
||||
bool needCopy,
|
||||
out MonoImageOpenStatus status,
|
||||
bool refOnly,
|
||||
[MarshalAs(UnmanagedType.LPStr)] string name);
|
||||
[DynDllImport("mono", "mono_image_open_from_data_with_name")]
|
||||
private static ImageOpenDelegate ImageOpen;
|
||||
|
||||
[DllImport("__Internal", CallingConvention = CallingConvention.Cdecl)]
|
||||
private static extern nint mono_assembly_load_from_full(nint image,
|
||||
[MarshalAs(UnmanagedType.LPStr)] string fileName,
|
||||
out MonoImageOpenStatus status,
|
||||
bool refOnly);
|
||||
[DynDllImport("mono", "mono_assembly_load_from_full")]
|
||||
private static AssemblyLoadDelegate AssemblyLoad;
|
||||
|
||||
static MonoAssemblyHelper()
|
||||
{
|
||||
// We can't use mono's __Internal because on Windows it will use GetModuleHandleW(NULL) that will
|
||||
// in turn return the module to the EXE and not mono.dll (at least on Unity versions < 5).
|
||||
typeof(MonoAssemblyHelper).ResolveDynDllImports(new()
|
||||
{
|
||||
["mono"] = new()
|
||||
{
|
||||
EnvVars.DOORSTOP_MONO_LIB_PATH
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static ReadAssemblyResult ReadAssemblyData(string filePath)
|
||||
{
|
||||
@@ -62,6 +69,20 @@ internal static class MonoAssemblyHelper
|
||||
return ReadAssemblyData(fullPath).Load(fullPath);
|
||||
}
|
||||
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
private delegate nint ImageOpenDelegate(nint data,
|
||||
uint dataLength,
|
||||
bool needCopy,
|
||||
out MonoImageOpenStatus status,
|
||||
bool refOnly,
|
||||
[MarshalAs(UnmanagedType.LPStr)] string name);
|
||||
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
private delegate nint AssemblyLoadDelegate(nint image,
|
||||
[MarshalAs(UnmanagedType.LPStr)] string fileName,
|
||||
out MonoImageOpenStatus status,
|
||||
bool refOnly);
|
||||
|
||||
private enum MonoImageOpenStatus
|
||||
{
|
||||
MONO_IMAGE_OK,
|
||||
@@ -83,11 +104,11 @@ internal static class MonoAssemblyHelper
|
||||
|
||||
fixed (byte* data = &AssemblyData[0])
|
||||
{
|
||||
var image = mono_image_open_from_data_with_name((nint) data, (uint) AssemblyData.Length, true,
|
||||
out var status, false, fullPath);
|
||||
var image = ImageOpen((nint) data, (uint) AssemblyData.Length, true,
|
||||
out var status, false, fullPath);
|
||||
if (status != MonoImageOpenStatus.MONO_IMAGE_OK)
|
||||
throw new BadImageFormatException($"Failed to load image {fullPath}: {status}");
|
||||
mono_assembly_load_from_full(image, fullPath, out status, false);
|
||||
AssemblyLoad(image, fullPath, out status, false);
|
||||
if (status != MonoImageOpenStatus.MONO_IMAGE_OK)
|
||||
throw new BadImageFormatException($"Failed to load assembly {fullPath}: {status}");
|
||||
return GetAssemblyByName(AssemblyName);
|
||||
|
||||
Reference in new issue
Block a user