mirror of
https://github.com/terrymacdonald/DisplayMagician.git
synced 2024-08-30 18:32:20 +00:00
Remove uneeded class
No longer require the class ProcessCommandLines as it's not needed any longer.
This commit is contained in:
parent
0c4023fa64
commit
15bcb0801b
@ -107,7 +107,6 @@
|
|||||||
<Compile Include="IconFromFile.cs" />
|
<Compile Include="IconFromFile.cs" />
|
||||||
<Compile Include="IconUtils.cs" />
|
<Compile Include="IconUtils.cs" />
|
||||||
<Compile Include="ImageUtils.cs" />
|
<Compile Include="ImageUtils.cs" />
|
||||||
<Compile Include="ProcessCommandLine.cs" />
|
|
||||||
<Compile Include="ProgramSettings.cs" />
|
<Compile Include="ProgramSettings.cs" />
|
||||||
<Compile Include="Properties\Resources.Designer.cs">
|
<Compile Include="Properties\Resources.Designer.cs">
|
||||||
<AutoGen>True</AutoGen>
|
<AutoGen>True</AutoGen>
|
||||||
|
@ -1,246 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.ComponentModel;
|
|
||||||
using System.Diagnostics;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
|
|
||||||
namespace DisplayMagician
|
|
||||||
{
|
|
||||||
public static class ProcessCommandLine
|
|
||||||
{
|
|
||||||
private static class Win32Native
|
|
||||||
{
|
|
||||||
public const uint PROCESS_BASIC_INFORMATION = 0;
|
|
||||||
|
|
||||||
[Flags]
|
|
||||||
public enum OpenProcessDesiredAccessFlags : uint
|
|
||||||
{
|
|
||||||
PROCESS_VM_READ = 0x0010,
|
|
||||||
PROCESS_QUERY_INFORMATION = 0x0400,
|
|
||||||
}
|
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
|
||||||
public struct ProcessBasicInformation
|
|
||||||
{
|
|
||||||
public IntPtr Reserved1;
|
|
||||||
public IntPtr PebBaseAddress;
|
|
||||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
|
|
||||||
public IntPtr[] Reserved2;
|
|
||||||
public IntPtr UniqueProcessId;
|
|
||||||
public IntPtr Reserved3;
|
|
||||||
}
|
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
|
||||||
public struct UnicodeString
|
|
||||||
{
|
|
||||||
public ushort Length;
|
|
||||||
public ushort MaximumLength;
|
|
||||||
public IntPtr Buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
// This is not the real struct!
|
|
||||||
// I faked it to get ProcessParameters address.
|
|
||||||
// Actual struct definition:
|
|
||||||
// https://docs.microsoft.com/en-us/windows/win32/api/winternl/ns-winternl-peb
|
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
|
||||||
public struct PEB
|
|
||||||
{
|
|
||||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
|
|
||||||
public IntPtr[] Reserved;
|
|
||||||
public IntPtr ProcessParameters;
|
|
||||||
}
|
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
|
||||||
public struct RtlUserProcessParameters
|
|
||||||
{
|
|
||||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
|
|
||||||
public byte[] Reserved1;
|
|
||||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)]
|
|
||||||
public IntPtr[] Reserved2;
|
|
||||||
public UnicodeString ImagePathName;
|
|
||||||
public UnicodeString CommandLine;
|
|
||||||
}
|
|
||||||
|
|
||||||
[DllImport("ntdll.dll")]
|
|
||||||
public static extern uint NtQueryInformationProcess(
|
|
||||||
IntPtr ProcessHandle,
|
|
||||||
uint ProcessInformationClass,
|
|
||||||
IntPtr ProcessInformation,
|
|
||||||
uint ProcessInformationLength,
|
|
||||||
out uint ReturnLength);
|
|
||||||
|
|
||||||
[DllImport("kernel32.dll")]
|
|
||||||
public static extern IntPtr OpenProcess(
|
|
||||||
OpenProcessDesiredAccessFlags dwDesiredAccess,
|
|
||||||
[MarshalAs(UnmanagedType.Bool)] bool bInheritHandle,
|
|
||||||
uint dwProcessId);
|
|
||||||
|
|
||||||
[DllImport("kernel32.dll")]
|
|
||||||
[return: MarshalAs(UnmanagedType.Bool)]
|
|
||||||
public static extern bool ReadProcessMemory(
|
|
||||||
IntPtr hProcess, IntPtr lpBaseAddress, IntPtr lpBuffer,
|
|
||||||
uint nSize, out uint lpNumberOfBytesRead);
|
|
||||||
|
|
||||||
[DllImport("kernel32.dll")]
|
|
||||||
[return: MarshalAs(UnmanagedType.Bool)]
|
|
||||||
public static extern bool CloseHandle(IntPtr hObject);
|
|
||||||
|
|
||||||
[DllImport("shell32.dll", SetLastError = true,
|
|
||||||
CharSet = CharSet.Unicode, EntryPoint = "CommandLineToArgvW")]
|
|
||||||
public static extern IntPtr CommandLineToArgv(string lpCmdLine, out int pNumArgs);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static bool ReadStructFromProcessMemory<TStruct>(
|
|
||||||
IntPtr hProcess, IntPtr lpBaseAddress, out TStruct val)
|
|
||||||
{
|
|
||||||
val = default;
|
|
||||||
var structSize = Marshal.SizeOf<TStruct>();
|
|
||||||
var mem = Marshal.AllocHGlobal(structSize);
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (Win32Native.ReadProcessMemory(
|
|
||||||
hProcess, lpBaseAddress, mem, (uint)structSize, out var len) &&
|
|
||||||
(len == structSize))
|
|
||||||
{
|
|
||||||
val = Marshal.PtrToStructure<TStruct>(mem);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
Marshal.FreeHGlobal(mem);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string ErrorToString(int error) =>
|
|
||||||
new string[]
|
|
||||||
{
|
|
||||||
"Success",
|
|
||||||
"Failed to open process for reading",
|
|
||||||
"Failed to query process information",
|
|
||||||
"PEB address was null",
|
|
||||||
"Failed to read PEB information",
|
|
||||||
"Failed to read process parameters",
|
|
||||||
"Failed to read command line from process"
|
|
||||||
}[Math.Abs(error)];
|
|
||||||
|
|
||||||
public static int Retrieve(Process process, out string commandLine)
|
|
||||||
{
|
|
||||||
int rc = 0;
|
|
||||||
commandLine = null;
|
|
||||||
var hProcess = Win32Native.OpenProcess(
|
|
||||||
Win32Native.OpenProcessDesiredAccessFlags.PROCESS_QUERY_INFORMATION |
|
|
||||||
Win32Native.OpenProcessDesiredAccessFlags.PROCESS_VM_READ, false, (uint)process.Id);
|
|
||||||
if (hProcess != IntPtr.Zero)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var sizePBI = Marshal.SizeOf<Win32Native.ProcessBasicInformation>();
|
|
||||||
var memPBI = Marshal.AllocHGlobal(sizePBI);
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var ret = Win32Native.NtQueryInformationProcess(
|
|
||||||
hProcess, Win32Native.PROCESS_BASIC_INFORMATION, memPBI,
|
|
||||||
(uint)sizePBI, out var len);
|
|
||||||
if (0 == ret)
|
|
||||||
{
|
|
||||||
var pbiInfo = Marshal.PtrToStructure<Win32Native.ProcessBasicInformation>(memPBI);
|
|
||||||
if (pbiInfo.PebBaseAddress != IntPtr.Zero)
|
|
||||||
{
|
|
||||||
if (ReadStructFromProcessMemory<Win32Native.PEB>(hProcess,
|
|
||||||
pbiInfo.PebBaseAddress, out var pebInfo))
|
|
||||||
{
|
|
||||||
if (ReadStructFromProcessMemory<Win32Native.RtlUserProcessParameters>(
|
|
||||||
hProcess, pebInfo.ProcessParameters, out var ruppInfo))
|
|
||||||
{
|
|
||||||
var clLen = ruppInfo.CommandLine.MaximumLength;
|
|
||||||
var memCL = Marshal.AllocHGlobal(clLen);
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (Win32Native.ReadProcessMemory(hProcess,
|
|
||||||
ruppInfo.CommandLine.Buffer, memCL, clLen, out len))
|
|
||||||
{
|
|
||||||
commandLine = Marshal.PtrToStringUni(memCL);
|
|
||||||
rc = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// couldn't read command line buffer
|
|
||||||
rc = -6;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
Marshal.FreeHGlobal(memCL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// couldn't read ProcessParameters
|
|
||||||
rc = -5;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// couldn't read PEB information
|
|
||||||
rc = -4;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// PebBaseAddress is null
|
|
||||||
rc = -3;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// NtQueryInformationProcess failed
|
|
||||||
rc = -2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
Marshal.FreeHGlobal(memPBI);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
Win32Native.CloseHandle(hProcess);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// couldn't open process for VM read
|
|
||||||
rc = -1;
|
|
||||||
}
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IReadOnlyList<string> CommandLineToArgs(string commandLine)
|
|
||||||
{
|
|
||||||
if (string.IsNullOrEmpty(commandLine)) { return Array.Empty<string>(); }
|
|
||||||
|
|
||||||
var argv = Win32Native.CommandLineToArgv(commandLine, out var argc);
|
|
||||||
if (argv == IntPtr.Zero)
|
|
||||||
{
|
|
||||||
throw new Win32Exception(Marshal.GetLastWin32Error());
|
|
||||||
}
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var args = new string[argc];
|
|
||||||
for (var i = 0; i < args.Length; ++i)
|
|
||||||
{
|
|
||||||
var p = Marshal.ReadIntPtr(argv, i * IntPtr.Size);
|
|
||||||
args[i] = Marshal.PtrToStringUni(p);
|
|
||||||
}
|
|
||||||
return args.ToList().AsReadOnly();
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
Marshal.FreeHGlobal(argv);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user