From 95d4073d7f1957f656ef4c3c78457fb239f5cb47 Mon Sep 17 00:00:00 2001 From: wj32 Date: Tue, 28 Apr 2009 07:42:03 +0000 Subject: [PATCH] * simplified tree model code * fixed PH on XP not retrieving process file names * resolved some unnoticed unhandled exceptions git-svn-id: svn://svn.code.sf.net/p/processhacker/code@1192 21ef857c-d57f-4fe0-8362-d861dc6d29cd --- .../Components/ProcessTree/ProcessTree.cs | 10 ++- .../ProcessTree/ProcessTreeModel.cs | 71 ++++++++++++------- trunk/ProcessHacker/Forms/HackerWindow.cs | 2 +- trunk/ProcessHacker/Program/Logging.cs | 6 +- .../ProcessHacker/Providers/ModuleProvider.cs | 6 ++ .../Providers/ProcessSystemProvider.cs | 45 +++++++++--- 6 files changed, 98 insertions(+), 42 deletions(-) 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)