public override void Apply() { // The process to patch native methods is as follows: // 1. Create a managed proxy method that calls NativeDetour's trampoline (we need to cache it // because we don't know the trampoline method when generating the DMD). // 2. Pass the proxy to the normal Harmony manipulator to apply prefixes, postfixes, transpilers, etc. // 3. NativeDetour the method to the managed proxy // 4. Cache the NativeDetour's trampoline (technically we wouldn't need to, this is just a workaround // for MonoMod's API. if (IsRunningOnDotNetCore) { Logger.Log(Logger.LogChannel.Warn, () => $"Patch target {Original.GetID()} is marked as extern. " + "Extern methods may not be patched because of inlining behaviour of coreclr (refer to https://github.com/dotnet/coreclr/pull/8263)." + "If you need to patch externs, consider using pure NativeDetour instead."); } var prevDmd = _dmd; _nativeDetour?.Dispose(); _dmd = GenerateManagedOriginal(); var ctx = new ILContext(_dmd.Definition); HarmonyManipulator.Manipulate(Original, Original.GetPatchInfo(), ctx); var target = _dmd.Generate(); _nativeDetour = new NativeDetour(Original, target, new NativeDetourConfig { ManualApply = true }); lock (TrampolineCache) { if (prevDmd != null) { TrampolineCache.Remove(prevDmd.GetHashCode()); } TrampolineCache[_dmd.GetHashCode()] = CreateDelegate(_trampolineDelegateType, _nativeDetour.GenerateTrampoline(_invokeTrampolineMethod)); } _nativeDetour.Apply(); }
private void Manipulator(ILContext ctx) { HarmonyManipulator.Manipulate(Original, Original.GetPatchInfo(), ctx); }