1 /*
2 * PROJECT: ReactOS Task Manager
3 * LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later)
4 * PURPOSE: Process Termination.
5 * COPYRIGHT: Copyright 1999-2001 Brian Palmer <brianp@reactos.org>
6 * Copyright 2005 Klemens Friedl <frik85@reactos.at>
7 * Copyright 2014 Ismael Ferreras Morezuelas <swyterzone+ros@gmail.com>
8 */
9
10 #include "precomp.h"
11
12 #define NTOS_MODE_USER
13 #include <ndk/psfuncs.h>
14
ProcessPage_OnEndProcess(void)15 void ProcessPage_OnEndProcess(void)
16 {
17 DWORD dwProcessId;
18 HANDLE hProcess;
19 WCHAR szTitle[256];
20 WCHAR strErrorText[260];
21
22 dwProcessId = GetSelectedProcessId();
23
24 if (dwProcessId == 0)
25 return;
26
27 hProcess = OpenProcess(PROCESS_TERMINATE | PROCESS_QUERY_INFORMATION, FALSE, dwProcessId);
28
29 /* forbid killing system processes even if we have privileges -- sigh, windows kludge! */
30 if (hProcess && IsCriticalProcess(hProcess))
31 {
32 LoadStringW(hInst, IDS_MSG_UNABLETERMINATEPRO, szTitle, 256);
33 LoadStringW(hInst, IDS_MSG_CLOSESYSTEMPROCESS, strErrorText, 256);
34 MessageBoxW(hMainWnd, strErrorText, szTitle, MB_OK|MB_ICONWARNING|MB_TOPMOST);
35 CloseHandle(hProcess);
36 return;
37 }
38
39 /* if this is a standard process just ask for confirmation before doing it */
40 LoadStringW(hInst, IDS_MSG_WARNINGTERMINATING, strErrorText, 256);
41 LoadStringW(hInst, IDS_MSG_TASKMGRWARNING, szTitle, 256);
42 if (!ConfirmMessageBox(hMainWnd, strErrorText, szTitle, MB_YESNO|MB_ICONWARNING|MB_TOPMOST))
43 {
44 if (hProcess) CloseHandle(hProcess);
45 return;
46 }
47
48 /* no such process or not enough privileges to open its token */
49 if (!hProcess)
50 {
51 GetLastErrorText(strErrorText, 260);
52 LoadStringW(hInst, IDS_MSG_UNABLETERMINATEPRO, szTitle, 256);
53 MessageBoxW(hMainWnd, strErrorText, szTitle, MB_OK|MB_ICONSTOP|MB_TOPMOST);
54 return;
55 }
56
57 /* try to kill it, and notify the user if didn't work */
58 if (!TerminateProcess(hProcess, 1))
59 {
60 GetLastErrorText(strErrorText, 260);
61 LoadStringW(hInst, IDS_MSG_UNABLETERMINATEPRO, szTitle, 256);
62 MessageBoxW(hMainWnd, strErrorText, szTitle, MB_OK|MB_ICONSTOP|MB_TOPMOST);
63 }
64
65 CloseHandle(hProcess);
66 }
67
IsCriticalProcess(HANDLE hProcess)68 BOOL IsCriticalProcess(HANDLE hProcess)
69 {
70 NTSTATUS status;
71 ULONG BreakOnTermination;
72
73 /* return early if the process handle does not exist */
74 if (!hProcess)
75 return FALSE;
76
77 /* the important system processes that we don't want to let the user
78 kill come marked as critical, this simplifies the check greatly.
79
80 a critical process brings the system down when is terminated:
81 <http://www.geoffchappell.com/studies/windows/win32/ntdll/api/rtl/peb/setprocessiscritical.htm> */
82
83 status = NtQueryInformationProcess(hProcess,
84 ProcessBreakOnTermination,
85 &BreakOnTermination,
86 sizeof(ULONG),
87 NULL);
88
89 if (NT_SUCCESS(status) && BreakOnTermination)
90 return TRUE;
91
92 return FALSE;
93 }
94
ShutdownProcessTreeHelper(HANDLE hSnapshot,HANDLE hParentProcess,DWORD dwParentPID)95 BOOL ShutdownProcessTreeHelper(HANDLE hSnapshot, HANDLE hParentProcess, DWORD dwParentPID)
96 {
97 HANDLE hChildHandle;
98 PROCESSENTRY32W ProcessEntry = {0};
99 ProcessEntry.dwSize = sizeof(ProcessEntry);
100
101 if (Process32FirstW(hSnapshot, &ProcessEntry))
102 {
103 do
104 {
105 if (ProcessEntry.th32ParentProcessID == dwParentPID)
106 {
107 hChildHandle = OpenProcess(PROCESS_TERMINATE | PROCESS_QUERY_INFORMATION,
108 FALSE,
109 ProcessEntry.th32ProcessID);
110 if (!hChildHandle || IsCriticalProcess(hChildHandle))
111 {
112 if (hChildHandle)
113 {
114 CloseHandle(hChildHandle);
115 }
116 continue;
117 }
118 if (!ShutdownProcessTreeHelper(hSnapshot, hChildHandle, ProcessEntry.th32ProcessID))
119 {
120 CloseHandle(hChildHandle);
121 return FALSE;
122 }
123 CloseHandle(hChildHandle);
124 }
125 } while (Process32NextW(hSnapshot, &ProcessEntry));
126 }
127
128 return TerminateProcess(hParentProcess, 0);
129 }
130
ShutdownProcessTree(HANDLE hParentProcess,DWORD dwParentPID)131 BOOL ShutdownProcessTree(HANDLE hParentProcess, DWORD dwParentPID)
132 {
133 HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
134 BOOL bResult;
135
136 if (!hSnapshot)
137 {
138 return FALSE;
139 }
140
141 bResult = ShutdownProcessTreeHelper(hSnapshot, hParentProcess, dwParentPID);
142 CloseHandle(hSnapshot);
143 return bResult;
144 }
145
ProcessPage_OnEndProcessTree(void)146 void ProcessPage_OnEndProcessTree(void)
147 {
148 DWORD dwProcessId;
149 HANDLE hProcess;
150 WCHAR szTitle[256];
151 WCHAR strErrorText[260];
152
153 dwProcessId = GetSelectedProcessId();
154
155 if (dwProcessId == 0)
156 return;
157
158 hProcess = OpenProcess(PROCESS_TERMINATE | PROCESS_QUERY_INFORMATION, FALSE, dwProcessId);
159
160 /* forbid killing system processes even if we have privileges -- sigh, windows kludge! */
161 if (hProcess && IsCriticalProcess(hProcess))
162 {
163 LoadStringW(hInst, IDS_MSG_UNABLETERMINATEPRO, szTitle, 256);
164 LoadStringW(hInst, IDS_MSG_CLOSESYSTEMPROCESS, strErrorText, 256);
165 MessageBoxW(hMainWnd, strErrorText, szTitle, MB_OK|MB_ICONWARNING|MB_TOPMOST);
166 CloseHandle(hProcess);
167 return;
168 }
169
170 LoadStringW(hInst, IDS_MSG_WARNINGTERMINATING, strErrorText, 256);
171 LoadStringW(hInst, IDS_MSG_TASKMGRWARNING, szTitle, 256);
172 if (!ConfirmMessageBox(hMainWnd, strErrorText, szTitle, MB_YESNO|MB_ICONWARNING))
173 {
174 if (hProcess) CloseHandle(hProcess);
175 return;
176 }
177
178 if (!hProcess)
179 {
180 GetLastErrorText(strErrorText, 260);
181 LoadStringW(hInst, IDS_MSG_UNABLETERMINATEPRO, szTitle, 256);
182 MessageBoxW(hMainWnd, strErrorText, szTitle, MB_OK|MB_ICONSTOP);
183 return;
184 }
185
186 if (!ShutdownProcessTree(hProcess, dwProcessId))
187 {
188 GetLastErrorText(strErrorText, 260);
189 LoadStringW(hInst, IDS_MSG_UNABLETERMINATEPRO, szTitle, 256);
190 MessageBoxW(hMainWnd, strErrorText, szTitle, MB_OK|MB_ICONSTOP);
191 }
192
193 CloseHandle(hProcess);
194 }
195