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); } }