Merge branch 'net5'

This commit is contained in:
goaaats 2022-06-22 17:38:01 +02:00
commit a78754ce22
No known key found for this signature in database
GPG key ID: 49E2AA8C6A76498B
100 changed files with 67306 additions and 923 deletions

View file

@ -64,7 +64,7 @@
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
<PackageReference Include="PeNet" Version="2.6.4" />
<PackageReference Include="Reloaded.Memory" Version="4.1.1" />
<PackageReference Include="Reloaded.Memory.Buffers" Version="1.3.5" />
<PackageReference Include="Reloaded.Memory.Buffers" Version="1.4.4" />
<PackageReference Include="Serilog" Version="2.10.0" />
<PackageReference Include="Serilog.Sinks.Async" Version="1.5.0" />
<PackageReference Include="Serilog.Sinks.Console" Version="4.0.1" />

View file

@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
@ -38,7 +39,6 @@ namespace Dalamud.Injector
public static void Main(int argc, IntPtr argvPtr)
{
List<string> args = new(argc);
Init(args);
unsafe
{
@ -47,6 +47,9 @@ namespace Dalamud.Injector
args.Add(Marshal.PtrToStringUni(argv[i]));
}
Init(args);
args.Remove("-v"); // Remove "verbose" flag
if (args.Count >= 2 && args[1].ToLowerInvariant() == "launch-test")
{
Environment.Exit(ProcessLaunchTestCommand(args));
@ -80,6 +83,8 @@ namespace Dalamud.Injector
}
startInfo = ExtractAndInitializeStartInfoFromArguments(startInfo, args);
args.Remove("--console"); // Remove "console" flag, already handled
args.Remove("--etw"); // Remove "etw" flag, already handled
var mainCommand = args[1].ToLowerInvariant();
if (mainCommand.Length > 0 && mainCommand.Length <= 6 && "inject"[..mainCommand.Length] == mainCommand)
@ -100,10 +105,23 @@ namespace Dalamud.Injector
}
}
private static string GetLogPath(string filename)
{
var baseDirectory = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
#if DEBUG
var logPath = Path.Combine(baseDirectory, $"{filename}.log");
#else
var logPath = Path.Combine(baseDirectory, "..", "..", "..", $"{filename}.log");
#endif
return logPath;
}
private static void Init(List<string> args)
{
InitLogging(args.Any(x => x == "-v"));
InitUnhandledException(args);
InitLogging();
var cwd = new FileInfo(Assembly.GetExecutingAssembly().Location).Directory;
if (cwd.FullName != Directory.GetCurrentDirectory())
@ -158,23 +176,18 @@ namespace Dalamud.Injector
};
}
private static void InitLogging()
private static void InitLogging(bool verbose)
{
var baseDirectory = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
#if DEBUG
var logPath = Path.Combine(baseDirectory, "dalamud.injector.log");
#else
var logPath = Path.Combine(baseDirectory, "..", "..", "..", "dalamud.injector.log");
verbose = true;
#endif
var levelSwitch = new LoggingLevelSwitch();
var levelSwitch = new LoggingLevelSwitch
{
MinimumLevel = verbose ? LogEventLevel.Verbose : LogEventLevel.Information,
};
#if DEBUG
levelSwitch.MinimumLevel = LogEventLevel.Verbose;
#else
levelSwitch.MinimumLevel = LogEventLevel.Information;
#endif
var logPath = GetLogPath("dalamud.injector");
CullLogFile(logPath, 1 * 1024 * 1024);
@ -236,8 +249,7 @@ namespace Dalamud.Injector
int len;
string key;
if (startInfo == null)
startInfo = new();
startInfo ??= new DalamudStartInfo();
var workingDirectory = startInfo.WorkingDirectory;
var configurationPath = startInfo.ConfigurationPath;
@ -288,7 +300,7 @@ namespace Dalamud.Injector
clientLanguage = ClientLanguage.Japanese;
else if (languageStr[0..(len = Math.Min(languageStr.Length, (key = "german").Length))] == key[0..len])
clientLanguage = ClientLanguage.German;
else if (languageStr[0..(len = Math.Min(languageStr.Length, (key = "deutsche").Length))] == key[0..len])
else if (languageStr[0..(len = Math.Min(languageStr.Length, (key = "deutsch").Length))] == key[0..len])
clientLanguage = ClientLanguage.German;
else if (languageStr[0..(len = Math.Min(languageStr.Length, (key = "french").Length))] == key[0..len])
clientLanguage = ClientLanguage.French;
@ -299,17 +311,25 @@ namespace Dalamud.Injector
else
throw new CommandLineException($"\"{languageStr}\" is not a valid supported language.");
return new()
{
WorkingDirectory = workingDirectory,
ConfigurationPath = configurationPath,
PluginDirectory = pluginDirectory,
DefaultPluginDirectory = defaultPluginDirectory,
AssetDirectory = assetDirectory,
Language = clientLanguage,
GameVersion = null,
DelayInitializeMs = delayInitializeMs,
};
startInfo.WorkingDirectory = workingDirectory;
startInfo.ConfigurationPath = configurationPath;
startInfo.PluginDirectory = pluginDirectory;
startInfo.DefaultPluginDirectory = defaultPluginDirectory;
startInfo.AssetDirectory = assetDirectory;
startInfo.Language = clientLanguage;
startInfo.DelayInitializeMs = delayInitializeMs;
startInfo.GameVersion = null;
// Set boot defaults
startInfo.BootShowConsole = args.Contains("--console");
startInfo.BootEnableEtw = args.Contains("--etw");
startInfo.BootLogPath = GetLogPath("dalamud.boot");
startInfo.BootEnabledGameFixes = new List<string> { "prevent_devicechange_crashes", "disable_game_openprocess_access_check", "redirect_openprocess" };
startInfo.BootDotnetOpenProcessHookMode = 0;
// startInfo.BootWaitMessageBox = 2;
// startInfo.BootUnhookDlls = new List<string>() { "kernel32.dll", "ntdll.dll", "user32.dll" };
return startInfo;
}
private static int ProcessHelpCommand(List<string> args, string? particularCommand = default)
@ -324,7 +344,7 @@ namespace Dalamud.Injector
Console.WriteLine("{0} help [command]", exeName);
if (particularCommand is null or "inject")
Console.WriteLine("{0} inject [-h/--help] [-a/--all] [--warn] [pid1] [pid2] [pid3] ...", exeName);
Console.WriteLine("{0} inject [-h/--help] [-a/--all] [--warn] [--fix-acl] [--se-debug-privilege] [pid1] [pid2] [pid3] ...", exeName);
if (particularCommand is null or "launch")
{
@ -332,7 +352,7 @@ namespace Dalamud.Injector
Console.WriteLine("{0} [-g path/to/ffxiv_dx11.exe] [--game=path/to/ffxiv_dx11.exe]", exeSpaces);
Console.WriteLine("{0} [-m entrypoint|inject] [--mode=entrypoint|inject]", exeSpaces);
Console.WriteLine("{0} [--handle-owner=inherited-handle-value]", exeSpaces);
Console.WriteLine("{0} [--without-dalamud]", exeSpaces);
Console.WriteLine("{0} [--without-dalamud] [--no-fix-acl]", exeSpaces);
Console.WriteLine("{0} [-- game_arg1=value1 game_arg2=value2 ...]", exeSpaces);
}
@ -341,6 +361,10 @@ namespace Dalamud.Injector
Console.WriteLine(" [--dalamud-asset-directory=path] [--dalamud-delay-initialize=0(ms)]");
Console.WriteLine(" [--dalamud-client-language=0-3|j(apanese)|e(nglish)|d|g(erman)|f(rench)]");
Console.WriteLine("Verbose logging:\t[-v]");
Console.WriteLine("Show Console:\t[--console]");
Console.WriteLine("Enable ETW:\t[--etw]");
return 0;
}
@ -351,6 +375,8 @@ namespace Dalamud.Injector
var targetProcessSpecified = false;
var warnManualInjection = false;
var showHelp = args.Count <= 2;
var tryFixAcl = false;
var tryClaimSeDebugPrivilege = false;
for (var i = 2; i < args.Count; i++)
{
@ -378,6 +404,14 @@ namespace Dalamud.Injector
targetProcessSpecified = true;
processes.AddRange(Process.GetProcessesByName("ffxiv_dx11"));
}
else if (args[i] == "--fix-acl" || args[i] == "--acl-fix")
{
tryFixAcl = true;
}
else if (args[i] == "--se-debug-privilege")
{
tryClaimSeDebugPrivilege = true;
}
else if (args[i] == "--warn")
{
warnManualInjection = true;
@ -416,8 +450,21 @@ namespace Dalamud.Injector
}
}
if (tryClaimSeDebugPrivilege)
{
try
{
GameStart.ClaimSeDebug();
Log.Information("SeDebugPrivilege claimed.");
}
catch (Win32Exception e2)
{
Log.Warning(e2, "Failed to claim SeDebugPrivilege");
}
}
foreach (var process in processes)
Inject(process, AdjustStartInfo(dalamudStartInfo, process.MainModule.FileName));
Inject(process, AdjustStartInfo(dalamudStartInfo, process.MainModule.FileName), tryFixAcl);
return 0;
}
@ -431,6 +478,7 @@ namespace Dalamud.Injector
var showHelp = args.Count <= 2;
var handleOwner = IntPtr.Zero;
var withoutDalamud = false;
var noFixAcl = false;
var parsingGameArgument = false;
for (var i = 2; i < args.Count; i++)
@ -447,6 +495,8 @@ namespace Dalamud.Injector
useFakeArguments = true;
else if (args[i] == "--without-dalamud")
withoutDalamud = true;
else if (args[i] == "--no-fix-acl" || args[i] == "--no-acl-fix")
noFixAcl = true;
else if (args[i] == "-g")
gamePath = args[++i];
else if (args[i].StartsWith("--game="))
@ -547,7 +597,7 @@ namespace Dalamud.Injector
}
var gameArgumentString = string.Join(" ", gameArguments.Select(x => EncodeParameterArgument(x)));
var process = NativeAclFix.LaunchGame(Path.GetDirectoryName(gamePath), gamePath, gameArgumentString, (Process p) =>
var process = GameStart.LaunchGame(Path.GetDirectoryName(gamePath), gamePath, gameArgumentString, noFixAcl, (Process p) =>
{
if (!withoutDalamud && mode == "entrypoint")
{
@ -558,14 +608,18 @@ namespace Dalamud.Injector
Log.Error("[HOOKS] RewriteRemoteEntryPointW failed");
throw new Exception("RewriteRemoteEntryPointW failed");
}
Log.Verbose("RewriteRemoteEntryPointW called!");
}
});
Log.Verbose("Game process started with PID {0}", process.Id);
if (!withoutDalamud && mode == "inject")
{
var startInfo = AdjustStartInfo(dalamudStartInfo, gamePath);
Log.Information("Using start info: {0}", JsonConvert.SerializeObject(startInfo));
Inject(process, startInfo);
Inject(process, startInfo, false);
}
var processHandleForOwner = IntPtr.Zero;
@ -634,21 +688,26 @@ namespace Dalamud.Injector
var gameVerStr = File.ReadAllText(Path.Combine(ffxivDir, "ffxivgame.ver"));
var gameVer = GameVersion.Parse(gameVerStr);
return new()
return new DalamudStartInfo(startInfo)
{
WorkingDirectory = startInfo.WorkingDirectory,
ConfigurationPath = startInfo.ConfigurationPath,
PluginDirectory = startInfo.PluginDirectory,
DefaultPluginDirectory = startInfo.DefaultPluginDirectory,
AssetDirectory = startInfo.AssetDirectory,
Language = startInfo.Language,
GameVersion = gameVer,
DelayInitializeMs = startInfo.DelayInitializeMs,
};
}
private static void Inject(Process process, DalamudStartInfo startInfo)
private static void Inject(Process process, DalamudStartInfo startInfo, bool tryFixAcl = false)
{
if (tryFixAcl)
{
try
{
GameStart.CopyAclFromSelfToTargetProcess(process.SafeHandle.DangerousGetHandle());
}
catch (Win32Exception e1)
{
Log.Warning(e1, "Failed to copy ACL");
}
}
var bootName = "Dalamud.Boot.dll";
var bootPath = Path.GetFullPath(bootName);

View file

@ -12,9 +12,9 @@ using Serilog;
namespace Dalamud.Injector
{
/// <summary>
/// Class responsible for stripping ACL protections from processes.
/// Class responsible for starting the game and stripping ACL protections from processes.
/// </summary>
public static class NativeAclFix
public static class GameStart
{
/// <summary>
/// Start a process without ACL protections.
@ -22,41 +22,47 @@ namespace Dalamud.Injector
/// <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="dontFixAcl">Don't actually fix the ACL.</param>
/// <param name="beforeResume">Action to execute before the process is started.</param>
/// <param name="waitForGameWindow">Wait for the game window to be ready before proceeding.</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)
/// <exception cref="GameStartException">Thrown when the process did not start correctly.</exception>
public static Process LaunchGame(string workingDir, string exePath, string arguments, bool dontFixAcl, Action<Process> beforeResume, bool waitForGameWindow = true)
{
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)
var psecDesc = IntPtr.Zero;
if (!dontFixAcl)
{
throw new Win32Exception(Marshal.GetLastWin32Error());
}
var userName = Environment.UserName;
if (!PInvoke.InitializeSecurityDescriptor(out var secDesc, PInvoke.SECURITY_DESCRIPTOR_REVISION))
{
throw new Win32Exception(Marshal.GetLastWin32Error());
}
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.SetSecurityDescriptorDacl(ref secDesc, true, newAcl, false))
{
throw new Win32Exception(Marshal.GetLastWin32Error());
}
if (PInvoke.SetEntriesInAcl(1, ref pExplicitAccess, IntPtr.Zero, out var newAcl) != 0)
{
throw new Win32Exception(Marshal.GetLastWin32Error());
}
var psecDesc = Marshal.AllocHGlobal(Marshal.SizeOf<PInvoke.SECURITY_DESCRIPTOR>());
Marshal.StructureToPtr(secDesc, psecDesc, true);
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());
}
psecDesc = Marshal.AllocHGlobal(Marshal.SizeOf<PInvoke.SECURITY_DESCRIPTOR>());
Marshal.StructureToPtr(secDesc, psecDesc, true);
}
var lpProcessInformation = default(PInvoke.PROCESS_INFORMATION);
try
@ -75,7 +81,15 @@ namespace Dalamud.Injector
var compatLayerPrev = Environment.GetEnvironmentVariable("__COMPAT_LAYER");
Environment.SetEnvironmentVariable("__COMPAT_LAYER", "RunAsInvoker");
if (!string.IsNullOrEmpty(compatLayerPrev) && !compatLayerPrev.Contains("RunAsInvoker"))
{
Environment.SetEnvironmentVariable("__COMPAT_LAYER", $"RunAsInvoker {compatLayerPrev}");
}
else if (string.IsNullOrEmpty(compatLayerPrev))
{
Environment.SetEnvironmentVariable("__COMPAT_LAYER", "RunAsInvoker");
}
try
{
if (!PInvoke.CreateProcess(
@ -98,7 +112,8 @@ namespace Dalamud.Injector
Environment.SetEnvironmentVariable("__COMPAT_LAYER", compatLayerPrev);
}
DisableSeDebug(lpProcessInformation.hProcess);
if (!dontFixAcl)
DisableSeDebug(lpProcessInformation.hProcess);
process = new ExistingProcess(lpProcessInformation.hProcess);
@ -107,49 +122,40 @@ namespace Dalamud.Injector
PInvoke.ResumeThread(lpProcessInformation.hThread);
// Ensure that the game main window is prepared
try
if (waitForGameWindow)
{
do
try
{
process.WaitForInputIdle();
var tries = 0;
const int maxTries = 420;
const int timeout = 50;
Thread.Sleep(100);
do
{
Thread.Sleep(timeout);
if (process.HasExited)
throw new GameStartException();
if (tries > maxTries)
throw new GameStartException($"Couldn't find game window after {maxTries * timeout}ms");
tries++;
}
while (TryFindGameWindow(process) == IntPtr.Zero);
}
catch (InvalidOperationException)
{
throw new GameStartException("Could not read process information.");
}
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());
}
if (!dontFixAcl)
CopyAclFromSelfToTargetProcess(lpProcessInformation.hProcess);
}
catch (Exception ex)
{
Log.Error(ex, "[NativeAclFix] Uncaught error during initialization, trying to kill process");
Log.Error(ex, "[GameStart] Uncaught error during initialization, trying to kill process");
try
{
@ -157,20 +163,98 @@ namespace Dalamud.Injector
}
catch (Exception killEx)
{
Log.Error(killEx, "[NativeAclFix] Could not kill process");
Log.Error(killEx, "[GameStart] Could not kill process");
}
throw;
}
finally
{
Marshal.FreeHGlobal(psecDesc);
if (psecDesc != IntPtr.Zero)
Marshal.FreeHGlobal(psecDesc);
PInvoke.CloseHandle(lpProcessInformation.hThread);
}
return process;
}
/// <summary>
/// Copies ACL of current process to the target process.
/// </summary>
/// <param name="hProcess">Native handle to the target process.</param>
/// <exception cref="Win32Exception">Thrown when a win32 error occurs.</exception>
public static void CopyAclFromSelfToTargetProcess(IntPtr hProcess)
{
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(
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());
}
}
public static void ClaimSeDebug()
{
var hToken = PInvoke.INVALID_HANDLE_VALUE;
try
{
if (!PInvoke.OpenThreadToken(PInvoke.GetCurrentThread(), PInvoke.TOKEN_QUERY | PInvoke.TOKEN_ADJUST_PRIVILEGES, false, out hToken))
{
if (Marshal.GetLastWin32Error() != PInvoke.ERROR_NO_TOKEN)
throw new Exception("ClaimSeDebug.OpenProcessToken#1", new Win32Exception(Marshal.GetLastWin32Error()));
if (!PInvoke.ImpersonateSelf(PInvoke.SECURITY_IMPERSONATION_LEVEL.SecurityImpersonation))
throw new Exception("ClaimSeDebug.ImpersonateSelf", new Win32Exception(Marshal.GetLastWin32Error()));
if (!PInvoke.OpenThreadToken(PInvoke.GetCurrentThread(), PInvoke.TOKEN_QUERY | PInvoke.TOKEN_ADJUST_PRIVILEGES, false, out hToken))
throw new Exception("ClaimSeDebug.OpenProcessToken#2", new Win32Exception(Marshal.GetLastWin32Error()));
}
var luidDebugPrivilege = default(PInvoke.LUID);
if (!PInvoke.LookupPrivilegeValue(null, PInvoke.SE_DEBUG_NAME, ref luidDebugPrivilege))
throw new Exception("ClaimSeDebug.LookupPrivilegeValue", new Win32Exception(Marshal.GetLastWin32Error()));
var tpLookup = new PInvoke.TOKEN_PRIVILEGES()
{
PrivilegeCount = 1,
Privileges = new PInvoke.LUID_AND_ATTRIBUTES[1]
{
new PInvoke.LUID_AND_ATTRIBUTES()
{
Luid = luidDebugPrivilege,
Attributes = PInvoke.SE_PRIVILEGE_ENABLED,
},
},
};
if (!PInvoke.AdjustTokenPrivileges(hToken, false, ref tpLookup, 0, IntPtr.Zero, IntPtr.Zero))
throw new Exception("ClaimSeDebug.AdjustTokenPrivileges", new Win32Exception(Marshal.GetLastWin32Error()));
}
finally
{
if (hToken != PInvoke.INVALID_HANDLE_VALUE && hToken != IntPtr.Zero)
PInvoke.CloseHandle(hToken);
}
}
private static void DisableSeDebug(IntPtr processHandle)
{
if (!PInvoke.OpenProcessToken(processHandle, PInvoke.TOKEN_QUERY | PInvoke.TOKEN_ADJUST_PRIVILEGES, out var tokenHandle))
@ -179,7 +263,7 @@ namespace Dalamud.Injector
}
var luidDebugPrivilege = default(PInvoke.LUID);
if (!PInvoke.LookupPrivilegeValue(null, "SeDebugPrivilege", ref luidDebugPrivilege))
if (!PInvoke.LookupPrivilegeValue(null, PInvoke.SE_DEBUG_NAME, ref luidDebugPrivilege))
{
throw new Win32Exception(Marshal.GetLastWin32Error());
}
@ -211,7 +295,7 @@ namespace Dalamud.Injector
tokenPrivileges.Privileges[0].Luid = luidDebugPrivilege;
tokenPrivileges.Privileges[0].Attributes = PInvoke.SE_PRIVILEGE_REMOVED;
if (!PInvoke.AdjustTokenPrivileges(tokenHandle, false, ref tokenPrivileges, 0, IntPtr.Zero, 0))
if (!PInvoke.AdjustTokenPrivileges(tokenHandle, false, ref tokenPrivileges, 0, IntPtr.Zero, IntPtr.Zero))
{
throw new Win32Exception(Marshal.GetLastWin32Error());
}
@ -239,13 +323,14 @@ namespace Dalamud.Injector
/// <summary>
/// Exception thrown when the process has exited before a window could be found.
/// </summary>
public class GameExitedException : Exception
public class GameStartException : Exception
{
/// <summary>
/// Initializes a new instance of the <see cref="GameExitedException"/> class.
/// Initializes a new instance of the <see cref="GameStartException"/> class.
/// </summary>
public GameExitedException()
: base("Game exited prematurely.")
/// <param name="message">The message to pass on.</param>
public GameStartException(string? message = null)
: base(message ?? "Game exited prematurely.")
{
}
}
@ -260,6 +345,10 @@ namespace Dalamud.Injector
private static class PInvoke
{
#region Constants
public static readonly IntPtr INVALID_HANDLE_VALUE = new(-1);
public const string SE_DEBUG_NAME = "SeDebugPrivilege";
public const UInt32 STANDARD_RIGHTS_ALL = 0x001F0000;
public const UInt32 SPECIFIC_RIGHTS_ALL = 0x0000FFFF;
public const UInt32 PROCESS_VM_WRITE = 0x0020;
@ -278,6 +367,8 @@ namespace Dalamud.Injector
public const UInt32 SE_PRIVILEGE_ENABLED = 0x00000002;
public const UInt32 SE_PRIVILEGE_REMOVED = 0x00000004;
public const UInt32 ERROR_NO_TOKEN = 0x000003F0;
public enum MULTIPLE_TRUSTEE_OPERATION
{
NO_MULTIPLE_TRUSTEE,
@ -334,6 +425,14 @@ namespace Dalamud.Injector
UNPROTECTED_DACL_SECURITY_INFORMATION = 0x20000000,
PROTECTED_SACL_SECURITY_INFORMATION = 0x40000000,
}
public enum SECURITY_IMPERSONATION_LEVEL
{
SecurityAnonymous,
SecurityIdentification,
SecurityImpersonation,
SecurityDelegation
}
#endregion
#region Methods
@ -384,12 +483,24 @@ namespace Dalamud.Injector
[DllImport("kernel32.dll", SetLastError = true)]
public static extern uint ResumeThread(IntPtr hThread);
[DllImport("advapi32.dll", SetLastError = true)]
public static extern bool ImpersonateSelf(
SECURITY_IMPERSONATION_LEVEL impersonationLevel
);
[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 OpenThreadToken(
IntPtr ThreadHandle,
uint DesiredAccess,
bool OpenAsSelf,
out IntPtr TokenHandle);
[DllImport("advapi32.dll", SetLastError = true)]
public static extern bool LookupPrivilegeValue(string lpSystemName, string lpName, ref LUID lpLuid);
@ -404,9 +515,9 @@ namespace Dalamud.Injector
IntPtr tokenHandle,
bool disableAllPrivileges,
ref TOKEN_PRIVILEGES newState,
UInt32 bufferLengthInBytes,
int cbPreviousState,
IntPtr previousState,
UInt32 returnLengthInBytes);
IntPtr cbOutPreviousState);
[DllImport("advapi32.dll", SetLastError = true)]
public static extern uint GetSecurityInfo(
@ -432,6 +543,9 @@ namespace Dalamud.Injector
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr GetCurrentProcess();
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr GetCurrentThread();
[DllImport("user32.dll", SetLastError = true)]
public static extern IntPtr FindWindowEx(IntPtr parentHandle, IntPtr hWndChildAfter, string className, IntPtr windowTitle);