/*
* Process Hacker -
* Node implementation for the process tree
*
* Copyright (C) 2008-2009 wj32
*
* This file is part of Process Hacker.
*
* Process Hacker is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Process Hacker is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Process Hacker. If not, see .
*/
using System;
using System.Collections.Generic;
using System.Drawing;
using Aga.Controls.Tree;
using ProcessHacker.Common;
using ProcessHacker.Native;
using ProcessHacker.Native.Api;
using ProcessHacker.Native.Objects;
using ProcessHacker.Native.Security;
namespace ProcessHacker
{
public class ProcessNode : Node, IDisposable
{
private ProcessNode _parent = null;
private List _children = new List();
private TreePath _treePath = null;
private ProcessItem _pitem;
private bool _wasNoIcon = false;
private Bitmap _icon;
private string _tooltipText;
private int _lastTooltipTickCount = 0;
public ProcessNode(ProcessItem pitem)
{
_pitem = pitem;
this.Tag = pitem.Pid;
if (_pitem.Icon == null)
{
_wasNoIcon = true;
_icon = global::ProcessHacker.Properties.Resources.Process_small.ToBitmap();
}
else
{
try
{
_icon = _pitem.Icon.ToBitmap();
}
catch
{
_wasNoIcon = true;
_icon = global::ProcessHacker.Properties.Resources.Process_small.ToBitmap();
}
}
}
~ProcessNode()
{
if (_icon != null)
this.Dispose();
}
public void Dispose()
{
if (_icon != null)
{
_icon.Dispose();
_icon = null;
}
}
public ProcessItem ProcessItem
{
get { return _pitem; }
set
{
_pitem = value;
if (_wasNoIcon && _pitem.Icon != null)
{
if (_icon != null)
_icon.Dispose();
_icon = new Bitmap(16, 16);
try
{
using (Graphics g = Graphics.FromImage(_icon))
g.DrawIcon(_pitem.Icon, new Rectangle(0, 0, 16, 16));
_wasNoIcon = false;
}
catch
{
_icon.Dispose();
_icon = null;
}
}
}
}
public new ProcessNode Parent
{
get { return _parent; }
set { _parent = value; }
}
public List Children
{
get { return _children; }
}
public TreePath TreePath
{
get { return _treePath; }
}
public string GetTooltipText(ProcessToolTipProvider provider)
{
int tickCount = Environment.TickCount;
if (tickCount - _lastTooltipTickCount >= Settings.RefreshInterval)
{
_tooltipText = provider.GetToolTip(this);
_lastTooltipTickCount = tickCount;
}
return _tooltipText;
}
public TreePath RefreshTreePath()
{
ProcessNode currentNode = this;
Stack stack = new Stack();
while (currentNode != null)
{
stack.Push(currentNode);
currentNode = currentNode.Parent;
}
_treePath = new TreePath(stack.ToArray());
return _treePath;
}
public void RefreshTreePathRecursive()
{
foreach (var child in _children)
child.RefreshTreePathRecursive();
this.RefreshTreePath();
}
public ProcessHacker.Components.NodePlotter.PlotterInfo CpuHistory
{
get
{
return new ProcessHacker.Components.NodePlotter.PlotterInfo()
{
UseSecondLine = true,
OverlaySecondLine = false,
UseLongData = false,
Data1 = _pitem.FloatHistoryManager[ProcessStats.CpuKernel],
Data2 = _pitem.FloatHistoryManager[ProcessStats.CpuUser],
LineColor1 = Properties.Settings.Default.PlotterCPUKernelColor,
LineColor2 = Properties.Settings.Default.PlotterCPUUserColor
};
}
}
public ProcessHacker.Components.NodePlotter.PlotterInfo IoHistory
{
get
{
return new ProcessHacker.Components.NodePlotter.PlotterInfo()
{
UseSecondLine = true,
OverlaySecondLine = true,
UseLongData = true,
LongData1 = _pitem.LongHistoryManager[ProcessStats.IoReadOther],
LongData2 = _pitem.LongHistoryManager[ProcessStats.IoWrite],
LineColor1 = Properties.Settings.Default.PlotterIOROColor,
LineColor2 = Properties.Settings.Default.PlotterIOWColor
};
}
}
public string Name
{
get { return _pitem.Name ?? ""; }
}
public string DisplayPid
{
get
{
if (_pitem.Pid >= 0)
return _pitem.Pid.ToString();
else
return "";
}
}
public int Pid
{
get { return _pitem.Pid; }
}
public int PPid
{
get { if (_pitem.Pid == _pitem.ParentPid) return -1; else return _pitem.ParentPid; }
}
public string PvtMemory
{
get { return Utils.FormatSize(_pitem.Process.VirtualMemoryCounters.PrivatePageCount); }
}
public string WorkingSet
{
get
{
return Utils.FormatSize(_pitem.Process.VirtualMemoryCounters.WorkingSetSize);
}
}
public string PeakWorkingSet
{
get { return Utils.FormatSize(_pitem.Process.VirtualMemoryCounters.PeakWorkingSetSize); }
}
private int GetWorkingSetNumber(NProcessHacker.WsInformationClass WsInformationClass)
{
NtStatus status;
int wsInfo;
int retLen;
try
{
using (var phandle = new ProcessHandle(_pitem.Pid,
ProcessAccess.QueryInformation | ProcessAccess.VmRead))
{
if ((status = NProcessHacker.PhQueryProcessWs(phandle, WsInformationClass, out wsInfo,
4, out retLen)) < NtStatus.Error)
return wsInfo * Program.ProcessProvider.System.PageSize;
}
}
catch
{ }
return 0;
}
public int WorkingSetNumber
{
get { return this.GetWorkingSetNumber(NProcessHacker.WsInformationClass.WsCount); }
}
public int PrivateWorkingSetNumber
{
get { return this.GetWorkingSetNumber(NProcessHacker.WsInformationClass.WsPrivateCount); }
}
public string PrivateWorkingSet
{
get { return Utils.FormatSize(this.PrivateWorkingSetNumber); }
}
public int SharedWorkingSetNumber
{
get { return this.GetWorkingSetNumber(NProcessHacker.WsInformationClass.WsSharedCount); }
}
public string SharedWorkingSet
{
get { return Utils.FormatSize(this.SharedWorkingSetNumber); }
}
public int ShareableWorkingSetNumber
{
get { return this.GetWorkingSetNumber(NProcessHacker.WsInformationClass.WsShareableCount); }
}
public string ShareableWorkingSet
{
get { return Utils.FormatSize(this.ShareableWorkingSetNumber); }
}
public string VirtualSize
{
get { return Utils.FormatSize(_pitem.Process.VirtualMemoryCounters.VirtualSize); }
}
public string PeakVirtualSize
{
get { return Utils.FormatSize(_pitem.Process.VirtualMemoryCounters.PeakVirtualSize); }
}
public string PagefileUsage
{
get { return Utils.FormatSize(_pitem.Process.VirtualMemoryCounters.PagefileUsage); }
}
public string PeakPagefileUsage
{
get { return Utils.FormatSize(_pitem.Process.VirtualMemoryCounters.PeakPagefileUsage); }
}
public string PageFaults
{
get { return _pitem.Process.VirtualMemoryCounters.PageFaultCount.ToString("N0"); }
}
public string Cpu
{
get
{
if (_pitem.CpuUsage == 0)
return "";
else
return _pitem.CpuUsage.ToString("F2");
}
}
private string GetBestUsername(string username, bool includeDomain)
{
if (username == null)
return "";
if (!username.Contains("\\"))
return username;
string[] split = username.Split(new char[] { '\\' }, 2);
string domain = split[0];
string user = split[1];
if (includeDomain)
return domain + "\\" + user;
else
return user;
}
public string Username
{
get { return this.GetBestUsername(_pitem.Username, Settings.ShowAccountDomains); }
}
public string SessionId
{
get
{
if (Pid < 4)
return "";
else
return _pitem.SessionId.ToString();
}
}
public string PriorityClass
{
get
{
try
{
using (var phandle = new ProcessHandle(Pid, Program.MinProcessQueryRights))
return PhUtils.FormatPriorityClass(phandle.GetPriorityClass());
}
catch
{
return "";
}
}
}
public string BasePriority
{
get
{
if (Pid < 4)
return "";
else
return _pitem.Process.BasePriority.ToString();
}
}
public string Description
{
get
{
if (Pid == 0)
return "System Idle Process";
else if (Pid == -2)
return "Deferred Procedure Calls";
else if (Pid == -3)
return "Interrupts";
else if (_pitem.VersionInfo != null && _pitem.VersionInfo.FileDescription != null)
return _pitem.VersionInfo.FileDescription;
else
return "";
}
}
public string Company
{
get
{
if (_pitem.VersionInfo != null && _pitem.VersionInfo.CompanyName != null)
return _pitem.VersionInfo.CompanyName;
else
return "";
}
}
public string FileName
{
get
{
if (_pitem.FileName == null)
return "";
else
return _pitem.FileName;
}
}
public string CommandLine
{
get
{
if (_pitem.CmdLine == null)
return "";
else
return _pitem.CmdLine.Replace("\0", "");
}
}
public string Threads
{
get
{
if (Pid < 4)
return "";
else
return _pitem.Process.NumberOfThreads.ToString();
}
}
public string Handles
{
get
{
if (Pid < 4)
return "";
else
return _pitem.Process.HandleCount.ToString();
}
}
public int GdiHandlesNumber
{
get
{
try
{
using (var phandle = new ProcessHandle(Pid, ProcessAccess.QueryInformation))
return phandle.GetGuiResources(false);
}
catch
{
return 0;
}
}
}
public string GdiHandles
{
get
{
if (Pid < 4)
return "";
else
{
int number = this.GdiHandlesNumber;
if (number == 0)
return "";
else
return number.ToString();
}
}
}
public int UserHandlesNumber
{
get
{
try
{
using (var phandle = new ProcessHandle(Pid, ProcessAccess.QueryInformation))
return phandle.GetGuiResources(true);
}
catch
{
return 0;
}
}
}
public string UserHandles
{
get
{
if (Pid < 4)
return "";
else
{
int number = this.UserHandlesNumber;
if (number == 0)
return "";
else
return number.ToString();
}
}
}
public long IoTotalNumber
{
get
{
if (_pitem.LongHistoryManager[ProcessStats.IoReadOther].Count == 0)
return 0;
else
return (_pitem.LongHistoryManager[ProcessStats.IoReadOther][0] +
_pitem.LongHistoryManager[ProcessStats.IoWrite][0]) * 1000 /
Settings.RefreshInterval;
}
}
public string IoTotal
{
get
{
if (this.IoTotalNumber == 0)
return "";
else
return Utils.FormatSize(this.IoTotalNumber) + "/s";
}
}
public long IoReadOtherNumber
{
get
{
if (_pitem.LongHistoryManager[ProcessStats.IoReadOther].Count == 0)
return 0;
else
return _pitem.LongHistoryManager[ProcessStats.IoReadOther][0] * 1000 /
Settings.RefreshInterval;
}
}
public string IoReadOther
{
get
{
if (this.IoReadOtherNumber == 0)
return "";
else
return Utils.FormatSize(this.IoReadOtherNumber) + "/s";
}
}
public long IoWriteNumber
{
get
{
if (_pitem.LongHistoryManager[ProcessStats.IoReadOther].Count == 0)
return 0;
else
return _pitem.LongHistoryManager[ProcessStats.IoWrite][0] * 1000 /
Settings.RefreshInterval;
}
}
public string IoWrite
{
get
{
if (this.IoWriteNumber == 0)
return "";
else
return Utils.FormatSize(this.IoWriteNumber) + "/s";
}
}
public string Integrity
{
get { return _pitem.Integrity; }
}
public int IntegrityLevel
{
get { return _pitem.IntegrityLevel; }
}
public int IoPriority
{
get
{
try
{
return _pitem.ProcessQueryHandle.GetIoPriority();
}
catch
{
return 0;
}
}
}
public int PagePriority
{
get
{
try
{
return _pitem.ProcessQueryHandle.GetPagePriority();
}
catch
{
return 0;
}
}
}
public Bitmap Icon
{
get { return _icon; }
}
public string StartTime
{
get
{
if (Pid < 4 || _pitem.CreateTime.Year == 1)
return "";
else
return _pitem.CreateTime.ToString();
}
}
public string RelativeStartTime
{
get
{
if (Pid < 4 || _pitem.CreateTime.Year == 1)
return "";
else
return Utils.FormatRelativeDateTime(_pitem.CreateTime);
}
}
public string TotalCpuTime
{
get { return Utils.FormatTimeSpan(new TimeSpan(_pitem.Process.KernelTime + _pitem.Process.UserTime)); }
}
public string KernelCpuTime
{
get { return Utils.FormatTimeSpan(new TimeSpan(_pitem.Process.KernelTime)); }
}
public string UserCpuTime
{
get { return Utils.FormatTimeSpan(new TimeSpan(_pitem.Process.UserTime)); }
}
public string VerificationStatus
{
get { return _pitem.VerifyResult == VerifyResult.Trusted ? "Verified" : ""; }
}
}
}