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