another fix

This commit is contained in:
Soreepeong 2023-03-10 22:53:48 +09:00
parent 9ee8ad67b4
commit f16628beb0

View file

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