diff --git a/Dalamud/Hooking/Internal/FunctionPointerVariableHook.cs b/Dalamud/Hooking/Internal/FunctionPointerVariableHook.cs index 3e88780eb..e75d9c180 100644 --- a/Dalamud/Hooking/Internal/FunctionPointerVariableHook.cs +++ b/Dalamud/Hooking/Internal/FunctionPointerVariableHook.cs @@ -58,7 +58,14 @@ internal class FunctionPointerVariableHook : Hook unsafe { - var pfnThunkBytes = (byte*)NativeFunctions.HeapAlloc(HookManager.NoFreeExecutableHeap, 0, 12); + // Note: WINE seemingly tries to clean up all heap allocations on process exit. + // We want our allocation to be kept there forever, until no running thread remains. + // Therefore we're using VirtualAlloc instead of HeapCreate/HeapAlloc. + var pfnThunkBytes = (byte*)NativeFunctions.VirtualAlloc( + 0, + 12, + NativeFunctions.AllocationType.Reserve | NativeFunctions.AllocationType.Commit, + MemoryProtection.ExecuteReadWrite); if (pfnThunkBytes == null) { throw new OutOfMemoryException("Failed to allocate memory for import hooks."); diff --git a/Dalamud/Hooking/Internal/HookManager.cs b/Dalamud/Hooking/Internal/HookManager.cs index d26bcefa0..303802ff6 100644 --- a/Dalamud/Hooking/Internal/HookManager.cs +++ b/Dalamud/Hooking/Internal/HookManager.cs @@ -16,13 +16,6 @@ namespace Dalamud.Hooking.Internal; [ServiceManager.EarlyLoadedService] internal class HookManager : IDisposable, IServiceType { - /// - /// Handle to an executable heap that we shall never free anything unless we can be absolutely sure that nothing is - /// referencing to it anymore. - /// - internal static readonly nint NoFreeExecutableHeap = - NativeFunctions.HeapCreate(NativeFunctions.HeapOptions.CreateEnableExecute, 0, 0); - private static readonly ModuleLog Log = new("HM"); [ServiceManager.ServiceConstructor]