diff --git a/Dalamud.Injector/Dalamud.Injector.csproj b/Dalamud.Injector/Dalamud.Injector.csproj
index 8e2137758..8712672e8 100644
--- a/Dalamud.Injector/Dalamud.Injector.csproj
+++ b/Dalamud.Injector/Dalamud.Injector.csproj
@@ -4,6 +4,7 @@
netcoreapp3.1
preview
enable
+ true
diff --git a/Dalamud.Injector/DalamudLauncher.cs b/Dalamud.Injector/DalamudLauncher.cs
index 531b7b80a..4c2c91f98 100644
--- a/Dalamud.Injector/DalamudLauncher.cs
+++ b/Dalamud.Injector/DalamudLauncher.cs
@@ -19,7 +19,7 @@ namespace Dalamud.Injector
public void Launch(string exePath)
{
- //
+
}
public void Relaunch(uint pid)
diff --git a/Dalamud.Injector/FFI/Win32.cs b/Dalamud.Injector/FFI/Win32.cs
deleted file mode 100644
index 394065fbc..000000000
--- a/Dalamud.Injector/FFI/Win32.cs
+++ /dev/null
@@ -1,65 +0,0 @@
-using Microsoft.Win32.SafeHandles;
-using System;
-using System.Collections.Generic;
-using System.Runtime.InteropServices;
-using System.Text;
-
-namespace Dalamud.Injector.FFI
-{
- internal static class Win32
- {
- [DllImport("kernel32", CallingConvention = CallingConvention.Winapi, SetLastError = true)]
- public static extern SafeProcessHandle OpenProcess(uint dwDesiredAccess, [MarshalAs(UnmanagedType.Bool)] bool bInheritHandle, uint dwProcessId);
-
- [DllImport("kernel32", CallingConvention = CallingConvention.Winapi, SetLastError = true)]
- public static extern NtStatus NtQueryInformationProcess(/* TODO */);
-
-
- }
-
- [StructLayout(LayoutKind.Sequential)]
- internal partial struct NtStatus
- {
- public uint Value { get; }
- }
-
- internal partial struct NtStatus
- {
- public NtStatus(uint value)
- {
- Value = value;
- }
-
- ///
- /// Equivalent to NT_SUCCESS
- ///
- public bool Success => Value <= 0x7FFFFFFF;
-
- ///
- /// Equivalent to NT_INFORMATION
- ///
- public bool Information => 0x40000000 <= Value && Value <= 0x7FFFFFFF;
-
- ///
- /// Equivalent to NT_WARNING
- ///
- public bool Warning => 0x80000000 <= Value && Value <= 0xBFFFFFFF;
-
- ///
- /// Equivalent to NT_ERROR
- ///
- public bool Error => 0xC0000000 <= Value;
- }
-
- [StructLayout(LayoutKind.Sequential)]
- internal struct PROCESS_BASIC_INFORMATION
- {
- // https://github.com/processhacker/processhacker/blob/e43d7c0513ec5368c3309a58c9f2c2a3ca5de367/phnt/include/ntpsapi.h#L272
- public NtStatus ExitStatus;
- public IntPtr PebBaseAddress;
- public IntPtr AffinityMask;
- public IntPtr BasePriority;
- public IntPtr UniqueProcessId;
- public IntPtr InheritedFromUniqueProcessId;
- }
-}
diff --git a/Dalamud.Injector/OS/Process.cs b/Dalamud.Injector/OS/Process.cs
deleted file mode 100644
index fd316bf91..000000000
--- a/Dalamud.Injector/OS/Process.cs
+++ /dev/null
@@ -1,33 +0,0 @@
-using Microsoft.Win32.SafeHandles;
-using System;
-using System.Collections.Generic;
-using System.Text;
-
-namespace Dalamud.Injector.OS
-{
- internal sealed partial class Process : IDisposable
- {
- private SafeProcessHandle m_handle;
- }
-
- internal sealed partial class Process {
- internal Process(SafeProcessHandle handle)
- {
- m_handle = handle;
- }
-
- public static Process Open(uint pid/* and perms? maybe? */)
- {
- //
- throw new NotImplementedException("TODO");
- }
-
-
-
- public void Dispose()
- {
- m_handle?.Dispose();
- m_handle = null!;
- }
- }
-}
diff --git a/Dalamud.Injector/Program/Program.cs b/Dalamud.Injector/Program/Program.cs
index d6552585c..c62e8e037 100644
--- a/Dalamud.Injector/Program/Program.cs
+++ b/Dalamud.Injector/Program/Program.cs
@@ -1,6 +1,7 @@
using System;
using CommandLine;
+
namespace Dalamud.Injector
{
internal static class Program
diff --git a/Dalamud.Injector/Windows/NtException.cs b/Dalamud.Injector/Windows/NtException.cs
new file mode 100644
index 000000000..6887dc3ff
--- /dev/null
+++ b/Dalamud.Injector/Windows/NtException.cs
@@ -0,0 +1,14 @@
+using System;
+
+namespace Dalamud.Injector.Windows
+{
+ internal sealed class NtException : Exception
+ {
+ public NtStatus Status { get; }
+
+ public NtException(NtStatus status)
+ {
+ Status = status;
+ }
+ }
+}
diff --git a/Dalamud.Injector/Windows/Process.cs b/Dalamud.Injector/Windows/Process.cs
new file mode 100644
index 000000000..38b585695
--- /dev/null
+++ b/Dalamud.Injector/Windows/Process.cs
@@ -0,0 +1,160 @@
+using Microsoft.Win32.SafeHandles;
+using System;
+using System.ComponentModel;
+using System.Runtime.InteropServices;
+
+namespace Dalamud.Injector.Windows
+{
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ internal sealed partial class Process : IDisposable
+ {
+ private SafeProcessHandle m_handle;
+ }
+
+ internal sealed partial class Process {
+ ///
+ ///
+ ///
+ /// A process handle. Note that this functinon will take the ownership of the handle.
+ public Process(SafeProcessHandle handle)
+ {
+ m_handle = handle;
+ }
+
+ public void Dispose()
+ {
+ m_handle?.Dispose();
+ m_handle = null!;
+ }
+
+ public static Process Open(uint pid)
+ {
+ const PROCESS_ACCESS_RIGHT access = PROCESS_ACCESS_RIGHT.PROCESS_VM_OPERATION |
+ PROCESS_ACCESS_RIGHT.PROCESS_VM_READ |
+ PROCESS_ACCESS_RIGHT.PROCESS_VM_WRITE |
+ PROCESS_ACCESS_RIGHT.PROCESS_QUERY_LIMITED_INFORMATION |
+ PROCESS_ACCESS_RIGHT.PROCESS_QUERY_INFORMATION |
+ PROCESS_ACCESS_RIGHT.PROCESS_CREATE_THREAD |
+ PROCESS_ACCESS_RIGHT.PROCESS_TERMINATE;
+
+ var handle = Win32.OpenProcess((uint) access, false, pid);
+ if (!handle.IsInvalid)
+ {
+ throw new Win32Exception();
+ }
+
+ return new Process(handle);
+ }
+
+ public int ReadMemory(IntPtr address, Span destination)
+ {
+ unsafe
+ {
+ fixed (byte* pDest = destination)
+ {
+ IntPtr bytesRead;
+
+ if (!Win32.ReadProcessMemory(m_handle, (void*)address, pDest, (IntPtr)destination.Length, &bytesRead))
+ {
+ throw new Win32Exception();
+ }
+
+ return (uint)bytesRead;
+ }
+ }
+ }
+
+ public void ReadMemoryExact(IntPtr address, Span destination)
+ {
+ var totalBytesRead = 0;
+ while (totalBytesRead < destination.Length)
+ {
+ var bytesRead = ReadMemory(address + totalBytesRead, destination[totalBytesRead..]);
+
+ if (bytesRead == 0)
+ {
+ throw new NotImplementedException("TODO: unexpected EOF");
+ }
+
+ totalBytesRead += bytesRead;
+ }
+ }
+
+ public IntPtr WriteMemory(IntPtr address, ReadOnlySpan source)
+ {
+ unsafe
+ {
+ fixed (byte* pSrc = source)
+ {
+ IntPtr bytesWritten;
+
+ if (!Win32.WriteProcessMemory(m_handle, (void*)address, pSrc, (IntPtr)source.Length, &bytesWritten))
+ {
+ throw new Win32Exception();
+ }
+
+ return bytesWritten;
+ }
+ }
+ }
+
+ public void Terminate(uint exitCode = 0)
+ {
+ if (!Win32.TerminateProcess(m_handle, exitCode))
+ {
+ throw new Win32Exception();
+ }
+ }
+
+ private IntPtr ReadPebAddress()
+ {
+ unsafe
+ {
+ var info = new PROCESS_BASIC_INFORMATION();
+ IntPtr _retLen;
+
+ var status = Win32.NtQueryInformationProcess(m_handle, PROCESSINFOCLASS.ProcessBasicInformation, &info, sizeof(PROCESS_BASIC_INFORMATION), &_retLen);
+ if (!status.Success)
+ {
+ // TODO
+ throw new InvalidOperationException("TODO");
+ }
+
+ return info.PebBaseAddress;
+ }
+ }
+
+ private ReadOnlySpan ReadMemoryAsUtf16(IntPtr address, int length)
+ {
+ var buffer = new byte[length];
+ ReadMemoryExact(address, buffer);
+
+ // TODO..
+
+ return MemoryMarshal.Cast(buffer);
+ }
+
+ public string ReadCommandLine()
+ {
+ unsafe
+ {
+ var pPeb = ReadPebAddress();
+ var pPebLdr = pPeb + (int)Marshal.OffsetOf("ProcessParameters");
+
+ Span procParamBuf = stackalloc byte[sizeof(RTL_USER_PROCESS_PARAMETERS)];
+ ReadMemoryExact(pPebLdr, procParamBuf);
+ ref var procParam = ref MemoryMarshal.AsRef(procParamBuf);
+
+ var commandLine = ReadMemoryAsUtf16(procParam.CommandLine.Buffer, procParam.CommandLine.Length);
+ }
+
+ throw new NotImplementedException();
+ }
+
+ }
+}
diff --git a/Dalamud.Injector/Windows/Win32.cs b/Dalamud.Injector/Windows/Win32.cs
new file mode 100644
index 000000000..f4589141c
--- /dev/null
+++ b/Dalamud.Injector/Windows/Win32.cs
@@ -0,0 +1,145 @@
+using Microsoft.Win32.SafeHandles;
+using System;
+using System.Runtime.InteropServices;
+
+namespace Dalamud.Injector.Windows
+{
+ internal static unsafe class Win32
+ {
+ [DllImport("kernel32", CallingConvention = CallingConvention.Winapi, SetLastError = true)]
+ public static extern SafeProcessHandle OpenProcess(uint dwDesiredAccess, [MarshalAs(UnmanagedType.Bool)] bool bInheritHandle, uint dwProcessId);
+
+ [DllImport("kernel32", CallingConvention = CallingConvention.Winapi, SetLastError = true)]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ public static extern bool TerminateProcess(SafeProcessHandle hProcess, uint uExitCode);
+
+ [DllImport("ntdll", CallingConvention = CallingConvention.Winapi, SetLastError = true)]
+ public static extern NtStatus NtQueryInformationProcess(SafeProcessHandle processHandle, PROCESSINFOCLASS processInfoClass, void* processInformation, int processInformationLength, IntPtr* returnLength);
+
+ [DllImport("kernel32", CallingConvention = CallingConvention.Winapi, SetLastError = true)]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ public static extern bool ReadProcessMemory(SafeProcessHandle hProcess, void* lpBaseAddress, void* lpBuffer, IntPtr nSize, IntPtr* lpNumberOfBytesRead);
+
+ [DllImport("kernel32", CallingConvention = CallingConvention.Winapi, SetLastError = true)]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ public static extern bool WriteProcessMemory(SafeProcessHandle hProcess, void* lpBaseAddress, void* lpBuffer, IntPtr nSize, IntPtr* lpNumberOfBytesWritten);
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal partial struct NtStatus
+ {
+ public uint Value { get; }
+ }
+
+ internal partial struct NtStatus
+ {
+ public NtStatus(uint value)
+ {
+ Value = value;
+ }
+
+ ///
+ /// Equivalent to NT_SUCCESS
+ ///
+ public bool Success => Value <= 0x7FFFFFFF;
+
+ ///
+ /// Equivalent to NT_INFORMATION
+ ///
+ public bool Information => 0x40000000 <= Value && Value <= 0x7FFFFFFF;
+
+ ///
+ /// Equivalent to NT_WARNING
+ ///
+ public bool Warning => 0x80000000 <= Value && Value <= 0xBFFFFFFF;
+
+ ///
+ /// Equivalent to NT_ERROR
+ ///
+ public bool Error => 0xC0000000 <= Value;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct UNICODE_STRING
+ {
+ public ushort Length;
+ public ushort MaximumLength;
+ public IntPtr Buffer;
+ }
+
+ internal enum PROCESSINFOCLASS : uint
+ {
+ ProcessBasicInformation = 0,
+ ProcessDebugPort = 7,
+ ProcessWow64Information = 26,
+ ProcessImageFileName = 27,
+ ProcessBreakOnTermination = 29,
+ ProcessSubsystemInformation = 75,
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct PROCESS_BASIC_INFORMATION
+ {
+ // https://github.com/processhacker/processhacker/blob/e43d7c0513ec5368c3309a58c9f2c2a3ca5de367/phnt/include/ntpsapi.h#L272
+ public NtStatus ExitStatus;
+ public IntPtr PebBaseAddress;
+ public IntPtr AffinityMask;
+ public IntPtr BasePriority;
+ public IntPtr UniqueProcessId;
+ public IntPtr InheritedFromUniqueProcessId;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct PEB
+ {
+ // https://github.com/processhacker/processhacker/blob/238287786b80abad647b988e60f69090cab4c8fe/phnt/include/ntpebteb.h#L57-L218
+ public byte InheritedAddressSpace;
+ public byte ReadImageFileExecOptions;
+ public byte BeingDebugged;
+ public byte BitField;
+ public IntPtr Mutant;
+ public IntPtr ImageBaseAddress;
+ public IntPtr Ldr;
+ public IntPtr ProcessParameters;
+ // ..snip..
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct RTL_USER_PROCESS_PARAMETERS
+ {
+
+ public uint MaximumLength;
+ public uint LengthInitialized;
+ public uint Flags;
+ public uint DebugFlags;
+ public IntPtr ConsoleHandle;
+ public uint ConsoleFlags;
+ public IntPtr StandardInput;
+ public IntPtr StandardOutput;
+ public IntPtr StandardError;
+ public UNICODE_STRING CurrentDirectory_DosPath;
+ public IntPtr CurrentDirectory_Handle;
+ public UNICODE_STRING DllPath;
+ public UNICODE_STRING ImagePathName;
+ public UNICODE_STRING CommandLine;
+ // ..snip..
+ }
+
+ [Flags]
+ internal enum PROCESS_ACCESS_RIGHT : uint
+ {
+ PROCESS_TERMINATE = 0x1,
+ PROCESS_CREATE_THREAD = 0x2,
+ PROCESS_VM_OPERATION = 0x8,
+ PROCESS_VM_READ = 0x10,
+ PROCESS_VM_WRITE = 0x20,
+ PROCESS_DUP_HANDLE = 0x40,
+ PROCESS_CREATE_PROCESS = 0x80,
+ PROCESS_SET_QUOTA = 0x100,
+ PROCESS_SET_INFORMATION = 0x200,
+ PROCESS_QUERY_INFORMATION = 0x400,
+ PROCESS_SUSPEND_RESUME = 0x800,
+ PROCESS_QUERY_LIMITED_INFORMATION = 0x1000,
+ SYNCHRONIZE = 0x100000,
+ }
+}
diff --git a/Dalamud/Dalamud.csproj b/Dalamud/Dalamud.csproj
index a5d982e6e..257e33532 100644
--- a/Dalamud/Dalamud.csproj
+++ b/Dalamud/Dalamud.csproj
@@ -6,21 +6,12 @@
true
enable
-
-
-
-
-
-
-
-
-
diff --git a/Dalamud/EntryPoint.cs b/Dalamud/EntryPoint.cs
index cf4be768e..e7e8404f4 100644
--- a/Dalamud/EntryPoint.cs
+++ b/Dalamud/EntryPoint.cs
@@ -1,9 +1,4 @@
using System;
-using System.IO;
-using System.Net;
-using Dalamud.Interface;
-using Serilog;
-using Serilog.Core;
using CoreHook;
namespace Dalamud