diff --git a/Dalamud/Configuration/Internal/EnvironmentConfiguration.cs b/Dalamud/Configuration/Internal/EnvironmentConfiguration.cs
new file mode 100644
index 000000000..b271ee4a4
--- /dev/null
+++ b/Dalamud/Configuration/Internal/EnvironmentConfiguration.cs
@@ -0,0 +1,33 @@
+using System;
+
+namespace Dalamud.Configuration.Internal
+{
+ ///
+ /// Environmental configuration settings.
+ ///
+ internal class EnvironmentConfiguration
+ {
+ ///
+ /// Gets a value indicating whether the DALAMUD_NOT_HAVE_INTERFACE setting has been enabled.
+ ///
+ public static bool DalamudNoInterface { get; } = GetEnvironmentVariable("DALAMUD_NOT_HAVE_INTERFACE");
+
+ ///
+ /// Gets a value indicating whether the XL_WINEONLINUX setting has been enabled.
+ ///
+ public static bool XlWineOnLinux { get; } = GetEnvironmentVariable("XL_WINEONLINUX");
+
+ ///
+ /// Gets a value indicating whether the DALAMUD_NOT_HAVE_PLUGINS setting has been enabled.
+ ///
+ public static bool DalamudNoPlugins { get; } = GetEnvironmentVariable("DALAMUD_NOT_HAVE_PLUGINS");
+
+ ///
+ /// Gets a value indicating whether the DalamudForceCoreHook setting has been enabled.
+ ///
+ public static bool DalamudForceCoreHook { get; } = GetEnvironmentVariable("DALAMUD_FORCE_COREHOOK");
+
+ private static bool GetEnvironmentVariable(string name)
+ => bool.Parse(Environment.GetEnvironmentVariable(name) ?? "false");
+ }
+}
diff --git a/Dalamud/Dalamud.cs b/Dalamud/Dalamud.cs
index 803fd346b..beacf3a6b 100644
--- a/Dalamud/Dalamud.cs
+++ b/Dalamud/Dalamud.cs
@@ -186,7 +186,7 @@ namespace Dalamud
Log.Information("[T2] LOC OK!");
- if (!bool.Parse(Environment.GetEnvironmentVariable("DALAMUD_NOT_HAVE_INTERFACE") ?? "false"))
+ if (!EnvironmentConfiguration.DalamudNoInterface)
{
try
{
diff --git a/Dalamud/Dalamud.csproj b/Dalamud/Dalamud.csproj
index 9415888d8..774f7aa25 100644
--- a/Dalamud/Dalamud.csproj
+++ b/Dalamud/Dalamud.csproj
@@ -64,6 +64,7 @@
+
@@ -93,6 +94,12 @@
+
+
+ PreserveNewest
+
+
+
diff --git a/Dalamud/Game/Network/Internal/WinSockHandlers.cs b/Dalamud/Game/Network/Internal/WinSockHandlers.cs
index 68be91fb1..281291210 100644
--- a/Dalamud/Game/Network/Internal/WinSockHandlers.cs
+++ b/Dalamud/Game/Network/Internal/WinSockHandlers.cs
@@ -20,7 +20,7 @@ namespace Dalamud.Game.Network.Internal
public WinSockHandlers()
{
this.ws2SocketHook = HookManager.DirtyLinuxUser ? null
- : Hook.FromSymbol("ws2_32.dll", "socket", this.OnSocket);
+ : Hook.FromSymbol("ws2_32.dll", "socket", this.OnSocket, true);
this.ws2SocketHook?.Enable();
}
diff --git a/Dalamud/Hooking/Hook.cs b/Dalamud/Hooking/Hook.cs
index feea082d7..25471a23f 100644
--- a/Dalamud/Hooking/Hook.cs
+++ b/Dalamud/Hooking/Hook.cs
@@ -1,6 +1,7 @@
using System;
using System.Reflection;
+using Dalamud.Configuration.Internal;
using Dalamud.Hooking.Internal;
using Dalamud.Memory;
using Reloaded.Hooks;
@@ -16,6 +17,8 @@ namespace Dalamud.Hooking
{
private readonly IntPtr address;
private readonly Reloaded.Hooks.Definitions.IHook hookImpl;
+ private readonly CoreHook.IHook coreHookImpl;
+ private readonly bool isCoreHook;
///
/// Initializes a new instance of the class.
@@ -24,8 +27,22 @@ 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)
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ /// Hook is not activated until Enable() method is called.
+ /// Please do not use CoreHook unless you have thoroughly troubleshot why Reloaded does not work.
+ ///
+ /// A memory address to install a hook.
+ /// Callback function. Delegate must have a same original function prototype.
+ /// Use the corehook hooking library instead of Reloaded.
+ public Hook(IntPtr address, T detour, bool useCoreHook)
{
address = HookManager.FollowJmp(address);
+ this.isCoreHook = useCoreHook || EnvironmentConfiguration.DalamudForceCoreHook;
var hasOtherHooks = HookManager.Originals.ContainsKey(address);
if (!hasOtherHooks)
@@ -35,7 +52,14 @@ namespace Dalamud.Hooking
}
this.address = address;
- this.hookImpl = ReloadedHooks.Instance.CreateHook(detour, address.ToInt64());
+ if (this.isCoreHook)
+ {
+ this.coreHookImpl = CoreHook.HookFactory.CreateHook(address, detour);
+ }
+ else
+ {
+ this.hookImpl = ReloadedHooks.Instance.CreateHook(detour, address.ToInt64());
+ }
HookManager.TrackedHooks.Add(new HookInfo(this, detour, Assembly.GetCallingAssembly()));
}
@@ -62,7 +86,14 @@ namespace Dalamud.Hooking
get
{
this.CheckDisposed();
- return this.hookImpl.OriginalFunction;
+ if (this.isCoreHook)
+ {
+ return this.coreHookImpl.Original;
+ }
+ else
+ {
+ return this.hookImpl.OriginalFunction;
+ }
}
}
@@ -74,7 +105,14 @@ namespace Dalamud.Hooking
get
{
this.CheckDisposed();
- return this.hookImpl.IsHookEnabled;
+ if (this.isCoreHook)
+ {
+ return this.coreHookImpl.Enabled;
+ }
+ else
+ {
+ return this.hookImpl.IsHookEnabled;
+ }
}
}
@@ -92,6 +130,19 @@ namespace Dalamud.Hooking
/// Callback function. Delegate must have a same original function prototype.
/// The hook with the supplied parameters.
public static Hook FromSymbol(string moduleName, string exportName, T detour)
+ => FromSymbol(moduleName, exportName, detour, false);
+
+ ///
+ /// Creates a hook. Hooking address is inferred by calling to GetProcAddress() function.
+ /// The hook is not activated until Enable() method is called.
+ /// Please do not use CoreHook unless you have thoroughly troubleshot why Reloaded does not work.
+ ///
+ /// 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.
+ /// Use the corehook hooking library instead of Reloaded.
+ /// The hook with the supplied parameters.
+ public static Hook FromSymbol(string moduleName, string exportName, T detour, bool useCoreHook)
{
var moduleHandle = NativeFunctions.GetModuleHandleW(moduleName);
if (moduleHandle == IntPtr.Zero)
@@ -101,7 +152,7 @@ namespace Dalamud.Hooking
if (procAddress == IntPtr.Zero)
throw new Exception($"Could not get the address of {moduleName}::{exportName}");
- return new Hook(procAddress, detour);
+ return new Hook(procAddress, detour, useCoreHook);
}
///
@@ -112,10 +163,19 @@ namespace Dalamud.Hooking
if (this.IsDisposed)
return;
- this.IsDisposed = true;
+ if (this.isCoreHook)
+ {
+ this.Disable();
+ // Disposing CoreHook causes an APPCRASH on game exit.
+ // We already overwrite the original hook code, so there shouldn't be any real risk with not disposing here.
+ // this.coreHookImpl.Dispose();
+ }
+ else
+ {
+ this.Disable();
+ }
- if (this.hookImpl.IsHookEnabled)
- this.hookImpl.Disable();
+ this.IsDisposed = true;
}
///
@@ -125,11 +185,19 @@ namespace Dalamud.Hooking
{
this.CheckDisposed();
- if (!this.hookImpl.IsHookActivated)
- this.hookImpl.Activate();
+ if (this.isCoreHook)
+ {
+ if (!this.coreHookImpl.Enabled)
+ this.coreHookImpl.Enabled = true;
+ }
+ else
+ {
+ if (!this.hookImpl.IsHookActivated)
+ this.hookImpl.Activate();
- if (!this.hookImpl.IsHookEnabled)
- this.hookImpl.Enable();
+ if (!this.hookImpl.IsHookEnabled)
+ this.hookImpl.Enable();
+ }
}
///
@@ -139,11 +207,19 @@ namespace Dalamud.Hooking
{
this.CheckDisposed();
- if (!this.hookImpl.IsHookActivated)
- return;
+ if (this.isCoreHook)
+ {
+ if (this.coreHookImpl.Enabled)
+ this.coreHookImpl.Enabled = false;
+ }
+ else
+ {
+ if (!this.hookImpl.IsHookActivated)
+ return;
- if (this.hookImpl.IsHookEnabled)
- this.hookImpl.Disable();
+ if (this.hookImpl.IsHookEnabled)
+ this.hookImpl.Disable();
+ }
}
///
diff --git a/Dalamud/Hooking/Internal/HookManager.cs b/Dalamud/Hooking/Internal/HookManager.cs
index 483a0e4af..1f67ee1e8 100644
--- a/Dalamud/Hooking/Internal/HookManager.cs
+++ b/Dalamud/Hooking/Internal/HookManager.cs
@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
+using Dalamud.Configuration.Internal;
using Dalamud.Logging.Internal;
using Dalamud.Memory;
using Iced.Intel;
@@ -40,7 +41,7 @@ namespace Dalamud.Hooking.Internal
bool Check1()
{
- return Environment.GetEnvironmentVariable("XL_WINEONLINUX") != null;
+ return EnvironmentConfiguration.XlWineOnLinux;
}
bool Check2()
diff --git a/Dalamud/Interface/Internal/InterfaceManager.cs b/Dalamud/Interface/Internal/InterfaceManager.cs
index de477ae0d..150c050e7 100644
--- a/Dalamud/Interface/Internal/InterfaceManager.cs
+++ b/Dalamud/Interface/Internal/InterfaceManager.cs
@@ -95,7 +95,7 @@ namespace Dalamud.Interface.Internal
}
this.setCursorHook = HookManager.DirtyLinuxUser ? null
- : Hook.FromSymbol("user32.dll", "SetCursor", this.SetCursorDetour);
+ : Hook.FromSymbol("user32.dll", "SetCursor", this.SetCursorDetour, true);
this.presentHook = new Hook(this.address.Present, this.PresentDetour);
this.resizeBuffersHook = new Hook(this.address.ResizeBuffers, this.ResizeBuffersDetour);
diff --git a/Dalamud/Plugin/Internal/PluginManager.cs b/Dalamud/Plugin/Internal/PluginManager.cs
index e1d3e0171..536f9e48e 100644
--- a/Dalamud/Plugin/Internal/PluginManager.cs
+++ b/Dalamud/Plugin/Internal/PluginManager.cs
@@ -56,8 +56,8 @@ namespace Dalamud.Plugin.Internal
if (!this.devPluginDirectory.Exists)
this.devPluginDirectory.Create();
- var noPlugins = bool.Parse(Environment.GetEnvironmentVariable("DALAMUD_NOT_HAVE_PLUGINS") ?? "false");
- if (this.SafeMode = noPlugins || configuration.PluginSafeMode)
+ this.SafeMode = EnvironmentConfiguration.DalamudNoPlugins || configuration.PluginSafeMode;
+ if (this.SafeMode)
{
configuration.PluginSafeMode = false;
configuration.Save();
diff --git a/Dalamud/Support/Troubleshooting.cs b/Dalamud/Support/Troubleshooting.cs
index 14440e48b..e2e892b77 100644
--- a/Dalamud/Support/Troubleshooting.cs
+++ b/Dalamud/Support/Troubleshooting.cs
@@ -74,6 +74,7 @@ namespace Dalamud.Support
DoPluginTest = configuration.DoPluginTest,
InterfaceLoaded = interfaceManager?.IsReady ?? false,
ThirdRepo = configuration.ThirdRepoList,
+ ForcedCoreHook = EnvironmentConfiguration.DalamudForceCoreHook,
};
var encodedPayload = Convert.ToBase64String(Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(payload)));
@@ -112,6 +113,8 @@ namespace Dalamud.Support
public bool InterfaceLoaded { get; set; }
+ public bool ForcedCoreHook { get; set; }
+
public List ThirdRepo { get; set; }
}
}
diff --git a/Dalamud/corehook64.dll b/Dalamud/corehook64.dll
new file mode 100644
index 000000000..9b21a40d1
Binary files /dev/null and b/Dalamud/corehook64.dll differ