Merge pull request #646 from goatcorp/corehook

This commit is contained in:
goaaats 2021-10-21 01:47:32 +02:00 committed by GitHub
commit a7ac7b48cf
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 141 additions and 21 deletions

View file

@ -0,0 +1,33 @@
using System;
namespace Dalamud.Configuration.Internal
{
/// <summary>
/// Environmental configuration settings.
/// </summary>
internal class EnvironmentConfiguration
{
/// <summary>
/// Gets a value indicating whether the DALAMUD_NOT_HAVE_INTERFACE setting has been enabled.
/// </summary>
public static bool DalamudNoInterface { get; } = GetEnvironmentVariable("DALAMUD_NOT_HAVE_INTERFACE");
/// <summary>
/// Gets a value indicating whether the XL_WINEONLINUX setting has been enabled.
/// </summary>
public static bool XlWineOnLinux { get; } = GetEnvironmentVariable("XL_WINEONLINUX");
/// <summary>
/// Gets a value indicating whether the DALAMUD_NOT_HAVE_PLUGINS setting has been enabled.
/// </summary>
public static bool DalamudNoPlugins { get; } = GetEnvironmentVariable("DALAMUD_NOT_HAVE_PLUGINS");
/// <summary>
/// Gets a value indicating whether the DalamudForceCoreHook setting has been enabled.
/// </summary>
public static bool DalamudForceCoreHook { get; } = GetEnvironmentVariable("DALAMUD_FORCE_COREHOOK");
private static bool GetEnvironmentVariable(string name)
=> bool.Parse(Environment.GetEnvironmentVariable(name) ?? "false");
}
}

View file

@ -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
{

View file

@ -64,6 +64,7 @@
<ItemGroup>
<PackageReference Include="CheapLoc" Version="1.1.6" />
<PackageReference Include="CoreHook" Version="1.0.4" />
<PackageReference Include="JetBrains.Annotations" Version="2021.2.0" />
<PackageReference Include="Lumina" Version="3.3.0" />
<PackageReference Include="Lumina.Excel" Version="5.50.0" />
@ -93,6 +94,12 @@
<AdditionalFiles Include="..\stylecop.json" />
</ItemGroup>
<ItemGroup>
<None Update="corehook64.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
<Target Name="AddRuntimeDependenciesToContent" BeforeTargets="GetCopyToOutputDirectoryItems" DependsOnTargets="GenerateBuildDependencyFile;GenerateBuildRuntimeConfigurationFiles">
<ItemGroup>
<ContentWithTargetPath Include="$(ProjectDepsFilePath)" CopyToOutputDirectory="PreserveNewest" TargetPath="$(ProjectDepsFileName)" />

View file

@ -20,7 +20,7 @@ namespace Dalamud.Game.Network.Internal
public WinSockHandlers()
{
this.ws2SocketHook = HookManager.DirtyLinuxUser ? null
: Hook<SocketDelegate>.FromSymbol("ws2_32.dll", "socket", this.OnSocket);
: Hook<SocketDelegate>.FromSymbol("ws2_32.dll", "socket", this.OnSocket, true);
this.ws2SocketHook?.Enable();
}

View file

@ -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<T> hookImpl;
private readonly CoreHook.IHook<T> coreHookImpl;
private readonly bool isCoreHook;
/// <summary>
/// Initializes a new instance of the <see cref="Hook{T}"/> class.
@ -24,8 +27,22 @@ namespace Dalamud.Hooking
/// <param name="address">A memory address to install a hook.</param>
/// <param name="detour">Callback function. Delegate must have a same original function prototype.</param>
public Hook(IntPtr address, T detour)
: this(address, detour, false)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="Hook{T}"/> 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.
/// </summary>
/// <param name="address">A memory address to install a hook.</param>
/// <param name="detour">Callback function. Delegate must have a same original function prototype.</param>
/// <param name="useCoreHook">Use the corehook hooking library instead of Reloaded.</param>
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<T>(detour, address.ToInt64());
if (this.isCoreHook)
{
this.coreHookImpl = CoreHook.HookFactory.CreateHook<T>(address, detour);
}
else
{
this.hookImpl = ReloadedHooks.Instance.CreateHook<T>(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
/// <param name="detour">Callback function. Delegate must have a same original function prototype.</param>
/// <returns>The hook with the supplied parameters.</returns>
public static Hook<T> FromSymbol(string moduleName, string exportName, T detour)
=> FromSymbol(moduleName, exportName, detour, false);
/// <summary>
/// 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.
/// </summary>
/// <param name="moduleName">A name of the module currently loaded in the memory. (e.g. ws2_32.dll).</param>
/// <param name="exportName">A name of the exported function name (e.g. send).</param>
/// <param name="detour">Callback function. Delegate must have a same original function prototype.</param>
/// <param name="useCoreHook">Use the corehook hooking library instead of Reloaded.</param>
/// <returns>The hook with the supplied parameters.</returns>
public static Hook<T> 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<T>(procAddress, detour);
return new Hook<T>(procAddress, detour, useCoreHook);
}
/// <summary>
@ -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;
}
/// <summary>
@ -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();
}
}
/// <summary>
@ -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();
}
}
/// <summary>

View file

@ -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()

View file

@ -95,7 +95,7 @@ namespace Dalamud.Interface.Internal
}
this.setCursorHook = HookManager.DirtyLinuxUser ? null
: Hook<SetCursorDelegate>.FromSymbol("user32.dll", "SetCursor", this.SetCursorDetour);
: Hook<SetCursorDelegate>.FromSymbol("user32.dll", "SetCursor", this.SetCursorDetour, true);
this.presentHook = new Hook<PresentDelegate>(this.address.Present, this.PresentDetour);
this.resizeBuffersHook = new Hook<ResizeBuffersDelegate>(this.address.ResizeBuffers, this.ResizeBuffersDetour);

View file

@ -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();

View file

@ -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<ThirdPartyRepoSettings> ThirdRepo { get; set; }
}
}

BIN
Dalamud/corehook64.dll Normal file

Binary file not shown.