//--------------------------------------------------------------------------- // KillProcessTreeWinHelper // // This is a recursive helper function that terminates all the processes // started by the specified process and them terminates the process itself // // Parameters: // dwProcessId - identifier of the process to terminate // // Returns: // Win32 error code. // BOOL WINAPI KillProcessTreeWinHelper(DWORD dwProcessId) { // create a snapshot auto_handle hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); if (!hSnapshot) return GetLastError(); auto_localmem<PROCESSENTRY32*> pEntry = ::LocalAlloc(LMEM_FIXED|LMEM_ZEROINIT,sizeof(PROCESSENTRY32)); pEntry->dwSize = sizeof(PROCESSENTRY32); if (!Process32First(hSnapshot, pEntry)) { return GetLastError(); } // kill all children first do { // there was a report of infinite recursion, so watching out for the obvious self-loop possibility DWORD pid = pEntry->th32ProcessID; if (pEntry->th32ParentProcessID == dwProcessId && dwProcessId!=pid) KillProcessTreeWinHelper(pid); } while (Process32Next(hSnapshot, pEntry)); // kill the process itself if (!KillProcess(dwProcessId)) return GetLastError(); return ERROR_SUCCESS; }
//--------------------------------------------------------------------------- // KillProcessEx // // Terminates the specified process and, optionally, all processes started // from the specified process (the so-called process tree). // // Parameters: // dwProcessId - identifier of the process to terminate // bTree - specifies whether the entire process tree should be // terminated // // Returns: // TRUE, if successful, FALSE - otherwise. // BOOL WINAPI KillProcessEx ( IN DWORD dwProcessId, IN BOOL bTree ) { if (!bTree) return KillProcess(dwProcessId); OSVERSIONINFO osvi; DWORD dwError; // determine operating system version osvi.dwOSVersionInfoSize = sizeof(osvi); GetVersionEx(&osvi); if (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT && osvi.dwMajorVersion < 5) { HINSTANCE hNtDll; NTSTATUS (WINAPI * _ZwQuerySystemInformation)(UINT, PVOID, ULONG, PULONG); // get handle to NTDLL.DLL hNtDll = GetModuleHandle(_T("ntdll.dll")); // _ASSERTE(hNtDll != NULL); // find the address of ZwQuerySystemInformation *(FARPROC *)&_ZwQuerySystemInformation = GetProcAddress(hNtDll, "ZwQuerySystemInformation"); if (_ZwQuerySystemInformation == NULL) return SetLastError(ERROR_PROC_NOT_FOUND), NULL; // obtain a handle to the default process heap HANDLE hHeap = GetProcessHeap(); NTSTATUS Status; ULONG cbBuffer = 0x8000; PVOID pBuffer = NULL; // it is difficult to say a priory which size of the buffer // will be enough to retrieve all information, so we start // with 32K buffer and increase its size until we get the // information successfully do { pBuffer = HeapAlloc(hHeap, 0, cbBuffer); if (pBuffer == NULL) return SetLastError(ERROR_NOT_ENOUGH_MEMORY), FALSE; Status = _ZwQuerySystemInformation( SystemProcessesAndThreadsInformation, pBuffer, cbBuffer, NULL); if (Status == STATUS_INFO_LENGTH_MISMATCH) { HeapFree(hHeap, 0, pBuffer); cbBuffer *= 2; } else if (!NT_SUCCESS(Status)) { HeapFree(hHeap, 0, pBuffer); return SetLastError(Status), NULL; } } while (Status == STATUS_INFO_LENGTH_MISMATCH); // call the helper function dwError = KillProcessTreeNtHelper((PSYSTEM_PROCESSES)pBuffer, dwProcessId); HeapFree(hHeap, 0, pBuffer); } else { // call the helper function dwError = KillProcessTreeWinHelper(dwProcessId); } SetLastError(dwError); return dwError == ERROR_SUCCESS; }
//--------------------------------------------------------------------------- // KillProcessTreeWinHelper // // This is a recursive helper function that terminates all the processes // started by the specified process and them terminates the process itself // // Parameters: // dwProcessId - identifier of the process to terminate // // Returns: // Win32 error code. // static BOOL WINAPI KillProcessTreeWinHelper ( IN DWORD dwProcessId ) { HINSTANCE hKernel; HANDLE (WINAPI * _CreateToolhelp32Snapshot)(DWORD, DWORD); BOOL (WINAPI * _Process32First)(HANDLE, PROCESSENTRY32 *); BOOL (WINAPI * _Process32Next)(HANDLE, PROCESSENTRY32 *); // get handle to KERNEL32.DLL hKernel = GetModuleHandle(_T("kernel32.dll")); // _ASSERTE(hKernel != NULL); // locate necessary functions in KERNEL32.DLL *(FARPROC *)&_CreateToolhelp32Snapshot = GetProcAddress(hKernel, "CreateToolhelp32Snapshot"); *(FARPROC *)&_Process32First = GetProcAddress(hKernel, "Process32First"); *(FARPROC *)&_Process32Next = GetProcAddress(hKernel, "Process32Next"); if (_CreateToolhelp32Snapshot == NULL || _Process32First == NULL || _Process32Next == NULL) return ERROR_PROC_NOT_FOUND; HANDLE hSnapshot; PROCESSENTRY32 Entry; // create a snapshot hSnapshot = _CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); if (hSnapshot == INVALID_HANDLE_VALUE) return GetLastError(); Entry.dwSize = sizeof(Entry); if (!_Process32First(hSnapshot, &Entry)) { DWORD dwError = GetLastError(); CloseHandle(hSnapshot); return dwError; } // kill all children first do { if (Entry.th32ParentProcessID == dwProcessId) KillProcessTreeWinHelper(Entry.th32ProcessID); Entry.dwSize = sizeof(Entry); } while (_Process32Next(hSnapshot, &Entry)); CloseHandle(hSnapshot); // kill the process itself if (!KillProcess(dwProcessId)) return GetLastError(); return ERROR_SUCCESS; }
//--------------------------------------------------------------------------- // KillProcessEx // // Terminates the specified process and, optionally, all processes started // from the specified process (the so-called process tree). // // Parameters: // dwProcessId - identifier of the process to terminate // bTree - specifies whether the entire process tree should be // terminated // // Returns: // TRUE, if successful, FALSE - otherwise. // BOOL WINAPI KillProcessEx(DWORD dwProcessId, BOOL bTree) { if (!bTree) { return KillProcess(dwProcessId); } OSVERSIONINFO osvi; DWORD dwError; // determine operating system version osvi.dwOSVersionInfoSize = sizeof(osvi); GetVersionEx(&osvi); if (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT && osvi.dwMajorVersion < 5) { // obtain a handle to the default process heap HANDLE hHeap = GetProcessHeap(); NTSTATUS Status; ULONG cbBuffer = 0x8000; PVOID pBuffer = NULL; // it is difficult to say a priory which size of the buffer // will be enough to retrieve all information, so we start // with 32K buffer and increase its size until we get the // information successfully do { pBuffer = HeapAlloc(hHeap, 0, cbBuffer); if (pBuffer == NULL) { return SetLastError(ERROR_NOT_ENOUGH_MEMORY), FALSE; } Status = ZwQuerySystemInformation( SystemProcessesAndThreadsInformation, pBuffer, cbBuffer, NULL); if (Status == STATUS_INFO_LENGTH_MISMATCH) { HeapFree(hHeap, 0, pBuffer); cbBuffer *= 2; } else if (!NT_SUCCESS(Status)) { HeapFree(hHeap, 0, pBuffer); return SetLastError(Status), NULL; } } while (Status == STATUS_INFO_LENGTH_MISMATCH); // call the helper function dwError = KillProcessTreeNtHelper((PSYSTEM_PROCESSES)pBuffer, dwProcessId); HeapFree(hHeap, 0, pBuffer); } else { // call the helper function dwError = KillProcessTreeWinHelper(dwProcessId); } SetLastError(dwError); return dwError == ERROR_SUCCESS; }