From 984ff81cb5082a682491f0028528e11ebfd81853 Mon Sep 17 00:00:00 2001 From: Raymond Date: Mon, 2 Aug 2021 17:08:01 -0400 Subject: [PATCH] Hook Changes --- Dalamud/Dalamud.cs | 1 + Dalamud/Dalamud.csproj | 7 - Dalamud/Hooking/Hook.cs | 208 ++++++++++++++---- .../Hooking/{Internal => }/IDalamudHook.cs | 4 +- Dalamud/Hooking/Internal/HookInfo.cs | 43 ++-- Dalamud/Hooking/Internal/HookManager.cs | 35 ++- .../Internal/Implementations/CoreHookImpl.cs | 133 ----------- .../Implementations/IDalamudHookImpl.cs | 28 --- .../Implementations/ReloadedHookImpl.cs | 196 ----------------- .../Interface/Internal/InterfaceManager.cs | 10 +- 10 files changed, 231 insertions(+), 434 deletions(-) rename Dalamud/Hooking/{Internal => }/IDalamudHook.cs (88%) delete mode 100644 Dalamud/Hooking/Internal/Implementations/CoreHookImpl.cs delete mode 100644 Dalamud/Hooking/Internal/Implementations/IDalamudHookImpl.cs delete mode 100644 Dalamud/Hooking/Internal/Implementations/ReloadedHookImpl.cs diff --git a/Dalamud/Dalamud.cs b/Dalamud/Dalamud.cs index 170a64082..e9357c4a6 100644 --- a/Dalamud/Dalamud.cs +++ b/Dalamud/Dalamud.cs @@ -12,6 +12,7 @@ using Dalamud.Game.ClientState; using Dalamud.Game.Command; using Dalamud.Game.Internal; using Dalamud.Game.Network; +using Dalamud.Game.Network.Internal; using Dalamud.Game.Text.SeStringHandling; using Dalamud.Hooking.Internal; using Dalamud.Interface.Internal; diff --git a/Dalamud/Dalamud.csproj b/Dalamud/Dalamud.csproj index 359a77692..2de2bcb7c 100644 --- a/Dalamud/Dalamud.csproj +++ b/Dalamud/Dalamud.csproj @@ -60,7 +60,6 @@ - @@ -107,12 +106,6 @@ - - - PreserveNewest - - - diff --git a/Dalamud/Hooking/Hook.cs b/Dalamud/Hooking/Hook.cs index 3e06f4726..ab6d1fd69 100644 --- a/Dalamud/Hooking/Hook.cs +++ b/Dalamud/Hooking/Hook.cs @@ -1,7 +1,13 @@ using System; +using System.Linq; +using System.Reflection; +using System.Runtime.InteropServices; using Dalamud.Hooking.Internal; -using Dalamud.Hooking.Internal.Implementations; +using Dalamud.Memory; +using Iced.Intel; +using Reloaded.Hooks; +using Serilog; namespace Dalamud.Hooking { @@ -10,9 +16,10 @@ namespace Dalamud.Hooking /// This class is basically a thin wrapper around the LocalHook type to provide helper functions. /// /// Delegate type to represents a function prototype. This must be the same prototype as original function do. - public sealed class Hook : IDisposable where T : Delegate + public sealed class Hook : IDisposable, IDalamudHook where T : Delegate { - private readonly IDalamudHookImpl hookImpl; + private readonly IntPtr address; + private readonly Reloaded.Hooks.Definitions.IHook hookImpl; /// /// Initializes a new instance of the class. @@ -21,50 +28,64 @@ namespace Dalamud.Hooking /// A memory address to install a hook. /// Callback function. Delegate must have a same original function prototype. public Hook(IntPtr address, T detour) - : this(address, detour, false) { - } + address = FollowJmp(address); - /// - /// Initializes a new instance of the class. - /// Hook is not activated until Enable() method is called. - /// - /// A memory address to install a hook. - /// Callback function. Delegate must have a same original function prototype. - /// Follow any JMPs to the actual method that needs hooking. - /// - /// The followJmp parameter is only used when ReloadedHooks are used, which currently is only for Linux users. - /// Generally, this is only necessary when hooking Win32 functions. - /// - public Hook(IntPtr address, T detour, bool followJmp) - { - this.hookImpl = HookManager.DirtyLinuxUser - ? new ReloadedHookImpl(address, detour, followJmp) - : new CoreHookImpl(address, detour); + var hasOtherHooks = HookManager.Originals.ContainsKey(address); + if (!hasOtherHooks) + { + MemoryHelper.ReadRaw(address, 0x32, out var original); + HookManager.Originals[address] = original; + } + + this.address = address; + this.hookImpl = ReloadedHooks.Instance.CreateHook(detour, address.ToInt64()); + + HookManager.TrackedHooks.Add(new HookInfo(this, detour, Assembly.GetCallingAssembly())); } /// /// Gets a memory address of the target function. /// /// Hook is already disposed. - public IntPtr Address => this.hookImpl.Address; + public IntPtr Address + { + get + { + this.CheckDisposed(); + return this.address; + } + } /// /// Gets a delegate function that can be used to call the actual function as if function is not hooked yet. /// /// Hook is already disposed. - public T Original => this.hookImpl.Original; + public T Original + { + get + { + this.CheckDisposed(); + return this.hookImpl.OriginalFunction; + } + } /// /// Gets a value indicating whether or not the hook is enabled. /// - public bool IsEnabled => this.hookImpl.IsEnabled; + public bool IsEnabled + { + get + { + this.CheckDisposed(); + return this.hookImpl.IsHookEnabled; + } + } /// /// Gets a value indicating whether or not the hook has been disposed. /// - public bool IsDisposed => this.hookImpl.IsDisposed; - + public bool IsDisposed { get; private set; } /// /// Creates a hook. Hooking address is inferred by calling to GetProcAddress() function. @@ -76,39 +97,138 @@ namespace Dalamud.Hooking /// The hook with the supplied parameters. public static Hook FromSymbol(string moduleName, string exportName, T detour) { - if (HookManager.DirtyLinuxUser) - { - var moduleHandle = NativeFunctions.GetModuleHandleW(moduleName); - if (moduleHandle == IntPtr.Zero) - throw new Exception($"Could not get a handle to module {moduleName}"); + var moduleHandle = NativeFunctions.GetModuleHandleW(moduleName); + if (moduleHandle == IntPtr.Zero) + throw new Exception($"Could not get a handle to module {moduleName}"); - var procAddress = NativeFunctions.GetProcAddress(moduleHandle, exportName); - if (procAddress == IntPtr.Zero) - throw new Exception($"Could not get the address of {moduleName}::{exportName}"); + var procAddress = NativeFunctions.GetProcAddress(moduleHandle, exportName); + if (procAddress == IntPtr.Zero) + throw new Exception($"Could not get the address of {moduleName}::{exportName}"); - return new Hook(procAddress, detour, true); - } - else - { - var address = CoreHook.LocalHook.GetProcAddress(moduleName, exportName); - return new Hook(address, detour); - } + return new Hook(procAddress, detour); } /// /// Remove a hook from the current process. /// - public void Dispose() => this.hookImpl.Dispose(); + public void Dispose() + { + if (this.IsDisposed) + return; + + this.IsDisposed = true; + + if (this.hookImpl.IsHookEnabled) + this.hookImpl.Disable(); + } /// /// Starts intercepting a call to the function. /// - public void Enable() => this.hookImpl.Enable(); + public void Enable() + { + this.CheckDisposed(); + + if (!this.hookImpl.IsHookActivated) + this.hookImpl.Activate(); + + if (!this.hookImpl.IsHookEnabled) + this.hookImpl.Enable(); + } /// /// Stops intercepting a call to the function. /// - public void Disable() => this.hookImpl.Disable(); + public void Disable() + { + this.CheckDisposed(); + if (!this.hookImpl.IsHookActivated) + return; + + if (this.hookImpl.IsHookEnabled) + this.hookImpl.Disable(); + } + + /// + /// Follow a JMP or Jcc instruction to the next logical location. + /// + /// Address of the instruction. + /// The address referenced by the jmp. + private static IntPtr FollowJmp(IntPtr address) + { + while (true) + { + var hasOtherHooks = HookManager.Originals.ContainsKey(address); + if (hasOtherHooks) + { + // This address has been hooked already. Do not follow a jmp into a trampoline of our own making. + Log.Verbose($"Detected hook trampoline at {address.ToInt64():X}, stopping jump resolution."); + return address; + } + + var bytes = MemoryHelper.ReadRaw(address, 8); + + var codeReader = new ByteArrayCodeReader(bytes); + var decoder = Decoder.Create(64, codeReader); + decoder.IP = (ulong)address.ToInt64(); + decoder.Decode(out var inst); + + if (inst.Mnemonic == Mnemonic.Jmp) + { + var kind = inst.Op0Kind; + + IntPtr newAddress; + switch (inst.Op0Kind) + { + case OpKind.NearBranch64: + case OpKind.NearBranch32: + case OpKind.NearBranch16: + newAddress = (IntPtr)inst.NearBranchTarget; + break; + case OpKind.Immediate16: + case OpKind.Immediate8to16: + case OpKind.Immediate8to32: + case OpKind.Immediate8to64: + case OpKind.Immediate32to64: + case OpKind.Immediate32 when IntPtr.Size == 4: + case OpKind.Immediate64: + newAddress = (IntPtr)inst.GetImmediate(0); + break; + case OpKind.Memory when inst.IsIPRelativeMemoryOperand: + newAddress = (IntPtr)inst.IPRelativeMemoryAddress; + newAddress = Marshal.ReadIntPtr(newAddress); + break; + case OpKind.Memory: + newAddress = (IntPtr)inst.MemoryDisplacement64; + newAddress = Marshal.ReadIntPtr(newAddress); + break; + default: + var debugBytes = string.Join(" ", bytes.Take(inst.Length).Select(b => $"{b:X2}")); + throw new Exception($"Unknown OpKind {inst.Op0Kind} from {debugBytes}"); + } + + Log.Verbose($"Resolving assembly jump ({kind}) from {address.ToInt64():X} to {newAddress.ToInt64():X}"); + address = newAddress; + } + else + { + break; + } + } + + return address; + } + + /// + /// Check if this object has been disposed already. + /// + private void CheckDisposed() + { + if (this.IsDisposed) + { + throw new ObjectDisposedException("Hook is already disposed."); + } + } } } diff --git a/Dalamud/Hooking/Internal/IDalamudHook.cs b/Dalamud/Hooking/IDalamudHook.cs similarity index 88% rename from Dalamud/Hooking/Internal/IDalamudHook.cs rename to Dalamud/Hooking/IDalamudHook.cs index 8fb95195f..deaf62957 100644 --- a/Dalamud/Hooking/Internal/IDalamudHook.cs +++ b/Dalamud/Hooking/IDalamudHook.cs @@ -1,11 +1,11 @@ using System; -namespace Dalamud.Hooking.Internal +namespace Dalamud.Hooking { /// /// Interface describing a generic hook. /// - internal interface IDalamudHook + public interface IDalamudHook { /// /// Gets the address to hook. diff --git a/Dalamud/Hooking/Internal/HookInfo.cs b/Dalamud/Hooking/Internal/HookInfo.cs index a702fed27..c2850b806 100644 --- a/Dalamud/Hooking/Internal/HookInfo.cs +++ b/Dalamud/Hooking/Internal/HookInfo.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Generic; using System.Diagnostics; using System.Reflection; @@ -12,6 +11,19 @@ namespace Dalamud.Hooking.Internal { private ulong? inProcessMemory = 0; + /// + /// Initializes a new instance of the class. + /// + /// The tracked hook. + /// The hook delegate. + /// The assembly implementing the hook. + public HookInfo(IDalamudHook hook, Delegate hookDelegate, Assembly assembly) + { + this.Hook = hook; + this.Delegate = hookDelegate; + this.Assembly = assembly; + } + /// /// Gets the RVA of the hook. /// @@ -19,9 +31,14 @@ namespace Dalamud.Hooking.Internal { get { - if (this.Hook.IsDisposed) return 0; - if (this.inProcessMemory == null) return null; - if (this.inProcessMemory.Value > 0) return this.inProcessMemory.Value; + if (this.Hook.IsDisposed) + return 0; + + if (this.inProcessMemory == null) + return null; + + if (this.inProcessMemory.Value > 0) + return this.inProcessMemory.Value; var p = Process.GetCurrentProcess().MainModule; var begin = (ulong)p.BaseAddress.ToInt64(); @@ -30,30 +47,28 @@ namespace Dalamud.Hooking.Internal if (hookAddr >= begin && hookAddr <= end) { - this.inProcessMemory = hookAddr - begin; - return this.inProcessMemory.Value; + return this.inProcessMemory = hookAddr - begin; } else { - this.inProcessMemory = null; - return null; + return this.inProcessMemory = null; } } } /// - /// Gets or sets the tracked hook. + /// Gets the tracked hook. /// - internal IDalamudHook Hook { get; set; } + internal IDalamudHook Hook { get; } /// - /// Gets or sets the tracked delegate. + /// Gets the tracked delegate. /// - internal Delegate Delegate { get; set; } + internal Delegate Delegate { get; } /// - /// Gets or sets the hooked assembly. + /// Gets the hooked assembly. /// - internal Assembly Assembly { get; set; } + internal Assembly Assembly { get; } } } diff --git a/Dalamud/Hooking/Internal/HookManager.cs b/Dalamud/Hooking/Internal/HookManager.cs index 29d80be47..5741b7d29 100644 --- a/Dalamud/Hooking/Internal/HookManager.cs +++ b/Dalamud/Hooking/Internal/HookManager.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; using Dalamud.Memory; +using Microsoft.Win32; namespace Dalamud.Hooking.Internal { @@ -33,8 +34,32 @@ namespace Dalamud.Hooking.Internal { if (checkLinuxOnce) { - var value = Environment.GetEnvironmentVariable("XL_WINEONLINUX"); - isRunningLinux = value is not null; + checkLinuxOnce = false; + + bool Check1() + { + return Environment.GetEnvironmentVariable("XL_WINEONLINUX") != null; + } + + bool Check2() + { + var hModule = NativeFunctions.GetModuleHandleW("ntdll.dll"); + var proc1 = NativeFunctions.GetProcAddress(hModule, "wine_get_version"); + var proc2 = NativeFunctions.GetProcAddress(hModule, "wine_get_build_id"); + + return proc1 != IntPtr.Zero || proc2 != IntPtr.Zero; + } + + bool Check3() + { + return Registry.CurrentUser.OpenSubKey(@"Software\Wine") != null || + Registry.LocalMachine.OpenSubKey(@"Software\Wine") != null; + } + + if (isRunningLinux = Check1() || Check2() || Check3()) + { + Log.Information($"Dalamud detected running on Wine"); + } } return isRunningLinux; @@ -47,9 +72,9 @@ namespace Dalamud.Hooking.Internal internal static List TrackedHooks { get; } = new(); /// - /// Gets a static list of original code for a hooked address. + /// Gets a static dictionary of original code for a hooked address. /// - internal static List<(IntPtr Address, byte[] Original)> Originals { get; } = new(); + internal static Dictionary Originals { get; } = new(); /// public void Dispose() @@ -74,7 +99,7 @@ namespace Dalamud.Hooking.Internal if (i > 0) { - Log.Debug($"Reverting hook at 0x{address.ToInt64():X}"); + Log.Verbose($"Reverting hook at 0x{address.ToInt64():X}"); fixed (byte* original = originalBytes) { MemoryHelper.ChangePermission(address, i, MemoryProtection.ExecuteReadWrite, out var oldPermissions); diff --git a/Dalamud/Hooking/Internal/Implementations/CoreHookImpl.cs b/Dalamud/Hooking/Internal/Implementations/CoreHookImpl.cs deleted file mode 100644 index bfff3eae8..000000000 --- a/Dalamud/Hooking/Internal/Implementations/CoreHookImpl.cs +++ /dev/null @@ -1,133 +0,0 @@ -using System; -using System.Reflection; -using System.Runtime.InteropServices; - -namespace Dalamud.Hooking.Internal.Implementations -{ - /// - /// Manages a hook which can be used to intercept a call to native function. - /// This class is basically a thin wrapper around the LocalHook type to provide helper functions. - /// - /// Delegate type to represents a function prototype. This must be the same prototype as original function do. - internal sealed class CoreHookImpl : IDisposable, IDalamudHookImpl where T : Delegate - { - private readonly IntPtr address; - - private readonly CoreHook.LocalHook hookImpl; - private readonly T original; - - /// - /// Initializes a new instance of the class. - /// Hook is not activated until Enable() method is called. - /// - /// A memory address to install a hook. - /// Callback function. Delegate must have a same original function prototype. - public CoreHookImpl(IntPtr address, T detour) - { - this.address = address; - - this.hookImpl = CoreHook.LocalHook.Create(address, detour, null); - this.original = Marshal.GetDelegateForFunctionPointer(this.hookImpl.OriginalAddress); - - HookManager.TrackedHooks.Add(new HookInfo(this, detour, Assembly.GetCallingAssembly())); - } - - /// - /// Gets a memory address of the target function. - /// - /// Hook is already disposed. - public IntPtr Address - { - get - { - this.CheckDisposed(); - return this.address; - } - } - - /// - /// Gets a delegate function that can be used to call the actual function as if function is not hooked yet. - /// - /// Hook is already disposed. - public T Original - { - get - { - this.CheckDisposed(); - return this.original; - } - } - - /// - /// Gets a value indicating whether or not the hook is enabled. - /// - public bool IsEnabled - { - get - { - this.CheckDisposed(); - return this.hookImpl.ThreadACL.IsExclusive; - } - } - - /// - /// Gets a value indicating whether or not the hook has been disposed. - /// - public bool IsDisposed { get; private set; } - - /// - /// Creates a hook. Hooking address is inferred by calling to GetProcAddress() function. - /// The hook is not activated until Enable() method is called. - /// - /// A name of the module currently loaded in the memory. (e.g. ws2_32.dll). - /// A name of the exported function name (e.g. send). - /// Callback function. Delegate must have a same original function prototype. - /// The hook with the supplied parameters. - public static IDalamudHookImpl FromSymbol(string moduleName, string exportName, T detour) - { - var address = CoreHook.LocalHook.GetProcAddress(moduleName, exportName); - return new CoreHookImpl(address, detour); - } - - /// - /// Remove a hook from the current process. - /// - public void Dispose() - { - if (this.IsDisposed) - return; - - this.IsDisposed = true; - this.hookImpl.Dispose(); - } - - /// - /// Starts intercepting a call to the function. - /// - public void Enable() - { - this.CheckDisposed(); - this.hookImpl.ThreadACL.SetExclusiveACL(null); - } - - /// - /// Stops intercepting a call to the function. - /// - public void Disable() - { - this.CheckDisposed(); - this.hookImpl.ThreadACL.SetExclusiveACL(null); - } - - /// - /// Check if this object has been disposed already. - /// - private void CheckDisposed() - { - if (this.IsDisposed) - { - throw new ObjectDisposedException("Hook is already disposed."); - } - } - } -} diff --git a/Dalamud/Hooking/Internal/Implementations/IDalamudHookImpl.cs b/Dalamud/Hooking/Internal/Implementations/IDalamudHookImpl.cs deleted file mode 100644 index 6290086d2..000000000 --- a/Dalamud/Hooking/Internal/Implementations/IDalamudHookImpl.cs +++ /dev/null @@ -1,28 +0,0 @@ -using System; - -namespace Dalamud.Hooking.Internal.Implementations -{ - /// - /// Manages a hook which can be used to intercept a call to native function. - /// This class is basically a thin wrapper around the LocalHook type to provide helper functions. - /// - /// Delegate type to represents a function prototype. This must be the same prototype as original function do. - internal interface IDalamudHookImpl : IDisposable, IDalamudHook where T : Delegate - { - /// - /// Gets a delegate function that can be used to call the actual function as if function is not hooked yet. - /// - /// Hook is already disposed. - public T Original { get; } - - /// - /// Starts intercepting a call to the function. - /// - public void Enable(); - - /// - /// Stops intercepting a call to the function. - /// - public void Disable(); - } -} diff --git a/Dalamud/Hooking/Internal/Implementations/ReloadedHookImpl.cs b/Dalamud/Hooking/Internal/Implementations/ReloadedHookImpl.cs deleted file mode 100644 index b8b0bebcc..000000000 --- a/Dalamud/Hooking/Internal/Implementations/ReloadedHookImpl.cs +++ /dev/null @@ -1,196 +0,0 @@ -using System; -using System.Linq; -using System.Reflection; -using System.Runtime.InteropServices; - -using Dalamud.Memory; - -namespace Dalamud.Hooking.Internal.Implementations -{ - /// - /// Manages a hook which can be used to intercept a call to native function. - /// This class is basically a thin wrapper around the LocalHook type to provide helper functions. - /// - /// Delegate type to represents a function prototype. This must be the same prototype as original function do. - internal sealed class ReloadedHookImpl : IDalamudHookImpl where T : Delegate - { - private readonly IntPtr address; - private readonly Reloaded.Hooks.Definitions.IHook hookImpl; - - /// - /// Initializes a new instance of the class. - /// Hook is not activated until Enable() method is called. - /// - /// A memory address to install a hook. - /// Callback function. Delegate must have a same original function prototype. - public ReloadedHookImpl(IntPtr address, T detour) - : this(address, detour, false) - { - } - - /// - /// Initializes a new instance of the class. - /// Hook is not activated until Enable() method is called. - /// - /// A memory address to install a hook. - /// Callback function. Delegate must have a same original function prototype. - /// Follow any JMPs to the actual method that needs hooking. - public ReloadedHookImpl(IntPtr address, T detour, bool followJmp) - { - if (followJmp) - { - // This is horrible hackery to follow various types of JMP. - // It likely needs to stop when entering a reloaded hook trampoline. - // I would much rather use Iced to check against a Instruction type. - while (true) - { - var b1 = Marshal.ReadByte(address); - if (b1 == 0xE9) - { - var jumpOffset = Marshal.ReadInt32(address + 1); - address += jumpOffset + 5; - continue; - } - - var b2 = Marshal.ReadByte(address, 1); - if (b1 == 0xFF && b2 == 0x25) - { - address = Marshal.ReadIntPtr(address + 6); - continue; - } - - break; - } - } - - var otherHook = HookManager.Originals.FirstOrDefault(o => o.Address == address); - if (otherHook == default) - { - MemoryHelper.ReadRaw(address, 50, out var original); - HookManager.Originals.Add((address, original)); - } - - this.address = address; - this.hookImpl = Reloaded.Hooks.ReloadedHooks.Instance.CreateHook(detour, address.ToInt64()); - - HookManager.TrackedHooks.Add(new HookInfo(this, detour, Assembly.GetCallingAssembly())); - } - - /// - /// Gets a memory address of the target function. - /// - /// Hook is already disposed. - public IntPtr Address - { - get - { - this.CheckDisposed(); - return this.address; - } - } - - /// - /// Gets a delegate function that can be used to call the actual function as if function is not hooked yet. - /// - /// Hook is already disposed. - public T Original - { - get - { - this.CheckDisposed(); - return this.hookImpl.OriginalFunction; - } - } - - /// - /// Gets a value indicating whether or not the hook is enabled. - /// - public bool IsEnabled - { - get - { - this.CheckDisposed(); - return this.hookImpl.IsHookEnabled; - } - } - - /// - /// Gets a value indicating whether or not the hook has been disposed. - /// - public bool IsDisposed { get; private set; } - - /// - /// Creates a hook. Hooking address is inferred by calling to GetProcAddress() function. - /// The hook is not activated until Enable() method is called. - /// - /// A name of the module currently loaded in the memory. (e.g. ws2_32.dll). - /// A name of the exported function name (e.g. send). - /// Callback function. Delegate must have a same original function prototype. - /// The hook with the supplied parameters. - public static IDalamudHookImpl FromSymbol(string moduleName, string exportName, T detour) - { - var moduleHandle = NativeFunctions.GetModuleHandleW(moduleName); - if (moduleHandle == IntPtr.Zero) - throw new Exception($"Could not get a handle to module {moduleName}"); - - var procAddress = NativeFunctions.GetProcAddress(moduleHandle, exportName); - if (procAddress == IntPtr.Zero) - throw new Exception($"Could not get the address of {moduleName}::{exportName}"); - - return new ReloadedHookImpl(procAddress, detour, true); - } - - /// - /// Remove a hook from the current process. - /// - public void Dispose() - { - if (this.IsDisposed) - return; - - this.IsDisposed = true; - - if (this.hookImpl.IsHookEnabled) - this.hookImpl.Disable(); - } - - /// - /// Starts intercepting a call to the function. - /// - public void Enable() - { - this.CheckDisposed(); - - if (!this.hookImpl.IsHookActivated) - this.hookImpl.Activate(); - - if (!this.hookImpl.IsHookEnabled) - this.hookImpl.Enable(); - } - - /// - /// Stops intercepting a call to the function. - /// - public void Disable() - { - this.CheckDisposed(); - - if (!this.hookImpl.IsHookActivated) - return; - - if (this.hookImpl.IsHookEnabled) - this.hookImpl.Disable(); - } - - /// - /// Check if this object has been disposed already. - /// - private void CheckDisposed() - { - if (this.IsDisposed) - { - throw new ObjectDisposedException("Hook is already disposed."); - } - } - } -} diff --git a/Dalamud/Interface/Internal/InterfaceManager.cs b/Dalamud/Interface/Internal/InterfaceManager.cs index 9c5fe3f6f..92ed70a67 100644 --- a/Dalamud/Interface/Internal/InterfaceManager.cs +++ b/Dalamud/Interface/Internal/InterfaceManager.cs @@ -104,8 +104,8 @@ namespace Dalamud.Interface.Internal this.setCursorHook = HookManager.DirtyLinuxUser ? null : Hook.FromSymbol("user32.dll", "SetCursor", this.SetCursorDetour); - this.presentHook = new Hook(this.address.Present, this.PresentDetour, true); - this.resizeBuffersHook = new Hook(this.address.ResizeBuffers, this.ResizeBuffersDetour, true); + this.presentHook = new Hook(this.address.Present, this.PresentDetour); + this.resizeBuffersHook = new Hook(this.address.ResizeBuffers, this.ResizeBuffersDetour); var setCursorAddress = this.setCursorHook?.Address ?? IntPtr.Zero; @@ -190,7 +190,7 @@ namespace Dalamud.Interface.Internal /// public void Enable() { - this.setCursorHook.Enable(); + this.setCursorHook?.Enable(); this.presentHook.Enable(); this.resizeBuffersHook.Enable(); @@ -226,7 +226,7 @@ namespace Dalamud.Interface.Internal Thread.Sleep(500); this.scene?.Dispose(); - this.setCursorHook.Dispose(); + this.setCursorHook?.Dispose(); this.presentHook.Dispose(); this.resizeBuffersHook.Dispose(); } @@ -502,7 +502,7 @@ namespace Dalamud.Interface.Internal private void Disable() { - this.setCursorHook.Disable(); + this.setCursorHook?.Disable(); this.presentHook.Disable(); this.resizeBuffersHook.Disable(); }