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 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 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 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 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 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