diff --git a/Dalamud/Hooking/Internal/FunctionPointerVariableHook.cs b/Dalamud/Hooking/Internal/FunctionPointerVariableHook.cs
index 3272f50b3..80bd65cf6 100644
--- a/Dalamud/Hooking/Internal/FunctionPointerVariableHook.cs
+++ b/Dalamud/Hooking/Internal/FunctionPointerVariableHook.cs
@@ -13,10 +13,12 @@ namespace Dalamud.Hooking.Internal;
/// Delegate type to represents a function prototype. This must be the same prototype as original function do.
internal class FunctionPointerVariableHook : Hook where T : Delegate
{
- private readonly IntPtr pfnOriginal;
- private readonly T originalDelegate;
+ private readonly nint pfnDetour;
private readonly T detourDelegate;
+ private nint pfnOriginal;
+ private T? originalDelegate;
+
private bool enabled = false;
///
@@ -40,9 +42,8 @@ internal class FunctionPointerVariableHook : Hook where T : Delegate
if (!HookManager.MultiHookTracker.TryGetValue(this.Address, out var indexList))
indexList = HookManager.MultiHookTracker[this.Address] = new();
- this.pfnOriginal = Marshal.ReadIntPtr(this.Address);
- this.originalDelegate = Marshal.GetDelegateForFunctionPointer(this.pfnOriginal);
this.detourDelegate = detour;
+ this.pfnDetour = Marshal.GetFunctionPointerForDelegate(detour);
// Add afterwards, so the hookIdent starts at 0.
indexList.Add(this);
@@ -100,7 +101,10 @@ internal class FunctionPointerVariableHook : Hook where T : Delegate
if (!NativeFunctions.VirtualProtect(this.Address, (UIntPtr)Marshal.SizeOf(), MemoryProtection.ExecuteReadWrite, out var oldProtect))
throw new Win32Exception(Marshal.GetLastWin32Error());
- Marshal.WriteIntPtr(this.Address, Marshal.GetFunctionPointerForDelegate(this.detourDelegate));
+ this.pfnOriginal = Marshal.ReadIntPtr(this.Address);
+ this.originalDelegate = Marshal.GetDelegateForFunctionPointer(this.pfnOriginal);
+ Marshal.WriteIntPtr(this.Address, this.pfnDetour);
+
NativeFunctions.VirtualProtect(this.Address, (UIntPtr)Marshal.SizeOf(), oldProtect, out _);
}
}
@@ -118,6 +122,9 @@ internal class FunctionPointerVariableHook : Hook where T : Delegate
if (!NativeFunctions.VirtualProtect(this.Address, (UIntPtr)Marshal.SizeOf(), MemoryProtection.ExecuteReadWrite, out var oldProtect))
throw new Win32Exception(Marshal.GetLastWin32Error());
+ if (Marshal.ReadIntPtr(this.Address) != this.pfnOriginal)
+ Environment.FailFast("Cannot disable this hook in a sane manner.");
+
Marshal.WriteIntPtr(this.Address, this.pfnOriginal);
NativeFunctions.VirtualProtect(this.Address, (UIntPtr)Marshal.SizeOf(), oldProtect, out _);
}