/* * Process Hacker - * main Process Hacker window * * Copyright (C) 2008 Dean * 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.Diagnostics; using System.Drawing; using System.Runtime.InteropServices; using System.Threading; using System.Windows.Forms; using Aga.Controls.Tree; using ProcessHacker.UI; using ProcessHacker.UI.Actions; using ProcessHacker.Components; namespace ProcessHacker { public partial class HackerWindow : Form { public delegate void LogUpdatedEventHandler(KeyValuePair? value); private delegate void AddMenuItemDelegate(string text, EventHandler onClick); #region Variables public HelpWindow HelpForm; public HandleFilterWindow HandleFilterWindow; public CSRProcessesWindow CSRProcessesWindow; public LogWindow LogWindow; public MiniSysInfo MiniSysInfoWindow; Thread sysInfoThread; public SysInfoWindow SysInfoWindow; ProcessSystemProvider processP; ServiceProvider serviceP; NetworkProvider networkP; Bitmap uacShieldIcon; UsageIcon cpuUsageIcon; Dictionary> processServices = new Dictionary>(); int processSelectedItems; int processSelectedPID; List listControls = new List(); Queue> statusMessages = new Queue>(); List> _log = new List>(); #endregion #region Properties public MenuItem WindowMenuItem { get { return windowMenuItem; } } public NotifyIcon NotifyIcon { get { return notifyIcon; } } public wyDay.Controls.VistaMenu VistaMenu { get { return vistaMenu; } } public ProcessSystemProvider ProcessProvider { get { return processP; } } public ProcessTree ProcessTree { get { return treeProcesses; } } public ServiceProvider ServiceProvider { get { return serviceP; } } public ListView ServiceList { get { return listServices.List; } } public NetworkProvider NetworkProvider { get { return networkP; } } public ListView NetworkList { get { return listNetwork.List; } } public IDictionary> ProcessServices { get { return processServices; } } public IList> Log { get { return _log; } } #endregion #region Events public event LogUpdatedEventHandler LogUpdated; #endregion #region Event Handlers #region Lists private void listProcesses_KeyDown(object sender, KeyEventArgs e) { if (e.KeyData == Keys.Delete) { terminateMenuItem_Click(null, null); } } private void listProcesses_SelectionChanged(object sender, EventArgs e) { processSelectedItems = treeProcesses.SelectedNodes.Count; if (processSelectedItems == 1) { processSelectedPID = treeProcesses.SelectedNodes[0].PID; } else { processSelectedPID = -1; } } private void listNetwork_DoubleClick(object sender, EventArgs e) { goToProcessNetworkMenuItem_Click(sender, e); } private void listServices_DoubleClick(object sender, EventArgs e) { propertiesServiceMenuItem_Click(null, null); } #endregion #region Main Menu private void runMenuItem_Click(object sender, EventArgs e) { Win32.RunFileDlg(this.Handle, 0, 0, null, null, 0); } private void runAsMenuItem_Click(object sender, EventArgs e) { } private void runAsAdministratorMenuItem_Click(object sender, EventArgs e) { PromptBox box = new PromptBox(); box.Text = "Enter the command to start"; box.TextBox.AutoCompleteSource = AutoCompleteSource.AllSystemSources; box.TextBox.AutoCompleteMode = AutoCompleteMode.SuggestAppend; if (box.ShowDialog() == DialogResult.OK) { Program.StartProgramAdmin(box.Value, "", null, Win32.ShowWindowType.Show, this.Handle); } } private void runAsServiceMenuItem_Click(object sender, EventArgs e) { RunWindow run = new RunWindow(); run.TopMost = this.TopMost; run.ShowDialog(); } private void showDetailsForAllProcessesMenuItem_Click(object sender, EventArgs e) { Program.StartProcessHackerAdmin("-v", () => { this.SaveSettings(); notifyIcon.Visible = false; Win32.ExitProcess(0); }, this.Handle); } private void apiLoggerMenuItem_Click(object sender, EventArgs e) { (new Forms.ApiLogWindow()).Show(); } private void findHandlesMenuItem_Click(object sender, EventArgs e) { if (HandleFilterWindow == null) HandleFilterWindow = new HandleFilterWindow(); HandleFilterWindow.Show(); HandleFilterWindow.Activate(); } private void inspectPEFileMenuItem_Click(object sender, EventArgs e) { OpenFileDialog ofd = new OpenFileDialog(); if (ofd.ShowDialog() == DialogResult.OK) { PEWindow pw = Program.GetPEWindow(ofd.FileName, new Program.PEWindowInvokeAction(delegate(PEWindow f) { try { f.Show(); } catch (Exception ex) { Logging.Log(ex); } })); } } private void reloadStructsMenuItem_Click(object sender, EventArgs e) { try { Program.Structs.Clear(); Structs.StructParser parser = new ProcessHacker.Structs.StructParser(Program.Structs); parser.Parse(Application.StartupPath + "\\structs.txt"); } catch (Exception ex) { MessageBox.Show(ex.Message, "Process Hacker", MessageBoxButtons.OK, MessageBoxIcon.Error); } } private void sysInfoMenuItem_Click(object sender, EventArgs e) { if (sysInfoThread == null || !sysInfoThread.IsAlive) { sysInfoThread = new Thread(() => { SysInfoWindow = new SysInfoWindow(); Application.Run(SysInfoWindow); }); sysInfoThread.Start(); } else { SysInfoWindow.BeginInvoke(new MethodInvoker(delegate { SysInfoWindow.Show(); SysInfoWindow.Activate(); })); } } private void logMenuItem_Click(object sender, EventArgs e) { if (LogWindow == null || LogWindow.IsDisposed) { LogWindow = new LogWindow(); } LogWindow.Show(); if (LogWindow.WindowState == FormWindowState.Minimized) LogWindow.WindowState = FormWindowState.Normal; LogWindow.Activate(); } private void aboutMenuItem_Click(object sender, EventArgs e) { AboutWindow about = new AboutWindow(); about.TopMost = this.TopMost; about.ShowDialog(); } private void optionsMenuItem_Click(object sender, EventArgs e) { OptionsWindow options = new OptionsWindow(); options.TopMost = this.TopMost; options.ShowDialog(); } private void freeMemoryMenuItem_Click(object sender, EventArgs e) { Program.CollectGarbage(); } private void helpMenuItem_Click(object sender, EventArgs e) { if (HelpForm == null) HelpForm = new HelpWindow(); HelpForm.Show(); HelpForm.Activate(); } private void exitMenuItem_Click(object sender, EventArgs e) { this.Exit(); } private void toolbarMenuItem_Click(object sender, EventArgs e) { toolbarMenuItem.Checked = !toolbarMenuItem.Checked; toolStrip.Visible = toolbarMenuItem.Checked; } private void updateNowMenuItem_Click(object sender, EventArgs e) { if (processP.RunCount > 1) processP.RunOnce(); if (serviceP.RunCount > 1) serviceP.RunOnce(); } private void updateProcessesMenuItem_Click(object sender, EventArgs e) { updateProcessesMenuItem.Checked = !updateProcessesMenuItem.Checked; processP.Enabled = updateProcessesMenuItem.Checked; } private void updateServicesMenuItem_Click(object sender, EventArgs e) { updateServicesMenuItem.Checked = !updateServicesMenuItem.Checked; serviceP.Enabled = updateServicesMenuItem.Checked; } private void csrProcessesMenuItem_Click(object sender, EventArgs e) { if (CSRProcessesWindow == null || CSRProcessesWindow.IsDisposed) CSRProcessesWindow = new CSRProcessesWindow(); CSRProcessesWindow.Show(); if (CSRProcessesWindow.WindowState == FormWindowState.Minimized) CSRProcessesWindow.WindowState = FormWindowState.Normal; CSRProcessesWindow.Activate(); } private void verifyFileSignatureMenuItem_Click(object sender, EventArgs e) { OpenFileDialog ofd = new OpenFileDialog(); ofd.CheckFileExists = true; ofd.CheckPathExists = true; ofd.Filter = "Executable files (*.exe;*.dll;*.sys;*.scr;*.cpl)|*.exe;*.dll;*.sys;*.scr;*.cpl|All files (*.*)|*.*"; if (ofd.ShowDialog() == DialogResult.OK) { try { var result = Win32.VerifyFile(ofd.FileName); string message = ""; switch (result) { case Win32.VerifyResult.Distrust: message = "is not trusted"; break; case Win32.VerifyResult.Expired: message = "has an expired certificate"; break; case Win32.VerifyResult.NoSignature: message = "does not have a digital signature"; break; case Win32.VerifyResult.Revoked: message = "has a revoked certificate"; break; case Win32.VerifyResult.SecuritySettings: message = "could not be verified due to security settings"; break; case Win32.VerifyResult.Trusted: message = "is trusted"; break; case Win32.VerifyResult.Unknown: message = "could not be verified"; break; default: message = "could not be verified"; break; } MessageBox.Show("The file \"" + ofd.FileName + "\" " + message + ".", "Process Hacker", MessageBoxButtons.OK, MessageBoxIcon.Information); } catch (Exception ex) { MessageBox.Show(ex.Message, "Process Hacker", MessageBoxButtons.OK, MessageBoxIcon.Error); } } } private void saveMenuItem_Click(object sender, EventArgs e) { Save.SaveToFile(); } #endregion #region Network Context Menu private void menuNetwork_Popup(object sender, EventArgs e) { if (listNetwork.SelectedItems.Count == 0) { menuNetwork.DisableAll(); } else if (listNetwork.SelectedItems.Count == 1) { menuNetwork.EnableAll(); } else { menuNetwork.EnableAll(); goToProcessNetworkMenuItem.Enabled = false; } if (listNetwork.Items.Count > 0) selectAllNetworkMenuItem.Enabled = true; else selectAllNetworkMenuItem.Enabled = false; } private void goToProcessNetworkMenuItem_Click(object sender, EventArgs e) { DeselectAll(treeProcesses.Tree); try { TreeNodeAdv node = treeProcesses.FindTreeNode((int)listNetwork.SelectedItems[0].Tag); node.EnsureVisible(); node.IsSelected = true; treeProcesses.Tree.FullUpdate(); tabControl.SelectedTab = tabProcesses; } catch (Exception ex) { Logging.Log(ex); } } private void selectAllNetworkMenuItem_Click(object sender, EventArgs e) { Misc.SelectAll(listNetwork.List.Items); } #endregion #region Notification Icon & Menu private void notifyIcon_MouseDoubleClick(object sender, MouseEventArgs e) { showHideMenuItem_Click(null, null); } private void menuIcon_Popup(object sender, EventArgs e) { List processes = new List(); // Clear the images so we don't get GDI+ handle leaks foreach (MenuItem item in processesMenuItem.MenuItems) vistaMenu.SetImage(item, null); processesMenuItem.MenuItems.DisposeAndClear(); // HACK: To be fixed later - we need some sort of locking for the process provider try { foreach (var process in processP.Dictionary.Values) { if (process.Pid > 0) { processes.Add(process); } } for (int i = 0; i < processes.Count && processes.Count > Properties.Settings.Default.IconMenuProcessCount; i++) { if (processes[i].CpuUsage == 0) { processes.RemoveAt(i); i--; } else if (processes[i].Username != Program.CurrentUsername) { processes.RemoveAt(i); i--; } } processes.Sort((i1, i2) => -i1.CpuUsage.CompareTo(i2.CpuUsage)); if (processes.Count > Properties.Settings.Default.IconMenuProcessCount) { int c = processes.Count; processes.RemoveRange(Properties.Settings.Default.IconMenuProcessCount, processes.Count - Properties.Settings.Default.IconMenuProcessCount); } foreach (var process in processes) { MenuItem processItem = new MenuItem(); MenuItem terminateItem = new MenuItem(); MenuItem suspendItem = new MenuItem(); MenuItem resumeItem = new MenuItem(); MenuItem propertiesItem = new MenuItem(); processItem.Text = process.Name + " (" + process.Pid.ToString() + ")"; processItem.Tag = process; terminateItem.Click += new EventHandler((sender_, e_) => { ProcessItem item = (ProcessItem)((MenuItem)sender_).Parent.Tag; ProcessActions.Terminate(this, new int[] { item.Pid }, new string[] { item.Name }, true); }); terminateItem.Text = "Terminate"; suspendItem.Click += new EventHandler((sender_, e_) => { ProcessItem item = (ProcessItem)((MenuItem)sender_).Parent.Tag; ProcessActions.Suspend(this, new int[] { item.Pid }, new string[] { item.Name }, true); }); suspendItem.Text = "Suspend"; resumeItem.Click += new EventHandler((sender_, e_) => { ProcessItem item = (ProcessItem)((MenuItem)sender_).Parent.Tag; ProcessActions.Resume(this, new int[] { item.Pid }, new string[] { item.Name }, true); }); resumeItem.Text = "Resume"; propertiesItem.Click += new EventHandler((sender_, e_) => { try { ProcessItem item = (ProcessItem)((MenuItem)sender_).Parent.Tag; ProcessWindow pForm = Program.GetProcessWindow(processP.Dictionary[item.Pid], new Program.PWindowInvokeAction(delegate(ProcessWindow f) { f.Show(); f.Activate(); })); } catch (Exception ex) { MessageBox.Show("Could not inspect the process:\n\n" + ex.Message, "Process Hacker", MessageBoxButtons.OK, MessageBoxIcon.Error); } }); propertiesItem.Text = "Properties..."; processItem.MenuItems.AddRange(new MenuItem[] { terminateItem, suspendItem, resumeItem, propertiesItem }); processesMenuItem.MenuItems.Add(processItem); vistaMenu.SetImage(processItem, (treeProcesses.Tree.Model as ProcessTreeModel).Nodes[process.Pid].Icon); } } catch { foreach (MenuItem item in processesMenuItem.MenuItems) vistaMenu.SetImage(item, null); processesMenuItem.MenuItems.DisposeAndClear(); } } private void showHideMenuItem_Click(object sender, EventArgs e) { this.Visible = !this.Visible; if (this.WindowState == FormWindowState.Minimized) this.WindowState = FormWindowState.Normal; this.Activate(); } private void sysInformationIconMenuItem_Click(object sender, EventArgs e) { sysInfoMenuItem_Click(sender, e); } private void enableAllNotificationsMenuItem_Click(object sender, EventArgs e) { NPMenuItem.Checked = true; TPMenuItem.Checked = true; NSMenuItem.Checked = true; startedSMenuItem.Checked = true; stoppedSMenuItem.Checked = true; DSMenuItem.Checked = true; } private void disableAllNotificationsMenuItem_Click(object sender, EventArgs e) { NPMenuItem.Checked = false; TPMenuItem.Checked = false; NSMenuItem.Checked = false; startedSMenuItem.Checked = false; stoppedSMenuItem.Checked = false; DSMenuItem.Checked = false; } private void exitTrayMenuItem_Click(object sender, EventArgs e) { this.Exit(); } #endregion #region Process Context Menu private void menuProcess_Popup(object sender, EventArgs e) { virtualizationProcessMenuItem.Checked = false; if (treeProcesses.SelectedTreeNodes.Count == 0) { menuProcess.DisableAll(); } else if (treeProcesses.SelectedTreeNodes.Count == 1) { menuProcess.EnableAll(); priorityMenuItem.Text = "&Priority"; terminateMenuItem.Text = "&Terminate Process"; suspendMenuItem.Text = "&Suspend Process"; resumeMenuItem.Text = "&Resume Process"; realTimeMenuItem.Checked = false; highMenuItem.Checked = false; aboveNormalMenuItem.Checked = false; normalMenuItem.Checked = false; belowNormalMenuItem.Checked = false; idleMenuItem.Checked = false; try { using (var phandle = new Win32.ProcessHandle(processSelectedPID, Program.MinProcessQueryRights)) { switch (phandle.GetPriorityClass()) { case ProcessPriorityClass.RealTime: realTimeMenuItem.Checked = true; break; case ProcessPriorityClass.High: highMenuItem.Checked = true; break; case ProcessPriorityClass.AboveNormal: aboveNormalMenuItem.Checked = true; break; case ProcessPriorityClass.Normal: normalMenuItem.Checked = true; break; case ProcessPriorityClass.BelowNormal: belowNormalMenuItem.Checked = true; break; case ProcessPriorityClass.Idle: idleMenuItem.Checked = true; break; } } } catch (Exception ex) { priorityMenuItem.Text = "(" + ex.Message + ")"; priorityMenuItem.Enabled = false; } try { using (var phandle = new Win32.ProcessHandle(processSelectedPID, Program.MinProcessQueryRights)) { try { using (var thandle = phandle.GetToken(Win32.TOKEN_RIGHTS.TOKEN_QUERY)) { if (virtualizationProcessMenuItem.Enabled = thandle.IsVirtualizationAllowed()) virtualizationProcessMenuItem.Checked = thandle.IsVirtualizationEnabled(); } } catch { } } } catch { virtualizationProcessMenuItem.Enabled = false; } try { if (processP.Dictionary[processSelectedPID].SessionId != Program.CurrentSessionId) injectDllProcessMenuItem.Enabled = false; } catch (Exception ex) { Logging.Log(ex); } } else { menuProcess.DisableAll(); terminateMenuItem.Text = "&Terminate Processes"; suspendMenuItem.Text = "&Suspend Processes"; resumeMenuItem.Text = "&Resume Processes"; terminateMenuItem.Enabled = true; suspendMenuItem.Enabled = true; resumeMenuItem.Enabled = true; copyProcessMenuItem.Enabled = true; } if (processSelectedPID < 0 && treeProcesses.SelectedNodes.Count == 1) { // probably DPCs or Interrupts priorityMenuItem.Text = "&Priority"; menuProcess.DisableAll(); propertiesProcessMenuItem.Enabled = true; } if (treeProcesses.Model.Nodes.Count == 0) { selectAllProcessMenuItem.Enabled = false; } else { selectAllProcessMenuItem.Enabled = true; } } private void terminateMenuItem_Click(object sender, EventArgs e) { if (treeProcesses.SelectedNodes.Count == 0) return; int[] pids = new int[treeProcesses.SelectedNodes.Count]; string[] names = new string[pids.Length]; for (int i = 0; i < treeProcesses.SelectedNodes.Count; i++) { pids[i] = treeProcesses.SelectedNodes[i].PID; names[i] = treeProcesses.SelectedNodes[i].Name; } ProcessActions.Terminate(this, pids, names, true); } private void suspendMenuItem_Click(object sender, EventArgs e) { if (treeProcesses.SelectedNodes.Count == 0) return; int[] pids = new int[treeProcesses.SelectedNodes.Count]; string[] names = new string[pids.Length]; for (int i = 0; i < treeProcesses.SelectedNodes.Count; i++) { pids[i] = treeProcesses.SelectedNodes[i].PID; names[i] = treeProcesses.SelectedNodes[i].Name; } ProcessActions.Suspend(this, pids, names, true); } private void resumeMenuItem_Click(object sender, EventArgs e) { if (treeProcesses.SelectedNodes.Count == 0) return; int[] pids = new int[treeProcesses.SelectedNodes.Count]; string[] names = new string[pids.Length]; for (int i = 0; i < treeProcesses.SelectedNodes.Count; i++) { pids[i] = treeProcesses.SelectedNodes[i].PID; names[i] = treeProcesses.SelectedNodes[i].Name; } ProcessActions.Resume(this, pids, names, true); } private void restartProcessMenuItem_Click(object sender, EventArgs e) { if (MessageBox.Show("Are you sure you want to restart the process?", "Process Hacker", MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button2) == DialogResult.Yes) { try { using (var phandle = new Win32.ProcessHandle(processSelectedPID, Program.MinProcessQueryRights | Program.MinProcessReadMemoryRights)) { string currentDirectory = phandle.GetPebString(Win32.ProcessHandle.PebOffset.CurrentDirectoryPath); string cmdLine = phandle.GetPebString(Win32.ProcessHandle.PebOffset.CommandLine); try { using (var phandle2 = new Win32.ProcessHandle(processSelectedPID, Win32.PROCESS_RIGHTS.PROCESS_TERMINATE)) phandle2.Terminate(); } catch (Exception ex) { MessageBox.Show("Could not terminate the process: " + ex.Message, "Process Hacker", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } try { Win32.STARTUPINFO startupInfo = new Win32.STARTUPINFO(); Win32.PROCESS_INFORMATION procInfo = new Win32.PROCESS_INFORMATION(); startupInfo.Size = Marshal.SizeOf(startupInfo); if (!Win32.CreateProcess(null, cmdLine, 0, 0, false, 0, 0, currentDirectory, ref startupInfo, ref procInfo)) Win32.ThrowLastWin32Error(); Win32.CloseHandle(procInfo.hProcess); Win32.CloseHandle(procInfo.hThread); } catch (Exception ex) { MessageBox.Show("Could not start the command '" + cmdLine + "': " + ex.Message, "Process Hacker", MessageBoxButtons.OK, MessageBoxIcon.Error); } } } catch (Exception ex) { MessageBox.Show("Could not restart the process: " + ex.Message, "Process Hacker", MessageBoxButtons.OK, MessageBoxIcon.Error); } } } private void reduceWorkingSetProcessMenuItem_Click(object sender, EventArgs e) { if (treeProcesses.SelectedNodes.Count == 0) return; int[] pids = new int[treeProcesses.SelectedNodes.Count]; string[] names = new string[pids.Length]; for (int i = 0; i < treeProcesses.SelectedNodes.Count; i++) { pids[i] = treeProcesses.SelectedNodes[i].PID; names[i] = treeProcesses.SelectedNodes[i].Name; } ProcessActions.ReduceWorkingSet(this, pids, names, false); } private void virtualizationProcessMenuItem_Click(object sender, EventArgs e) { if (MessageBox.Show("Are you sure you want to set virtualization for this process?", "Process Hacker", MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button2) == DialogResult.No) return; try { using (var phandle = new Win32.ProcessHandle(processSelectedPID, Program.MinProcessQueryRights)) { using (var thandle = phandle.GetToken(Win32.TOKEN_RIGHTS.TOKEN_WRITE)) { thandle.SetVirtualizationEnabled(!virtualizationProcessMenuItem.Checked); } } } catch (Exception ex) { MessageBox.Show(ex.Message, "Process Hacker", MessageBoxButtons.OK, MessageBoxIcon.Error); } } private void inspectProcessMenuItem_Click(object sender, EventArgs e) { // user hasn't got any processes selected if (processSelectedPID == -1) return; try { ProcessWindow pForm = Program.GetProcessWindow(processP.Dictionary[processSelectedPID], new Program.PWindowInvokeAction(delegate(ProcessWindow f) { Program.FocusWindow(f); })); } catch (Exception ex) { MessageBox.Show("Could not inspect the process:\n\n" + ex.Message, "Process Hacker", MessageBoxButtons.OK, MessageBoxIcon.Error); } } private void affinityProcessMenuItem_Click(object sender, EventArgs e) { ProcessAffinity affForm = new ProcessAffinity(processSelectedPID); try { affForm.TopMost = this.TopMost; affForm.ShowDialog(); } catch (Exception ex) { Logging.Log(ex); } } private void injectDllProcessMenuItem_Click(object sender, EventArgs e) { OpenFileDialog ofd = new OpenFileDialog(); ofd.Filter = "DLL Files (*.dll)|*.dll|All Files (*.*)|*.*"; if (ofd.ShowDialog() == DialogResult.OK) { try { using (var phandle = new Win32.ProcessHandle(processSelectedPID, Win32.PROCESS_RIGHTS.PROCESS_CREATE_THREAD | Win32.PROCESS_RIGHTS.PROCESS_VM_OPERATION | Win32.PROCESS_RIGHTS.PROCESS_VM_WRITE)) { phandle.InjectDll(ofd.FileName, 2000); } } catch (Exception ex) { MessageBox.Show(ex.Message, "Process Hacker", MessageBoxButtons.OK, MessageBoxIcon.Error); } } } private void setTokenProcessMenuItem_Click(object sender, EventArgs e) { ProcessPickerWindow picker = new ProcessPickerWindow(); picker.Label = "Select the source of the token:"; if (picker.ShowDialog() == DialogResult.OK) { try { Program.KPH.SetProcessToken(picker.SelectedPid, processSelectedPID); } catch (Exception ex) { MessageBox.Show(ex.Message, "Process Hacker", MessageBoxButtons.OK, MessageBoxIcon.Error); } } } private void terminatorProcessMenuItem_Click(object sender, EventArgs e) { TerminatorWindow w = new TerminatorWindow(processSelectedPID); w.Text = "Terminator - " + processP.Dictionary[processSelectedPID].Name + " (PID " + processSelectedPID.ToString() + ")"; w.ShowDialog(); } #region Run As private void launchAsUserProcessMenuItem_Click(object sender, EventArgs e) { try { Properties.Settings.Default.RunAsCommand = processP.Dictionary[processSelectedPID].FileName; RunWindow run = new RunWindow(); run.TopMost = this.TopMost; run.ShowDialog(); } catch (Exception ex) { Logging.Log(ex); } } private void launchAsThisUserProcessMenuItem_Click(object sender, EventArgs e) { try { RunWindow run = new RunWindow(); run.TopMost = this.TopMost; run.UsePID(processSelectedPID); run.ShowDialog(); } catch (Exception ex) { Logging.Log(ex); } } #endregion #region Injector private void startProcessProcessMenuItem_Click(object sender, EventArgs e) { PromptBox box = new PromptBox(); box.TextBox.AutoCompleteSource = AutoCompleteSource.FileSystem; box.TextBox.AutoCompleteMode = AutoCompleteMode.SuggestAppend; if (box.ShowDialog() == DialogResult.OK) { ProcessStartInfo info = new ProcessStartInfo(); info.FileName = Application.StartupPath + "\\Injector.exe"; info.Arguments = "createprocessc " + processSelectedPID.ToString() + " \"" + box.Value.Replace("\"", "\\\"") + "\""; info.RedirectStandardOutput = true; info.UseShellExecute = false; info.CreateNoWindow = true; Process p = Process.Start(info); p.WaitForExit(); if (p.ExitCode != 0) { InformationBox infoBox = new InformationBox(p.StandardOutput.ReadToEnd() + "\r\nReturn code: " + p.ExitCode + " (" + Win32.GetErrorMessage(p.ExitCode) + ")"); infoBox.ShowDialog(); } } } private void getCommandLineProcessMenuItem_Click(object sender, EventArgs e) { ProcessStartInfo info = new ProcessStartInfo(); info.FileName = Application.StartupPath + "\\Injector.exe"; info.Arguments = "cmdline " + processSelectedPID.ToString(); info.RedirectStandardOutput = true; info.UseShellExecute = false; info.CreateNoWindow = true; Process p = Process.Start(info); p.WaitForExit(); InformationBox infoBox = new InformationBox(p.StandardOutput.ReadToEnd() + (p.ExitCode != 0 ? "\r\nReturn code: " + p.ExitCode + " (" + Win32.GetErrorMessage(p.ExitCode) + ")" : "")); infoBox.ShowDialog(); } private void exitProcessProcessMenuItem_Click(object sender, EventArgs e) { if (MessageBox.Show("Are you sure you want to terminate the selected process?", "Process Hacker", MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button2) == DialogResult.No) return; ProcessStartInfo info = new ProcessStartInfo(); info.FileName = Application.StartupPath + "\\Injector.exe"; info.Arguments = "exitprocess " + processSelectedPID.ToString(); info.RedirectStandardOutput = true; info.UseShellExecute = false; info.CreateNoWindow = true; Process p = Process.Start(info); p.WaitForExit(); if (p.ExitCode != 0) { InformationBox infoBox = new InformationBox(p.StandardOutput.ReadToEnd() + "\r\nReturn code: " + p.ExitCode + " (" + Win32.GetErrorMessage(p.ExitCode) + ")"); infoBox.ShowDialog(); } } #endregion #region Priority private void realTimeMenuItem_Click(object sender, EventArgs e) { SetProcessPriority(ProcessPriorityClass.RealTime); } private void highMenuItem_Click(object sender, EventArgs e) { SetProcessPriority(ProcessPriorityClass.High); } private void aboveNormalMenuItem_Click(object sender, EventArgs e) { SetProcessPriority(ProcessPriorityClass.AboveNormal); } private void normalMenuItem_Click(object sender, EventArgs e) { SetProcessPriority(ProcessPriorityClass.Normal); } private void belowNormalMenuItem_Click(object sender, EventArgs e) { SetProcessPriority(ProcessPriorityClass.BelowNormal); } private void idleMenuItem_Click(object sender, EventArgs e) { SetProcessPriority(ProcessPriorityClass.Idle); } #endregion private void searchProcessMenuItem_Click(object sender, EventArgs e) { try { Process.Start(Properties.Settings.Default.SearchEngine.Replace("%s", treeProcesses.SelectedNodes[0].Name)); } catch (Exception ex) { MessageBox.Show(ex.Message, "Process Hacker", MessageBoxButtons.OK, MessageBoxIcon.Error); } } private void reanalyzeProcessMenuItem_Click(object sender, EventArgs e) { try { processP.QueueFileProcessing(processSelectedPID); } catch (Exception ex) { Logging.Log(ex); } } private void selectAllProcessMenuItem_Click(object sender, EventArgs e) { Misc.SelectAll(treeProcesses.Tree.AllNodes); } #endregion #region Providers private void processP_Updated() { networkP.RunOnceAsync(); processP.DictionaryAdded += new ProcessSystemProvider.ProviderDictionaryAdded(processP_DictionaryAdded); processP.DictionaryRemoved += new ProcessSystemProvider.ProviderDictionaryRemoved(processP_DictionaryRemoved); processP.Updated -= new ProcessSystemProvider.ProviderUpdateOnce(processP_Updated); try { Process.GetCurrentProcess().PriorityClass = ProcessPriorityClass.High; } catch { } Program.CollectGarbage(); if (processP.RunCount >= 1) this.Invoke(new MethodInvoker(delegate { treeProcesses.Tree.EndUpdate(); this.Cursor = Cursors.Default; this.UpdateCommon(); })); } private void processP_InfoUpdater() { this.BeginInvoke(new MethodInvoker(delegate { cpuUsageIcon.Update(processP.CurrentCpuKernelUsage, processP.CurrentCpuUserUsage); if (NotifyIcon.Icon != null) Win32.DestroyIcon(notifyIcon.Icon.Handle); notifyIcon.Icon = cpuUsageIcon.GetIcon(); UpdateStatusInfo(); notifyIcon.Text = "Process Hacker\n" + "CPU Usage: " + (processP.CurrentCpuUsage * 100).ToString("F2") + "%"; if (processP.Dictionary.ContainsKey(processP.PIDWithMostCpuUsage)) if (processP.Dictionary[processP.PIDWithMostCpuUsage].Name != null) if (notifyIcon.Text.Length + processP.Dictionary[processP.PIDWithMostCpuUsage].Name.Length + 7 < 62) notifyIcon.Text += "\n" + processP.Dictionary[processP.PIDWithMostCpuUsage].Name + ": " + processP.Dictionary[processP.PIDWithMostCpuUsage].CpuUsage.ToString("F2") + "%"; })); } public void processP_DictionaryAdded(ProcessItem item) { ProcessItem parent = null; string parentText = ""; if (item.HasParent) { try { parent = processP.Dictionary[item.ParentPid]; parentText += " started by " + parent.Name + " (PID " + parent.Pid.ToString() + ")"; } catch (Exception ex) { Logging.Log(ex); } } this.QueueMessage("New Process: " + item.Name + " (PID " + item.Pid.ToString() + ")" + parentText, item.Icon); if (NPMenuItem.Checked) notifyIcon.ShowBalloonTip(2000, "New Process", "The process " + item.Name + " (" + item.Pid.ToString() + ") was started" + ((parentText != "") ? " by " + parent.Name + " (PID " + parent.Pid.ToString() + ")" : "") + ".", ToolTipIcon.Info); } public void processP_DictionaryRemoved(ProcessItem item) { this.QueueMessage("Terminated Process: " + item.Name + " (PID " + item.Pid.ToString() + ")", null); if (processServices.ContainsKey(item.Pid)) processServices.Remove(item.Pid); if (TPMenuItem.Checked) notifyIcon.ShowBalloonTip(2000, "Terminated Process", "The process " + item.Name + " (" + item.Pid.ToString() + ") was terminated.", ToolTipIcon.Info); } private void serviceP_Updated() { listServices.BeginInvoke(new MethodInvoker(delegate { listServices.List.EndUpdate(); })); HighlightingContext.StateHighlighting = true; serviceP.DictionaryAdded += new ServiceProvider.ProviderDictionaryAdded(serviceP_DictionaryAdded); serviceP.DictionaryModified += new ServiceProvider.ProviderDictionaryModified(serviceP_DictionaryModified); serviceP.DictionaryRemoved += new ServiceProvider.ProviderDictionaryRemoved(serviceP_DictionaryRemoved); serviceP.Updated -= new ServiceProvider.ProviderUpdateOnce(serviceP_Updated); if (processP.RunCount >= 1) this.Invoke(new MethodInvoker(UpdateCommon)); } public void serviceP_DictionaryAdded(ServiceItem item) { this.QueueMessage("New Service: " + item.Status.ServiceName + " (" + item.Status.ServiceStatusProcess.ServiceType.ToString() + ")" + ((item.Status.DisplayName != "") ? " (" + item.Status.DisplayName + ")" : ""), null); if (NSMenuItem.Checked) notifyIcon.ShowBalloonTip(2000, "New Service", "The service " + item.Status.ServiceName + " (" + item.Status.DisplayName + ") has been created.", ToolTipIcon.Info); } public void serviceP_DictionaryAdded_Process(ServiceItem item) { if (item.Status.ServiceStatusProcess.ProcessID != 0) { if (!processServices.ContainsKey(item.Status.ServiceStatusProcess.ProcessID)) processServices.Add(item.Status.ServiceStatusProcess.ProcessID, new List()); processServices[item.Status.ServiceStatusProcess.ProcessID].Add(item.Status.ServiceName); } } public void serviceP_DictionaryModified(ServiceItem oldItem, ServiceItem newItem) { Win32.SERVICE_STATE oldState = oldItem.Status.ServiceStatusProcess.CurrentState; Win32.SERVICE_STATE newState = newItem.Status.ServiceStatusProcess.CurrentState; if ((oldState == Win32.SERVICE_STATE.Paused || oldState == Win32.SERVICE_STATE.Stopped || oldState == Win32.SERVICE_STATE.StartPending) && newState == Win32.SERVICE_STATE.Running) { this.QueueMessage("Service Started: " + newItem.Status.ServiceName + " (" + newItem.Status.ServiceStatusProcess.ServiceType.ToString() + ")" + ((newItem.Status.DisplayName != "") ? " (" + newItem.Status.DisplayName + ")" : ""), null); if (startedSMenuItem.Checked) notifyIcon.ShowBalloonTip(2000, "Service Started", "The service " + newItem.Status.ServiceName + " (" + newItem.Status.DisplayName + ") has been started.", ToolTipIcon.Info); } if (oldState == Win32.SERVICE_STATE.Running && newState == Win32.SERVICE_STATE.Paused) this.QueueMessage("Service Paused: " + newItem.Status.ServiceName + " (" + newItem.Status.ServiceStatusProcess.ServiceType.ToString() + ")" + ((newItem.Status.DisplayName != "") ? " (" + newItem.Status.DisplayName + ")" : ""), null); if (oldState == Win32.SERVICE_STATE.Running && newState == Win32.SERVICE_STATE.Stopped) { this.QueueMessage("Service Stopped: " + newItem.Status.ServiceName + " (" + newItem.Status.ServiceStatusProcess.ServiceType.ToString() + ")" + ((newItem.Status.DisplayName != "") ? " (" + newItem.Status.DisplayName + ")" : ""), null); if (stoppedSMenuItem.Checked) notifyIcon.ShowBalloonTip(2000, "Service Stopped", "The service " + newItem.Status.ServiceName + " (" + newItem.Status.DisplayName + ") has been stopped.", ToolTipIcon.Info); } } public void serviceP_DictionaryModified_Process(ServiceItem oldItem, ServiceItem newItem) { ServiceItem sitem = (ServiceItem)newItem; if (sitem.Status.ServiceStatusProcess.ProcessID != 0) { if (!processServices.ContainsKey(sitem.Status.ServiceStatusProcess.ProcessID)) processServices.Add(sitem.Status.ServiceStatusProcess.ProcessID, new List()); if (!processServices[sitem.Status.ServiceStatusProcess.ProcessID].Contains( sitem.Status.ServiceName)) processServices[sitem.Status.ServiceStatusProcess.ProcessID].Add(sitem.Status.ServiceName); processServices[sitem.Status.ServiceStatusProcess.ProcessID].Sort(); } else { int oldId = ((ServiceItem)oldItem).Status.ServiceStatusProcess.ProcessID; if (processServices.ContainsKey(oldId)) { if (processServices[oldId].Contains( sitem.Status.ServiceName)) processServices[oldId].Remove(sitem.Status.ServiceName); } } } public void serviceP_DictionaryRemoved(ServiceItem item) { this.QueueMessage("Deleted Service: " + item.Status.ServiceName + " (" + item.Status.ServiceStatusProcess.ServiceType.ToString() + ")" + ((item.Status.DisplayName != "") ? " (" + item.Status.DisplayName + ")" : ""), null); if (DSMenuItem.Checked) notifyIcon.ShowBalloonTip(2000, "Service Deleted", "The service " + item.Status.ServiceName + " (" + item.Status.DisplayName + ") has been deleted.", ToolTipIcon.Info); } public void serviceP_DictionaryRemoved_Process(ServiceItem item) { if (item.Status.ServiceStatusProcess.ProcessID != 0) { if (processServices.ContainsKey(item.Status.ServiceStatusProcess.ProcessID)) { if (processServices[item.Status.ServiceStatusProcess.ProcessID].Contains( item.Status.ServiceName)) processServices[item.Status.ServiceStatusProcess.ProcessID].Remove(item.Status.ServiceName); } } } #endregion #region Service Context Menu private void menuService_Popup(object sender, EventArgs e) { if (listServices.SelectedItems.Count == 0) { menuService.DisableAll(); goToProcessServiceMenuItem.Visible = true; startServiceMenuItem.Visible = true; continueServiceMenuItem.Visible = true; pauseServiceMenuItem.Visible = true; stopServiceMenuItem.Visible = true; selectAllServiceMenuItem.Enabled = true; } else if (listServices.SelectedItems.Count == 1) { menuService.EnableAll(); goToProcessServiceMenuItem.Visible = true; startServiceMenuItem.Visible = true; continueServiceMenuItem.Visible = true; pauseServiceMenuItem.Visible = true; stopServiceMenuItem.Visible = true; try { ServiceItem item = serviceP.Dictionary[listServices.SelectedItems[0].Name]; if (item.Status.ServiceStatusProcess.ProcessID != 0) { goToProcessServiceMenuItem.Enabled = true; } else { goToProcessServiceMenuItem.Enabled = false; } if ((item.Status.ServiceStatusProcess.ControlsAccepted & Win32.SERVICE_ACCEPT.PauseContinue) == 0) { continueServiceMenuItem.Visible = false; pauseServiceMenuItem.Visible = false; } else { continueServiceMenuItem.Visible = true; pauseServiceMenuItem.Visible = true; } if (item.Status.ServiceStatusProcess.CurrentState == Win32.SERVICE_STATE.Paused) { startServiceMenuItem.Enabled = false; pauseServiceMenuItem.Enabled = false; } else if (item.Status.ServiceStatusProcess.CurrentState == Win32.SERVICE_STATE.Running) { startServiceMenuItem.Enabled = false; continueServiceMenuItem.Enabled = false; } else if (item.Status.ServiceStatusProcess.CurrentState == Win32.SERVICE_STATE.Stopped) { pauseServiceMenuItem.Enabled = false; stopServiceMenuItem.Enabled = false; } if ((item.Status.ServiceStatusProcess.ControlsAccepted & Win32.SERVICE_ACCEPT.Stop) == 0 && item.Status.ServiceStatusProcess.CurrentState == Win32.SERVICE_STATE.Running) { stopServiceMenuItem.Enabled = false; } } catch { menuService.DisableAll(); copyServiceMenuItem.Enabled = true; propertiesServiceMenuItem.Enabled = true; } } else { menuService.DisableAll(); goToProcessServiceMenuItem.Visible = false; startServiceMenuItem.Visible = false; continueServiceMenuItem.Visible = false; pauseServiceMenuItem.Visible = false; stopServiceMenuItem.Visible = false; copyServiceMenuItem.Enabled = true; propertiesServiceMenuItem.Enabled = true; selectAllServiceMenuItem.Enabled = true; } if (listServices.List.Items.Count == 0) selectAllServiceMenuItem.Enabled = false; } private void goToProcessServiceMenuItem_Click(object sender, EventArgs e) { DeselectAll(treeProcesses.Tree); try { TreeNodeAdv node = treeProcesses.FindTreeNode(serviceP.Dictionary[ listServices.SelectedItems[0].Name].Status.ServiceStatusProcess.ProcessID); node.EnsureVisible(); node.IsSelected = true; treeProcesses.Tree.FullUpdate(); tabControl.SelectedTab = tabProcesses; } catch (Exception ex) { Logging.Log(ex); } } private void startServiceMenuItem_Click(object sender, EventArgs e) { ServiceActions.Start(this, listServices.SelectedItems[0].Name, false); } private void continueServiceMenuItem_Click(object sender, EventArgs e) { ServiceActions.Continue(this, listServices.SelectedItems[0].Name, false); } private void pauseServiceMenuItem_Click(object sender, EventArgs e) { ServiceActions.Pause(this, listServices.SelectedItems[0].Name, false); } private void stopServiceMenuItem_Click(object sender, EventArgs e) { ServiceActions.Stop(this, listServices.SelectedItems[0].Name, false); } private void deleteServiceMenuItem_Click(object sender, EventArgs e) { ServiceActions.Delete(this, listServices.SelectedItems[0].Name, true); } private void propertiesServiceMenuItem_Click(object sender, EventArgs e) { List selected = new List(); ServiceWindow sw; foreach (ListViewItem item in listServices.SelectedItems) selected.Add(item.Name); if (selected.Count == 1) { sw = new ServiceWindow(selected[0]); } else { sw = new ServiceWindow(selected.ToArray()); } sw.TopMost = this.TopMost; sw.ShowDialog(); } private void selectAllServiceMenuItem_Click(object sender, EventArgs e) { Misc.SelectAll(listServices.Items); } #endregion #region Tab Controls private void tabControlBig_SelectedIndexChanged(object sender, EventArgs e) { if (tabControl.SelectedTab == tabNetwork) { if (processP.RunCount > 0) { networkP.Enabled = true; networkP.RunOnceAsync(); } } else { networkP.Enabled = false; } } #endregion #region Timers private void timerMessages_Tick(object sender, EventArgs e) { if (statusMessages.Count != 0) { KeyValuePair v = statusMessages.Dequeue(); statusText.Text = v.Key; if (v.Value != null) statusIcon.Icon = v.Value; else statusIcon.Icon = null; } else { statusText.Text = ""; statusIcon.Icon = null; } } #endregion #region ToolStrip Items private void findHandlesToolStripButton_Click(object sender, EventArgs e) { findHandlesMenuItem_Click(sender, e); } private void refreshToolStripButton_Click(object sender, EventArgs e) { updateNowMenuItem_Click(sender, e); } private void sysInfoToolStripButton_Click(object sender, EventArgs e) { sysInfoMenuItem_Click(sender, e); } private void optionsToolStripButton_Click(object sender, EventArgs e) { optionsMenuItem_Click(sender, e); } #endregion #region Trees private void treeProcesses_NodeMouseDoubleClick(object sender, TreeNodeAdvMouseEventArgs e) { inspectProcessMenuItem_Click(null, null); } #endregion #endregion #region Form-related Helper functions public void ApplyFont(Font f) { treeProcesses.Tree.Font = f; if (f.Height > 16) treeProcesses.Tree.RowHeight = f.Height; else treeProcesses.Tree.RowHeight = 16; listServices.List.Font = f; listNetwork.List.Font = f; } public void ClearLog() { _log.Clear(); if (this.LogUpdated != null) this.LogUpdated(null); } private void CreateShutdownMenuItems() { AddMenuItemDelegate addMenuItem = (string text, EventHandler onClick) => { shutdownMenuItem.MenuItems.Add(new MenuItem(text, onClick)); shutdownTrayMenuItem.MenuItems.Add(new MenuItem(text, onClick)); shutDownToolStripMenuItem.DropDownItems.Add(text, null, onClick); }; addMenuItem("Lock", (sender, e) => { Win32.LockWorkStation(); }); addMenuItem("Logoff", (sender, e) => { Win32.ExitWindowsEx(Win32.ExitWindowsFlags.Logoff, 0); }); addMenuItem("-", null); addMenuItem("Sleep", (sender, e) => { Win32.SetSuspendState(false, false, false); }); addMenuItem("Hibernate", (sender, e) => { Win32.SetSuspendState(true, false, false); }); addMenuItem("-", null); addMenuItem("Restart", (sender, e) => { if (MessageBox.Show("Are you sure you want to restart your computer?", "Process Hacker", MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button2) == DialogResult.Yes) Win32.ExitWindowsEx(Win32.ExitWindowsFlags.Reboot, 0); }); addMenuItem("Shutdown", (sender, e) => { if (MessageBox.Show("Are you sure you want to shutdown your computer?", "Process Hacker", MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button2) == DialogResult.Yes) Win32.ExitWindowsEx(Win32.ExitWindowsFlags.Shutdown, 0); }); addMenuItem("Poweroff", (sender, e) => { if (MessageBox.Show("Are you sure you want to poweroff your computer?", "Process Hacker", MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button2) == DialogResult.Yes) Win32.ExitWindowsEx(Win32.ExitWindowsFlags.Poweroff, 0); }); } private void DeleteSettings() { //Type localFileSettingsProviderType = typeof(System.Configuration.LocalFileSettingsProvider); //PropertyInfo storeType = // localFileSettingsProviderType.GetProperty("Store", BindingFlags.NonPublic); //object store = storeType.GetValue(Properties.Settings.Default.Properties["AlwaysOnTop"].Provider, null); //MethodInfo getUserConfig = // store.GetType().GetMethod("GetUserConfig", BindingFlags.NonPublic); //object localConfig = getUserConfig.Invoke(store, new object[] { false }); //object roamingConfig = getUserConfig.Invoke(store, new object[] { true }); //PropertyInfo filePath = localConfig.GetType().GetProperty("FilePath", BindingFlags.NonPublic); //try { System.IO.File.Delete(filePath.GetValue(localConfig, null) as string); } //catch { } //try { System.IO.File.Delete(filePath.GetValue(roamingConfig, null) as string); } //catch { } if (System.IO.Directory.Exists(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + "\\wj32")) System.IO.Directory.Delete(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + "\\wj32", true); if (System.IO.Directory.Exists(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\wj32")) System.IO.Directory.Delete(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\wj32", true); } public void DeselectAll(ListView list) { foreach (ListViewItem item in list.SelectedItems) item.Selected = false; } public void DeselectAll(TreeViewAdv tree) { foreach (TreeNodeAdv node in tree.AllNodes) node.IsSelected = false; } // Technique from http://www.vb-helper.com/howto_2008_uac_shield.html private Bitmap GetUacShieldIcon() { const int width = 50; const int height = 50; const int margin = 4; Bitmap shieldImage; Button button = new Button() { Text = " ", Size = new Size(width, height), FlatStyle = FlatStyle.System }; button.SetShieldIcon(true); Bitmap buttonImage = new Bitmap(width, height); button.Refresh(); button.DrawToBitmap(buttonImage, new Rectangle(0, 0, width, height)); int minX = width; int maxX = 0; int minY = width; int maxY = 0; for (int y = margin; y < height - margin; y++) { var targetColor = buttonImage.GetPixel(margin, y); for (int x = margin; x < width - margin; x++) { if (buttonImage.GetPixel(x, y).Equals(targetColor)) { buttonImage.SetPixel(x, y, Color.Transparent); } else { if (minY > y) minY = y; if (minX > x) minX = x; if (maxY < y) maxY = y; if (maxX < x) maxX = x; } } } int shieldWidth = maxX - minX + 1; int shieldHeight = maxY - minY + 1; shieldImage = new Bitmap(shieldWidth, shieldHeight); using (Graphics g = Graphics.FromImage(shieldImage)) g.DrawImage(buttonImage, 0, 0, new Rectangle(minX, minY, shieldWidth, shieldHeight), GraphicsUnit.Pixel); buttonImage.Dispose(); return shieldImage; } private void LoadSettings() { this.TopMost = Properties.Settings.Default.AlwaysOnTop; this.Location = Properties.Settings.Default.WindowLocation; this.Size = Properties.Settings.Default.WindowSize; if (Properties.Settings.Default.WindowState != FormWindowState.Minimized) this.WindowState = Properties.Settings.Default.WindowState; else this.WindowState = FormWindowState.Normal; PromptBox.LastValue = Properties.Settings.Default.PromptBoxText; toolbarMenuItem.Checked = toolStrip.Visible = Properties.Settings.Default.ToolbarVisible; ColumnSettings.LoadSettings(Properties.Settings.Default.ProcessTreeColumns, treeProcesses.Tree); ColumnSettings.LoadSettings(Properties.Settings.Default.ServiceListViewColumns, listServices.List); ColumnSettings.LoadSettings(Properties.Settings.Default.NetworkListViewColumns, listNetwork.List); HighlightingContext.Colors[ListViewItemState.New] = Properties.Settings.Default.ColorNew; HighlightingContext.Colors[ListViewItemState.Removed] = Properties.Settings.Default.ColorRemoved; TreeNodeAdv.StateColors[TreeNodeAdv.NodeState.New] = Properties.Settings.Default.ColorNew; TreeNodeAdv.StateColors[TreeNodeAdv.NodeState.Removed] = Properties.Settings.Default.ColorRemoved; Program.ImposterNames = new System.Collections.Specialized.StringCollection(); foreach (string s in Properties.Settings.Default.ImposterNames.Split(',')) Program.ImposterNames.Add(s.Trim()); HistoryManager.GlobalMaxCount = Properties.Settings.Default.MaxSamples; ProcessHacker.Components.Plotter.GlobalMoveStep = Properties.Settings.Default.PlotterStep; Win32.LoadLibrary(Properties.Settings.Default.DbgHelpPath); try { var modules = Win32.ProcessHandle.FromHandle(Program.CurrentProcess).GetModules(); foreach (var module in modules) { if (module.FileName.ToLowerInvariant().EndsWith("dbghelp.dll")) { var fi = new System.IO.FileInfo(module.FileName); Win32.LoadLibrary(fi.DirectoryName + "\\symsrv.dll"); break; } } } catch { } } public void QueueMessage(string message) { this.QueueMessage(message, null); } public void QueueMessage(string message, Icon icon) { var value = new KeyValuePair(DateTime.Now, message); _log.Add(value); statusMessages.Enqueue(new KeyValuePair(message, icon)); if (this.LogUpdated != null) this.LogUpdated(value); } private void SaveSettings() { if (this.WindowState == FormWindowState.Normal && this.Visible) { Properties.Settings.Default.WindowLocation = this.Location; Properties.Settings.Default.WindowSize = this.Size; } Properties.Settings.Default.AlwaysOnTop = this.TopMost; Properties.Settings.Default.WindowState = this.WindowState == FormWindowState.Minimized ? FormWindowState.Normal : this.WindowState; Properties.Settings.Default.ToolbarVisible = toolStrip.Visible; Properties.Settings.Default.PromptBoxText = PromptBox.LastValue; Properties.Settings.Default.ProcessTreeColumns = ColumnSettings.SaveSettings(treeProcesses.Tree); Properties.Settings.Default.ServiceListViewColumns = ColumnSettings.SaveSettings(listServices.List); Properties.Settings.Default.NetworkListViewColumns = ColumnSettings.SaveSettings(listNetwork.List); Properties.Settings.Default.NewProcesses = NPMenuItem.Checked; Properties.Settings.Default.TerminatedProcesses = TPMenuItem.Checked; Properties.Settings.Default.NewServices = NSMenuItem.Checked; Properties.Settings.Default.StartedServices = startedSMenuItem.Checked; Properties.Settings.Default.StoppedServices = stoppedSMenuItem.Checked; Properties.Settings.Default.DeletedServices = DSMenuItem.Checked; try { Properties.Settings.Default.Save(); } catch { } } public void SelectAll(TreeViewAdv tree) { foreach (TreeNodeAdv node in tree.AllNodes) node.IsSelected = true; } private void UpdateStatusInfo() { if (processP.RunCount >= 1) statusGeneral.Text = string.Format("{0} processes", processP.Dictionary.Count - 2); else statusGeneral.Text = "Loading..."; statusCPU.Text = "CPU: " + (processP.CurrentCpuUsage * 100).ToString("N2") + "%"; statusMemory.Text = "Phys. Memory: " + ((float)(processP.System.NumberOfPhysicalPages - processP.Performance.AvailablePages) * 100 / processP.System.NumberOfPhysicalPages).ToString("N2") + "%"; } #endregion #region Helper functions private void SetProcessPriority(ProcessPriorityClass priority) { try { using (var phandle = new Win32.ProcessHandle(processSelectedPID, Win32.PROCESS_RIGHTS.PROCESS_SET_INFORMATION)) phandle.SetPriorityClass(priority); } catch (Exception ex) { MessageBox.Show("The priority could not be set:\n\n" + ex.Message, "Process Hacker", MessageBoxButtons.OK, MessageBoxIcon.Error); } } #endregion protected override void WndProc(ref Message m) { switch (m.Msg) { // Magic number - PH uses this to detect previous instances. case 0x9991: { this.Visible = true; if (this.WindowState == FormWindowState.Minimized) this.WindowState = FormWindowState.Normal; m.Result = new IntPtr(0x1119); return; } //break; case (int)Win32.WindowMessage.SysCommand: { if (m.WParam.ToInt32() == 0xf020) // SC_MINIMIZE { try { if (this.NotifyIcon.Visible && Properties.Settings.Default.HideWhenMinimized) { this.Visible = false; return; } } catch { } } } break; case (int)Win32.WindowMessage.Activate: case (int)Win32.WindowMessage.KillFocus: { if (treeProcesses != null && treeProcesses.Tree != null) treeProcesses.Tree.Invalidate(); } break; } base.WndProc(ref m); } private void Exit() { //processP.Dispose(); //serviceP.Dispose(); //networkP.Dispose(); notifyIcon.Visible = false; SaveSettings(); if (Program.KPH != null) Program.KPH.Close(); try { Win32.ExitProcess(0); } catch { } } private void HackerWindow_FormClosing(object sender, FormClosingEventArgs e) { if (e.CloseReason == CloseReason.WindowsShutDown) { this.Exit(); return; } if (Properties.Settings.Default.HideWhenClosed) { e.Cancel = true; showHideMenuItem_Click(sender, null); return; } this.Exit(); } private void CheckedMenuItem_Click(object sender, EventArgs e) { ((MenuItem)sender).Checked = !((MenuItem)sender).Checked; } private void UpdateCommon() { timerMessages.Enabled = true; treeProcesses.RefreshItems(); } private void LoadVerifySettings() { // Try to get a setting. If the file is corrupt, we can reset the settings. try { var a = Properties.Settings.Default.AlwaysOnTop; } catch (Exception ex) { Logging.Log(ex); try { ThemingScope.Activate(); } catch { } if (Program.WindowsVersion == WindowsVersion.Vista) { TaskDialog td = new TaskDialog(); td.WindowTitle = "Process Hacker"; td.MainInstruction = "Process Hacker could not initialize the configuration manager"; td.Content = "The Process Hacker configuration file is corrupt or the configuration manager " + "could not be initialized. Do you want Process Hacker to reset your settings?"; td.MainIcon = TaskDialogIcon.Warning; td.CommonButtons = TaskDialogCommonButtons.Cancel; td.Buttons = new TaskDialogButton[] { new TaskDialogButton((int)DialogResult.Yes, "Yes, reset the settings and restart Process Hacker"), new TaskDialogButton((int)DialogResult.No, "No, attempt to start Process Hacker anyway"), new TaskDialogButton((int)DialogResult.Retry, "Show me the error message") }; td.UseCommandLinks = true; td.Callback = (taskDialog, args, userData) => { if (args.Notification == TaskDialogNotification.ButtonClicked) { if (args.ButtonId == (int)DialogResult.Yes) { taskDialog.SetMarqueeProgressBar(true); taskDialog.SetProgressBarMarquee(true, 1000); try { this.DeleteSettings(); Process.Start(Application.ExecutablePath); } catch (Exception ex2) { taskDialog.SetProgressBarMarquee(false, 1000); MessageBox.Show("The settings could not be reset:\r\n\r\n" + ex.ToString(), "Process Hacker", MessageBoxButtons.OK, MessageBoxIcon.Error); return true; } return false; } else if (args.ButtonId == (int)DialogResult.Retry) { InformationBox box = new InformationBox(ex.ToString()); box.ShowDialog(); return true; } } return false; }; int result = td.Show(this); if (result == (int)DialogResult.No) { return; } } else { if (MessageBox.Show("Process Hacker cannot start because your configuration file is corrupt. " + "Do you want Process Hacker to reset your settings?", "Process Hacker", MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation) == DialogResult.Yes) { try { this.DeleteSettings(); MessageBox.Show("Process Hacker has reset your settings and will now restart.", "Process Hacker", MessageBoxButtons.OK, MessageBoxIcon.Information); Process.Start(Application.ExecutablePath); } catch (Exception ex2) { Logging.Log(ex2); MessageBox.Show("Process Hacker could not reset your settings. Please delete the folder " + "'wj32' in your Application Data/Local Application Data directories.", "Process Hacker", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); } } } Win32.ExitProcess(0); } } private void LoadFixMenuItems() { if (!System.IO.File.Exists(Application.StartupPath + "\\Assistant.exe")) { runAsServiceMenuItem.Enabled = false; runAsProcessMenuItem.Visible = false; } if (Program.KPH == null) csrProcessesMenuItem.Visible = false; if (Program.KPH == null || Program.WindowsVersion != WindowsVersion.XP) setTokenProcessMenuItem.Visible = false; } private void LoadUac() { if (Program.ElevationType == Win32.TOKEN_ELEVATION_TYPE.TokenElevationTypeLimited) { uacShieldIcon = this.GetUacShieldIcon(); vistaMenu.SetImage(showDetailsForAllProcessesMenuItem, uacShieldIcon); //vistaMenu.SetImage(startServiceMenuItem, uacShieldIcon); //vistaMenu.SetImage(continueServiceMenuItem, uacShieldIcon); //vistaMenu.SetImage(pauseServiceMenuItem, uacShieldIcon); //vistaMenu.SetImage(stopServiceMenuItem, uacShieldIcon); //vistaMenu.SetImage(deleteServiceMenuItem, uacShieldIcon); //runAsServiceMenuItem.Visible = false; //runAsProcessMenuItem.Visible = false; } else { runAsAdministratorMenuItem.Visible = false; showDetailsForAllProcessesMenuItem.Visible = false; } } private void LoadNotificationIcon() { notifyIcon.ContextMenu = menuIcon; notifyIcon.Visible = Properties.Settings.Default.ShowIcon; NPMenuItem.Checked = Properties.Settings.Default.NewProcesses; TPMenuItem.Checked = Properties.Settings.Default.TerminatedProcesses; NSMenuItem.Checked = Properties.Settings.Default.NewServices; startedSMenuItem.Checked = Properties.Settings.Default.StartedServices; stoppedSMenuItem.Checked = Properties.Settings.Default.StoppedServices; DSMenuItem.Checked = Properties.Settings.Default.DeletedServices; NPMenuItem.Click += new EventHandler(CheckedMenuItem_Click); TPMenuItem.Click += new EventHandler(CheckedMenuItem_Click); NSMenuItem.Click += new EventHandler(CheckedMenuItem_Click); startedSMenuItem.Click += new EventHandler(CheckedMenuItem_Click); stoppedSMenuItem.Click += new EventHandler(CheckedMenuItem_Click); DSMenuItem.Click += new EventHandler(CheckedMenuItem_Click); } private void LoadControls() { cpuUsageIcon = new UsageIcon(16, 16); listControls.Add(treeProcesses.Tree); listControls.Add(listServices); GenericViewMenu.AddMenuItems(copyProcessMenuItem.MenuItems, treeProcesses.Tree); GenericViewMenu.AddMenuItems(copyServiceMenuItem.MenuItems, listServices.List, null); GenericViewMenu.AddMenuItems(copyNetworkMenuItem.MenuItems, listNetwork.List, null); treeProcesses.ContextMenu = menuProcess; listServices.ContextMenu = menuService; listNetwork.ContextMenu = menuNetwork; Program.SecondarySharedThreadProvider = new SharedThreadProvider(Properties.Settings.Default.RefreshInterval); Program.SharedThreadProvider = new SharedThreadProvider(Properties.Settings.Default.RefreshInterval); Program.SharedThreadProvider.Add(processP); Program.SharedThreadProvider.Add(serviceP); Program.SharedThreadProvider.Add(networkP); processP.Interval = Properties.Settings.Default.RefreshInterval; treeProcesses.Provider = processP; treeProcesses.Tree.BeginUpdate(); this.Cursor = Cursors.WaitCursor; processP.RunOnceAsync(); processP.Updated += new ProcessSystemProvider.ProviderUpdateOnce(processP_Updated); processP.Updated += new ProcessSystemProvider.ProviderUpdateOnce(processP_InfoUpdater); processP.Enabled = true; updateProcessesMenuItem.Checked = true; cpuUsageIcon.BackColor = Color.Black; cpuUsageIcon.Color = Color.FromArgb(0, 255, 0); HighlightingContext.HighlightingDuration = Properties.Settings.Default.HighlightingDuration; HighlightingContext.StateHighlighting = false; listServices.List.BeginUpdate(); serviceP.Interval = Properties.Settings.Default.RefreshInterval; listServices.Provider = serviceP; serviceP.RunOnceAsync(); serviceP.DictionaryAdded += new ServiceProvider.ProviderDictionaryAdded(serviceP_DictionaryAdded_Process); serviceP.DictionaryModified += new ServiceProvider.ProviderDictionaryModified(serviceP_DictionaryModified_Process); serviceP.DictionaryRemoved += new ServiceProvider.ProviderDictionaryRemoved(serviceP_DictionaryRemoved_Process); serviceP.Updated += new ServiceProvider.ProviderUpdateOnce(serviceP_Updated); serviceP.Enabled = true; updateServicesMenuItem.Checked = true; networkP.Interval = Properties.Settings.Default.RefreshInterval; listNetwork.Provider = networkP; networkP.Enabled = true; treeProcesses.Tree.MouseDown += (sender, e) => { if (e.Button == MouseButtons.Right && e.Location.Y < treeProcesses.Tree.ColumnHeaderHeight) { ContextMenu menu = new ContextMenu(); menu.MenuItems.Add(new MenuItem("Choose Columns...", (sender_, e_) => { (new ChooseColumnsWindow(treeProcesses.Tree) { TopMost = this.TopMost }).ShowDialog(); copyProcessMenuItem.MenuItems.DisposeAndClear(); GenericViewMenu.AddMenuItems(copyProcessMenuItem.MenuItems, treeProcesses.Tree); treeProcesses.Tree.Invalidate(); })); menu.Show(treeProcesses.Tree, e.Location); } }; treeProcesses.Tree.ColumnClicked += (sender, e) => { DeselectAll(treeProcesses.Tree); }; treeProcesses.Tree.ColumnReordered += (sender, e) => { copyProcessMenuItem.MenuItems.DisposeAndClear(); GenericViewMenu.AddMenuItems(copyProcessMenuItem.MenuItems, treeProcesses.Tree); }; tabControlBig_SelectedIndexChanged(null, null); } private void LoadAddShortcuts() { treeProcesses.Tree.KeyDown += (sender, e) => { if (e.Control && e.KeyCode == Keys.A) Misc.SelectAll(treeProcesses.TreeNodes); if (e.Control && e.KeyCode == Keys.C) GenericViewMenu.TreeViewAdvCopy(treeProcesses.Tree, -1); }; listServices.List.KeyDown += (sender, e) => { if (e.Control && e.KeyCode == Keys.A) Misc.SelectAll(listServices.List.Items); if (e.Control && e.KeyCode == Keys.C) GenericViewMenu.ListViewCopy(listServices.List, -1); }; listNetwork.List.KeyDown += (sender, e) => { if (e.Control && e.KeyCode == Keys.A) Misc.SelectAll(listNetwork.List.Items); if (e.Control && e.KeyCode == Keys.C) GenericViewMenu.ListViewCopy(listNetwork.List, -1); }; } private void LoadApplyCommandLineArgs() { tabControl.SelectedTab = tabControl.TabPages["tab" + Program.SelectTab]; } public HackerWindow() { Program.HackerWindow = this; processP = Program.ProcessProvider; serviceP = Program.ServiceProvider; networkP = Program.NetworkProvider; this.LoadVerifySettings(); InitializeComponent(); // Force the handle to be created { var handle = this.Handle; } this.SuspendLayout(); this.CreateShutdownMenuItems(); this.LoadFixMenuItems(); this.LoadNotificationIcon(); this.LoadUac(); this.LoadSettings(); this.LoadControls(); this.LoadAddShortcuts(); this.ResumeLayout(); if ((!Properties.Settings.Default.StartHidden && !Program.StartHidden) || Program.StartVisible) { this.Visible = true; } if (tabControl.SelectedTab == tabProcesses) treeProcesses.Tree.Select(); statusText.Text = "Waiting..."; try { if (System.IO.File.Exists(Application.StartupPath + "\\structs.txt")) { Structs.StructParser parser = new ProcessHacker.Structs.StructParser(Program.Structs); parser.Parse(Application.StartupPath + "\\structs.txt"); } } catch (Exception ex) { QueueMessage("Error loading structure definitions: " + ex.Message); } try { this.Text += " [" + Win32.ProcessHandle.FromHandle(Program.CurrentProcess). GetToken(Win32.TOKEN_RIGHTS.TOKEN_QUERY).GetUser().GetName(true) + (Program.KPH != null ? "+" : "") + "]"; } catch { } // If it's Vista and we're elevated, we should allow the magic window message to allow // Allow only one instance to work. if (Program.WindowsVersion == WindowsVersion.Vista && Program.ElevationType == Win32.TOKEN_ELEVATION_TYPE.TokenElevationTypeFull) { Win32.ChangeWindowMessageFilter((Win32.WindowMessage)0x9991, Win32.UipiFilterFlag.Add); } } private void HackerWindow_Load(object sender, EventArgs e) { Program.UpdateWindows(); this.ApplyFont(Properties.Settings.Default.Font); this.BeginInvoke(new MethodInvoker(this.LoadApplyCommandLineArgs)); } private void HackerWindow_SizeChanged(object sender, EventArgs e) { tabControl.Invalidate(false); } private void HackerWindow_VisibleChanged(object sender, EventArgs e) { treeProcesses.Draw = this.Visible; } protected override void OnResize(EventArgs e) { // // Size grip bug fix as per // http://jelle.druyts.net/2003/10/20/StatusBarResizeBug.aspx // if (statusBar != null) { statusBar.SizingGrip = (WindowState == FormWindowState.Normal); } base.OnResize(e); } } }