From 429316747de4dd1921cd0bb1cb81fff2e1cbd9dd Mon Sep 17 00:00:00 2001 From: nebel Date: Sun, 4 Jun 2023 01:48:18 +0900 Subject: [PATCH] Add minBytes and maxBytes to Unhooker --- .../Internal/FunctionPointerVariableHook.cs | 2 +- Dalamud/Hooking/Internal/HookManager.cs | 8 ++++--- Dalamud/Hooking/Internal/Unhooker.cs | 21 ++++++++++++++----- 3 files changed, 22 insertions(+), 9 deletions(-) diff --git a/Dalamud/Hooking/Internal/FunctionPointerVariableHook.cs b/Dalamud/Hooking/Internal/FunctionPointerVariableHook.cs index 1c0bcfa05..e1900a903 100644 --- a/Dalamud/Hooking/Internal/FunctionPointerVariableHook.cs +++ b/Dalamud/Hooking/Internal/FunctionPointerVariableHook.cs @@ -41,7 +41,7 @@ internal class FunctionPointerVariableHook : Hook { lock (HookManager.HookEnableSyncRoot) { - var unhooker = HookManager.RegisterUnhooker(this.Address); + var unhooker = HookManager.RegisterUnhooker(this.Address, 8, 8); if (!HookManager.MultiHookTracker.TryGetValue(this.Address, out var indexList)) { diff --git a/Dalamud/Hooking/Internal/HookManager.cs b/Dalamud/Hooking/Internal/HookManager.cs index 11a7be337..43858d012 100644 --- a/Dalamud/Hooking/Internal/HookManager.cs +++ b/Dalamud/Hooking/Internal/HookManager.cs @@ -46,11 +46,13 @@ internal class HookManager : IDisposable, IServiceType /// an existing instance if the address registered previously. /// /// The address of the instruction. + /// The minimum amount of bytes to restore when unhooking. Defaults to 0. + /// The maximum amount of bytes to restore when unhooking. Defaults to 0x32. /// A new Unhooker instance. - public static Unhooker RegisterUnhooker(IntPtr address) + public static Unhooker RegisterUnhooker(IntPtr address, int minBytes = 0, int maxBytes = 0x32) { - Log.Verbose($"Registering hook at 0x{address.ToInt64():X}"); - return Unhookers.GetOrAdd(address, adr => new Unhooker(adr)); + Log.Verbose($"Registering hook at 0x{address.ToInt64():X} (minBytes=0x{minBytes:X}, maxBytes=0x{maxBytes:X})"); + return Unhookers.GetOrAdd(address, _ => new Unhooker(address, minBytes, maxBytes)); } /// diff --git a/Dalamud/Hooking/Internal/Unhooker.cs b/Dalamud/Hooking/Internal/Unhooker.cs index e609dd85e..09b071ee9 100644 --- a/Dalamud/Hooking/Internal/Unhooker.cs +++ b/Dalamud/Hooking/Internal/Unhooker.cs @@ -11,6 +11,7 @@ namespace Dalamud.Hooking.Internal; public class Unhooker { private readonly IntPtr address; + private readonly int minBytes; private byte[] originalBytes; private bool trimmed; @@ -20,10 +21,18 @@ public class Unhooker /// removed. As such this class should be instantiated before the function is actually hooked. /// /// The address which will be hooked. - public Unhooker(IntPtr address) + /// The minimum amount of bytes to restore when unhooking. + /// The maximum amount of bytes to restore when unhooking. + internal Unhooker(IntPtr address, int minBytes, int maxBytes) { + if (minBytes < 0 || minBytes > maxBytes) + { + throw new ArgumentException($"minBytes ({minBytes}) must be <= maxBytes ({maxBytes}) and nonnegative."); + } + this.address = address; - MemoryHelper.ReadRaw(address, 0x32, out this.originalBytes); + this.minBytes = minBytes; + MemoryHelper.ReadRaw(address, maxBytes, out this.originalBytes); } /// @@ -39,7 +48,9 @@ public class Unhooker return; } - this.originalBytes = this.originalBytes[..this.GetFullHookLength()]; + var len = int.Max(this.GetFullHookLength(), this.minBytes); + + this.originalBytes = this.originalBytes[..len]; this.trimmed = true; } @@ -51,7 +62,7 @@ public class Unhooker /// public void Unhook() { - var len = this.trimmed ? this.originalBytes.Length : this.GetNaiveHookLength(); + var len = this.trimmed ? this.originalBytes.Length : int.Max(this.GetNaiveHookLength(), this.minBytes); if (len > 0) { HookManager.Log.Verbose($"Reverting hook at 0x{this.address.ToInt64():X} ({len} bytes, trimmed={this.trimmed})"); @@ -82,7 +93,7 @@ public class Unhooker { if (current[i] != this.originalBytes[i]) { - return i + 1; + return int.Max(i + 1, this.minBytes); } }