using System;
using System.Runtime.InteropServices;
namespace WhiteMagic.Execution;
///
/// Direct native-to-managed delegate calls for the in-process scenario.
/// This is the third execution tier: no remote thread is created; the call runs
/// synchronously on the current thread.
///
///
///
/// This class assumes the WhiteMagic consumer has already arranged to run inside the
/// target process. Bootstrapping the managed loader (e.g., via a CLR host or native
/// shim) that places WhiteMagic into a foreign process is a separate follow-up change
/// and is not implemented here.
///
public sealed class InProcessInvoker
{
private readonly MemoryBase _memory;
/// Creates an invoker bound to the supplied memory reader.
public InProcessInvoker(MemoryBase memory)
{
_memory = memory ?? throw new ArgumentNullException(nameof(memory));
}
///
/// Creates a managed delegate of type that calls
/// the native function at .
///
/// A delegate type whose signature matches the native function.
public TDelegate CreateFunction(IntPtr address)
where TDelegate : Delegate
{
if (address == IntPtr.Zero)
{
throw new ArgumentException(
"Function address cannot be zero.", nameof(address));
}
return Marshal.GetDelegateForFunctionPointer(address);
}
///
/// Reads the vtable pointer stored at the start of an object in memory.
///
/// The address of the object instance.
/// The address of the vtable.
public IntPtr ReadVTable(IntPtr objectAddress)
{
return _memory.Read(objectAddress);
}
///
/// Reads a function pointer from a vtable by index.
///
/// The address of the vtable.
/// The zero-based index of the method slot.
/// The address in the specified vtable slot.
public IntPtr ReadVTableFunction(IntPtr vTableAddress, int methodIndex)
{
ArgumentOutOfRangeException.ThrowIfNegative(methodIndex);
int pointerSize = _memory.Is64Bit ? 8 : 4;
IntPtr slotAddress = vTableAddress + (methodIndex * pointerSize);
return _memory.Read(slotAddress);
}
///
/// Convenience helper that reads an object's vtable and returns the function
/// address at the requested method index.
///
public IntPtr GetObjectVTableFunction(IntPtr objectAddress, int methodIndex)
{
IntPtr vTable = ReadVTable(objectAddress);
return ReadVTableFunction(vTable, methodIndex);
}
}