diff --git a/trunk/ProcessHacker/Components/ProcessTree.cs b/trunk/ProcessHacker/Components/ProcessTree.cs
deleted file mode 100644
index 01836a089..000000000
--- a/trunk/ProcessHacker/Components/ProcessTree.cs
+++ /dev/null
@@ -1,565 +0,0 @@
-/*
- * Process Hacker
- *
- * Copyright (C) 2008 wj32
- *
- * This program 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.
- *
- * This program 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 this program. If not, see .
- */
-
-using System;
-using System.Collections.Generic;
-using System.Diagnostics;
-using System.Reflection;
-using System.Windows.Forms;
-using System.Drawing;
-using Aga.Controls.Tree;
-
-namespace ProcessHacker
-{
- public partial class ProcessTree : UserControl
- {
- ProcessProvider _provider;
- ProcessTreeModel _treeModel;
- public new event KeyEventHandler KeyDown;
- public new event MouseEventHandler MouseDown;
- public new event MouseEventHandler MouseUp;
- public event EventHandler SelectionChanged;
-
- public ProcessTree()
- {
- InitializeComponent();
-
- treeProcesses.KeyDown += new KeyEventHandler(ProcessTree_KeyDown);
- treeProcesses.MouseDown += new MouseEventHandler(treeProcesses_MouseDown);
- treeProcesses.MouseUp += new MouseEventHandler(treeProcesses_MouseUp);
-
- nodeName.ToolTipProvider = new ProcessTooltips(this);
- }
-
- private void treeProcesses_SelectionChanged(object sender, EventArgs e)
- {
- if (this.SelectionChanged != null)
- this.SelectionChanged(sender, e);
- }
-
- private void treeProcesses_MouseUp(object sender, MouseEventArgs e)
- {
- if (this.MouseUp != null)
- this.MouseUp(sender, e);
- }
-
- private void treeProcesses_MouseDown(object sender, MouseEventArgs e)
- {
- if (this.MouseDown != null)
- this.MouseDown(sender, e);
- }
-
- private void ProcessTree_KeyDown(object sender, KeyEventArgs e)
- {
- if (this.KeyDown != null)
- this.KeyDown(sender, e);
- }
-
- #region Properties
-
- public override bool Focused
- {
- get
- {
- return treeProcesses.Focused;
- }
- }
-
- public override ContextMenu ContextMenu
- {
- get { return treeProcesses.ContextMenu; }
- set { treeProcesses.ContextMenu = value; }
- }
-
- public override ContextMenuStrip ContextMenuStrip
- {
- get { return treeProcesses.ContextMenuStrip; }
- set { treeProcesses.ContextMenuStrip = value; }
- }
-
- public TreeViewAdv Tree
- {
- get { return treeProcesses; }
- }
-
- public ProcessTreeModel Model
- {
- get { return _treeModel; }
- }
-
- public ProcessProvider Provider
- {
- get { return _provider; }
- set
- {
- if (_provider != null)
- {
- _provider.DictionaryAdded -= new Provider.ProviderDictionaryAdded(provider_DictionaryAdded);
- _provider.DictionaryModified -= new Provider.ProviderDictionaryModified(provider_DictionaryModified);
- _provider.DictionaryRemoved -= new Provider.ProviderDictionaryRemoved(provider_DictionaryRemoved);
- }
-
- _provider = value;
-
- treeProcesses.Model = _treeModel = new ProcessTreeModel();
-
- if (_provider != null)
- {
- foreach (ProcessItem item in _provider.Dictionary.Values)
- {
- provider_DictionaryAdded(item);
- }
-
- _provider.UseInvoke = true;
- _provider.Invoke = new Provider.ProviderInvokeMethod(this.BeginInvoke);
- _provider.DictionaryAdded += new Provider.ProviderDictionaryAdded(provider_DictionaryAdded);
- _provider.DictionaryModified += new Provider.ProviderDictionaryModified(provider_DictionaryModified);
- _provider.DictionaryRemoved += new Provider.ProviderDictionaryRemoved(provider_DictionaryRemoved);
- }
- }
- }
-
- #endregion
-
- #region Core Process List
-
- private Color GetProcessColor(ProcessItem p)
- {
- if (Program.HackerWindow.ProcessServices.ContainsKey(p.PID) &&
- Program.HackerWindow.ProcessServices[p.PID].Count > 0)
- return Properties.Settings.Default.ColorServiceProcesses;
- else if (p.IsBeingDebugged)
- return Properties.Settings.Default.ColorBeingDebugged;
- else if (p.Username == "NT AUTHORITY\\SYSTEM")
- return Properties.Settings.Default.ColorSystemProcesses;
- else if (p.Username == System.Security.Principal.WindowsIdentity.GetCurrent().Name)
- return Properties.Settings.Default.ColorOwnProcesses;
- else
- return SystemColors.Window;
- }
-
- private void provider_DictionaryAdded(ProcessItem item)
- {
- _treeModel.Add(item);
-
- TreeNodeAdv node = this.FindTreeNode(item.PID);
-
- if (node != null)
- {
- node.BackColor = GetProcessColor(item);
- node.ExpandAll();
- }
- }
-
- private void provider_DictionaryModified(ProcessItem oldItem, ProcessItem newItem)
- {
- _treeModel.Modify(oldItem, newItem);
-
- TreeNodeAdv node = this.FindTreeNode(newItem.PID);
-
- if (node != null)
- {
- node.BackColor = GetProcessColor(newItem);
- }
- }
-
- private void provider_DictionaryRemoved(ProcessItem item)
- {
- _treeModel.Remove(item);
- }
-
- public void RefreshItems()
- {
- foreach (TreeNodeAdv node in treeProcesses.AllNodes)
- {
- try
- {
- ProcessNode pNode = this.FindNode(node);
- ProcessItem item = _provider.Dictionary[pNode.PID];
-
- node.BackColor = this.GetProcessColor(item);
- }
- catch
- { }
- }
- }
-
- public Dictionary Nodes
- {
- get { return _treeModel.Nodes; }
- }
-
- public TreeNodeAdv FindTreeNode(int PID)
- {
- return treeProcesses.FindNode(_treeModel.GetPath(_treeModel.Nodes[PID]));
- }
-
- public ProcessNode FindNode(TreeNodeAdv node)
- {
- return treeProcesses.GetPath(node).LastNode as ProcessNode;
- }
-
- #endregion
-
- #region Interfacing
-
- public void BeginUpdate()
- {
- treeProcesses.BeginUpdate();
- }
-
- public void EndUpdate()
- {
- treeProcesses.EndUpdate();
- }
-
- public IEnumerable TreeNodes
- {
- get { return treeProcesses.AllNodes; }
- }
-
- public System.Collections.ObjectModel.ReadOnlyCollection SelectedTreeNodes
- {
- get { return treeProcesses.SelectedNodes; }
- }
-
- public System.Collections.ObjectModel.ReadOnlyCollection SelectedNodes
- {
- get
- {
- List nodes = new List();
-
- foreach (TreeNodeAdv node in treeProcesses.SelectedNodes)
- nodes.Add(treeProcesses.GetPath(node).LastNode as ProcessNode);
-
- System.Collections.ObjectModel.ReadOnlyCollection collection =
- new System.Collections.ObjectModel.ReadOnlyCollection(nodes);
-
- return collection;
- }
- }
-
- #endregion
- }
-
- public class ProcessTreeModel : ITreeModel
- {
- private Dictionary _processes = new Dictionary();
- private List _roots = new List();
-
- public void Add(ProcessItem item)
- {
- ProcessNode itemNode = new ProcessNode(item);
-
- // find this process' parent
- if (_processes.ContainsKey(item.ParentPID))
- _processes[item.ParentPID].Children.Add(itemNode);
- else
- _roots.Add(itemNode);
-
- _processes.Add(item.PID, itemNode);
-
- ProcessNode[] rootNodes = _roots.ToArray();
-
- // find this process' children
- foreach (ProcessNode node in rootNodes)
- {
- if (node.PPID == item.PID)
- {
- _roots.Remove(node);
- itemNode.Children.Add(node);
- }
- }
-
- this.StructureChanged(this, new TreePathEventArgs(new TreePath()));
- }
-
- public void Modify(ProcessItem oldItem, ProcessItem newItem)
- {
- _processes[newItem.PID].ProcessItem = newItem;
-
- ProcessNode node = _processes[newItem.PID];
-
- this.NodesChanged(this, new TreeModelEventArgs(this.GetPath(
- _processes.ContainsKey(node.PPID) ? _processes[node.PPID] : null),
- new object[] { node }));
- }
-
- public void Remove(ProcessItem item)
- {
- ProcessNode targetNode = _processes[item.PID];
- ProcessNode[] nodes = _roots.ToArray();
-
- foreach (ProcessNode node in nodes)
- {
- if (node.PID == item.PID)
- {
- _roots.Remove(node);
- this.MoveChildrenToRoot(node);
- break;
- }
- else if (_processes.ContainsKey(targetNode.PPID))
- {
- ProcessNode foundNode = _processes[targetNode.PPID];
-
- if (foundNode != null)
- {
- foundNode.Children.Remove(targetNode);
- this.MoveChildrenToRoot(targetNode);
- break;
- }
- }
- }
-
- _processes.Remove(item.PID);
-
- this.StructureChanged(this, new TreePathEventArgs(new TreePath()));
- }
-
- public TreePath GetPath(ProcessNode node)
- {
- if (node == null)
- return TreePath.Empty;
- else
- {
- Stack stack = new Stack();
-
- while (true)
- {
- stack.Push(node);
-
- if (_processes.ContainsKey(node.PPID))
- {
- ProcessNode newNode = _processes[node.PPID];
-
- if (newNode == node)
- break;
-
- node = newNode;
- }
- else
- break;
- }
-
- return new TreePath(stack.ToArray());
- }
- }
-
- public void MoveChildrenToRoot(ProcessNode node)
- {
- ProcessNode[] children = node.Children.ToArray();
-
- _roots.AddRange(children);
- }
-
- public Dictionary Nodes
- {
- get { return _processes; }
- }
-
- #region ITreeModel Members
-
- public System.Collections.IEnumerable GetChildren(TreePath treePath)
- {
- if (treePath.IsEmpty())
- return _roots;
- else
- return (treePath.LastNode as ProcessNode).Children;
- }
-
- public bool IsLeaf(TreePath treePath)
- {
- if (treePath.IsEmpty())
- return false;
- else
- return (treePath.LastNode as ProcessNode).Children.Count == 0;
- }
-
- public event EventHandler NodesChanged;
-
- public event EventHandler NodesInserted;
-
- public event EventHandler NodesRemoved;
-
- public event EventHandler StructureChanged;
-
- #endregion
- }
-
- public class ProcessNode : Node
- {
- private List _children = new List();
- private ProcessItem _pitem;
- private bool _wasNoIcon = false;
- private Bitmap _icon;
-
- 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
- {
- _icon = _pitem.Icon.ToBitmap();
- }
- }
-
- public ProcessItem ProcessItem
- {
- get { return _pitem; }
- set
- {
- _pitem = value;
-
- if (_wasNoIcon && _pitem.Icon != null)
- {
- _icon = _pitem.Icon.ToBitmap();
- _wasNoIcon = false;
- }
- }
- }
-
- public List Children
- {
- get { return _children; }
- }
-
- public string Name
- {
- get { return _pitem.Name; }
- }
-
- public int PID
- {
- get { return _pitem.PID; }
- }
-
- public int PPID
- {
- get { return _pitem.ParentPID; }
- }
-
- public string Memory
- {
- get { return _pitem.MemoryUsage; }
- }
-
- public string CPU
- {
- get { return _pitem.CPUUsage.ToString("F2"); }
- }
-
- private string GetBestUsername(string username, bool includeDomain)
- {
- 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, Properties.Settings.Default.ShowAccountDomains); }
- }
-
- public Bitmap Icon
- {
- get { return _icon; }
- }
- }
-
- public class ProcessTooltips : IToolTipProvider
- {
- private ProcessTree _tree;
-
- public ProcessTooltips(ProcessTree owner)
- {
- _tree = owner;
- }
-
- public string GetToolTip(TreeNodeAdv node, Aga.Controls.Tree.NodeControls.NodeControl nodeControl)
- {
- try
- {
- ProcessNode pNode = _tree.FindNode(node);
-
- string filename = "";
-
- if (pNode.PID == 4)
- {
- filename = Misc.GetKernelFileName();
- }
- else
- {
- filename = pNode.ProcessItem.Process.MainModule.FileName;
- }
-
- FileVersionInfo info = FileVersionInfo.GetVersionInfo(
- Misc.GetRealPath(filename));
-
- string fileText = (pNode.ProcessItem.CmdLine != null ? (pNode.ProcessItem.CmdLine + "\n\n") : "") + info.FileName + "\n" +
- info.FileDescription + " (" + info.FileVersion + ")\n" +
- info.CompanyName;
-
- if (!Program.HackerWindow.ProcessServices.ContainsKey(pNode.PID))
- {
- return fileText;
- }
- else
- {
- string servicesText = "";
-
- foreach (string service in Program.HackerWindow.ProcessServices[pNode.PID])
- {
- if (Program.HackerWindow.ServiceProvider.Dictionary.ContainsKey(service))
- {
- if (Program.HackerWindow.ServiceProvider.Dictionary[service].Status.DisplayName != "")
- servicesText += service + " (" +
- Program.HackerWindow.ServiceProvider.Dictionary[service].Status.DisplayName + ")\n";
- else
- servicesText += service + "\n";
- }
- else
- {
- servicesText += service + "\n";
- }
- }
-
- return fileText + "\n\nServices:\n" + servicesText.TrimEnd('\n');
- }
- }
- catch
- { }
-
- return string.Empty;
- }
- }
-}
diff --git a/trunk/ProcessHacker/Components/ProcessTree/ProcessNode.cs b/trunk/ProcessHacker/Components/ProcessTree/ProcessNode.cs
new file mode 100644
index 000000000..6e738869d
--- /dev/null
+++ b/trunk/ProcessHacker/Components/ProcessTree/ProcessNode.cs
@@ -0,0 +1,119 @@
+/*
+ * Process Hacker
+ *
+ * Copyright (C) 2008 wj32
+ *
+ * This program 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.
+ *
+ * This program 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 this program. If not, see .
+ */
+
+using System.Collections.Generic;
+using System.Drawing;
+using Aga.Controls.Tree;
+
+namespace ProcessHacker
+{
+ public class ProcessNode : Node
+ {
+ private List _children = new List();
+ private ProcessItem _pitem;
+ private bool _wasNoIcon = false;
+ private Bitmap _icon;
+
+ 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
+ {
+ _icon = _pitem.Icon.ToBitmap();
+ }
+ }
+
+ public ProcessItem ProcessItem
+ {
+ get { return _pitem; }
+ set
+ {
+ _pitem = value;
+
+ if (_wasNoIcon && _pitem.Icon != null)
+ {
+ _icon = _pitem.Icon.ToBitmap();
+ _wasNoIcon = false;
+ }
+ }
+ }
+
+ public List Children
+ {
+ get { return _children; }
+ }
+
+ public string Name
+ {
+ get { return _pitem.Name; }
+ }
+
+ public int PID
+ {
+ get { return _pitem.PID; }
+ }
+
+ public int PPID
+ {
+ get { return _pitem.ParentPID; }
+ }
+
+ public string Memory
+ {
+ get { return _pitem.MemoryUsage; }
+ }
+
+ public string CPU
+ {
+ get { return _pitem.CPUUsage.ToString("F2"); }
+ }
+
+ private string GetBestUsername(string username, bool includeDomain)
+ {
+ 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, Properties.Settings.Default.ShowAccountDomains); }
+ }
+
+ public Bitmap Icon
+ {
+ get { return _icon; }
+ }
+ }
+}
diff --git a/trunk/ProcessHacker/Components/ProcessTree/ProcessTooltips.cs b/trunk/ProcessHacker/Components/ProcessTree/ProcessTooltips.cs
new file mode 100644
index 000000000..21dbd64c7
--- /dev/null
+++ b/trunk/ProcessHacker/Components/ProcessTree/ProcessTooltips.cs
@@ -0,0 +1,91 @@
+/*
+ * Process Hacker
+ *
+ * Copyright (C) 2008 wj32
+ *
+ * This program 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.
+ *
+ * This program 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 this program. If not, see .
+ */
+
+using System.Diagnostics;
+using Aga.Controls.Tree;
+
+namespace ProcessHacker
+{
+ public class ProcessTooltips : IToolTipProvider
+ {
+ private ProcessTree _tree;
+
+ public ProcessTooltips(ProcessTree owner)
+ {
+ _tree = owner;
+ }
+
+ public string GetToolTip(TreeNodeAdv node, Aga.Controls.Tree.NodeControls.NodeControl nodeControl)
+ {
+ try
+ {
+ ProcessNode pNode = _tree.FindNode(node);
+
+ string filename = "";
+
+ if (pNode.PID == 4)
+ {
+ filename = Misc.GetKernelFileName();
+ }
+ else
+ {
+ filename = pNode.ProcessItem.Process.MainModule.FileName;
+ }
+
+ FileVersionInfo info = FileVersionInfo.GetVersionInfo(
+ Misc.GetRealPath(filename));
+
+ string fileText = (pNode.ProcessItem.CmdLine != null ? (pNode.ProcessItem.CmdLine + "\n\n") : "") + info.FileName + "\n" +
+ info.FileDescription + " (" + info.FileVersion + ")\n" +
+ info.CompanyName;
+
+ if (!Program.HackerWindow.ProcessServices.ContainsKey(pNode.PID))
+ {
+ return fileText;
+ }
+ else
+ {
+ string servicesText = "";
+
+ foreach (string service in Program.HackerWindow.ProcessServices[pNode.PID])
+ {
+ if (Program.HackerWindow.ServiceProvider.Dictionary.ContainsKey(service))
+ {
+ if (Program.HackerWindow.ServiceProvider.Dictionary[service].Status.DisplayName != "")
+ servicesText += service + " (" +
+ Program.HackerWindow.ServiceProvider.Dictionary[service].Status.DisplayName + ")\n";
+ else
+ servicesText += service + "\n";
+ }
+ else
+ {
+ servicesText += service + "\n";
+ }
+ }
+
+ return fileText + "\n\nServices:\n" + servicesText.TrimEnd('\n');
+ }
+ }
+ catch
+ { }
+
+ return string.Empty;
+ }
+ }
+}
diff --git a/trunk/ProcessHacker/Components/ProcessTree.Designer.cs b/trunk/ProcessHacker/Components/ProcessTree/ProcessTree.Designer.cs
similarity index 100%
rename from trunk/ProcessHacker/Components/ProcessTree.Designer.cs
rename to trunk/ProcessHacker/Components/ProcessTree/ProcessTree.Designer.cs
diff --git a/trunk/ProcessHacker/Components/ProcessTree/ProcessTree.cs b/trunk/ProcessHacker/Components/ProcessTree/ProcessTree.cs
new file mode 100644
index 000000000..c43e35b59
--- /dev/null
+++ b/trunk/ProcessHacker/Components/ProcessTree/ProcessTree.cs
@@ -0,0 +1,258 @@
+/*
+ * Process Hacker
+ *
+ * Copyright (C) 2008 wj32
+ *
+ * This program 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.
+ *
+ * This program 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 this program. If not, see .
+ */
+
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+using System.Windows.Forms;
+using Aga.Controls.Tree;
+
+namespace ProcessHacker
+{
+ public partial class ProcessTree : UserControl
+ {
+ ProcessProvider _provider;
+ ProcessTreeModel _treeModel;
+ public new event KeyEventHandler KeyDown;
+ public new event MouseEventHandler MouseDown;
+ public new event MouseEventHandler MouseUp;
+ public event EventHandler SelectionChanged;
+
+ public ProcessTree()
+ {
+ InitializeComponent();
+
+ treeProcesses.KeyDown += new KeyEventHandler(ProcessTree_KeyDown);
+ treeProcesses.MouseDown += new MouseEventHandler(treeProcesses_MouseDown);
+ treeProcesses.MouseUp += new MouseEventHandler(treeProcesses_MouseUp);
+
+ nodeName.ToolTipProvider = new ProcessTooltips(this);
+ }
+
+ private void treeProcesses_SelectionChanged(object sender, EventArgs e)
+ {
+ if (this.SelectionChanged != null)
+ this.SelectionChanged(sender, e);
+ }
+
+ private void treeProcesses_MouseUp(object sender, MouseEventArgs e)
+ {
+ if (this.MouseUp != null)
+ this.MouseUp(sender, e);
+ }
+
+ private void treeProcesses_MouseDown(object sender, MouseEventArgs e)
+ {
+ if (this.MouseDown != null)
+ this.MouseDown(sender, e);
+ }
+
+ private void ProcessTree_KeyDown(object sender, KeyEventArgs e)
+ {
+ if (this.KeyDown != null)
+ this.KeyDown(sender, e);
+ }
+
+ #region Properties
+
+ public override bool Focused
+ {
+ get
+ {
+ return treeProcesses.Focused;
+ }
+ }
+
+ public override ContextMenu ContextMenu
+ {
+ get { return treeProcesses.ContextMenu; }
+ set { treeProcesses.ContextMenu = value; }
+ }
+
+ public override ContextMenuStrip ContextMenuStrip
+ {
+ get { return treeProcesses.ContextMenuStrip; }
+ set { treeProcesses.ContextMenuStrip = value; }
+ }
+
+ public TreeViewAdv Tree
+ {
+ get { return treeProcesses; }
+ }
+
+ public ProcessTreeModel Model
+ {
+ get { return _treeModel; }
+ }
+
+ public ProcessProvider Provider
+ {
+ get { return _provider; }
+ set
+ {
+ if (_provider != null)
+ {
+ _provider.DictionaryAdded -= new Provider.ProviderDictionaryAdded(provider_DictionaryAdded);
+ _provider.DictionaryModified -= new Provider.ProviderDictionaryModified(provider_DictionaryModified);
+ _provider.DictionaryRemoved -= new Provider.ProviderDictionaryRemoved(provider_DictionaryRemoved);
+ }
+
+ _provider = value;
+
+ treeProcesses.Model = _treeModel = new ProcessTreeModel();
+
+ if (_provider != null)
+ {
+ foreach (ProcessItem item in _provider.Dictionary.Values)
+ {
+ provider_DictionaryAdded(item);
+ }
+
+ _provider.UseInvoke = true;
+ _provider.Invoke = new Provider.ProviderInvokeMethod(this.BeginInvoke);
+ _provider.DictionaryAdded += new Provider.ProviderDictionaryAdded(provider_DictionaryAdded);
+ _provider.DictionaryModified += new Provider.ProviderDictionaryModified(provider_DictionaryModified);
+ _provider.DictionaryRemoved += new Provider.ProviderDictionaryRemoved(provider_DictionaryRemoved);
+ }
+ }
+ }
+
+ #endregion
+
+ #region Core Process List
+
+ private Color GetProcessColor(ProcessItem p)
+ {
+ if (Program.HackerWindow.ProcessServices.ContainsKey(p.PID) &&
+ Program.HackerWindow.ProcessServices[p.PID].Count > 0)
+ return Properties.Settings.Default.ColorServiceProcesses;
+ else if (p.IsBeingDebugged)
+ return Properties.Settings.Default.ColorBeingDebugged;
+ else if (p.Username == "NT AUTHORITY\\SYSTEM")
+ return Properties.Settings.Default.ColorSystemProcesses;
+ else if (p.Username == System.Security.Principal.WindowsIdentity.GetCurrent().Name)
+ return Properties.Settings.Default.ColorOwnProcesses;
+ else
+ return SystemColors.Window;
+ }
+
+ private void provider_DictionaryAdded(ProcessItem item)
+ {
+ _treeModel.Add(item);
+
+ TreeNodeAdv node = this.FindTreeNode(item.PID);
+
+ if (node != null)
+ {
+ node.BackColor = GetProcessColor(item);
+ node.ExpandAll();
+ }
+ }
+
+ private void provider_DictionaryModified(ProcessItem oldItem, ProcessItem newItem)
+ {
+ _treeModel.Modify(oldItem, newItem);
+
+ TreeNodeAdv node = this.FindTreeNode(newItem.PID);
+
+ if (node != null)
+ {
+ node.BackColor = GetProcessColor(newItem);
+ }
+ }
+
+ private void provider_DictionaryRemoved(ProcessItem item)
+ {
+ _treeModel.Remove(item);
+ }
+
+ public void RefreshItems()
+ {
+ foreach (TreeNodeAdv node in treeProcesses.AllNodes)
+ {
+ try
+ {
+ ProcessNode pNode = this.FindNode(node);
+ ProcessItem item = _provider.Dictionary[pNode.PID];
+
+ node.BackColor = this.GetProcessColor(item);
+ }
+ catch
+ { }
+ }
+ }
+
+ public Dictionary Nodes
+ {
+ get { return _treeModel.Nodes; }
+ }
+
+ public TreeNodeAdv FindTreeNode(int PID)
+ {
+ return treeProcesses.FindNode(_treeModel.GetPath(_treeModel.Nodes[PID]));
+ }
+
+ public ProcessNode FindNode(TreeNodeAdv node)
+ {
+ return treeProcesses.GetPath(node).LastNode as ProcessNode;
+ }
+
+ #endregion
+
+ #region Interfacing
+
+ public void BeginUpdate()
+ {
+ treeProcesses.BeginUpdate();
+ }
+
+ public void EndUpdate()
+ {
+ treeProcesses.EndUpdate();
+ }
+
+ public IEnumerable TreeNodes
+ {
+ get { return treeProcesses.AllNodes; }
+ }
+
+ public System.Collections.ObjectModel.ReadOnlyCollection SelectedTreeNodes
+ {
+ get { return treeProcesses.SelectedNodes; }
+ }
+
+ public System.Collections.ObjectModel.ReadOnlyCollection SelectedNodes
+ {
+ get
+ {
+ List nodes = new List();
+
+ foreach (TreeNodeAdv node in treeProcesses.SelectedNodes)
+ nodes.Add(treeProcesses.GetPath(node).LastNode as ProcessNode);
+
+ System.Collections.ObjectModel.ReadOnlyCollection collection =
+ new System.Collections.ObjectModel.ReadOnlyCollection(nodes);
+
+ return collection;
+ }
+ }
+
+ #endregion
+ }
+}
diff --git a/trunk/ProcessHacker/Components/ProcessTree.resx b/trunk/ProcessHacker/Components/ProcessTree/ProcessTree.resx
similarity index 100%
rename from trunk/ProcessHacker/Components/ProcessTree.resx
rename to trunk/ProcessHacker/Components/ProcessTree/ProcessTree.resx
diff --git a/trunk/ProcessHacker/Components/ProcessTree/ProcessTreeModel.cs b/trunk/ProcessHacker/Components/ProcessTree/ProcessTreeModel.cs
new file mode 100644
index 000000000..225cf7bf8
--- /dev/null
+++ b/trunk/ProcessHacker/Components/ProcessTree/ProcessTreeModel.cs
@@ -0,0 +1,169 @@
+/*
+ * Process Hacker
+ *
+ * Copyright (C) 2008 wj32
+ *
+ * This program 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.
+ *
+ * This program 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 this program. If not, see .
+ */
+
+using System;
+using System.Collections.Generic;
+using Aga.Controls.Tree;
+
+namespace ProcessHacker
+{
+ public class ProcessTreeModel : ITreeModel
+ {
+ private Dictionary _processes = new Dictionary();
+ private List _roots = new List();
+
+ public void Add(ProcessItem item)
+ {
+ ProcessNode itemNode = new ProcessNode(item);
+
+ // find this process' parent
+ if (_processes.ContainsKey(item.ParentPID))
+ _processes[item.ParentPID].Children.Add(itemNode);
+ else
+ _roots.Add(itemNode);
+
+ _processes.Add(item.PID, itemNode);
+
+ ProcessNode[] rootNodes = _roots.ToArray();
+
+ // find this process' children
+ foreach (ProcessNode node in rootNodes)
+ {
+ if (node.PPID == item.PID)
+ {
+ _roots.Remove(node);
+ itemNode.Children.Add(node);
+ }
+ }
+
+ this.StructureChanged(this, new TreePathEventArgs(new TreePath()));
+ }
+
+ public void Modify(ProcessItem oldItem, ProcessItem newItem)
+ {
+ _processes[newItem.PID].ProcessItem = newItem;
+
+ ProcessNode node = _processes[newItem.PID];
+
+ this.NodesChanged(this, new TreeModelEventArgs(this.GetPath(
+ _processes.ContainsKey(node.PPID) ? _processes[node.PPID] : null),
+ new object[] { node }));
+ }
+
+ public void Remove(ProcessItem item)
+ {
+ ProcessNode targetNode = _processes[item.PID];
+ ProcessNode[] nodes = _roots.ToArray();
+
+ foreach (ProcessNode node in nodes)
+ {
+ if (node.PID == item.PID)
+ {
+ _roots.Remove(node);
+ this.MoveChildrenToRoot(node);
+ break;
+ }
+ else if (_processes.ContainsKey(targetNode.PPID))
+ {
+ ProcessNode foundNode = _processes[targetNode.PPID];
+
+ if (foundNode != null)
+ {
+ foundNode.Children.Remove(targetNode);
+ this.MoveChildrenToRoot(targetNode);
+ break;
+ }
+ }
+ }
+
+ _processes.Remove(item.PID);
+
+ this.StructureChanged(this, new TreePathEventArgs(new TreePath()));
+ }
+
+ public TreePath GetPath(ProcessNode node)
+ {
+ if (node == null)
+ return TreePath.Empty;
+ else
+ {
+ Stack stack = new Stack();
+
+ while (true)
+ {
+ stack.Push(node);
+
+ if (_processes.ContainsKey(node.PPID))
+ {
+ ProcessNode newNode = _processes[node.PPID];
+
+ if (newNode == node)
+ break;
+
+ node = newNode;
+ }
+ else
+ break;
+ }
+
+ return new TreePath(stack.ToArray());
+ }
+ }
+
+ public void MoveChildrenToRoot(ProcessNode node)
+ {
+ ProcessNode[] children = node.Children.ToArray();
+
+ _roots.AddRange(children);
+ }
+
+ public Dictionary Nodes
+ {
+ get { return _processes; }
+ }
+
+ #region ITreeModel Members
+
+ public System.Collections.IEnumerable GetChildren(TreePath treePath)
+ {
+ if (treePath.IsEmpty())
+ return _roots;
+ else
+ return (treePath.LastNode as ProcessNode).Children;
+ }
+
+ public bool IsLeaf(TreePath treePath)
+ {
+ if (treePath.IsEmpty())
+ return false;
+ else
+ return (treePath.LastNode as ProcessNode).Children.Count == 0;
+ }
+
+ public event EventHandler NodesChanged;
+
+ public event EventHandler NodesInserted;
+
+ public event EventHandler NodesRemoved;
+
+ public event EventHandler StructureChanged;
+
+ #endregion
+ }
+}
diff --git a/trunk/ProcessHacker/ProcessHacker.csproj b/trunk/ProcessHacker/ProcessHacker.csproj
index 1b0ca56ba..f9e405903 100644
--- a/trunk/ProcessHacker/ProcessHacker.csproj
+++ b/trunk/ProcessHacker/ProcessHacker.csproj
@@ -135,7 +135,7 @@
ThreadList.cs
Designer
-
+
ProcessTree.cs
Designer
@@ -237,6 +237,9 @@
HandleList.cs
+
+
+
UserControl
@@ -250,10 +253,10 @@
ThreadList.cs
-
+
UserControl
-
+
ProcessTree.cs