diff --git a/trunk/ProcessHacker/Components/ProcessTree/ProcessTree.cs b/trunk/ProcessHacker/Components/ProcessTree/ProcessTree.cs
index 252df4955..dba264ec6 100644
--- a/trunk/ProcessHacker/Components/ProcessTree/ProcessTree.cs
+++ b/trunk/ProcessHacker/Components/ProcessTree/ProcessTree.cs
@@ -391,9 +391,15 @@ namespace ProcessHacker
try
{
ProcessNode pNode = this.FindNode(node);
- ProcessItem item = _provider.Dictionary[pNode.PID];
- node.BackColor = this.GetProcessColor(item);
+ // May not be in the dictionary if the process has terminated but
+ // the node is still being highlighted.
+ if (_provider.Dictionary.ContainsKey(pNode.PID))
+ {
+ ProcessItem item = _provider.Dictionary[pNode.PID];
+
+ node.BackColor = this.GetProcessColor(item);
+ }
}
catch (Exception ex)
{
diff --git a/trunk/ProcessHacker/Components/ProcessTree/ProcessTreeModel.cs b/trunk/ProcessHacker/Components/ProcessTree/ProcessTreeModel.cs
index 0f600751d..198617e5f 100644
--- a/trunk/ProcessHacker/Components/ProcessTree/ProcessTreeModel.cs
+++ b/trunk/ProcessHacker/Components/ProcessTree/ProcessTreeModel.cs
@@ -27,6 +27,9 @@ using System.Windows.Forms;
namespace ProcessHacker
{
+ ///
+ /// The process tree model. None of the methods are thread-safe.
+ ///
public class ProcessTreeModel : ITreeModel
{
private ProcessTree _tree;
@@ -42,18 +45,22 @@ namespace ProcessHacker
{
ProcessNode itemNode = new ProcessNode(item);
- // find this process' parent
+ // Find the process' parent and add the process to it if we found it.
if (item.HasParent && _processes.ContainsKey(item.ParentPid))
+ {
_processes[item.ParentPid].Children.Add(itemNode);
+ }
else
+ {
+ // The process doesn't have a parent, so add it to the root nodes.
_roots.Add(itemNode);
+ }
+ // Add the process to the list of all processes.
_processes.Add(item.Pid, itemNode);
- ProcessNode[] rootNodes = _roots.ToArray();
-
- // find this process' children
- foreach (ProcessNode node in rootNodes)
+ // Find this process' children and add them.
+ foreach (ProcessNode node in _roots)
{
if (node.ProcessItem.HasParent && node.PPID == item.Pid)
{
@@ -80,45 +87,54 @@ namespace ProcessHacker
public void Remove(ProcessItem item)
{
ProcessNode targetNode = _processes[item.Pid];
- ProcessNode[] nodes = _roots.ToArray();
ProcessNode[] targetChildren = null;
+ // Dispose of the process node we're removing.
targetNode.Dispose();
- foreach (ProcessNode node in nodes)
- {
- if (node.PID == item.Pid)
- {
- _roots.Remove(node);
- this.MoveChildrenToRoot(node);
- break;
- }
- else if (targetNode.ProcessItem.HasParent && _processes.ContainsKey(targetNode.PPID))
- {
- ProcessNode foundNode = _processes[targetNode.PPID];
+ // Check if the process is a root.
+ ProcessNode rootNode = _roots.Find(node => node.PID == item.Pid);
- if (foundNode != null)
+ if (rootNode != null)
+ {
+ // Remove the process from the roots and make its children root nodes.
+ _roots.Remove(rootNode);
+ this.MoveChildrenToRoot(rootNode);
+ }
+ else
+ {
+ // The process isn't a root, so we have to search for the process' parent.
+ if (targetNode.ProcessItem.HasParent && _processes.ContainsKey(targetNode.PPID))
+ {
+ ProcessNode parentNode = _processes[targetNode.PPID];
+
+ if (parentNode != null)
{
- foundNode.Children.Remove(targetNode);
+ // Remove the node from its parent and make its children root nodes.
+ parentNode.Children.Remove(targetNode);
targetChildren = targetNode.Children.ToArray();
this.MoveChildrenToRoot(targetNode);
- break;
}
}
}
+ // Remove the process from the process dictionary.
_processes.Remove(item.Pid);
this.StructureChanged(this, new TreePathEventArgs(new TreePath()));
- foreach (ProcessNode n in targetChildren)
+ // Expand the children because TreeViewAdv collapses them by default.
+ if (targetChildren != null)
{
- try
+ foreach (ProcessNode n in targetChildren)
{
- _tree.FindTreeNode(n).ExpandAll();
- }
- catch (Exception ex)
- {
- Logging.Log(ex);
+ try
+ {
+ _tree.FindTreeNode(n).ExpandAll();
+ }
+ catch (Exception ex)
+ {
+ Logging.Log(ex);
+ }
}
}
@@ -316,6 +332,7 @@ namespace ProcessHacker
public bool IsLeaf(TreePath treePath)
{
+ // When we're sorting the whole tree is a flat list, so there are no children.
if (this.GetSortColumn() != "")
return true;
diff --git a/trunk/ProcessHacker/Forms/HackerWindow.cs b/trunk/ProcessHacker/Forms/HackerWindow.cs
index 0e6813c81..0bdc9926e 100644
--- a/trunk/ProcessHacker/Forms/HackerWindow.cs
+++ b/trunk/ProcessHacker/Forms/HackerWindow.cs
@@ -1341,7 +1341,7 @@ namespace ProcessHacker
ProcessItem parent = null;
string parentText = "";
- if (item.HasParent)
+ if (item.HasParent && processP.Dictionary.ContainsKey(item.ParentPid))
{
try
{
diff --git a/trunk/ProcessHacker/Program/Logging.cs b/trunk/ProcessHacker/Program/Logging.cs
index f1fb83c22..ae676f9c7 100644
--- a/trunk/ProcessHacker/Program/Logging.cs
+++ b/trunk/ProcessHacker/Program/Logging.cs
@@ -51,7 +51,7 @@ namespace ProcessHacker
string debugMessage =
DateTime.Now.ToString("hh:mm:ss:fff:") +
" ProcessHacker (T" + System.Threading.Thread.CurrentThread.ManagedThreadId +
- "): (" + importance.ToString() + ") " + message + "\n" + Environment.StackTrace;
+ "): (" + importance.ToString() + ") " + message + "\r\n\r\n" + Environment.StackTrace;
OutputDebugString(debugMessage);
@@ -70,7 +70,9 @@ namespace ProcessHacker
string message = ex.Message;
if (ex.InnerException != null)
- message += "\nInner exception:\n" + ex.InnerException.ToString();
+ message += "\r\nInner exception:\r\n" + ex.InnerException.ToString();
+ if (ex.StackTrace != null)
+ message += "\r\n" + ex.StackTrace;
Log(Importance.Error, message);
}
diff --git a/trunk/ProcessHacker/Providers/ModuleProvider.cs b/trunk/ProcessHacker/Providers/ModuleProvider.cs
index ff2610ed1..51b857b13 100644
--- a/trunk/ProcessHacker/Providers/ModuleProvider.cs
+++ b/trunk/ProcessHacker/Providers/ModuleProvider.cs
@@ -154,6 +154,12 @@ namespace ProcessHacker
private void UpdateModules()
{
+ if (_processHandle == null)
+ {
+ Logging.Log(Logging.Importance.Warning, "ModuleProvider: Process Handle is null, exiting...");
+ return;
+ }
+
var processModules = _processHandle.GetModules();
var modules = new Dictionary();
var newdictionary = new Dictionary(this.Dictionary);
diff --git a/trunk/ProcessHacker/Providers/ProcessSystemProvider.cs b/trunk/ProcessHacker/Providers/ProcessSystemProvider.cs
index a2bcfc6a2..a91eafa53 100644
--- a/trunk/ProcessHacker/Providers/ProcessSystemProvider.cs
+++ b/trunk/ProcessHacker/Providers/ProcessSystemProvider.cs
@@ -267,6 +267,9 @@ namespace ProcessHacker
if (fileName == null)
fileName = this.GetFileName(pid);
+ if (fileName == null)
+ Logging.Log(Logging.Importance.Warning, "Could not get file name for PID " + pid.ToString());
+
fpResult.FileName = fileName;
if (fileName != null)
@@ -486,9 +489,9 @@ namespace ProcessHacker
{
try
{
- using (var phandle = new ProcessHandle(pid, ProcessAccess.QueryLimitedInformation))
+ using (var phandle = new ProcessHandle(pid, Program.MinProcessQueryRights))
{
- // first try to get the native file name, to prevent PEB
+ // First try to get the native file name, to prevent PEB
// file name spoofing.
try
{
@@ -497,7 +500,7 @@ namespace ProcessHacker
catch
{ }
- // if we couldn't get it or we couldn't resolve the \Device prefix,
+ // If we couldn't get it or we couldn't resolve the \Device prefix,
// we'll just use the normal method (which only works on Vista).
if ((fileName == null || fileName.StartsWith("\\Device\\")) &&
OSVersion.HasWin32ImageFileName)
@@ -514,14 +517,30 @@ namespace ProcessHacker
catch
{ }
- // If all else failed, we get the main module file name.
if (fileName == null || fileName.StartsWith("\\Device\\"))
{
try
{
using (var phandle =
new ProcessHandle(pid, ProcessAccess.QueryInformation | ProcessAccess.VmRead))
- fileName = phandle.GetMainModule().FileName;
+ {
+ // We can try to use the PEB.
+ try
+ {
+ fileName = FileUtils.DeviceFileNameToDos(
+ FileUtils.FixPath(phandle.GetPebString(PebOffset.ImagePathName)));
+ }
+ catch
+ { }
+
+ // If all else failed, we get the main module file name.
+ try
+ {
+ fileName = phandle.GetMainModule().FileName;
+ }
+ catch
+ { }
+ }
}
catch
{ }
@@ -568,6 +587,10 @@ namespace ProcessHacker
item.ImportFunctions = result.ImportFunctions;
item.ImportModules = result.ImportModules;
}
+ else
+ {
+ Logging.Log(Logging.Importance.Warning, "Unknown stage " + result.Stage.ToString("x"));
+ }
if (this.FileProcessingReceived != null)
this.FileProcessingReceived(result.Stage, result.Pid);
@@ -928,12 +951,14 @@ namespace ProcessHacker
{
this.FillFpResult(item, this.ProcessFileStage1(pid, null, false, false));
}
-
- if (pid > 0)
+ else
{
- WorkQueue.GlobalQueueWorkItem(
- new ProcessFileDelegate(this.ProcessFileStage1),
- pid, item.FileName, false);
+ if (pid > 0)
+ {
+ WorkQueue.GlobalQueueWorkItem(
+ new ProcessFileDelegate(this.ProcessFileStage1),
+ pid, item.FileName, false);
+ }
}
if (pid == 0 || pid == 4)