diff --git a/trunk/ProcessHacker/UI/Actions/ProcessActions.cs b/trunk/ProcessHacker/UI/Actions/ProcessActions.cs
new file mode 100644
index 000000000..1d2aa4230
--- /dev/null
+++ b/trunk/ProcessHacker/UI/Actions/ProcessActions.cs
@@ -0,0 +1,312 @@
+/*
+ * Process Hacker -
+ * process actions
+ *
+ * Copyright (C) 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.Windows.Forms;
+using ProcessHacker.Components;
+
+namespace ProcessHacker.UI.Actions
+{
+ public static class ProcessActions
+ {
+ private static bool Prompt(IWin32Window window, int[] pids, string[] names,
+ string action, string content, bool promptOnlyIfDangerous)
+ {
+ string name = "the selected process(es)";
+
+ if (pids.Length == 1)
+ name = names[0];
+ else
+ name = "the selected processes";
+
+ bool dangerous = false;
+
+ foreach (int pid in pids)
+ {
+ if (Misc.IsDangerousPid(pid))
+ {
+ dangerous = true;
+ break;
+ }
+ }
+
+ if (promptOnlyIfDangerous && !dangerous)
+ return true;
+
+ DialogResult result = DialogResult.No;
+
+ if (Program.WindowsVersion == WindowsVersion.Vista)
+ {
+ TaskDialog td = new TaskDialog();
+
+ td.WindowTitle = "Process Hacker";
+ td.MainInstruction = "Do you want to " + action + " " + name + "?";
+ td.Content = content;
+
+ if (dangerous)
+ {
+ td.MainIcon = TaskDialogIcon.Warning;
+ td.Content = "You are about to " + action + " one or more system processes. " +
+ "Doing so will cause system instability. Are you sure you want to continue?";
+ }
+
+ if (pids.Length > 1)
+ {
+ td.ExpandFooterArea = true;
+ td.ExpandedInformation = "Processes:\r\n";
+
+ for (int i = 0; i < pids.Length; i++)
+ {
+ td.ExpandedInformation += names[i] + " (PID " + pids[i].ToString() + ")\r\n";
+ }
+
+ td.ExpandedInformation = td.ExpandedInformation.Trim();
+ }
+
+ td.Buttons = new TaskDialogButton[]
+ {
+ new TaskDialogButton((int)DialogResult.Yes, char.ToUpper(action[0]) + action.Substring(1)),
+ new TaskDialogButton((int)DialogResult.No, "Cancel")
+ };
+ td.DefaultButton = (int)DialogResult.No;
+
+ result = (DialogResult)td.Show(window);
+ }
+ else if (Program.WindowsVersion == WindowsVersion.XP)
+ {
+ if (dangerous)
+ {
+ result = MessageBox.Show("You are about to " + action + " one or more system processes. " +
+ "Are you sure you want to " + action + " " + name + "?",
+ "Process Hacker", MessageBoxButtons.YesNo,
+ MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button2);
+ }
+ else
+ {
+ result = MessageBox.Show("Are you sure you want to " + action + " " + name + "?",
+ "Process Hacker", MessageBoxButtons.YesNo,
+ MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button2);
+ }
+ }
+
+ return result == DialogResult.Yes;
+ }
+
+ private static bool ElevateIfRequired(IWin32Window window, int[] pids, string[] names,
+ Win32.PROCESS_RIGHTS access, string action)
+ {
+ if (Program.WindowsVersion == WindowsVersion.Vista &&
+ Program.ElevationType == Win32.TOKEN_ELEVATION_TYPE.TokenElevationTypeLimited &&
+ Program.KPH == null)
+ {
+ try
+ {
+ foreach (int pid in pids)
+ {
+ using (var phandle = new Win32.ProcessHandle(pid, access))
+ { }
+ }
+ }
+ catch (WindowsException ex)
+ {
+ TaskDialog td = new TaskDialog();
+
+ td.WindowTitle = "Process Hacker";
+ td.MainIcon = TaskDialogIcon.Shield;
+ td.MainInstruction = "Do you want to elevate the action?";
+ td.Content = "The action cannot be performed in the current security context. " +
+ "Do you want Process Hacker to prompt for the appropriate credentials and elevate the action?";
+
+ td.ExpandedInformation = "Error: " + ex.Message + " (0x" + ex.ErrorCode.ToString("x") + ")";
+ td.ExpandFooterArea = true;
+
+ td.Buttons = new TaskDialogButton[]
+ {
+ new TaskDialogButton((int)DialogResult.Yes, "Elevate\nPrompt for credentials and elevate the action."),
+ new TaskDialogButton((int)DialogResult.No, "Continue\nAttempt to perform the action without elevation.")
+ };
+ td.CommonButtons = TaskDialogCommonButtons.Cancel;
+ td.UseCommandLinks = true;
+ td.Callback = (taskDialog, args, userData) =>
+ {
+ if (args.Notification == TaskDialogNotification.Created)
+ {
+ taskDialog.SetButtonElevationRequiredState((int)DialogResult.Yes, true);
+ }
+
+ return false;
+ };
+
+ DialogResult result = (DialogResult)td.Show(window);
+
+ if (result == DialogResult.Yes)
+ {
+ string objects = "";
+
+ foreach (int pid in pids)
+ objects += pid + ",";
+
+ Program.StartProcessHackerAdmin("-e -type process -action " + action + " -obj \"" +
+ objects + "\" -hwnd " + window.Handle.ToString(), null, window.Handle);
+
+ return true;
+ }
+ else if (result == DialogResult.No)
+ {
+ return false;
+ }
+ else if (result == DialogResult.Cancel)
+ {
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
+ public static void Terminate(IWin32Window window, int[] pids, string[] names, bool prompt)
+ {
+ if (ElevateIfRequired(window, pids, names, Win32.PROCESS_RIGHTS.PROCESS_TERMINATE, "terminate"))
+ return;
+
+ if (prompt && !Prompt(window, pids, names, "terminate",
+ "Terminating a process will cause unsaved data to be lost. " +
+ "Terminating a system process will cause system instability. " +
+ "Are you sure you want to continue?", false))
+ return;
+
+ for (int i = 0; i < pids.Length; i++)
+ {
+ try
+ {
+ using (Win32.ProcessHandle phandle = new Win32.ProcessHandle(pids[i],
+ Win32.PROCESS_RIGHTS.PROCESS_TERMINATE))
+ phandle.Terminate();
+ }
+ catch (Exception ex)
+ {
+ DialogResult r = MessageBox.Show(window, "Could not terminate process \"" + names[i] +
+ "\" with PID " + pids[i].ToString() + ":\n\n" +
+ ex.Message, "Process Hacker", MessageBoxButtons.OKCancel, MessageBoxIcon.Error);
+
+ if (r == DialogResult.Cancel)
+ return;
+ }
+ }
+ }
+
+ public static void Suspend(IWin32Window window, int[] pids, string[] names, bool prompt)
+ {
+ if (ElevateIfRequired(window, pids, names, Win32.PROCESS_RIGHTS.PROCESS_SUSPEND_RESUME, "suspend"))
+ return;
+
+ if (prompt && !Prompt(window, pids, names, "suspend",
+ "Suspending a process will pause its execution. " +
+ "Suspending a system process will cause system instability. " +
+ "Are you sure you want to continue?", true))
+ return;
+
+ for (int i = 0; i < pids.Length; i++)
+ {
+ try
+ {
+ using (Win32.ProcessHandle phandle = new Win32.ProcessHandle(pids[i],
+ Win32.PROCESS_RIGHTS.PROCESS_SUSPEND_RESUME))
+ phandle.Suspend();
+ }
+ catch (Exception ex)
+ {
+ DialogResult r = MessageBox.Show(window, "Could not suspend process \"" + names[i] +
+ "\" with PID " + pids[i].ToString() + ":\n\n" +
+ ex.Message, "Process Hacker", MessageBoxButtons.OKCancel, MessageBoxIcon.Error);
+
+ if (r == DialogResult.Cancel)
+ return;
+ }
+ }
+ }
+
+ public static void Resume(IWin32Window window, int[] pids, string[] names, bool prompt)
+ {
+ if (ElevateIfRequired(window, pids, names, Win32.PROCESS_RIGHTS.PROCESS_SUSPEND_RESUME, "resume"))
+ return;
+
+ if (prompt && !Prompt(window, pids, names, "resume",
+ "Resuming a process will begin its execution. " +
+ "Resuming a system process may lead to system instability. " +
+ "Are you sure you want to continue?", true))
+ return;
+
+ for (int i = 0; i < pids.Length; i++)
+ {
+ try
+ {
+ using (Win32.ProcessHandle phandle = new Win32.ProcessHandle(pids[i],
+ Win32.PROCESS_RIGHTS.PROCESS_SUSPEND_RESUME))
+ phandle.Resume();
+ }
+ catch (Exception ex)
+ {
+ DialogResult r = MessageBox.Show(window, "Could not resume process \"" + names[i] +
+ "\" with PID " + pids[i].ToString() + ":\n\n" +
+ ex.Message, "Process Hacker", MessageBoxButtons.OKCancel, MessageBoxIcon.Error);
+
+ if (r == DialogResult.Cancel)
+ return;
+ }
+ }
+ }
+
+ public static void ReduceWorkingSet(IWin32Window window, int[] pids, string[] names, bool prompt)
+ {
+ if (ElevateIfRequired(window, pids, names,
+ Win32.PROCESS_RIGHTS.PROCESS_QUERY_INFORMATION | Win32.PROCESS_RIGHTS.PROCESS_SET_QUOTA,
+ "reduceworkingset"))
+ return;
+
+ if (prompt && !Prompt(window, pids, names, "reduce the working set of",
+ "Reducing the working set of a process reduces its physical memory consumption. " +
+ "Are you sure you want to continue?", true))
+ return;
+
+ for (int i = 0; i < pids.Length; i++)
+ {
+ try
+ {
+ using (Win32.ProcessHandle phandle = new Win32.ProcessHandle(pids[i],
+ Win32.PROCESS_RIGHTS.PROCESS_QUERY_INFORMATION | Win32.PROCESS_RIGHTS.PROCESS_SET_QUOTA))
+ phandle.EmptyWorkingSet();
+ }
+ catch (Exception ex)
+ {
+ DialogResult r = MessageBox.Show(window, "Could not reduce the working set of process \"" + names[i] +
+ "\" with PID " + pids[i].ToString() + ":\n\n" +
+ ex.Message, "Process Hacker", MessageBoxButtons.OKCancel, MessageBoxIcon.Error);
+
+ if (r == DialogResult.Cancel)
+ return;
+ }
+ }
+ }
+ }
+}
diff --git a/trunk/ProcessHacker/UI/Actions/ServiceActions.cs b/trunk/ProcessHacker/UI/Actions/ServiceActions.cs
new file mode 100644
index 000000000..f15f123e6
--- /dev/null
+++ b/trunk/ProcessHacker/UI/Actions/ServiceActions.cs
@@ -0,0 +1,243 @@
+/*
+ * Process Hacker -
+ * service actions
+ *
+ * Copyright (C) 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.Windows.Forms;
+using ProcessHacker.Components;
+
+namespace ProcessHacker.UI.Actions
+{
+ public static class ServiceActions
+ {
+ private static bool Prompt(IWin32Window window, string service, string action, string content, TaskDialogIcon icon)
+ {
+ DialogResult result = DialogResult.No;
+
+ if (Program.WindowsVersion == WindowsVersion.Vista)
+ {
+ TaskDialog td = new TaskDialog();
+
+ td.WindowTitle = "Process Hacker";
+ td.MainInstruction = "Do you want to " + action + " " + service + "?";
+ td.MainIcon = icon;
+ td.Content = content;
+
+ td.Buttons = new TaskDialogButton[]
+ {
+ new TaskDialogButton((int)DialogResult.Yes, char.ToUpper(action[0]) + action.Substring(1)),
+ new TaskDialogButton((int)DialogResult.No, "Cancel")
+ };
+ td.DefaultButton = (int)DialogResult.No;
+
+ result = (DialogResult)td.Show(window);
+ }
+ else if (Program.WindowsVersion == WindowsVersion.XP)
+ {
+ result = MessageBox.Show("Are you sure you want to " + action + " " + service + "?",
+ "Process Hacker", MessageBoxButtons.YesNo,
+ MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button2);
+ }
+
+ return result == DialogResult.Yes;
+ }
+
+ private static bool ElevateIfRequired(IWin32Window window, string service,
+ Win32.SERVICE_RIGHTS access, string action)
+ {
+ if (Program.WindowsVersion == WindowsVersion.Vista &&
+ Program.ElevationType == Win32.TOKEN_ELEVATION_TYPE.TokenElevationTypeLimited)
+ {
+ try
+ {
+ using (var shandle = new Win32.ServiceHandle(service, access))
+ { }
+ }
+ catch (WindowsException ex)
+ {
+ TaskDialog td = new TaskDialog();
+
+ td.WindowTitle = "Process Hacker";
+ td.MainIcon = TaskDialogIcon.Shield;
+ td.MainInstruction = "Do you want to elevate the action?";
+ td.Content = "The action cannot be performed in the current security context. " +
+ "Do you want Process Hacker to prompt for the appropriate credentials and elevate the action?";
+
+ td.ExpandedInformation = "Error: " + ex.Message + " (0x" + ex.ErrorCode.ToString("x") + ")";
+ td.ExpandFooterArea = true;
+
+ td.Buttons = new TaskDialogButton[]
+ {
+ new TaskDialogButton((int)DialogResult.Yes, "Elevate\nPrompt for credentials and elevate the action."),
+ new TaskDialogButton((int)DialogResult.No, "Continue\nAttempt to perform the action without elevation.")
+ };
+ td.CommonButtons = TaskDialogCommonButtons.Cancel;
+ td.UseCommandLinks = true;
+ td.Callback = (taskDialog, args, userData) =>
+ {
+ if (args.Notification == TaskDialogNotification.Created)
+ {
+ taskDialog.SetButtonElevationRequiredState((int)DialogResult.Yes, true);
+ }
+
+ return false;
+ };
+
+ DialogResult result = (DialogResult)td.Show(window);
+
+ if (result == DialogResult.Yes)
+ {
+ Program.StartProcessHackerAdmin("-e -type service -action " + action + " -obj \"" +
+ service + "\" -hwnd " + window.Handle.ToString(), null, window.Handle);
+
+ return true;
+ }
+ else if (result == DialogResult.No)
+ {
+ return false;
+ }
+ else if (result == DialogResult.Cancel)
+ {
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
+ public static void Start(IWin32Window window, string service, bool prompt)
+ {
+ if (ElevateIfRequired(window, service, Win32.SERVICE_RIGHTS.SERVICE_START, "start"))
+ return;
+
+ if (prompt && !Prompt(window, service, "start",
+ "", TaskDialogIcon.None))
+ return;
+
+ try
+ {
+ using (Win32.ServiceHandle shandle = new Win32.ServiceHandle(service,
+ Win32.SERVICE_RIGHTS.SERVICE_START))
+ shandle.Start();
+ }
+ catch (Exception ex)
+ {
+ DialogResult r = MessageBox.Show(window, "Could not start the service \"" + service +
+ "\":\n\n" +
+ ex.Message, "Process Hacker", MessageBoxButtons.OK, MessageBoxIcon.Error);
+ }
+ }
+
+ public static void Continue(IWin32Window window, string service, bool prompt)
+ {
+ if (ElevateIfRequired(window, service, Win32.SERVICE_RIGHTS.SERVICE_PAUSE_CONTINUE, "continue"))
+ return;
+
+ if (prompt && !Prompt(window, service, "continue",
+ "", TaskDialogIcon.None))
+ return;
+
+ try
+ {
+ using (Win32.ServiceHandle shandle = new Win32.ServiceHandle(service,
+ Win32.SERVICE_RIGHTS.SERVICE_PAUSE_CONTINUE))
+ shandle.Control(Win32.SERVICE_CONTROL.Continue);
+ }
+ catch (Exception ex)
+ {
+ DialogResult r = MessageBox.Show(window, "Could not continue the service \"" + service +
+ "\":\n\n" +
+ ex.Message, "Process Hacker", MessageBoxButtons.OK, MessageBoxIcon.Error);
+ }
+ }
+
+ public static void Pause(IWin32Window window, string service, bool prompt)
+ {
+ if (ElevateIfRequired(window, service, Win32.SERVICE_RIGHTS.SERVICE_PAUSE_CONTINUE, "pause"))
+ return;
+
+ if (prompt && !Prompt(window, service, "pause",
+ "", TaskDialogIcon.None))
+ return;
+
+ try
+ {
+ using (Win32.ServiceHandle shandle = new Win32.ServiceHandle(service,
+ Win32.SERVICE_RIGHTS.SERVICE_PAUSE_CONTINUE))
+ shandle.Control(Win32.SERVICE_CONTROL.Pause);
+ }
+ catch (Exception ex)
+ {
+ DialogResult r = MessageBox.Show(window, "Could not pause the service \"" + service +
+ "\":\n\n" +
+ ex.Message, "Process Hacker", MessageBoxButtons.OK, MessageBoxIcon.Error);
+ }
+ }
+
+ public static void Stop(IWin32Window window, string service, bool prompt)
+ {
+ if (ElevateIfRequired(window, service, Win32.SERVICE_RIGHTS.SERVICE_STOP, "stop"))
+ return;
+
+ if (prompt && !Prompt(window, service, "stop",
+ "", TaskDialogIcon.None))
+ return;
+
+ try
+ {
+ using (Win32.ServiceHandle shandle = new Win32.ServiceHandle(service,
+ Win32.SERVICE_RIGHTS.SERVICE_STOP))
+ shandle.Control(Win32.SERVICE_CONTROL.Stop);
+ }
+ catch (Exception ex)
+ {
+ DialogResult r = MessageBox.Show(window, "Could not stop the service \"" + service +
+ "\":\n\n" +
+ ex.Message, "Process Hacker", MessageBoxButtons.OK, MessageBoxIcon.Error);
+ }
+ }
+
+ public static void Delete(IWin32Window window, string service, bool prompt)
+ {
+ if (ElevateIfRequired(window, service, (Win32.SERVICE_RIGHTS)Win32.STANDARD_RIGHTS.DELETE, "delete"))
+ return;
+
+ if (prompt && !Prompt(window, service, "delete",
+ "Deleting a service can prevent the system from starting or functioning properly. " +
+ "Are you sure you want to continue?", TaskDialogIcon.Warning))
+ return;
+
+ try
+ {
+ using (Win32.ServiceHandle shandle = new Win32.ServiceHandle(service,
+ (Win32.SERVICE_RIGHTS)Win32.STANDARD_RIGHTS.DELETE))
+ shandle.Delete();
+ }
+ catch (Exception ex)
+ {
+ DialogResult r = MessageBox.Show(window, "Could not delete the service \"" + service +
+ "\":\n\n" +
+ ex.Message, "Process Hacker", MessageBoxButtons.OK, MessageBoxIcon.Error);
+ }
+ }
+ }
+}