mirror of
https://github.com/mirror/processhacker
synced 2026-06-08 16:03:24 +00:00
56a3556768
* added more functions in ProcessHandle and ThreadHandle * added integrity, I/O priority and page priority columns * added sorting to WS columns * improved the perceived responsiveness of several components * removed Program.UpdateWindows() * added thread exception handler for debug builds git-svn-id: svn://svn.code.sf.net/p/processhacker/code@1141 21ef857c-d57f-4fe0-8362-d861dc6d29cd
727 lines
29 KiB
C#
727 lines
29 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Net;
|
|
using System.Runtime.InteropServices;
|
|
using System.Text;
|
|
using ProcessHacker.Native.Api;
|
|
using ProcessHacker.Native.Objects;
|
|
using ProcessHacker.Native.Security;
|
|
|
|
namespace ProcessHacker.Native
|
|
{
|
|
public class Windows
|
|
{
|
|
public delegate bool EnumKernelModulesDelegate(KernelModule kernelModule);
|
|
|
|
public delegate string GetProcessNameCallback(int pid);
|
|
|
|
public static GetProcessNameCallback GetProcessName;
|
|
|
|
/// <summary>
|
|
/// A cache for type names; QuerySystemInformation with ALL_TYPES_INFORMATION fails for some
|
|
/// reason. The dictionary relates object type numbers to their names.
|
|
/// </summary>
|
|
internal static Dictionary<byte, string> ObjectTypes = new Dictionary<byte, string>();
|
|
|
|
public static void EnumKernelModules(EnumKernelModulesDelegate enumCallback)
|
|
{
|
|
int requiredSize = 0;
|
|
int[] imageBases;
|
|
|
|
Win32.EnumDeviceDrivers(null, 0, out requiredSize);
|
|
imageBases = new int[requiredSize / 4];
|
|
Win32.EnumDeviceDrivers(imageBases, requiredSize, out requiredSize);
|
|
|
|
for (int i = 0; i < imageBases.Length; i++)
|
|
{
|
|
if (imageBases[i] == 0)
|
|
continue;
|
|
|
|
StringBuilder name = new StringBuilder(0x400);
|
|
StringBuilder fileName = new StringBuilder(0x400);
|
|
|
|
Win32.GetDeviceDriverBaseName(imageBases[i], name, name.Capacity * 2);
|
|
Win32.GetDeviceDriverFileName(imageBases[i], fileName, name.Capacity * 2);
|
|
|
|
if (!enumCallback(
|
|
new KernelModule((uint)imageBases[i],
|
|
name.ToString(),
|
|
FileUtils.FixPath(fileName.ToString()))))
|
|
break;
|
|
}
|
|
}
|
|
|
|
public static string GetAccountName(int sid, bool includeDomain)
|
|
{
|
|
StringBuilder name = new StringBuilder(255);
|
|
StringBuilder domain = new StringBuilder(255);
|
|
int namelen = 255;
|
|
int domainlen = 255;
|
|
SidNameUse use = SidNameUse.User;
|
|
|
|
try
|
|
{
|
|
if (!Win32.LookupAccountSid(null, sid, name, out namelen, domain, out domainlen, out use))
|
|
{
|
|
// if the name is longer than 255 characters, increase the capacity.
|
|
name.EnsureCapacity(namelen);
|
|
domain.EnsureCapacity(domainlen);
|
|
|
|
if (!Win32.LookupAccountSid(null, sid, name, out namelen, domain, out domainlen, out use))
|
|
{
|
|
if (name.ToString() == "" && domain.ToString() == "")
|
|
Win32.ThrowLastError();
|
|
}
|
|
}
|
|
}
|
|
catch
|
|
{
|
|
// if we didn't find a name, then return the string SID version.
|
|
return (new System.Security.Principal.SecurityIdentifier(new IntPtr(sid))).ToString();
|
|
}
|
|
|
|
if (includeDomain)
|
|
{
|
|
return ((domain.ToString() != "") ? domain.ToString() + "\\" : "") + name.ToString();
|
|
}
|
|
else
|
|
{
|
|
return name.ToString();
|
|
}
|
|
}
|
|
|
|
public static SidNameUse GetAccountType(int SID)
|
|
{
|
|
StringBuilder name = new StringBuilder(255);
|
|
StringBuilder domain = new StringBuilder(255);
|
|
int namelen = 255;
|
|
int domainlen = 255;
|
|
SidNameUse use = SidNameUse.User;
|
|
|
|
// we don't actually need to get the account name
|
|
if (!Win32.LookupAccountSid(null, SID, name, out namelen, domain, out domainlen, out use))
|
|
{
|
|
name.EnsureCapacity(namelen);
|
|
domain.EnsureCapacity(domainlen);
|
|
|
|
if (!Win32.LookupAccountSid(null, SID, name, out namelen, domain, out domainlen, out use))
|
|
{
|
|
if (name.ToString() == "" && domain.ToString() == "")
|
|
throw new Exception("Could not lookup account SID: " + Win32.GetLastErrorMessage());
|
|
}
|
|
}
|
|
|
|
return use;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Enumerates the handles opened by every running process.
|
|
/// </summary>
|
|
/// <returns>An array containing information about the handles.</returns>
|
|
public static SystemHandleInformation[] GetHandles()
|
|
{
|
|
int retLength = 0;
|
|
int handleCount = 0;
|
|
SystemHandleInformation[] returnHandles;
|
|
|
|
using (MemoryAlloc data = new MemoryAlloc(0x1000))
|
|
{
|
|
int status;
|
|
|
|
// This is needed because NtQuerySystemInformation with SystemHandleInformation doesn't
|
|
// actually give a real return length when called with an insufficient buffer. This code
|
|
// tries repeatedly to call the function, doubling the buffer size each time it fails.
|
|
while ((uint)(status = Win32.NtQuerySystemInformation(SystemInformationClass.SystemHandleInformation,
|
|
data.Memory, data.Size, out retLength)) == Win32.STATUS_INFO_LENGTH_MISMATCH)
|
|
{
|
|
data.Resize(data.Size * 2);
|
|
|
|
// Fail if we've resized it to over 16MB - protect from infinite resizing
|
|
if (data.Size > 16 * 1024 * 1024)
|
|
throw new OutOfMemoryException();
|
|
}
|
|
|
|
if (status < 0)
|
|
Win32.ThrowLastError(status);
|
|
|
|
// The structure of the buffer is the handle count plus an array of SYSTEM_HANDLE_INFORMATION
|
|
// structures.
|
|
handleCount = data.ReadInt32(0);
|
|
returnHandles = new SystemHandleInformation[handleCount];
|
|
|
|
for (int i = 0; i < handleCount; i++)
|
|
{
|
|
returnHandles[i] = data.ReadStruct<SystemHandleInformation>(4, i);
|
|
}
|
|
|
|
return returnHandles;
|
|
}
|
|
}
|
|
|
|
public static KernelModule[] GetKernelModules()
|
|
{
|
|
int requiredSize = 0;
|
|
int[] imageBases;
|
|
|
|
Win32.EnumDeviceDrivers(null, 0, out requiredSize);
|
|
imageBases = new int[requiredSize / 4];
|
|
Win32.EnumDeviceDrivers(imageBases, requiredSize, out requiredSize);
|
|
|
|
KernelModule[] kernelModules = new KernelModule[imageBases.Length];
|
|
|
|
for (int i = 0; i < imageBases.Length; i++)
|
|
{
|
|
if (imageBases[i] == 0)
|
|
continue;
|
|
|
|
StringBuilder name = new StringBuilder(0x400);
|
|
StringBuilder fileName = new StringBuilder(0x400);
|
|
|
|
Win32.GetDeviceDriverBaseName(imageBases[i], name, name.Capacity * 2);
|
|
Win32.GetDeviceDriverFileName(imageBases[i], fileName, name.Capacity * 2);
|
|
|
|
kernelModules[i] = new KernelModule((uint)imageBases[i], name.ToString(), FileUtils.FixPath(fileName.ToString()));
|
|
}
|
|
|
|
return kernelModules;
|
|
}
|
|
|
|
public static Dictionary<int, List<NetworkConnection>> GetNetworkConnections()
|
|
{
|
|
var retDict = new Dictionary<int, List<NetworkConnection>>();
|
|
int length = 0;
|
|
|
|
Win32.GetExtendedTcpTable(IntPtr.Zero, ref length, false, 2, TcpTableClass.OwnerPidAll, 0);
|
|
|
|
using (var mem = new MemoryAlloc(length))
|
|
{
|
|
if (Win32.GetExtendedTcpTable(mem, ref length, false, 2,
|
|
TcpTableClass.OwnerPidAll, 0) != 0)
|
|
Win32.ThrowLastError();
|
|
|
|
int count = mem.ReadInt32(0);
|
|
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
var struc = mem.ReadStruct<MibTcpRowOwnerPid>(4, i);
|
|
|
|
if (!retDict.ContainsKey(struc.OwningProcessId))
|
|
retDict.Add(struc.OwningProcessId, new List<NetworkConnection>());
|
|
|
|
retDict[struc.OwningProcessId].Add(new NetworkConnection()
|
|
{
|
|
Protocol = NetworkProtocol.Tcp,
|
|
Local = new IPEndPoint(struc.LocalAddress, ((ushort)struc.LocalPort).SwapBytes()),
|
|
Remote = new IPEndPoint(struc.RemoteAddress, ((ushort)struc.RemotePort).SwapBytes()),
|
|
State = struc.State,
|
|
PID = struc.OwningProcessId
|
|
});
|
|
}
|
|
}
|
|
|
|
Win32.GetExtendedUdpTable(IntPtr.Zero, ref length, false, 2, UdpTableClass.OwnerPid, 0);
|
|
|
|
using (var mem = new MemoryAlloc(length))
|
|
{
|
|
if (Win32.GetExtendedUdpTable(mem, ref length, false, 2, UdpTableClass.OwnerPid, 0) != 0)
|
|
Win32.ThrowLastError();
|
|
|
|
int count = mem.ReadInt32(0);
|
|
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
var struc = mem.ReadStruct<MibUdpRowOwnerPid>(4, i);
|
|
|
|
if (!retDict.ContainsKey(struc.OwningProcessId))
|
|
retDict.Add(struc.OwningProcessId, new List<NetworkConnection>());
|
|
|
|
retDict[struc.OwningProcessId].Add(
|
|
new NetworkConnection()
|
|
{
|
|
Protocol = NetworkProtocol.Udp,
|
|
Local = new IPEndPoint(struc.LocalAddress, ((ushort)struc.LocalPort).SwapBytes()),
|
|
PID = struc.OwningProcessId
|
|
});
|
|
}
|
|
}
|
|
|
|
return retDict;
|
|
}
|
|
|
|
public static string GetPrivilegeDisplayName(string PrivilegeName)
|
|
{
|
|
StringBuilder sb = null;
|
|
int size = 0;
|
|
int languageId = 0;
|
|
|
|
Win32.LookupPrivilegeDisplayName(0, PrivilegeName, sb, out size, out languageId);
|
|
sb = new StringBuilder(size);
|
|
Win32.LookupPrivilegeDisplayName(0, PrivilegeName, sb, out size, out languageId);
|
|
|
|
return sb.ToString();
|
|
}
|
|
|
|
public static string GetPrivilegeName(Luid Luid)
|
|
{
|
|
StringBuilder sb = null;
|
|
int size = 0;
|
|
|
|
Win32.LookupPrivilegeName(0, ref Luid, sb, out size);
|
|
sb = new StringBuilder(size);
|
|
Win32.LookupPrivilegeName(0, ref Luid, sb, out size);
|
|
|
|
return sb.ToString();
|
|
}
|
|
|
|
public static Dictionary<int, SystemProcess> GetProcesses()
|
|
{
|
|
return GetProcesses(null);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets a dictionary containing the currently running processes.
|
|
/// </summary>
|
|
/// <returns>A dictionary, indexed by process ID.</returns>
|
|
public static Dictionary<int, SystemProcess> GetProcesses(Dictionary<int, object> processesWithThreads)
|
|
{
|
|
int retLength;
|
|
Dictionary<int, SystemProcess> returnProcesses;
|
|
|
|
using (MemoryAlloc data = new MemoryAlloc(0x4000))
|
|
{
|
|
int status;
|
|
int attempts = 0;
|
|
|
|
while (true)
|
|
{
|
|
attempts++;
|
|
|
|
if ((status = Win32.NtQuerySystemInformation(SystemInformationClass.SystemProcessInformation, data.Memory,
|
|
data.Size, out retLength)) < 0)
|
|
{
|
|
if (attempts > 3)
|
|
Win32.ThrowLastError(status);
|
|
|
|
data.Resize(retLength);
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
returnProcesses = new Dictionary<int, SystemProcess>();
|
|
|
|
int i = 0;
|
|
SystemProcess currentProcess = new SystemProcess();
|
|
|
|
while (true)
|
|
{
|
|
currentProcess.Process = data.ReadStruct<SystemProcessInformation>(i, 0);
|
|
currentProcess.Name = Utils.ReadUnicodeString(currentProcess.Process.ImageName);
|
|
|
|
if (processesWithThreads != null)
|
|
{
|
|
if (processesWithThreads.ContainsKey(currentProcess.Process.ProcessId) &&
|
|
currentProcess.Process.ProcessId != 0)
|
|
{
|
|
currentProcess.Threads = new Dictionary<int, SystemThreadInformation>();
|
|
|
|
for (int j = 0; j < currentProcess.Process.NumberOfThreads; j++)
|
|
{
|
|
var thread = data.ReadStruct<SystemThreadInformation>(i +
|
|
Marshal.SizeOf(typeof(SystemProcessInformation)), j);
|
|
|
|
currentProcess.Threads.Add(thread.ClientId.UniqueThread, thread);
|
|
}
|
|
}
|
|
}
|
|
|
|
returnProcesses.Add(currentProcess.Process.ProcessId, currentProcess);
|
|
|
|
if (currentProcess.Process.NextEntryOffset == 0)
|
|
break;
|
|
|
|
i += currentProcess.Process.NextEntryOffset;
|
|
}
|
|
|
|
return returnProcesses;
|
|
}
|
|
}
|
|
|
|
public static Dictionary<string, EnumServiceStatusProcess> GetServices()
|
|
{
|
|
using (ServiceManagerHandle manager =
|
|
new ServiceManagerHandle(ScManagerAccess.EnumerateService))
|
|
{
|
|
int requiredSize;
|
|
int servicesReturned;
|
|
int resume;
|
|
|
|
// get required size
|
|
Win32.EnumServicesStatusEx(manager, 0, ServiceQueryType.Win32 | ServiceQueryType.Driver,
|
|
ServiceQueryState.All, IntPtr.Zero, 0, out requiredSize, out servicesReturned,
|
|
out resume, 0);
|
|
|
|
using (MemoryAlloc data = new MemoryAlloc(requiredSize))
|
|
{
|
|
var dictionary = new Dictionary<string, EnumServiceStatusProcess>();
|
|
|
|
if (!Win32.EnumServicesStatusEx(manager, 0, ServiceQueryType.Win32 | ServiceQueryType.Driver,
|
|
ServiceQueryState.All, data,
|
|
data.Size, out requiredSize, out servicesReturned,
|
|
out resume, 0))
|
|
Win32.ThrowLastError();
|
|
|
|
for (int i = 0; i < servicesReturned; i++)
|
|
{
|
|
var service = data.ReadStruct<EnumServiceStatusProcess>(i);
|
|
|
|
dictionary.Add(service.ServiceName, service);
|
|
}
|
|
|
|
return dictionary;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public class KernelModule
|
|
{
|
|
public KernelModule(uint baseAddress, string baseName, string fileName)
|
|
{
|
|
this.BaseAddress = baseAddress;
|
|
this.BaseName = baseName;
|
|
this.FileName = fileName;
|
|
}
|
|
|
|
public uint BaseAddress { get; private set; }
|
|
public string BaseName { get; private set; }
|
|
public string FileName { get; private set; }
|
|
}
|
|
|
|
public struct ObjectInformation
|
|
{
|
|
public string OrigName;
|
|
public string BestName;
|
|
public string TypeName;
|
|
}
|
|
|
|
[StructLayout(LayoutKind.Sequential)]
|
|
public struct SystemHandleInformation
|
|
{
|
|
public int ProcessId;
|
|
public byte ObjectTypeNumber;
|
|
public HandleFlags Flags;
|
|
public short Handle;
|
|
public int Object;
|
|
public int GrantedAccess;
|
|
|
|
public ObjectInformation GetHandleInfo()
|
|
{
|
|
using (ProcessHandle process = new ProcessHandle(this.ProcessId, ProcessAccess.DupHandle))
|
|
{
|
|
return this.GetHandleInfo(process);
|
|
}
|
|
}
|
|
|
|
public ObjectInformation GetHandleInfo(ProcessHandle process)
|
|
{
|
|
int objectHandleI;
|
|
int retLength = 0;
|
|
Win32Handle objectHandle = null;
|
|
|
|
if (this.Handle == 0 || this.Handle == -1 || this.Handle == -2)
|
|
throw new WindowsException(6);
|
|
|
|
// Duplicate the handle if we're not using KPH
|
|
if (KProcessHacker.Instance == null)
|
|
{
|
|
int status;
|
|
|
|
if ((status = Win32.NtDuplicateObject(process, this.Handle, -1, out objectHandleI, 0, 0, 0)) < 0)
|
|
Win32.ThrowLastError();
|
|
|
|
objectHandle = new Win32Handle(objectHandleI);
|
|
}
|
|
|
|
ObjectInformation info = new ObjectInformation();
|
|
|
|
// If the cache contains the object type's name, use it. Otherwise, query the type
|
|
// for its name.
|
|
lock (Windows.ObjectTypes)
|
|
{
|
|
if (Windows.ObjectTypes.ContainsKey(this.ObjectTypeNumber))
|
|
{
|
|
info.TypeName = Windows.ObjectTypes[this.ObjectTypeNumber];
|
|
}
|
|
else
|
|
{
|
|
int baseAddress = 0;
|
|
|
|
if (KProcessHacker.Instance != null)
|
|
{
|
|
KProcessHacker.Instance.ZwQueryObject(process, this.Handle, ObjectInformationClass.ObjectTypeInformation,
|
|
IntPtr.Zero, 0, out retLength, out baseAddress);
|
|
}
|
|
else
|
|
{
|
|
Win32.NtQueryObject(objectHandle, ObjectInformationClass.ObjectTypeInformation,
|
|
IntPtr.Zero, 0, out retLength);
|
|
}
|
|
|
|
if (retLength > 0)
|
|
{
|
|
using (MemoryAlloc otiMem = new MemoryAlloc(retLength))
|
|
{
|
|
if (KProcessHacker.Instance != null)
|
|
{
|
|
if (KProcessHacker.Instance.ZwQueryObject(process, this.Handle, ObjectInformationClass.ObjectTypeInformation,
|
|
otiMem, otiMem.Size, out retLength, out baseAddress) < 0)
|
|
throw new Exception("ZwQueryObject failed.");
|
|
}
|
|
else
|
|
{
|
|
if (Win32.NtQueryObject(objectHandle, ObjectInformationClass.ObjectTypeInformation,
|
|
otiMem, otiMem.Size, out retLength) < 0)
|
|
throw new Exception("NtQueryObject failed.");
|
|
}
|
|
|
|
var oti = otiMem.ReadStruct<ObjectTypeInformation>();
|
|
var str = oti.Name;
|
|
|
|
if (KProcessHacker.Instance != null)
|
|
str.Buffer += -baseAddress + otiMem;
|
|
|
|
info.TypeName = Utils.ReadUnicodeString(str);
|
|
Windows.ObjectTypes.Add(this.ObjectTypeNumber, info.TypeName);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (KProcessHacker.Instance != null && info.TypeName == "File")
|
|
{
|
|
// use KProcessHacker for files
|
|
info.OrigName = KProcessHacker.Instance.GetFileObjectName(this);
|
|
}
|
|
else if (info.TypeName == "File" && (int)this.GrantedAccess == 0x0012019f)
|
|
{
|
|
// KProcessHacker not available, fall back to using hack (i.e. not querying the name at all)
|
|
}
|
|
else
|
|
{
|
|
int baseAddress = 0;
|
|
|
|
if (KProcessHacker.Instance != null)
|
|
{
|
|
KProcessHacker.Instance.ZwQueryObject(process, this.Handle, ObjectInformationClass.ObjectNameInformation,
|
|
IntPtr.Zero, 0, out retLength, out baseAddress);
|
|
}
|
|
else
|
|
{
|
|
Win32.NtQueryObject(objectHandle, ObjectInformationClass.ObjectNameInformation,
|
|
IntPtr.Zero, 0, out retLength);
|
|
}
|
|
|
|
if (retLength > 0)
|
|
{
|
|
using (MemoryAlloc oniMem = new MemoryAlloc(retLength))
|
|
{
|
|
if (KProcessHacker.Instance != null)
|
|
{
|
|
if (KProcessHacker.Instance.ZwQueryObject(process, this.Handle, ObjectInformationClass.ObjectNameInformation,
|
|
oniMem, oniMem.Size, out retLength, out baseAddress) < 0)
|
|
throw new Exception("ZwQueryObject failed.");
|
|
}
|
|
else
|
|
{
|
|
if (Win32.NtQueryObject(objectHandle, ObjectInformationClass.ObjectNameInformation,
|
|
oniMem, oniMem.Size, out retLength) < 0)
|
|
throw new Exception("NtQueryObject failed.");
|
|
}
|
|
|
|
var oni = oniMem.ReadStruct<ObjectNameInformation>();
|
|
var str = oni.Name;
|
|
|
|
if (KProcessHacker.Instance != null)
|
|
str.Buffer += -baseAddress + oniMem;
|
|
|
|
info.OrigName = Utils.ReadUnicodeString(str);
|
|
}
|
|
}
|
|
}
|
|
|
|
// get a better name for the handle
|
|
try
|
|
{
|
|
switch (info.TypeName)
|
|
{
|
|
case "File":
|
|
// resolves \Device\Harddisk1 into C:, for example
|
|
info.BestName = FileUtils.DeviceFileNameToDos(info.OrigName);
|
|
|
|
break;
|
|
|
|
case "Key":
|
|
string hklmString = "\\registry\\machine";
|
|
string hkcrString = "\\registry\\machine\\software\\classes";
|
|
string hkcuString = "\\registry\\user\\" +
|
|
System.Security.Principal.WindowsIdentity.GetCurrent().User.ToString().ToLower();
|
|
string hkcucrString = "\\registry\\user\\" +
|
|
System.Security.Principal.WindowsIdentity.GetCurrent().User.ToString().ToLower() + "_classes";
|
|
string hkuString = "\\registry\\user";
|
|
|
|
if (info.OrigName.ToLower().StartsWith(hkcrString))
|
|
info.BestName = "HKCR" + info.OrigName.Substring(hkcrString.Length);
|
|
else if (info.OrigName.ToLower().StartsWith(hklmString))
|
|
info.BestName = "HKLM" + info.OrigName.Substring(hklmString.Length);
|
|
else if (info.OrigName.ToLower().StartsWith(hkcucrString))
|
|
info.BestName = "HKCU\\Software\\Classes" + info.OrigName.Substring(hkcucrString.Length);
|
|
else if (info.OrigName.ToLower().StartsWith(hkcuString))
|
|
info.BestName = "HKCU" + info.OrigName.Substring(hkcuString.Length);
|
|
else if (info.OrigName.ToLower().StartsWith(hkuString))
|
|
info.BestName = "HKU" + info.OrigName.Substring(hkuString.Length);
|
|
else
|
|
info.BestName = info.OrigName;
|
|
|
|
break;
|
|
|
|
case "Process":
|
|
{
|
|
int processId;
|
|
|
|
if (KProcessHacker.Instance != null)
|
|
{
|
|
processId = KProcessHacker.Instance.KphGetProcessId(process, this.Handle);
|
|
|
|
if (processId == 0)
|
|
throw new Exception("Invalid PID");
|
|
}
|
|
else
|
|
{
|
|
using (Win32Handle processHandle =
|
|
new Win32Handle(process, this.Handle, (int)OSVersion.MinProcessQueryInfoAccess))
|
|
{
|
|
if ((processId = Win32.GetProcessId(processHandle)) == 0)
|
|
Win32.ThrowLastError();
|
|
}
|
|
}
|
|
|
|
string processName = Windows.GetProcessName(processId);
|
|
|
|
if (processName != null)
|
|
info.BestName = processName + " (" + processId.ToString() + ")";
|
|
else
|
|
info.BestName = "Non-existent process (" + processId.ToString() + ")";
|
|
}
|
|
|
|
break;
|
|
|
|
case "Thread":
|
|
{
|
|
int processId;
|
|
int threadId;
|
|
|
|
if (KProcessHacker.Instance != null)
|
|
{
|
|
threadId = KProcessHacker.Instance.KphGetThreadId(process, this.Handle, out processId);
|
|
|
|
if (threadId == 0 || processId == 0)
|
|
throw new Exception("Invalid TID or PID");
|
|
}
|
|
else
|
|
{
|
|
using (Win32Handle threadHandle =
|
|
new Win32Handle(process, this.Handle, (int)OSVersion.MinThreadQueryInfoAccess))
|
|
{
|
|
if ((threadId = Win32.GetThreadId(threadHandle)) == 0)
|
|
Win32.ThrowLastError();
|
|
|
|
if ((processId = Win32.GetProcessIdOfThread(threadHandle)) == 0)
|
|
Win32.ThrowLastError();
|
|
}
|
|
}
|
|
|
|
string processName = Windows.GetProcessName(processId);
|
|
|
|
if (processName != null)
|
|
info.BestName = processName + " (" + processId.ToString() + "): " +
|
|
threadId.ToString();
|
|
else
|
|
info.BestName = "Non-existent process (" + processId.ToString() + "): " +
|
|
threadId.ToString();
|
|
}
|
|
|
|
break;
|
|
|
|
case "Token":
|
|
{
|
|
using (Win32Handle tokenHandle =
|
|
new Win32Handle(process, this.Handle, (int)TokenAccess.Query))
|
|
{
|
|
info.BestName = TokenHandle.FromHandle(tokenHandle).GetUser().GetName(true);
|
|
}
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
if (info.OrigName != null &&
|
|
info.OrigName != "")
|
|
{
|
|
info.BestName = info.OrigName;
|
|
}
|
|
else
|
|
{
|
|
info.BestName = null;
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
catch
|
|
{
|
|
if (info.OrigName != null && info.OrigName != "")
|
|
{
|
|
info.BestName = info.OrigName;
|
|
}
|
|
else
|
|
{
|
|
info.BestName = null;
|
|
}
|
|
}
|
|
|
|
if (objectHandle != null)
|
|
objectHandle.Dispose();
|
|
|
|
return info;
|
|
}
|
|
}
|
|
|
|
public enum NetworkProtocol
|
|
{
|
|
Tcp, Udp
|
|
}
|
|
|
|
public struct NetworkConnection
|
|
{
|
|
public string ID;
|
|
public int PID;
|
|
public NetworkProtocol Protocol;
|
|
public string LocalString;
|
|
public IPEndPoint Local;
|
|
public string RemoteString;
|
|
public IPEndPoint Remote;
|
|
public MibTcpState State;
|
|
}
|
|
|
|
public struct SystemProcess
|
|
{
|
|
public string Name;
|
|
public SystemProcessInformation Process;
|
|
public Dictionary<int, SystemThreadInformation> Threads;
|
|
}
|
|
}
|