diff --git a/Dalamud.Injector/Windows/NtException.cs b/Dalamud.Injector/Windows/NtException.cs index 6887dc3ff..c4f2d25c9 100644 --- a/Dalamud.Injector/Windows/NtException.cs +++ b/Dalamud.Injector/Windows/NtException.cs @@ -2,11 +2,11 @@ using System; namespace Dalamud.Injector.Windows { - internal sealed class NtException : Exception + internal sealed class NtStatusException : Exception { public NtStatus Status { get; } - public NtException(NtStatus status) + public NtStatusException(NtStatus status) { Status = status; } diff --git a/Dalamud.Injector/Windows/Process.cs b/Dalamud.Injector/Windows/Process.cs index 8645a7bd3..0fdb04899 100644 --- a/Dalamud.Injector/Windows/Process.cs +++ b/Dalamud.Injector/Windows/Process.cs @@ -5,18 +5,13 @@ using System.Runtime.InteropServices; namespace Dalamud.Injector.Windows { - /// - /// - /// - /// - /// - /// internal sealed partial class Process : IDisposable { private SafeProcessHandle m_handle; } - internal sealed partial class Process { + internal sealed partial class Process + { /// /// /// @@ -51,6 +46,12 @@ namespace Dalamud.Injector.Windows return new Process(handle); } + /// + /// Reads the process memory. + /// + /// + /// The number of bytes that is actually read and written into the buffer. + /// public int ReadMemory(IntPtr address, Span destination) { unsafe @@ -64,6 +65,7 @@ namespace Dalamud.Injector.Windows throw new Win32Exception(); } + // this is okay as Span can't really be longer than int.Max return (int)bytesRead; } } @@ -75,11 +77,12 @@ namespace Dalamud.Injector.Windows while (totalBytesRead < destination.Length) { var bytesRead = ReadMemory(address + totalBytesRead, destination[totalBytesRead..]); - - if (bytesRead == 0) - { - throw new NotImplementedException("TODO: unexpected EOF"); - } + + // err -> partial read -> page fault? + //if (bytesRead == 0) + //{ + // throw new NotImplementedException("TODO: unexpected EOF"); + //} totalBytesRead += bytesRead; } @@ -116,43 +119,39 @@ namespace Dalamud.Injector.Windows unsafe { var info = new PROCESS_BASIC_INFORMATION(); - IntPtr _retLen; + var status = Win32.NtQueryInformationProcess(m_handle, PROCESSINFOCLASS.ProcessBasicInformation, &info, sizeof(PROCESS_BASIC_INFORMATION), (IntPtr*)IntPtr.Zero); - var status = Win32.NtQueryInformationProcess(m_handle, PROCESSINFOCLASS.ProcessBasicInformation, &info, sizeof(PROCESS_BASIC_INFORMATION), &_retLen); if (!status.Success) { - // TODO - throw new InvalidOperationException("TODO"); + throw new NtStatusException(status); } 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() + public string[] ReadCommandLine() { unsafe { var pPeb = ReadPebAddress(); - var pPebProc = ReadMemoryExact(pPeb + (int)Marshal.OffsetOf("ProcessParameters"); - var + // Read peb (partially) + Span pebBuf = stackalloc byte[sizeof(PEB)]; + ReadMemoryExact(pPeb, pebBuf); + ref readonly var peb = ref MemoryMarshal.AsRef(pebBuf); + // Read process parameters Span procParamBuf = stackalloc byte[sizeof(RTL_USER_PROCESS_PARAMETERS)]; - ReadMemoryExact(pPebLdr, procParamBuf); - ref var procParam = ref MemoryMarshal.AsRef(procParamBuf); + ReadMemoryExact(peb.ProcessParameters, procParamBuf); + ref readonly var procParam = ref MemoryMarshal.AsRef(procParamBuf); + + // Read commandline + var commandLineBuf = new byte[procParam.CommandLine.Length]; // arbitrary length; allocate to gc heap + ReadMemoryExact(procParam.CommandLine.Buffer, commandLineBuf); + + - 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 index f4589141c..68cd9e1e7 100644 --- a/Dalamud.Injector/Windows/Win32.cs +++ b/Dalamud.Injector/Windows/Win32.cs @@ -23,6 +23,12 @@ namespace Dalamud.Injector.Windows [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); + + [DllImport("kernel32", CallingConvention = CallingConvention.Winapi, SetLastError = true)] + public static extern void* LocalFree(void* hMem); + + [DllImport("kernel32", CallingConvention = CallingConvention.Winapi, SetLastError = true)] + public static extern void* CommandLineToArgvW(, int* pNumArgs); } [StructLayout(LayoutKind.Sequential)]