/// <inheritdoc /> public override MethodBase DetourTo(MethodBase replacement) { // Unpatch an existing detour if it exists nativeDetour?.Dispose(); // Generate a new DMD of the modified unhollowed method, and apply harmony patches to it var copiedDmd = CopyOriginal(); HarmonyManipulator.Manipulate(copiedDmd.OriginalMethod, copiedDmd.OriginalMethod.GetPatchInfo(), new ILContext(copiedDmd.Definition)); // Generate the MethodInfo instances var managedHookedMethod = copiedDmd.Generate(); var unmanagedTrampolineMethod = GenerateNativeToManagedTrampoline(managedHookedMethod).Generate(); // Apply a detour from the unmanaged implementation to the patched harmony method var unmanagedDelegateType = DelegateTypeFactory.instance.CreateDelegateType(unmanagedTrampolineMethod, CallingConvention.Cdecl); var detourPtr = Marshal.GetFunctionPointerForDelegate(unmanagedTrampolineMethod.CreateDelegate(unmanagedDelegateType)); nativeDetour = new FastNativeDetour(originalNativeMethodInfo->methodPointer, detourPtr); nativeDetour.Apply(); // TODO: Add an ILHook for the original unhollowed method to go directly to managedHookedMethod // Right now it goes through three times as much interop conversion as it needs to, when being called from managed side return(managedHookedMethod); }
public static FastNativeDetour CreateAndApply <T>(IntPtr from, T to, out T original, CallingConvention?callingConvention = null) where T : Delegate { var toPtr = callingConvention != null?MonoExtensions.GetFunctionPointerForDelegate(to, callingConvention.Value) : Marshal.GetFunctionPointerForDelegate(to); var result = new FastNativeDetour(from, toPtr); original = result.GenerateTrampoline <T>(); result.Apply(); return(result); }