From 79fb6c51045b29991c4413b7ee3d35682f14e8b0 Mon Sep 17 00:00:00 2001 From: Mino Date: Wed, 1 Apr 2020 20:00:15 +0900 Subject: [PATCH] I don't even know what I'm doing --- Dalamud.Bootstrap/GameProcess.cs | 40 +++++++++---------- Dalamud.Bootstrap/Windows/Process.cs | 39 +++++++++++------- .../Windows/ProcessCreationOptions.cs | 11 +++++ 3 files changed, 55 insertions(+), 35 deletions(-) create mode 100644 Dalamud.Bootstrap/Windows/ProcessCreationOptions.cs diff --git a/Dalamud.Bootstrap/GameProcess.cs b/Dalamud.Bootstrap/GameProcess.cs index 5140c541f..b0214fda2 100644 --- a/Dalamud.Bootstrap/GameProcess.cs +++ b/Dalamud.Bootstrap/GameProcess.cs @@ -1,17 +1,13 @@ using System; using Dalamud.Bootstrap.SqexArg; using Dalamud.Bootstrap.Windows; +using Microsoft.Win32.SafeHandles; namespace Dalamud.Bootstrap { - internal sealed class GameProcess : IDisposable + internal sealed class GameProcess : Process { - private Process m_process; - - public GameProcess(Process process) - { - m_process = process; - } + public GameProcess(SafeProcessHandle handle) : base(handle) { } public static GameProcess Open(uint pid) { @@ -25,15 +21,9 @@ namespace Dalamud.Bootstrap // TODO: unfuck VM_WRITE - var process = Process.Open(pid, access); + var handle = Process.OpenHandle(pid, access); - return new GameProcess(process); - } - - public void Dispose() - { - m_process?.Dispose(); - m_process = null!; + return new GameProcess(handle); } /// @@ -60,24 +50,34 @@ namespace Dalamud.Bootstrap return createdTick & 0xFFFF_0000; } - public ArgumentBuilder ReadArguments() + /// + /// Reads command-line arguments from the game and decrypts them if necessary. + /// + /// + /// Command-line arguments that looks like this: + /// /DEV.TestSID =ABCD /UserPath =C:\Examples + /// + public string ReadArguments() { - var arguments = m_process.ReadArguments(); + var processArguments = m_process.GetArguments(); - if (arguments.Length < 2) + // arg[0] is a path to exe(normally), arg[1] is actual stuff. + if (processArguments.Length < 2) { throw new BootstrapException($"Process id {m_process.GetPid()} have no arguments to parse."); } - var argument = arguments[1]; + // We're interested in argument that contains session id + var argument = processArguments[1]; + // If it's encrypted, we need to decrypt it first if (EncryptedArgument.TryParse(argument, out var encryptedArgument)) { var key = GetArgumentEncryptionKey(); argument = encryptedArgument.Decrypt(key); } - return ArgumentBuilder.Parse(argument); + return argument; } } } diff --git a/Dalamud.Bootstrap/Windows/Process.cs b/Dalamud.Bootstrap/Windows/Process.cs index e7bfc3d21..4df7ad514 100644 --- a/Dalamud.Bootstrap/Windows/Process.cs +++ b/Dalamud.Bootstrap/Windows/Process.cs @@ -10,9 +10,9 @@ namespace Dalamud.Bootstrap /// /// A class that provides a wrapper over operations on Win32 process. /// - internal sealed partial class Process : IDisposable + internal class Process : IDisposable { - private SafeProcessHandle m_handle; + protected SafeProcessHandle Handle { get; set; } /// /// Creates a process object that can be used to manipulate process's internal state. @@ -20,32 +20,38 @@ namespace Dalamud.Bootstrap /// A process handle. Note that this functinon will take the ownership of the handle. public Process(SafeProcessHandle handle) { - m_handle = handle; + Handle = handle; } + public void Dispose() { - m_handle?.Dispose(); - m_handle = null!; + DisposeImpl(); } - public static Process Open(uint pid, PROCESS_ACCESS_RIGHT access) + protected virtual void DisposeImpl() { - var handle = Win32.OpenProcess((uint) access, false, pid); + Handle?.Dispose(); + Handle = null!; + } + + protected static SafeProcessHandle OpenHandle(uint pid, PROCESS_ACCESS_RIGHT access) + { + var handle = Win32.OpenProcess((uint)access, false, pid); if (handle.IsInvalid) { ProcessException.ThrowLastOsError(pid); } - return new Process(handle); + return handle; } - public uint GetPid() => Win32.GetProcessId(m_handle); + public uint GetPid() => Win32.GetProcessId(Handle); public void Terminate(uint exitCode = 0) { - if (!Win32.TerminateProcess(m_handle, exitCode)) + if (!Win32.TerminateProcess(Handle, exitCode)) { ProcessException.ThrowLastOsError(GetPid()); } @@ -65,7 +71,7 @@ namespace Dalamud.Bootstrap { IntPtr bytesRead; - if (!Win32.ReadProcessMemory(m_handle, (void*)address, pDest, (IntPtr)destination.Length, &bytesRead)) + if (!Win32.ReadProcessMemory(Handle, (void*)address, pDest, (IntPtr)destination.Length, &bytesRead)) { ProcessException.ThrowLastOsError(GetPid()); } @@ -119,7 +125,7 @@ namespace Dalamud.Bootstrap unsafe { var info = new PROCESS_BASIC_INFORMATION(); - var status = Win32.NtQueryInformationProcess(m_handle, PROCESSINFOCLASS.ProcessBasicInformation, &info, sizeof(PROCESS_BASIC_INFORMATION), (IntPtr*)IntPtr.Zero); + var status = Win32.NtQueryInformationProcess(Handle, PROCESSINFOCLASS.ProcessBasicInformation, &info, sizeof(PROCESS_BASIC_INFORMATION), (IntPtr*)IntPtr.Zero); if (!status.Success) { @@ -133,7 +139,10 @@ namespace Dalamud.Bootstrap } } - public string[] ReadArguments() + /// + /// Reads command-line arguments from the process. + /// + public string[] GetArguments() { unsafe { @@ -158,7 +167,7 @@ namespace Dalamud.Bootstrap { FileTime creationTime, exitTime, kernelTime, userTime; - if (!Win32.GetProcessTimes(m_handle, &creationTime, &exitTime, &kernelTime, &userTime)) + if (!Win32.GetProcessTimes(Handle, &creationTime, &exitTime, &kernelTime, &userTime)) { ProcessException.ThrowLastOsError(GetPid()); } @@ -213,7 +222,7 @@ namespace Dalamud.Bootstrap // On success, receives the number of characters written to the buffer, not including the null-terminating character. var size = buffer.Capacity; - if (!Win32.QueryFullProcessImageNameW(m_handle, 0, buffer, ref size)) + if (!Win32.QueryFullProcessImageNameW(Handle, 0, buffer, ref size)) { ProcessException.ThrowLastOsError(GetPid()); } diff --git a/Dalamud.Bootstrap/Windows/ProcessCreationOptions.cs b/Dalamud.Bootstrap/Windows/ProcessCreationOptions.cs new file mode 100644 index 000000000..7edd6fec0 --- /dev/null +++ b/Dalamud.Bootstrap/Windows/ProcessCreationOptions.cs @@ -0,0 +1,11 @@ +namespace Dalamud.Bootstrap.Windows +{ + internal sealed class ProcessCreationOptions + { + public string ImagePath { get; set; } = null!; + + public string? CommandLine { get; set; } = null; + + public bool CreateSuspended { get; set; } = true; + } +}