Add some Import related stuff to PeRunner. Build BizExvoker which will be used to import managed libraries as dependencies to PEs
This commit is contained in:
parent
3f8a89d171
commit
5c8efb51ba
|
@ -90,7 +90,9 @@
|
||||||
<Compile Include="BinaryQuickSerializer.cs" />
|
<Compile Include="BinaryQuickSerializer.cs" />
|
||||||
<Compile Include="Bit.cs" />
|
<Compile Include="Bit.cs" />
|
||||||
<Compile Include="BitReverse.cs" />
|
<Compile Include="BitReverse.cs" />
|
||||||
|
<Compile Include="BizInvoke\BizExvoker.cs" />
|
||||||
<Compile Include="BizInvoke\BizInvoker.cs" />
|
<Compile Include="BizInvoke\BizInvoker.cs" />
|
||||||
|
<Compile Include="BizInvoke\BizInvokeUtilities.cs" />
|
||||||
<Compile Include="BizInvoke\DynamicLibraryImportResolver.cs" />
|
<Compile Include="BizInvoke\DynamicLibraryImportResolver.cs" />
|
||||||
<Compile Include="Buffer.cs" />
|
<Compile Include="Buffer.cs" />
|
||||||
<Compile Include="Colors.cs" />
|
<Compile Include="Colors.cs" />
|
||||||
|
|
|
@ -0,0 +1,150 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Reflection.Emit;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace BizHawk.Common.BizInvoke
|
||||||
|
{
|
||||||
|
public static class BizExvoker
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// the assembly that all delegate types are placed in
|
||||||
|
/// </summary>
|
||||||
|
private static readonly AssemblyBuilder ImplAssemblyBuilder;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// the module that all delegate types are placed in
|
||||||
|
/// </summary>
|
||||||
|
private static readonly ModuleBuilder ImplModuleBuilder;
|
||||||
|
|
||||||
|
static BizExvoker()
|
||||||
|
{
|
||||||
|
var aname = new AssemblyName("BizExvokeProxyAssembly");
|
||||||
|
ImplAssemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(aname, AssemblyBuilderAccess.Run);
|
||||||
|
ImplModuleBuilder = ImplAssemblyBuilder.DefineDynamicModule("BizExvokerModule");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// holds the delegate types for a type
|
||||||
|
/// </summary>
|
||||||
|
private class DelegateStorage
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// the type that this storage was made for
|
||||||
|
/// </summary>
|
||||||
|
public Type OriginalType { get; }
|
||||||
|
/// <summary>
|
||||||
|
/// the type that the delegate types reside in
|
||||||
|
/// </summary>
|
||||||
|
public Type StorageType { get; }
|
||||||
|
|
||||||
|
public List<StoredDelegateInfo> DelegateTypes { get; } = new List<StoredDelegateInfo>();
|
||||||
|
|
||||||
|
public class StoredDelegateInfo
|
||||||
|
{
|
||||||
|
public MethodInfo Method { get; }
|
||||||
|
public Type DelegateType { get; }
|
||||||
|
public string EntryPointName { get; }
|
||||||
|
public StoredDelegateInfo(MethodInfo method, Type delegateType, string entryPointName)
|
||||||
|
{
|
||||||
|
Method = method;
|
||||||
|
DelegateType = delegateType;
|
||||||
|
EntryPointName = entryPointName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public DelegateStorage(Type type)
|
||||||
|
{
|
||||||
|
var methods = type.GetMethods(BindingFlags.Instance | BindingFlags.Public)
|
||||||
|
.Select(m => new
|
||||||
|
{
|
||||||
|
Info = m,
|
||||||
|
Attr = m.GetCustomAttributes(true).OfType<BizExportAttribute>().FirstOrDefault()
|
||||||
|
})
|
||||||
|
.Where(a => a.Attr != null)
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
var typeBuilder = ImplModuleBuilder.DefineType(
|
||||||
|
"Bizhawk.BizExvokeHolder" + type.Name, TypeAttributes.Class | TypeAttributes.Public | TypeAttributes.Sealed);
|
||||||
|
|
||||||
|
foreach (var a in methods)
|
||||||
|
{
|
||||||
|
MethodBuilder unused;
|
||||||
|
var delegateType = BizInvokeUtilities.CreateDelegateType(a.Info, a.Attr.CallingConvention, typeBuilder, out unused).CreateType();
|
||||||
|
DelegateTypes.Add(new StoredDelegateInfo(a.Info, delegateType, a.Attr.EntryPoint ?? a.Info.Name));
|
||||||
|
}
|
||||||
|
StorageType = typeBuilder.CreateType();
|
||||||
|
OriginalType = type;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class ExvokerImpl : IImportResolver
|
||||||
|
{
|
||||||
|
private readonly Dictionary<string, IntPtr> EntryPoints = new Dictionary<string, IntPtr>();
|
||||||
|
|
||||||
|
private readonly List<Delegate> Delegates = new List<Delegate>();
|
||||||
|
|
||||||
|
public ExvokerImpl(object o, DelegateStorage d)
|
||||||
|
{
|
||||||
|
foreach (var sdt in d.DelegateTypes)
|
||||||
|
{
|
||||||
|
var del = Delegate.CreateDelegate(sdt.DelegateType, o, sdt.Method);
|
||||||
|
Delegates.Add(del); // prevent garbage collection of the delegate, which would invalidate the pointer
|
||||||
|
EntryPoints.Add(sdt.EntryPointName, Marshal.GetFunctionPointerForDelegate(del));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public IntPtr Resolve(string entryPoint)
|
||||||
|
{
|
||||||
|
IntPtr ret;
|
||||||
|
EntryPoints.TryGetValue(entryPoint, out ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static readonly Dictionary<Type, DelegateStorage> Impls = new Dictionary<Type, DelegateStorage>();
|
||||||
|
|
||||||
|
|
||||||
|
public static IImportResolver GetExvoker(object o)
|
||||||
|
{
|
||||||
|
DelegateStorage ds;
|
||||||
|
lock (Impls)
|
||||||
|
{
|
||||||
|
var type = o.GetType();
|
||||||
|
if (!Impls.TryGetValue(type, out ds))
|
||||||
|
{
|
||||||
|
ds = new DelegateStorage(type);
|
||||||
|
Impls.Add(type, ds);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return new ExvokerImpl(o, ds);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// mark an instance method to be exported by BizExvoker
|
||||||
|
/// </summary>
|
||||||
|
[AttributeUsage(AttributeTargets.Method)]
|
||||||
|
public class BizExportAttribute : Attribute
|
||||||
|
{
|
||||||
|
public CallingConvention CallingConvention { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the name of entry point; if not given, the method's name is used
|
||||||
|
/// </summary>
|
||||||
|
public string EntryPoint { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="BizImportAttribute"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="c">unmanaged calling convention</param>
|
||||||
|
public BizExportAttribute(CallingConvention c)
|
||||||
|
{
|
||||||
|
CallingConvention = c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,91 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Reflection.Emit;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace BizHawk.Common.BizInvoke
|
||||||
|
{
|
||||||
|
public static class BizInvokeUtilities
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// create a delegate type to match a method type
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="method">the method to "clone"</param>
|
||||||
|
/// <param name="nativeCall">native calling convention to use</param>
|
||||||
|
/// <param name="enclosingType">the type to define this delegate type as a nested type on</param>
|
||||||
|
/// <param name="invokeMethod">the methodBuilder for the magic Invoke method on the resulting type</param>
|
||||||
|
/// <returns>the resulting typeBuilder</returns>
|
||||||
|
public static TypeBuilder CreateDelegateType(MethodInfo method, CallingConvention nativeCall, TypeBuilder enclosingType,
|
||||||
|
out MethodBuilder invokeMethod)
|
||||||
|
{
|
||||||
|
var paramInfos = method.GetParameters();
|
||||||
|
var paramTypes = paramInfos.Select(p => p.ParameterType).ToArray();
|
||||||
|
var returnType = method.ReturnType;
|
||||||
|
|
||||||
|
// create the delegate type
|
||||||
|
var delegateType = enclosingType.DefineNestedType(
|
||||||
|
"DelegateType" + method.Name,
|
||||||
|
TypeAttributes.Class | TypeAttributes.NestedPrivate | TypeAttributes.Sealed,
|
||||||
|
typeof(MulticastDelegate));
|
||||||
|
|
||||||
|
var delegateCtor = delegateType.DefineConstructor(
|
||||||
|
MethodAttributes.RTSpecialName | MethodAttributes.HideBySig | MethodAttributes.Public,
|
||||||
|
CallingConventions.Standard,
|
||||||
|
new[] { typeof(object), typeof(IntPtr) });
|
||||||
|
|
||||||
|
delegateCtor.SetImplementationFlags(MethodImplAttributes.Runtime | MethodImplAttributes.Managed);
|
||||||
|
|
||||||
|
var delegateInvoke = delegateType.DefineMethod(
|
||||||
|
"Invoke",
|
||||||
|
MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.NewSlot | MethodAttributes.Virtual,
|
||||||
|
returnType,
|
||||||
|
paramTypes);
|
||||||
|
|
||||||
|
// we have to project all of the attributes from the baseMethod to the delegateInvoke
|
||||||
|
// so for something like [Out], the interop engine will see it and use it
|
||||||
|
for (int i = 0; i < paramInfos.Length; i++)
|
||||||
|
{
|
||||||
|
var p = delegateInvoke.DefineParameter(i + 1, ParameterAttributes.None, paramInfos[i].Name);
|
||||||
|
foreach (var a in paramInfos[i].GetCustomAttributes(false))
|
||||||
|
{
|
||||||
|
p.SetCustomAttribute(GetAttributeBuilder(a));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
var p = delegateInvoke.DefineParameter(0, ParameterAttributes.Retval, method.ReturnParameter.Name);
|
||||||
|
foreach (var a in method.ReturnParameter.GetCustomAttributes(false))
|
||||||
|
{
|
||||||
|
p.SetCustomAttribute(GetAttributeBuilder(a));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
delegateInvoke.SetImplementationFlags(MethodImplAttributes.Runtime | MethodImplAttributes.Managed);
|
||||||
|
|
||||||
|
// add the [UnmanagedFunctionPointer] to the delegate so interop will know how to call it
|
||||||
|
var attr = new CustomAttributeBuilder(typeof(UnmanagedFunctionPointerAttribute).GetConstructor(new[] { typeof(CallingConvention) }), new object[] { nativeCall });
|
||||||
|
delegateType.SetCustomAttribute(attr);
|
||||||
|
|
||||||
|
invokeMethod = delegateInvoke;
|
||||||
|
return delegateType;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// get an attribute builder to clone an attribute to a delegate type
|
||||||
|
/// </summary>
|
||||||
|
private static CustomAttributeBuilder GetAttributeBuilder(object o)
|
||||||
|
{
|
||||||
|
// anything more clever we can do here?
|
||||||
|
var t = o.GetType();
|
||||||
|
if (t == typeof(OutAttribute) || t == typeof(InAttribute))
|
||||||
|
{
|
||||||
|
return new CustomAttributeBuilder(t.GetConstructor(Type.EmptyTypes), new object[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new InvalidOperationException("Unknown parameter attribute " + t.Name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -46,13 +46,13 @@ namespace BizHawk.Common.BizInvoke
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// the module that all proxies are placed in
|
/// the module that all proxies are placed in
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private static readonly ModuleBuilder ImplModuleBilder;
|
private static readonly ModuleBuilder ImplModuleBuilder;
|
||||||
|
|
||||||
static BizInvoker()
|
static BizInvoker()
|
||||||
{
|
{
|
||||||
var aname = new AssemblyName("BizInvokeProxyAssembly");
|
var aname = new AssemblyName("BizInvokeProxyAssembly");
|
||||||
ImplAssemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(aname, AssemblyBuilderAccess.Run);
|
ImplAssemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(aname, AssemblyBuilderAccess.Run);
|
||||||
ImplModuleBilder = ImplAssemblyBuilder.DefineDynamicModule("BizInvokerModule");
|
ImplModuleBuilder = ImplAssemblyBuilder.DefineDynamicModule("BizInvokerModule");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -155,7 +155,7 @@ namespace BizHawk.Common.BizInvoke
|
||||||
// hooks that will be run on the created proxy object
|
// hooks that will be run on the created proxy object
|
||||||
var postCreateHooks = new List<Action<object, IImportResolver>>();
|
var postCreateHooks = new List<Action<object, IImportResolver>>();
|
||||||
|
|
||||||
var type = ImplModuleBilder.DefineType("Bizhawk.BizInvokeProxy" + baseType.Name, TypeAttributes.Class | TypeAttributes.Public | TypeAttributes.Sealed, baseType);
|
var type = ImplModuleBuilder.DefineType("Bizhawk.BizInvokeProxy" + baseType.Name, TypeAttributes.Class | TypeAttributes.Public | TypeAttributes.Sealed, baseType);
|
||||||
|
|
||||||
var monitorField = monitor ? type.DefineField("MonitorField", typeof(IMonitor), FieldAttributes.Public) : null;
|
var monitorField = monitor ? type.DefineField("MonitorField", typeof(IMonitor), FieldAttributes.Public) : null;
|
||||||
|
|
||||||
|
@ -188,54 +188,14 @@ namespace BizHawk.Common.BizInvoke
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private static Action<object, IImportResolver> ImplementMethodDelegate(TypeBuilder type, MethodInfo baseMethod, CallingConvention nativeCall, string entryPointName, FieldInfo monitorField)
|
private static Action<object, IImportResolver> ImplementMethodDelegate(TypeBuilder type, MethodInfo baseMethod, CallingConvention nativeCall, string entryPointName, FieldInfo monitorField)
|
||||||
{
|
{
|
||||||
|
// create the delegate type
|
||||||
|
MethodBuilder delegateInvoke;
|
||||||
|
var delegateType = BizInvokeUtilities.CreateDelegateType(baseMethod, nativeCall, type, out delegateInvoke);
|
||||||
|
|
||||||
var paramInfos = baseMethod.GetParameters();
|
var paramInfos = baseMethod.GetParameters();
|
||||||
var paramTypes = paramInfos.Select(p => p.ParameterType).ToArray();
|
var paramTypes = paramInfos.Select(p => p.ParameterType).ToArray();
|
||||||
var returnType = baseMethod.ReturnType;
|
var returnType = baseMethod.ReturnType;
|
||||||
|
|
||||||
// create the delegate type
|
|
||||||
var delegateType = type.DefineNestedType(
|
|
||||||
"DelegateType" + baseMethod.Name,
|
|
||||||
TypeAttributes.Class | TypeAttributes.NestedPrivate | TypeAttributes.Sealed,
|
|
||||||
typeof(MulticastDelegate));
|
|
||||||
|
|
||||||
var delegateCtor = delegateType.DefineConstructor(
|
|
||||||
MethodAttributes.RTSpecialName | MethodAttributes.HideBySig | MethodAttributes.Public,
|
|
||||||
CallingConventions.Standard,
|
|
||||||
new[] { typeof(object), typeof(IntPtr) });
|
|
||||||
|
|
||||||
delegateCtor.SetImplementationFlags(MethodImplAttributes.Runtime | MethodImplAttributes.Managed);
|
|
||||||
|
|
||||||
var delegateInvoke = delegateType.DefineMethod(
|
|
||||||
"Invoke",
|
|
||||||
MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.NewSlot | MethodAttributes.Virtual,
|
|
||||||
returnType,
|
|
||||||
paramTypes);
|
|
||||||
|
|
||||||
// we have to project all of the attributes from the baseMethod to the delegateInvoke
|
|
||||||
// so for something like [Out], the interop engine will see it and use it
|
|
||||||
for (int i = 0; i < paramInfos.Length; i++)
|
|
||||||
{
|
|
||||||
var p = delegateInvoke.DefineParameter(i + 1, ParameterAttributes.None, paramInfos[i].Name);
|
|
||||||
foreach (var a in paramInfos[i].GetCustomAttributes(false))
|
|
||||||
{
|
|
||||||
p.SetCustomAttribute(GetAttributeBuilder(a));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
var p = delegateInvoke.DefineParameter(0, ParameterAttributes.Retval, baseMethod.ReturnParameter.Name);
|
|
||||||
foreach (var a in baseMethod.ReturnParameter.GetCustomAttributes(false))
|
|
||||||
{
|
|
||||||
p.SetCustomAttribute(GetAttributeBuilder(a));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
delegateInvoke.SetImplementationFlags(MethodImplAttributes.Runtime | MethodImplAttributes.Managed);
|
|
||||||
|
|
||||||
// add the [UnmanagedFunctionPointer] to the delegate so interop will know how to call it
|
|
||||||
var attr = new CustomAttributeBuilder(typeof(UnmanagedFunctionPointerAttribute).GetConstructor(new[] { typeof(CallingConvention) }), new object[] { nativeCall });
|
|
||||||
delegateType.SetCustomAttribute(attr);
|
|
||||||
|
|
||||||
// define a field on the class to hold the delegate
|
// define a field on the class to hold the delegate
|
||||||
var field = type.DefineField(
|
var field = type.DefineField(
|
||||||
"DelegateField" + baseMethod.Name,
|
"DelegateField" + baseMethod.Name,
|
||||||
|
@ -522,18 +482,6 @@ namespace BizHawk.Common.BizInvoke
|
||||||
|
|
||||||
throw new InvalidOperationException("Unrecognized parameter type!");
|
throw new InvalidOperationException("Unrecognized parameter type!");
|
||||||
}
|
}
|
||||||
|
|
||||||
private static CustomAttributeBuilder GetAttributeBuilder(object o)
|
|
||||||
{
|
|
||||||
// anything more clever we can do here?
|
|
||||||
var t = o.GetType();
|
|
||||||
if (t == typeof(OutAttribute) || t == typeof(InAttribute))
|
|
||||||
{
|
|
||||||
return new CustomAttributeBuilder(t.GetConstructor(Type.EmptyTypes), new object[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new InvalidOperationException("Unknown parameter attribute " + t.Name);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
@ -12,6 +12,12 @@ namespace BizHawk.Common
|
||||||
|
|
||||||
public static class ImportResolverExtensions
|
public static class ImportResolverExtensions
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Resolve an entry point and throw an exception if that resolution is NULL
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="dll"></param>
|
||||||
|
/// <param name="entryPoint"></param>
|
||||||
|
/// <returns></returns>
|
||||||
public static IntPtr SafeResolve(this IImportResolver dll, string entryPoint)
|
public static IntPtr SafeResolve(this IImportResolver dll, string entryPoint)
|
||||||
{
|
{
|
||||||
var ret = dll.Resolve(entryPoint);
|
var ret = dll.Resolve(entryPoint);
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
using PeNet;
|
using BizHawk.Common;
|
||||||
|
using PeNet;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
@ -11,7 +12,7 @@ namespace BizHawk.Emulation.Cores.Waterbox
|
||||||
{
|
{
|
||||||
private static readonly ulong CanonicalStart = 0x0000036f00000000;
|
private static readonly ulong CanonicalStart = 0x0000036f00000000;
|
||||||
|
|
||||||
public class PeWrapper
|
public class PeWrapper : IImportResolver
|
||||||
{
|
{
|
||||||
public Dictionary<int, IntPtr> ExportsByOrdinal { get; } = new Dictionary<int, IntPtr>();
|
public Dictionary<int, IntPtr> ExportsByOrdinal { get; } = new Dictionary<int, IntPtr>();
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -19,6 +20,8 @@ namespace BizHawk.Emulation.Cores.Waterbox
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Dictionary<string, IntPtr> ExportsByName { get; } = new Dictionary<string, IntPtr>();
|
public Dictionary<string, IntPtr> ExportsByName { get; } = new Dictionary<string, IntPtr>();
|
||||||
|
|
||||||
|
public Dictionary<string, Dictionary<string, IntPtr>> ImportsByModule { get; } = new Dictionary<string, Dictionary<string, IntPtr>>();
|
||||||
|
|
||||||
public string ModuleName { get; }
|
public string ModuleName { get; }
|
||||||
|
|
||||||
private readonly byte[] _fileData;
|
private readonly byte[] _fileData;
|
||||||
|
@ -146,10 +149,36 @@ namespace BizHawk.Emulation.Cores.Waterbox
|
||||||
}
|
}
|
||||||
|
|
||||||
// collect information about imports
|
// collect information about imports
|
||||||
// NB: Hints are not the same as Ordinals. Off by 1??
|
// NB: Hints are not the same as Ordinals
|
||||||
foreach (var import in _pe.ImportedFunctions)
|
foreach (var import in _pe.ImportedFunctions)
|
||||||
{
|
{
|
||||||
|
Dictionary<string, IntPtr> module;
|
||||||
|
if (!ImportsByModule.TryGetValue(import.DLL, out module))
|
||||||
|
{
|
||||||
|
module = new Dictionary<string, IntPtr>();
|
||||||
|
ImportsByModule.Add(import.DLL, module);
|
||||||
|
}
|
||||||
|
module.Add(import.Name, Z.US(import.Thunk));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public IntPtr Resolve(string entryPoint)
|
||||||
|
{
|
||||||
|
IntPtr ret;
|
||||||
|
ExportsByName.TryGetValue(entryPoint, out ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ConnectImports(string moduleName, IImportResolver module)
|
||||||
|
{
|
||||||
|
Dictionary<string, IntPtr> imports;
|
||||||
|
if (ImportsByModule.TryGetValue(moduleName, out imports))
|
||||||
|
{
|
||||||
|
foreach (var kvp in imports)
|
||||||
|
{
|
||||||
|
var valueArray = new IntPtr[] { module.SafeResolve(kvp.Key) };
|
||||||
|
Marshal.Copy(valueArray, 0, kvp.Value, 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue