chore: fix some warnings, cleanup

This commit is contained in:
goat 2022-04-25 20:04:17 +02:00
parent 9a38a9470c
commit 96ed22534c
No known key found for this signature in database
GPG key ID: 7773BB5B43BA52E5
49 changed files with 413 additions and 440 deletions

View file

@ -1,8 +1,6 @@
using System; using System;
using System.Numerics; using System.Numerics;
using Dalamud.Interface;
using Dalamud.Interface.Colors;
using Dalamud.Interface.Windowing; using Dalamud.Interface.Windowing;
using ImGuiNET; using ImGuiNET;

View file

@ -6,7 +6,6 @@ using System.Linq;
using System.Reflection; using System.Reflection;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Text; using System.Text;
using System.Threading;
using Dalamud.Game; using Dalamud.Game;
using Newtonsoft.Json; using Newtonsoft.Json;
@ -573,7 +572,7 @@ namespace Dalamud.Injector
return null; return null;
} }
return new NativeAclFix.ExistingProcess(inheritableCurrentProcessHandle); return new ExistingProcess(inheritableCurrentProcessHandle);
} }
private static int ProcessLaunchTestCommand(List<string> args) private static int ProcessLaunchTestCommand(List<string> args)
@ -605,7 +604,7 @@ namespace Dalamud.Injector
var result = JsonSerializer.CreateDefault().Deserialize<Dictionary<string, int>>(new JsonTextReader(helperProcess.StandardOutput)); var result = JsonSerializer.CreateDefault().Deserialize<Dictionary<string, int>>(new JsonTextReader(helperProcess.StandardOutput));
var pid = result["pid"]; var pid = result["pid"];
var handle = (IntPtr)result["handle"]; var handle = (IntPtr)result["handle"];
var resultProcess = new NativeAclFix.ExistingProcess(handle); var resultProcess = new ExistingProcess(handle);
Console.WriteLine("PID: {0}, Handle: {1}", pid, handle); Console.WriteLine("PID: {0}, Handle: {1}", pid, handle);
Console.WriteLine("Press Enter to force quit"); Console.WriteLine("Press Enter to force quit");
Console.ReadLine(); Console.ReadLine();

View file

@ -0,0 +1,34 @@
using System;
using System.Diagnostics;
using System.Reflection;
using Microsoft.Win32.SafeHandles;
namespace Dalamud.Injector;
/// <summary>
/// Class representing an already held process handle.
/// </summary>
internal class ExistingProcess : Process
{
/// <summary>
/// Initializes a new instance of the <see cref="ExistingProcess"/> class.
/// </summary>
/// <param name="handle">The existing held process handle.</param>
public ExistingProcess(IntPtr handle)
{
this.SetHandle(handle);
}
private void SetHandle(IntPtr handle)
{
var baseType = this.GetType().BaseType;
if (baseType == null)
return;
var setProcessHandleMethod = baseType.GetMethod(
"SetProcessHandle",
BindingFlags.NonPublic | BindingFlags.Instance);
setProcessHandleMethod?.Invoke(this, new object[] { new SafeProcessHandle(handle, true) });
}
}

View file

@ -1,21 +1,262 @@
using System; using System;
using System.Collections.Generic;
using System.ComponentModel; using System.ComponentModel;
using System.Runtime.InteropServices;
using System.Linq;
using System.Diagnostics; using System.Diagnostics;
using System.Reflection; using System.Diagnostics.CodeAnalysis;
using Microsoft.Win32.SafeHandles; using System.Runtime.InteropServices;
using System.Threading; using System.Threading;
using Serilog; using Serilog;
// ReSharper disable InconsistentNaming // ReSharper disable InconsistentNaming
namespace Dalamud.Injector namespace Dalamud.Injector
{ {
/// <summary>
/// Class responsible for stripping ACL protections from processes.
/// </summary>
public static class NativeAclFix public static class NativeAclFix
{ {
/// <summary>
/// Start a process without ACL protections.
/// </summary>
/// <param name="workingDir">The working directory.</param>
/// <param name="exePath">The path to the executable file.</param>
/// <param name="arguments">Arguments to pass to the executable file.</param>
/// <param name="beforeResume">Action to execute before the process is started.</param>
/// <returns>The started process.</returns>
/// <exception cref="Win32Exception">Thrown when a win32 error occurs.</exception>
/// <exception cref="GameExitedException">Thrown when the process did not start correctly.</exception>
public static Process LaunchGame(string workingDir, string exePath, string arguments, Action<Process> beforeResume)
{
Process process = null;
var userName = Environment.UserName;
var pExplicitAccess = default(PInvoke.EXPLICIT_ACCESS);
PInvoke.BuildExplicitAccessWithName(
ref pExplicitAccess,
userName,
PInvoke.STANDARD_RIGHTS_ALL | PInvoke.SPECIFIC_RIGHTS_ALL & ~PInvoke.PROCESS_VM_WRITE,
PInvoke.GRANT_ACCESS,
0);
if (PInvoke.SetEntriesInAcl(1, ref pExplicitAccess, IntPtr.Zero, out var newAcl) != 0)
{
throw new Win32Exception(Marshal.GetLastWin32Error());
}
if (!PInvoke.InitializeSecurityDescriptor(out var secDesc, PInvoke.SECURITY_DESCRIPTOR_REVISION))
{
throw new Win32Exception(Marshal.GetLastWin32Error());
}
if (!PInvoke.SetSecurityDescriptorDacl(ref secDesc, true, newAcl, false))
{
throw new Win32Exception(Marshal.GetLastWin32Error());
}
var psecDesc = Marshal.AllocHGlobal(Marshal.SizeOf<PInvoke.SECURITY_DESCRIPTOR>());
Marshal.StructureToPtr(secDesc, psecDesc, true);
var lpProcessInformation = default(PInvoke.PROCESS_INFORMATION);
try
{
var lpProcessAttributes = new PInvoke.SECURITY_ATTRIBUTES
{
nLength = Marshal.SizeOf<PInvoke.SECURITY_ATTRIBUTES>(),
lpSecurityDescriptor = psecDesc,
bInheritHandle = false,
};
var lpStartupInfo = new PInvoke.STARTUPINFO
{
cb = Marshal.SizeOf<PInvoke.STARTUPINFO>(),
};
var compatLayerPrev = Environment.GetEnvironmentVariable("__COMPAT_LAYER");
Environment.SetEnvironmentVariable("__COMPAT_LAYER", "RunAsInvoker");
try
{
if (!PInvoke.CreateProcess(
null,
$"\"{exePath}\" {arguments}",
ref lpProcessAttributes,
IntPtr.Zero,
false,
PInvoke.CREATE_SUSPENDED,
IntPtr.Zero,
workingDir,
ref lpStartupInfo,
out lpProcessInformation))
{
throw new Win32Exception(Marshal.GetLastWin32Error());
}
}
finally
{
Environment.SetEnvironmentVariable("__COMPAT_LAYER", compatLayerPrev);
}
DisableSeDebug(lpProcessInformation.hProcess);
process = new ExistingProcess(lpProcessInformation.hProcess);
beforeResume?.Invoke(process);
PInvoke.ResumeThread(lpProcessInformation.hThread);
// Ensure that the game main window is prepared
try
{
do
{
process.WaitForInputIdle();
Thread.Sleep(100);
}
while (TryFindGameWindow(process) == IntPtr.Zero);
}
catch (InvalidOperationException)
{
throw new GameExitedException();
}
if (PInvoke.GetSecurityInfo(
PInvoke.GetCurrentProcess(),
PInvoke.SE_OBJECT_TYPE.SE_KERNEL_OBJECT,
PInvoke.SECURITY_INFORMATION.DACL_SECURITY_INFORMATION,
IntPtr.Zero,
IntPtr.Zero,
out var pACL,
IntPtr.Zero,
IntPtr.Zero) != 0)
{
throw new Win32Exception(Marshal.GetLastWin32Error());
}
if (PInvoke.SetSecurityInfo(
lpProcessInformation.hProcess,
PInvoke.SE_OBJECT_TYPE.SE_KERNEL_OBJECT,
PInvoke.SECURITY_INFORMATION.DACL_SECURITY_INFORMATION | PInvoke.SECURITY_INFORMATION.UNPROTECTED_DACL_SECURITY_INFORMATION,
IntPtr.Zero,
IntPtr.Zero,
pACL,
IntPtr.Zero) != 0)
{
throw new Win32Exception(Marshal.GetLastWin32Error());
}
}
catch (Exception ex)
{
Log.Error(ex, "[NativeAclFix] Uncaught error during initialization, trying to kill process");
try
{
process?.Kill();
}
catch (Exception killEx)
{
Log.Error(killEx, "[NativeAclFix] Could not kill process");
}
throw;
}
finally
{
Marshal.FreeHGlobal(psecDesc);
PInvoke.CloseHandle(lpProcessInformation.hThread);
}
return process;
}
private static void DisableSeDebug(IntPtr processHandle)
{
if (!PInvoke.OpenProcessToken(processHandle, PInvoke.TOKEN_QUERY | PInvoke.TOKEN_ADJUST_PRIVILEGES, out var tokenHandle))
{
throw new Win32Exception(Marshal.GetLastWin32Error());
}
var luidDebugPrivilege = default(PInvoke.LUID);
if (!PInvoke.LookupPrivilegeValue(null, "SeDebugPrivilege", ref luidDebugPrivilege))
{
throw new Win32Exception(Marshal.GetLastWin32Error());
}
var requiredPrivileges = new PInvoke.PRIVILEGE_SET
{
PrivilegeCount = 1,
Control = PInvoke.PRIVILEGE_SET_ALL_NECESSARY,
Privilege = new PInvoke.LUID_AND_ATTRIBUTES[1],
};
requiredPrivileges.Privilege[0].Luid = luidDebugPrivilege;
requiredPrivileges.Privilege[0].Attributes = PInvoke.SE_PRIVILEGE_ENABLED;
if (!PInvoke.PrivilegeCheck(tokenHandle, ref requiredPrivileges, out bool bResult))
{
throw new Win32Exception(Marshal.GetLastWin32Error());
}
// SeDebugPrivilege is enabled; try disabling it
if (bResult)
{
var tokenPrivileges = new PInvoke.TOKEN_PRIVILEGES
{
PrivilegeCount = 1,
Privileges = new PInvoke.LUID_AND_ATTRIBUTES[1],
};
tokenPrivileges.Privileges[0].Luid = luidDebugPrivilege;
tokenPrivileges.Privileges[0].Attributes = PInvoke.SE_PRIVILEGE_REMOVED;
if (!PInvoke.AdjustTokenPrivileges(tokenHandle, false, ref tokenPrivileges, 0, IntPtr.Zero, 0))
{
throw new Win32Exception(Marshal.GetLastWin32Error());
}
}
PInvoke.CloseHandle(tokenHandle);
}
private static IntPtr TryFindGameWindow(Process process)
{
IntPtr hwnd = IntPtr.Zero;
while ((hwnd = PInvoke.FindWindowEx(IntPtr.Zero, hwnd, "FFXIVGAME", IntPtr.Zero)) != IntPtr.Zero)
{
PInvoke.GetWindowThreadProcessId(hwnd, out uint pid);
if (pid == process.Id && PInvoke.IsWindowVisible(hwnd))
{
break;
}
}
return hwnd;
}
/// <summary>
/// Exception thrown when the process has exited before a window could be found.
/// </summary>
public class GameExitedException : Exception
{
/// <summary>
/// Initializes a new instance of the <see cref="GameExitedException"/> class.
/// </summary>
public GameExitedException()
: base("Game exited prematurely.")
{
}
}
// Definitions taken from PInvoke.net (with some changes) // Definitions taken from PInvoke.net (with some changes)
[SuppressMessage("StyleCop.CSharp.NamingRules", "SA1307:Accessible fields should begin with upper-case letter", Justification = "WINAPI conventions")]
[SuppressMessage("StyleCop.CSharp.ReadabilityRules", "SA1121:Use built-in type alias", Justification = "WINAPI conventions")]
[SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1400:Access modifier should be declared", Justification = "WINAPI conventions")]
[SuppressMessage("StyleCop.CSharp.NamingRules", "SA1306:Field names should begin with lower-case letter", Justification = "WINAPI conventions")]
[SuppressMessage("StyleCop.CSharp.NamingRules", "SA1310:Field names should not contain underscore", Justification = "WINAPI conventions")]
[SuppressMessage("StyleCop.CSharp.ReadabilityRules", "SA1124:Do not use regions", Justification = "WINAPI conventions")]
private static class PInvoke private static class PInvoke
{ {
#region Constants #region Constants
@ -37,11 +278,10 @@ namespace Dalamud.Injector
public const UInt32 SE_PRIVILEGE_ENABLED = 0x00000002; public const UInt32 SE_PRIVILEGE_ENABLED = 0x00000002;
public const UInt32 SE_PRIVILEGE_REMOVED = 0x00000004; public const UInt32 SE_PRIVILEGE_REMOVED = 0x00000004;
public enum MULTIPLE_TRUSTEE_OPERATION public enum MULTIPLE_TRUSTEE_OPERATION
{ {
NO_MULTIPLE_TRUSTEE, NO_MULTIPLE_TRUSTEE,
TRUSTEE_IS_IMPERSONATE TRUSTEE_IS_IMPERSONATE,
} }
public enum TRUSTEE_FORM public enum TRUSTEE_FORM
@ -50,7 +290,7 @@ namespace Dalamud.Injector
TRUSTEE_IS_NAME, TRUSTEE_IS_NAME,
TRUSTEE_BAD_FORM, TRUSTEE_BAD_FORM,
TRUSTEE_IS_OBJECTS_AND_SID, TRUSTEE_IS_OBJECTS_AND_SID,
TRUSTEE_IS_OBJECTS_AND_NAME TRUSTEE_IS_OBJECTS_AND_NAME,
} }
public enum TRUSTEE_TYPE public enum TRUSTEE_TYPE
@ -63,7 +303,7 @@ namespace Dalamud.Injector
TRUSTEE_IS_WELL_KNOWN_GROUP, TRUSTEE_IS_WELL_KNOWN_GROUP,
TRUSTEE_IS_DELETED, TRUSTEE_IS_DELETED,
TRUSTEE_IS_INVALID, TRUSTEE_IS_INVALID,
TRUSTEE_IS_COMPUTER TRUSTEE_IS_COMPUTER,
} }
public enum SE_OBJECT_TYPE public enum SE_OBJECT_TYPE
@ -80,8 +320,10 @@ namespace Dalamud.Injector
SE_DS_OBJECT_ALL, SE_DS_OBJECT_ALL,
SE_PROVIDER_DEFINED_OBJECT, SE_PROVIDER_DEFINED_OBJECT,
SE_WMIGUID_OBJECT, SE_WMIGUID_OBJECT,
SE_REGISTRY_WOW64_32KEY SE_REGISTRY_WOW64_32KEY,
} }
[Flags]
public enum SECURITY_INFORMATION public enum SECURITY_INFORMATION
{ {
OWNER_SECURITY_INFORMATION = 1, OWNER_SECURITY_INFORMATION = 1,
@ -90,12 +332,120 @@ namespace Dalamud.Injector
SACL_SECURITY_INFORMATION = 8, SACL_SECURITY_INFORMATION = 8,
UNPROTECTED_SACL_SECURITY_INFORMATION = 0x10000000, UNPROTECTED_SACL_SECURITY_INFORMATION = 0x10000000,
UNPROTECTED_DACL_SECURITY_INFORMATION = 0x20000000, UNPROTECTED_DACL_SECURITY_INFORMATION = 0x20000000,
PROTECTED_SACL_SECURITY_INFORMATION = 0x40000000 PROTECTED_SACL_SECURITY_INFORMATION = 0x40000000,
} }
#endregion #endregion
#region Methods
[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Auto)]
public static extern void BuildExplicitAccessWithName(
ref EXPLICIT_ACCESS pExplicitAccess,
string pTrusteeName,
uint accessPermissions,
uint accessMode,
uint inheritance);
[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Auto)]
public static extern int SetEntriesInAcl(
int cCountOfExplicitEntries,
ref EXPLICIT_ACCESS pListOfExplicitEntries,
IntPtr oldAcl,
out IntPtr newAcl);
[DllImport("advapi32.dll", SetLastError = true)]
public static extern bool InitializeSecurityDescriptor(
out SECURITY_DESCRIPTOR pSecurityDescriptor,
uint dwRevision);
[DllImport("advapi32.dll", SetLastError = true)]
public static extern bool SetSecurityDescriptorDacl(
ref SECURITY_DESCRIPTOR pSecurityDescriptor,
bool bDaclPresent,
IntPtr pDacl,
bool bDaclDefaulted);
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
public static extern bool CreateProcess(
string lpApplicationName,
string lpCommandLine,
ref SECURITY_ATTRIBUTES lpProcessAttributes,
IntPtr lpThreadAttributes,
bool bInheritHandles,
UInt32 dwCreationFlags,
IntPtr lpEnvironment,
string lpCurrentDirectory,
[In] ref STARTUPINFO lpStartupInfo,
out PROCESS_INFORMATION lpProcessInformation);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool CloseHandle(IntPtr hObject);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern uint ResumeThread(IntPtr hThread);
[DllImport("advapi32.dll", SetLastError = true)]
public static extern bool OpenProcessToken(
IntPtr processHandle,
UInt32 desiredAccess,
out IntPtr tokenHandle);
[DllImport("advapi32.dll", SetLastError = true)]
public static extern bool LookupPrivilegeValue(string lpSystemName, string lpName, ref LUID lpLuid);
[DllImport("advapi32.dll", SetLastError = true)]
public static extern bool PrivilegeCheck(
IntPtr clientToken,
ref PRIVILEGE_SET requiredPrivileges,
out bool pfResult);
[DllImport("advapi32.dll", SetLastError = true)]
public static extern bool AdjustTokenPrivileges(
IntPtr tokenHandle,
bool disableAllPrivileges,
ref TOKEN_PRIVILEGES newState,
UInt32 bufferLengthInBytes,
IntPtr previousState,
UInt32 returnLengthInBytes);
[DllImport("advapi32.dll", SetLastError = true)]
public static extern uint GetSecurityInfo(
IntPtr handle,
SE_OBJECT_TYPE objectType,
SECURITY_INFORMATION securityInfo,
IntPtr pSidOwner,
IntPtr pSidGroup,
out IntPtr pDacl,
IntPtr pSacl,
IntPtr pSecurityDescriptor);
[DllImport("advapi32.dll", SetLastError = true)]
public static extern uint SetSecurityInfo(
IntPtr handle,
SE_OBJECT_TYPE objectType,
SECURITY_INFORMATION securityInfo,
IntPtr psidOwner,
IntPtr psidGroup,
IntPtr pDacl,
IntPtr pSacl);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr GetCurrentProcess();
[DllImport("user32.dll", SetLastError = true)]
public static extern IntPtr FindWindowEx(IntPtr parentHandle, IntPtr hWndChildAfter, string className, IntPtr windowTitle);
[DllImport("user32.dll", SetLastError = true)]
public static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool IsWindowVisible(IntPtr hWnd);
#endregion
#region Structures #region Structures
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto, Pack = 0)] [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto, Pack = 0)]
public struct TRUSTEE : IDisposable public struct TRUSTEE : IDisposable
{ {
@ -105,12 +455,16 @@ namespace Dalamud.Injector
public TRUSTEE_TYPE TrusteeType; public TRUSTEE_TYPE TrusteeType;
private IntPtr ptstrName; private IntPtr ptstrName;
public string Name => Marshal.PtrToStringAuto(this.ptstrName) ?? string.Empty;
#pragma warning disable CA1416
void IDisposable.Dispose() void IDisposable.Dispose()
{ {
if (ptstrName != IntPtr.Zero) Marshal.Release(ptstrName); if (this.ptstrName != IntPtr.Zero) Marshal.Release(this.ptstrName);
} }
public string Name { get { return Marshal.PtrToStringAuto(ptstrName); } } #pragma warning restore CA1416
} }
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto, Pack = 0)] [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto, Pack = 0)]
@ -204,341 +558,6 @@ namespace Dalamud.Injector
public LUID_AND_ATTRIBUTES[] Privileges; public LUID_AND_ATTRIBUTES[] Privileges;
} }
#endregion #endregion
#region Methods
[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Auto)]
public static extern void BuildExplicitAccessWithName(
ref EXPLICIT_ACCESS pExplicitAccess,
string pTrusteeName,
uint AccessPermissions,
uint AccessMode,
uint Inheritance);
[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Auto)]
public static extern int SetEntriesInAcl(
int cCountOfExplicitEntries,
ref EXPLICIT_ACCESS pListOfExplicitEntries,
IntPtr OldAcl,
out IntPtr NewAcl);
[DllImport("advapi32.dll", SetLastError = true)]
public static extern bool InitializeSecurityDescriptor(
out SECURITY_DESCRIPTOR pSecurityDescriptor,
uint dwRevision);
[DllImport("advapi32.dll", SetLastError = true)]
public static extern bool SetSecurityDescriptorDacl(
ref SECURITY_DESCRIPTOR pSecurityDescriptor,
bool bDaclPresent,
IntPtr pDacl,
bool bDaclDefaulted);
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
public static extern bool CreateProcess(
string lpApplicationName,
string lpCommandLine,
ref SECURITY_ATTRIBUTES lpProcessAttributes,
IntPtr lpThreadAttributes,
bool bInheritHandles,
UInt32 dwCreationFlags,
IntPtr lpEnvironment,
string lpCurrentDirectory,
[In] ref STARTUPINFO lpStartupInfo,
out PROCESS_INFORMATION lpProcessInformation);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool CloseHandle(IntPtr hObject);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern uint ResumeThread(IntPtr hThread);
[DllImport("advapi32.dll", SetLastError = true)]
public static extern bool OpenProcessToken(
IntPtr ProcessHandle,
UInt32 DesiredAccess,
out IntPtr TokenHandle);
[DllImport("advapi32.dll", SetLastError = true)]
public static extern bool LookupPrivilegeValue(string lpSystemName, string lpName, ref LUID lpLuid);
[DllImport("advapi32.dll", SetLastError = true)]
public static extern bool PrivilegeCheck(
IntPtr ClientToken,
ref PRIVILEGE_SET RequiredPrivileges,
out bool pfResult);
[DllImport("advapi32.dll", SetLastError = true)]
public static extern bool AdjustTokenPrivileges(
IntPtr TokenHandle,
bool DisableAllPrivileges,
ref TOKEN_PRIVILEGES NewState,
UInt32 BufferLengthInBytes,
IntPtr PreviousState,
UInt32 ReturnLengthInBytes);
[DllImport("advapi32.dll", SetLastError = true)]
public static extern uint GetSecurityInfo(
IntPtr handle,
SE_OBJECT_TYPE ObjectType,
SECURITY_INFORMATION SecurityInfo,
IntPtr pSidOwner,
IntPtr pSidGroup,
out IntPtr pDacl,
IntPtr pSacl,
IntPtr pSecurityDescriptor);
[DllImport("advapi32.dll", SetLastError = true)]
public static extern uint SetSecurityInfo(
IntPtr handle,
SE_OBJECT_TYPE ObjectType,
SECURITY_INFORMATION SecurityInfo,
IntPtr psidOwner,
IntPtr psidGroup,
IntPtr pDacl,
IntPtr pSacl);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr GetCurrentProcess();
#endregion
}
public class ExistingProcess : Process
{
public ExistingProcess(IntPtr handle)
{
SetHandle(handle);
}
private void SetHandle(IntPtr handle)
{
var baseType = GetType().BaseType;
if (baseType == null)
return;
var setProcessHandleMethod = baseType.GetMethod("SetProcessHandle",
BindingFlags.NonPublic | BindingFlags.Instance);
setProcessHandleMethod?.Invoke(this, new object[] {new SafeProcessHandle(handle, true)});
}
}
public class GameExitedException : Exception
{
public GameExitedException()
: base("Game exited prematurely.")
{
}
}
public static Process LaunchGame(string workingDir, string exePath, string arguments, Action<Process> beforeResume)
{
Process process = null;
var userName = Environment.UserName;
var pExplicitAccess = new PInvoke.EXPLICIT_ACCESS();
PInvoke.BuildExplicitAccessWithName(
ref pExplicitAccess,
userName,
PInvoke.STANDARD_RIGHTS_ALL | PInvoke.SPECIFIC_RIGHTS_ALL & ~PInvoke.PROCESS_VM_WRITE,
PInvoke.GRANT_ACCESS,
0);
if (PInvoke.SetEntriesInAcl(1, ref pExplicitAccess, IntPtr.Zero, out var newAcl) != 0)
{
throw new Win32Exception(Marshal.GetLastWin32Error());
}
var secDesc = new PInvoke.SECURITY_DESCRIPTOR();
if (!PInvoke.InitializeSecurityDescriptor(out secDesc, PInvoke.SECURITY_DESCRIPTOR_REVISION))
{
throw new Win32Exception(Marshal.GetLastWin32Error());
}
if (!PInvoke.SetSecurityDescriptorDacl(ref secDesc, true, newAcl, false))
{
throw new Win32Exception(Marshal.GetLastWin32Error());
}
var psecDesc = Marshal.AllocHGlobal(Marshal.SizeOf<PInvoke.SECURITY_DESCRIPTOR>());
Marshal.StructureToPtr<PInvoke.SECURITY_DESCRIPTOR>(secDesc, psecDesc, true);
var lpProcessInformation = new PInvoke.PROCESS_INFORMATION();
try
{
var lpProcessAttributes = new PInvoke.SECURITY_ATTRIBUTES
{
nLength = Marshal.SizeOf<PInvoke.SECURITY_ATTRIBUTES>(),
lpSecurityDescriptor = psecDesc,
bInheritHandle = false
};
var lpStartupInfo = new PInvoke.STARTUPINFO
{
cb = Marshal.SizeOf<PInvoke.STARTUPINFO>()
};
var compatLayerPrev = Environment.GetEnvironmentVariable("__COMPAT_LAYER");
Environment.SetEnvironmentVariable("__COMPAT_LAYER", "RunAsInvoker");
try
{
if (!PInvoke.CreateProcess(
null,
$"\"{exePath}\" {arguments}",
ref lpProcessAttributes,
IntPtr.Zero,
false,
PInvoke.CREATE_SUSPENDED,
IntPtr.Zero,
workingDir,
ref lpStartupInfo,
out lpProcessInformation))
{
throw new Win32Exception(Marshal.GetLastWin32Error());
}
}
finally
{
Environment.SetEnvironmentVariable("__COMPAT_LAYER", compatLayerPrev);
}
DisableSeDebug(lpProcessInformation.hProcess);
process = new ExistingProcess(lpProcessInformation.hProcess);
beforeResume?.Invoke(process);
PInvoke.ResumeThread(lpProcessInformation.hThread);
// Ensure that the game main window is prepared
try
{
do
{
process.WaitForInputIdle();
Thread.Sleep(100);
} while (IntPtr.Zero == TryFindGameWindow(process));
}
catch (InvalidOperationException)
{
throw new GameExitedException();
}
if (PInvoke.GetSecurityInfo(
PInvoke.GetCurrentProcess(),
PInvoke.SE_OBJECT_TYPE.SE_KERNEL_OBJECT,
PInvoke.SECURITY_INFORMATION.DACL_SECURITY_INFORMATION,
IntPtr.Zero, IntPtr.Zero,
out var pACL,
IntPtr.Zero, IntPtr.Zero) != 0)
{
throw new Win32Exception(Marshal.GetLastWin32Error());
}
if (PInvoke.SetSecurityInfo(
lpProcessInformation.hProcess,
PInvoke.SE_OBJECT_TYPE.SE_KERNEL_OBJECT,
PInvoke.SECURITY_INFORMATION.DACL_SECURITY_INFORMATION | PInvoke.SECURITY_INFORMATION.UNPROTECTED_DACL_SECURITY_INFORMATION,
IntPtr.Zero, IntPtr.Zero, pACL, IntPtr.Zero) != 0)
{
throw new Win32Exception(Marshal.GetLastWin32Error());
}
}
catch (Exception ex)
{
Log.Error(ex, "[NativeAclFix] Uncaught error during initialization, trying to kill process");
try
{
process?.Kill();
}
catch (Exception killEx)
{
Log.Error(killEx, "[NativeAclFix] Could not kill process");
}
throw;
}
finally
{
Marshal.FreeHGlobal(psecDesc);
PInvoke.CloseHandle(lpProcessInformation.hThread);
}
return process;
}
private static void DisableSeDebug(IntPtr ProcessHandle)
{
if (!PInvoke.OpenProcessToken(ProcessHandle, PInvoke.TOKEN_QUERY | PInvoke.TOKEN_ADJUST_PRIVILEGES, out var TokenHandle))
{
throw new Win32Exception(Marshal.GetLastWin32Error());
}
var luidDebugPrivilege = new PInvoke.LUID();
if (!PInvoke.LookupPrivilegeValue(null, "SeDebugPrivilege", ref luidDebugPrivilege))
{
throw new Win32Exception(Marshal.GetLastWin32Error());
}
var RequiredPrivileges = new PInvoke.PRIVILEGE_SET
{
PrivilegeCount = 1,
Control = PInvoke.PRIVILEGE_SET_ALL_NECESSARY,
Privilege = new PInvoke.LUID_AND_ATTRIBUTES[1]
};
RequiredPrivileges.Privilege[0].Luid = luidDebugPrivilege;
RequiredPrivileges.Privilege[0].Attributes = PInvoke.SE_PRIVILEGE_ENABLED;
if (!PInvoke.PrivilegeCheck(TokenHandle, ref RequiredPrivileges, out bool bResult))
{
throw new Win32Exception(Marshal.GetLastWin32Error());
}
if (bResult) // SeDebugPrivilege is enabled; try disabling it
{
var TokenPrivileges = new PInvoke.TOKEN_PRIVILEGES
{
PrivilegeCount = 1,
Privileges = new PInvoke.LUID_AND_ATTRIBUTES[1]
};
TokenPrivileges.Privileges[0].Luid = luidDebugPrivilege;
TokenPrivileges.Privileges[0].Attributes = PInvoke.SE_PRIVILEGE_REMOVED;
if (!PInvoke.AdjustTokenPrivileges(TokenHandle, false, ref TokenPrivileges, 0, IntPtr.Zero, 0))
{
throw new Win32Exception(Marshal.GetLastWin32Error());
}
}
PInvoke.CloseHandle(TokenHandle);
}
[DllImport("user32.dll", SetLastError = true)]
private static extern IntPtr FindWindowEx(IntPtr parentHandle, IntPtr hWndChildAfter, string className, IntPtr windowTitle);
[DllImport("user32.dll", SetLastError = true)]
private static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool IsWindowVisible(IntPtr hWnd);
private static IntPtr TryFindGameWindow(Process process)
{
IntPtr hwnd = IntPtr.Zero;
while (IntPtr.Zero != (hwnd = FindWindowEx(IntPtr.Zero, hwnd, "FFXIVGAME", IntPtr.Zero)))
{
GetWindowThreadProcessId(hwnd, out uint pid);
if (pid == process.Id && IsWindowVisible(hwnd))
{
break;
}
}
return hwnd;
} }
} }
} }

View file

@ -3,8 +3,8 @@ using System.Collections.Generic;
using System.Globalization; using System.Globalization;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using Dalamud.Game.Text; using Dalamud.Game.Text;
using Dalamud.Interface.GameFonts;
using Dalamud.Interface.Style; using Dalamud.Interface.Style;
using Newtonsoft.Json; using Newtonsoft.Json;
using Serilog; using Serilog;

View file

@ -1,15 +1,12 @@
using System; using System;
using System.Diagnostics; using System.Diagnostics;
using System.IO; using System.IO;
using System.Linq;
using System.Net; using System.Net;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Text;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Dalamud.Configuration.Internal; using Dalamud.Configuration.Internal;
using Dalamud.Game;
using Dalamud.Logging.Internal; using Dalamud.Logging.Internal;
using Dalamud.Support; using Dalamud.Support;
using Dalamud.Utility; using Dalamud.Utility;

View file

@ -18,7 +18,6 @@ using Dalamud.Interface.Internal.Windows;
using Dalamud.IoC; using Dalamud.IoC;
using Dalamud.IoC.Internal; using Dalamud.IoC.Internal;
using Dalamud.Plugin.Internal; using Dalamud.Plugin.Internal;
using Dalamud.Plugin.Internal.Types;
using Dalamud.Utility; using Dalamud.Utility;
using Serilog; using Serilog;

View file

@ -1,7 +1,5 @@
using System; using System;
using Dalamud.Game.ClientState.JobGauge.Enums;
namespace Dalamud.Game.ClientState.JobGauge.Types namespace Dalamud.Game.ClientState.JobGauge.Types
{ {
/// <summary> /// <summary>

View file

@ -7,7 +7,6 @@ using Dalamud.Game.ClientState.Resolvers;
using Dalamud.Game.ClientState.Statuses; using Dalamud.Game.ClientState.Statuses;
using Dalamud.Game.Text.SeStringHandling; using Dalamud.Game.Text.SeStringHandling;
using Dalamud.Memory; using Dalamud.Memory;
using JetBrains.Annotations;
namespace Dalamud.Game.ClientState.Party namespace Dalamud.Game.ClientState.Party
{ {

View file

@ -1,8 +1,6 @@
using System; using System;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using Dalamud.Game.Internal;
namespace Dalamud.Game namespace Dalamud.Game
{ {
/// <summary> /// <summary>

View file

@ -1,7 +1,5 @@
using System; using System;
using Dalamud.Game.Internal;
namespace Dalamud.Game.Gui namespace Dalamud.Game.Gui
{ {
/// <summary> /// <summary>

View file

@ -1,6 +1,4 @@
using Dalamud.Game.Text.SeStringHandling; namespace Dalamud.Game.Gui.ContextMenus
namespace Dalamud.Game.Gui.ContextMenus
{ {
/// <summary> /// <summary>
/// Provides game object context to a context menu. /// Provides game object context to a context menu.

View file

@ -1,5 +1,4 @@
using System; using System;
using System.Runtime.InteropServices;
namespace Dalamud.Game.Gui namespace Dalamud.Game.Gui
{ {

View file

@ -1,5 +1,3 @@
using System;
using Dalamud.Data; using Dalamud.Data;
using Lumina.Excel.GeneratedSheets; using Lumina.Excel.GeneratedSheets;

View file

@ -1,7 +1,5 @@
using System; using System;
using Dalamud.Game.Internal;
namespace Dalamud.Game.Libc namespace Dalamud.Game.Libc
{ {
/// <summary> /// <summary>

View file

@ -1,7 +1,5 @@
using System; using System;
using Dalamud.Game.Internal;
namespace Dalamud.Game.Network namespace Dalamud.Game.Network
{ {
/// <summary> /// <summary>

View file

@ -3,7 +3,6 @@ using System.Net.Sockets;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using Dalamud.Hooking; using Dalamud.Hooking;
using Dalamud.Hooking.Internal;
namespace Dalamud.Game.Network.Internal namespace Dalamud.Game.Network.Internal
{ {

View file

@ -1,4 +1,3 @@
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;

View file

@ -1,4 +1,3 @@
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;

View file

@ -1,10 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
using System.Linq;
using Dalamud.Data;
using Dalamud.Game.Text.SeStringHandling.Payloads;
using Dalamud.IoC; using Dalamud.IoC;
using Dalamud.IoC.Internal; using Dalamud.IoC.Internal;
using Lumina.Excel.GeneratedSheets; using Lumina.Excel.GeneratedSheets;

View file

@ -1,5 +1,4 @@
using System; using System;
using System.Collections.Generic;
using System.Reflection; using System.Reflection;
using Dalamud.Configuration.Internal; using Dalamud.Configuration.Internal;

View file

@ -4,11 +4,9 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using Dalamud.Configuration.Internal;
using Dalamud.Logging.Internal; using Dalamud.Logging.Internal;
using Dalamud.Memory; using Dalamud.Memory;
using Iced.Intel; using Iced.Intel;
using Microsoft.Win32;
namespace Dalamud.Hooking.Internal namespace Dalamud.Hooking.Internal
{ {

View file

@ -1,9 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
namespace Dalamud.Interface.GameFonts namespace Dalamud.Interface.GameFonts
{ {

View file

@ -1,9 +1,3 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Dalamud.Interface.GameFonts namespace Dalamud.Interface.GameFonts
{ {
/// <summary> /// <summary>

View file

@ -1,9 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using System.Numerics; using System.Numerics;
using System.Text;
using System.Threading.Tasks;
using ImGuiNET; using ImGuiNET;

View file

@ -5,7 +5,6 @@ using System.Numerics;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Text; using System.Text;
using Dalamud.Configuration.Internal;
using Dalamud.Data; using Dalamud.Data;
using Dalamud.Interface.Internal; using Dalamud.Interface.Internal;
using ImGuiNET; using ImGuiNET;

View file

@ -1,8 +1,4 @@
using System; using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Dalamud.Interface.GameFonts namespace Dalamud.Interface.GameFonts
{ {

View file

@ -3,8 +3,6 @@ using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using Dalamud.Interface;
namespace Dalamud.Interface.ImGuiFileDialog namespace Dalamud.Interface.ImGuiFileDialog
{ {
/// <summary> /// <summary>

View file

@ -1,4 +1,3 @@
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Numerics; using System.Numerics;

View file

@ -1,8 +1,4 @@
using System; using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Dalamud.Interface.ImGuiFileDialog namespace Dalamud.Interface.ImGuiFileDialog
{ {

View file

@ -15,11 +15,9 @@ using Dalamud.Game.ClientState.Keys;
using Dalamud.Game.Gui.Internal; using Dalamud.Game.Gui.Internal;
using Dalamud.Game.Internal.DXGI; using Dalamud.Game.Internal.DXGI;
using Dalamud.Hooking; using Dalamud.Hooking;
using Dalamud.Hooking.Internal;
using Dalamud.Interface.GameFonts; using Dalamud.Interface.GameFonts;
using Dalamud.Interface.Internal.ManagedAsserts; using Dalamud.Interface.Internal.ManagedAsserts;
using Dalamud.Interface.Internal.Notifications; using Dalamud.Interface.Internal.Notifications;
using Dalamud.Interface.Internal.Windows.StyleEditor;
using Dalamud.Interface.Style; using Dalamud.Interface.Style;
using Dalamud.Interface.Windowing; using Dalamud.Interface.Windowing;
using Dalamud.Utility; using Dalamud.Utility;

View file

@ -1,9 +1,5 @@
using System; using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Numerics; using System.Numerics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using Dalamud.Game; using Dalamud.Game;
@ -19,7 +15,7 @@ namespace Dalamud.Interface.Internal
/// <summary> /// <summary>
/// This class displays a debug window to inspect native addons. /// This class displays a debug window to inspect native addons.
/// </summary> /// </summary>
internal unsafe class UIDebug internal unsafe class UiDebug
{ {
private const int UnitListCount = 18; private const int UnitListCount = 18;
@ -52,9 +48,9 @@ namespace Dalamud.Interface.Internal
private AtkUnitBase* selectedUnitBase = null; private AtkUnitBase* selectedUnitBase = null;
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="UIDebug"/> class. /// Initializes a new instance of the <see cref="UiDebug"/> class.
/// </summary> /// </summary>
public UIDebug() public UiDebug()
{ {
var sigScanner = Service<SigScanner>.Get(); var sigScanner = Service<SigScanner>.Get();
var getSingletonAddr = sigScanner.ScanText("E8 ?? ?? ?? ?? 41 B8 01 00 00 00 48 8D 15 ?? ?? ?? ?? 48 8B 48 20 E8 ?? ?? ?? ?? 48 8B CF"); var getSingletonAddr = sigScanner.ScanText("E8 ?? ?? ?? ?? 41 B8 01 00 00 00 48 8D 15 ?? ?? ?? ?? 48 8B 48 20 E8 ?? ?? ?? ?? 48 8B CF");

View file

@ -1,5 +1,4 @@
using System; using System;
using System.Diagnostics;
using System.IO; using System.IO;
using System.Numerics; using System.Numerics;

View file

@ -4,7 +4,6 @@ using System.IO;
using System.Linq; using System.Linq;
using System.Numerics; using System.Numerics;
using Dalamud.Game;
using Dalamud.Game.Gui; using Dalamud.Game.Gui;
using Dalamud.Interface.Windowing; using Dalamud.Interface.Windowing;
using Dalamud.Plugin.Internal; using Dalamud.Plugin.Internal;

View file

@ -72,7 +72,7 @@ namespace Dalamud.Interface.Internal.Windows
private bool resolveGameData = false; private bool resolveGameData = false;
private bool resolveObjects = false; private bool resolveObjects = false;
private UIDebug addonInspector = null; private UiDebug addonInspector = null;
private Hook<MessageBoxWDelegate>? messageBoxMinHook; private Hook<MessageBoxWDelegate>? messageBoxMinHook;
private bool hookUseMinHook = false; private bool hookUseMinHook = false;
@ -877,7 +877,7 @@ namespace Dalamud.Interface.Internal.Windows
private void DrawAddonInspector() private void DrawAddonInspector()
{ {
this.addonInspector ??= new UIDebug(); this.addonInspector ??= new UiDebug();
this.addonInspector.Draw(); this.addonInspector.Draw();
} }

View file

@ -1,7 +1,5 @@
using System; using System;
using ImGuiScene;
namespace Dalamud.Interface.Internal.Windows.PluginInstaller namespace Dalamud.Interface.Internal.Windows.PluginInstaller
{ {
/// <summary> /// <summary>

View file

@ -1,7 +1,5 @@
using System; using System;
using ImGuiScene;
namespace Dalamud.Interface.Internal.Windows.PluginInstaller namespace Dalamud.Interface.Internal.Windows.PluginInstaller
{ {
/// <summary> /// <summary>

View file

@ -2,7 +2,6 @@
using Dalamud.Plugin.Internal; using Dalamud.Plugin.Internal;
using Dalamud.Utility; using Dalamud.Utility;
using ImGuiScene;
namespace Dalamud.Interface.Internal.Windows.PluginInstaller namespace Dalamud.Interface.Internal.Windows.PluginInstaller
{ {

View file

@ -5,7 +5,6 @@ using System.Diagnostics;
using System.Diagnostics.CodeAnalysis; using System.Diagnostics.CodeAnalysis;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Net.Http;
using System.Numerics; using System.Numerics;
using System.Threading.Tasks; using System.Threading.Tasks;

View file

@ -4,8 +4,6 @@ using System.Linq;
using System.Reflection; using System.Reflection;
using Dalamud.Game; using Dalamud.Game;
using Dalamud.Game.Internal;
using Dalamud.Hooking;
using Dalamud.Hooking.Internal; using Dalamud.Hooking.Internal;
using Dalamud.Interface.Windowing; using Dalamud.Interface.Windowing;
using Dalamud.Plugin.Internal; using Dalamud.Plugin.Internal;

View file

@ -1,6 +1,5 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics;
using System.Linq; using System.Linq;
using System.Numerics; using System.Numerics;

View file

@ -12,7 +12,6 @@ using Dalamud.Game.Gui.Dtr;
using Dalamud.Game.Text; using Dalamud.Game.Text;
using Dalamud.Interface.Colors; using Dalamud.Interface.Colors;
using Dalamud.Interface.Components; using Dalamud.Interface.Components;
using Dalamud.Interface.GameFonts;
using Dalamud.Interface.Windowing; using Dalamud.Interface.Windowing;
using Dalamud.Plugin.Internal; using Dalamud.Plugin.Internal;
using Dalamud.Utility; using Dalamud.Utility;

View file

@ -9,7 +9,6 @@ using Dalamud.Game;
using Dalamud.Game.ClientState; using Dalamud.Game.ClientState;
using Dalamud.Game.Gui; using Dalamud.Game.Gui;
using Dalamud.Interface.Animation.EasingFunctions; using Dalamud.Interface.Animation.EasingFunctions;
using Dalamud.Interface.GameFonts;
using Dalamud.Interface.Windowing; using Dalamud.Interface.Windowing;
using ImGuiNET; using ImGuiNET;
using ImGuiScene; using ImGuiScene;

View file

@ -6,7 +6,6 @@ using System.Reflection;
using System.Threading.Tasks; using System.Threading.Tasks;
using Dalamud.Game; using Dalamud.Game;
using Serilog;
namespace Dalamud.Logging.Internal namespace Dalamud.Logging.Internal
{ {

View file

@ -14,7 +14,6 @@ using Dalamud.Game.Text.Sanitizer;
using Dalamud.Game.Text.SeStringHandling; using Dalamud.Game.Text.SeStringHandling;
using Dalamud.Game.Text.SeStringHandling.Payloads; using Dalamud.Game.Text.SeStringHandling.Payloads;
using Dalamud.Interface; using Dalamud.Interface;
using Dalamud.Interface.Internal;
using Dalamud.Plugin.Internal; using Dalamud.Plugin.Internal;
using Dalamud.Plugin.Ipc; using Dalamud.Plugin.Ipc;
using Dalamud.Plugin.Ipc.Exceptions; using Dalamud.Plugin.Ipc.Exceptions;

View file

@ -1,4 +1,3 @@
using System;
using System.IO; using System.IO;
namespace Dalamud.Plugin.Internal.Exceptions namespace Dalamud.Plugin.Internal.Exceptions

View file

@ -1,5 +1,3 @@
using System;
namespace Dalamud.Plugin.Internal.Exceptions namespace Dalamud.Plugin.Internal.Exceptions
{ {
/// <summary> /// <summary>

View file

@ -1126,7 +1126,9 @@ namespace Dalamud.Plugin.Internal
this.assemblyLocationMonoHook = new MonoMod.RuntimeDetour.Hook(locationTarget, locationPatch); this.assemblyLocationMonoHook = new MonoMod.RuntimeDetour.Hook(locationTarget, locationPatch);
#pragma warning disable CS0618 #pragma warning disable CS0618
#pragma warning disable SYSLIB0012
var codebaseTarget = targetType.GetProperty(nameof(Assembly.CodeBase))?.GetGetMethod(); var codebaseTarget = targetType.GetProperty(nameof(Assembly.CodeBase))?.GetGetMethod();
#pragma warning restore SYSLIB0012
#pragma warning restore CS0618 #pragma warning restore CS0618
var codebasePatch = typeof(PluginManager).GetMethod(nameof(AssemblyCodeBasePatch), BindingFlags.NonPublic | BindingFlags.Static); var codebasePatch = typeof(PluginManager).GetMethod(nameof(AssemblyCodeBasePatch), BindingFlags.NonPublic | BindingFlags.Static);
this.assemblyCodeBaseMonoHook = new MonoMod.RuntimeDetour.Hook(codebaseTarget, codebasePatch); this.assemblyCodeBaseMonoHook = new MonoMod.RuntimeDetour.Hook(codebaseTarget, codebasePatch);

View file

@ -8,7 +8,6 @@ using System.Net.Http;
using System.Numerics; using System.Numerics;
using System.Reflection; using System.Reflection;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Text; using System.Text;
using Dalamud.Configuration.Internal; using Dalamud.Configuration.Internal;