diff --git a/Dalamud/Hooking/Internal/FunctionPointerVariableHook.cs b/Dalamud/Hooking/Internal/FunctionPointerVariableHook.cs index c80033509..970c55fee 100644 --- a/Dalamud/Hooking/Internal/FunctionPointerVariableHook.cs +++ b/Dalamud/Hooking/Internal/FunctionPointerVariableHook.cs @@ -12,7 +12,7 @@ namespace Dalamud.Hooking.Internal; /// Manages a hook with MinHook. /// /// Delegate type to represents a function prototype. This must be the same prototype as original function do. -internal unsafe class FunctionPointerVariableHook : Hook +internal class FunctionPointerVariableHook : Hook where T : Delegate { private readonly nint pfnDetour; @@ -21,13 +21,13 @@ internal unsafe class FunctionPointerVariableHook : Hook // ReSharper disable once NotAccessedField.Local private readonly T detourDelegate; - private readonly byte* pfnThunk; - private readonly nint* ppfnThunkJumpTarget; + private readonly nint pfnThunk; + private readonly nint ppfnThunkJumpTarget; private readonly nint pfnOriginal; private readonly T originalDelegate; - private bool enabled = false; + private bool enabled; /// /// Initializes a new instance of the class. @@ -55,20 +55,26 @@ internal unsafe class FunctionPointerVariableHook : Hook this.detourDelegate = detour; this.pfnDetour = Marshal.GetFunctionPointerForDelegate(detour); - this.pfnThunk = (byte*)NativeFunctions.HeapAlloc(HookManager.NoFreeExecutableHeap, 0, 12); - if (this.pfnThunk == null) + unsafe { - throw new OutOfMemoryException("Failed to allocate memory for import hooks."); + var pfnThunkBytes = (byte*)NativeFunctions.HeapAlloc(HookManager.NoFreeExecutableHeap, 0, 12); + if (pfnThunkBytes == null) + { + throw new OutOfMemoryException("Failed to allocate memory for import hooks."); + } + + // movabs rax, imm + pfnThunkBytes[0] = 0x48; + pfnThunkBytes[1] = 0xB8; + + // jmp rax + pfnThunkBytes[10] = 0xFF; + pfnThunkBytes[11] = 0xE0; + + this.pfnThunk = (nint)pfnThunkBytes; } - // movabs rax, imm - this.pfnThunk[0] = 0x48; - this.pfnThunk[1] = 0xB8; - this.ppfnThunkJumpTarget = (nint*)&this.pfnThunk[2]; - - // jmp rax - this.pfnThunk[10] = 0xFF; - this.pfnThunk[11] = 0xE0; + this.ppfnThunkJumpTarget = this.pfnThunk + 2; if (!NativeFunctions.VirtualProtect( this.Address, @@ -81,8 +87,8 @@ internal unsafe class FunctionPointerVariableHook : Hook this.pfnOriginal = Marshal.ReadIntPtr(this.Address); this.originalDelegate = Marshal.GetDelegateForFunctionPointer(this.pfnOriginal); - *this.ppfnThunkJumpTarget = this.pfnOriginal; - Marshal.WriteIntPtr(this.Address, this.pfnDetour); + Marshal.WriteIntPtr(this.ppfnThunkJumpTarget, this.pfnOriginal); + Marshal.WriteIntPtr(this.Address, this.pfnThunk); // This really should not fail, but then even if it does, whatever. NativeFunctions.VirtualProtect(this.Address, (UIntPtr)Marshal.SizeOf(), oldProtect, out _); @@ -145,7 +151,7 @@ internal unsafe class FunctionPointerVariableHook : Hook lock (HookManager.HookEnableSyncRoot) { - *this.ppfnThunkJumpTarget = this.pfnDetour; + Marshal.WriteIntPtr(this.ppfnThunkJumpTarget, this.pfnDetour); this.enabled = true; } } @@ -162,7 +168,7 @@ internal unsafe class FunctionPointerVariableHook : Hook lock (HookManager.HookEnableSyncRoot) { - *this.ppfnThunkJumpTarget = this.pfnOriginal; + Marshal.WriteIntPtr(this.ppfnThunkJumpTarget, this.pfnOriginal); this.enabled = false; } }