From 9c0411b4f29bc691572a50de126edd2f0acaf9a4 Mon Sep 17 00:00:00 2001 From: Bill Hoffman Date: Mon, 10 May 2004 12:06:24 -0400 Subject: [PATCH] ENH: change to c code so it can be built with mingw --- Source/kwsys/CMakeLists.txt | 2 +- Source/kwsys/ProcessWin32Kill.c | 454 ++++++++++++++++++++++++++++++ Source/kwsys/ProcessWin32Kill.cxx | 446 ----------------------------- 3 files changed, 455 insertions(+), 447 deletions(-) create mode 100644 Source/kwsys/ProcessWin32Kill.c delete mode 100644 Source/kwsys/ProcessWin32Kill.cxx diff --git a/Source/kwsys/CMakeLists.txt b/Source/kwsys/CMakeLists.txt index c5abeac3d..e253027f9 100644 --- a/Source/kwsys/CMakeLists.txt +++ b/Source/kwsys/CMakeLists.txt @@ -275,7 +275,7 @@ IF(KWSYS_USE_Process) ${PROJECT_BINARY_DIR}/${KWSYS_NAMESPACE}ProcessFwd9xEnc.c PROPERTIES GENERATED 1) SET(KWSYS_H_FILES ${KWSYS_H_FILES} ProcessWin32Kill) - SET(KWSYS_SRCS ${KWSYS_SRCS} ProcessWin32Kill.cxx) + SET(KWSYS_SRCS ${KWSYS_SRCS} ProcessWin32Kill.c) ELSE(NOT UNIX) # Use the UNIX implementation. SET(KWSYS_SRCS ${KWSYS_SRCS} ProcessUNIX.c) diff --git a/Source/kwsys/ProcessWin32Kill.c b/Source/kwsys/ProcessWin32Kill.c new file mode 100644 index 000000000..5ab867ab3 --- /dev/null +++ b/Source/kwsys/ProcessWin32Kill.c @@ -0,0 +1,454 @@ +/*========================================================================= + + Program: KWSys - Kitware System Library + Module: $RCSfile$ + + Copyright (c) Kitware, Inc., Insight Consortium. All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ +#define KWSYS_IN_PROCESS_C +#include "kwsysPrivate.h" +#include KWSYS_HEADER(ProcessWin32Kill.h) + +/* The following process tree kill implementation is taken from + http://www.alexfedotov.com/articles/killproc.asp + It will work only on some versions of windows. Hopefully + I will eventually get some time to do a real implementation of this + for all windows versions. */ + +#include +#include +#include +#include +#include +#include + +//--------------------------------------------------------------------------- +// KillProcess +// +// Terminates the specified process. +// +// Parameters: +// dwProcessId - identifier of the process to terminate +// +// Returns: +// TRUE, if successful, FALSE - otherwise. +// +static BOOL +WINAPI +KillProcess( + IN DWORD dwProcessId + ) +{ + HANDLE hProcess; + DWORD dwError; + + // first try to obtain handle to the process without the use of any + // additional privileges + hProcess = OpenProcess(PROCESS_TERMINATE, FALSE, dwProcessId); + if (hProcess == NULL) + { + OSVERSIONINFO osvi; + TOKEN_PRIVILEGES Priv, PrivOld; + DWORD cbPriv; + HANDLE hToken; + + if (GetLastError() != ERROR_ACCESS_DENIED) + return FALSE; + + // determine operating system version + osvi.dwOSVersionInfoSize = sizeof(osvi); + GetVersionEx(&osvi); + + // we cannot do anything else if this is not Windows NT + if (osvi.dwPlatformId != VER_PLATFORM_WIN32_NT) + return SetLastError(ERROR_ACCESS_DENIED), FALSE; + + // enable SE_DEBUG_NAME privilege and try again + + cbPriv = sizeof(PrivOld); + + // obtain the token of the current thread + if (!OpenThreadToken(GetCurrentThread(), + TOKEN_QUERY|TOKEN_ADJUST_PRIVILEGES, + FALSE, &hToken)) + { + if (GetLastError() != ERROR_NO_TOKEN) + return FALSE; + + // revert to the process token + if (!OpenProcessToken(GetCurrentProcess(), + TOKEN_QUERY|TOKEN_ADJUST_PRIVILEGES, + &hToken)) + return FALSE; + } + + if(!(ANYSIZE_ARRAY > 0)) + { + return 0; + } + + Priv.PrivilegeCount = 1; + Priv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; + LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &Priv.Privileges[0].Luid); + + // try to enable the privilege + if (!AdjustTokenPrivileges(hToken, FALSE, &Priv, sizeof(Priv), + &PrivOld, &cbPriv)) + { + dwError = GetLastError(); + CloseHandle(hToken); + return SetLastError(dwError), FALSE; + } + + if (GetLastError() == ERROR_NOT_ALL_ASSIGNED) + { + // the SE_DEBUG_NAME privilege is not present in the caller's + // token + CloseHandle(hToken); + return SetLastError(ERROR_ACCESS_DENIED), FALSE; + } + + // try to open process handle again + hProcess = OpenProcess(PROCESS_TERMINATE, FALSE, dwProcessId); + dwError = GetLastError(); + + // restore the original state of the privilege + AdjustTokenPrivileges(hToken, FALSE, &PrivOld, sizeof(PrivOld), + NULL, NULL); + CloseHandle(hToken); + + if (hProcess == NULL) + { + return SetLastError(FALSE), 0; + } + + } + + // terminate the process + if (!TerminateProcess(hProcess, (UINT)-1)) + { + dwError = GetLastError(); + CloseHandle(hProcess); + return SetLastError(dwError), FALSE; + } + + CloseHandle(hProcess); + + // completed successfully + return TRUE; +} + +typedef LONG NTSTATUS; +typedef LONG KPRIORITY; + +#define NT_SUCCESS(Status) ((NTSTATUS)(Status) >= 0) + +#define STATUS_INFO_LENGTH_MISMATCH ((NTSTATUS)0xC0000004L) + +#define SystemProcessesAndThreadsInformation 5 + +typedef struct _CLIENT_ID { + DWORD UniqueProcess; + DWORD UniqueThread; +} CLIENT_ID; + +typedef struct _UNICODE_STRING { + USHORT Length; + USHORT MaximumLength; + PWSTR Buffer; +} UNICODE_STRING; + +typedef struct _VM_COUNTERS { + SIZE_T PeakVirtualSize; + SIZE_T VirtualSize; + ULONG PageFaultCount; + SIZE_T PeakWorkingSetSize; + SIZE_T WorkingSetSize; + SIZE_T QuotaPeakPagedPoolUsage; + SIZE_T QuotaPagedPoolUsage; + SIZE_T QuotaPeakNonPagedPoolUsage; + SIZE_T QuotaNonPagedPoolUsage; + SIZE_T PagefileUsage; + SIZE_T PeakPagefileUsage; +} VM_COUNTERS; + +typedef struct _SYSTEM_THREADS { + LARGE_INTEGER KernelTime; + LARGE_INTEGER UserTime; + LARGE_INTEGER CreateTime; + ULONG WaitTime; + PVOID StartAddress; + CLIENT_ID ClientId; + KPRIORITY Priority; + KPRIORITY BasePriority; + ULONG ContextSwitchCount; + LONG State; + LONG WaitReason; +} SYSTEM_THREADS, * PSYSTEM_THREADS; + +// Note that the size of the SYSTEM_PROCESSES structure is different on +// NT 4 and Win2K, but we don't care about it, since we don't access neither +// IoCounters member nor Threads array + +typedef struct _SYSTEM_PROCESSES { + ULONG NextEntryDelta; + ULONG ThreadCount; + ULONG Reserved1[6]; + LARGE_INTEGER CreateTime; + LARGE_INTEGER UserTime; + LARGE_INTEGER KernelTime; + UNICODE_STRING ProcessName; + KPRIORITY BasePriority; + ULONG ProcessId; + ULONG InheritedFromProcessId; + ULONG HandleCount; + ULONG Reserved2[2]; + VM_COUNTERS VmCounters; +#if _WIN32_WINNT >= 0x500 + IO_COUNTERS IoCounters; +#endif + SYSTEM_THREADS Threads[1]; +} SYSTEM_PROCESSES, * PSYSTEM_PROCESSES; + +//--------------------------------------------------------------------------- +// KillProcessTreeNtHelper +// +// This is a recursive helper function that terminates all the processes +// started by the specified process and them terminates the process itself +// +// Parameters: +// pInfo - processes information +// dwProcessId - identifier of the process to terminate +// +// Returns: +// Win32 error code. +// +static +BOOL +WINAPI +KillProcessTreeNtHelper( + IN PSYSTEM_PROCESSES pInfo, + IN DWORD dwProcessId + ) +{ + PSYSTEM_PROCESSES p; + if(!pInfo) + { + return 0; + } + + p = pInfo; + + // kill all children first + for (;;) + { + if (p->InheritedFromProcessId == dwProcessId) + KillProcessTreeNtHelper(pInfo, p->ProcessId); + + if (p->NextEntryDelta == 0) + break; + + // find the address of the next process structure + p = (PSYSTEM_PROCESSES)(((LPBYTE)p) + p->NextEntryDelta); + } + + // kill the process itself + if (!KillProcess(dwProcessId)) + return GetLastError(); + + return 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 hSnapshot; + PROCESSENTRY32 Entry; + + 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")); + if(!hKernel) + { + return 0; + } + + // 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; + + + // 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. +// +static BOOL +WINAPI +KillProcessEx( + IN DWORD dwProcessId, + IN BOOL bTree + ) +{ + OSVERSIONINFO osvi; + DWORD dwError; + HANDLE hHeap; + NTSTATUS Status; + ULONG cbBuffer; + PVOID pBuffer = NULL; + + if (!bTree) + return KillProcess(dwProcessId); + + + // 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")); + if(!hNtDll) + { + return 0; + } + + // find the address of ZwQuerySystemInformation + *(FARPROC *)&_ZwQuerySystemInformation = + GetProcAddress(hNtDll, "ZwQuerySystemInformation"); + if (_ZwQuerySystemInformation == NULL) + return SetLastError(ERROR_PROC_NOT_FOUND), 0; + + // obtain a handle to the default process heap + hHeap = GetProcessHeap(); + + cbBuffer = 0x8000; + + // 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), 0; + } + } + 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; +} + +int kwsysProcessWin32Kill(int pid) +{ + return KillProcessEx(pid, 1)? 1:0; +} diff --git a/Source/kwsys/ProcessWin32Kill.cxx b/Source/kwsys/ProcessWin32Kill.cxx deleted file mode 100644 index 3afe14a6c..000000000 --- a/Source/kwsys/ProcessWin32Kill.cxx +++ /dev/null @@ -1,446 +0,0 @@ -/*========================================================================= - - Program: KWSys - Kitware System Library - Module: $RCSfile$ - - Copyright (c) Kitware, Inc., Insight Consortium. All rights reserved. - See Copyright.txt or http://www.kitware.com/Copyright.htm for details. - - This software is distributed WITHOUT ANY WARRANTY; without even - the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR - PURPOSE. See the above copyright notices for more information. - -=========================================================================*/ -#define KWSYS_IN_PROCESS_C -#include "kwsysPrivate.h" -#include KWSYS_HEADER(ProcessWin32Kill.h) - -/* The following process tree kill implementation is taken from - http://www.alexfedotov.com/articles/killproc.asp - It will work only on some versions of windows. Hopefully - I will eventually get some time to do a real implementation of this - for all windows versions. */ - -#include -#include -#include -#include -#include - -//--------------------------------------------------------------------------- -// KillProcess -// -// Terminates the specified process. -// -// Parameters: -// dwProcessId - identifier of the process to terminate -// -// Returns: -// TRUE, if successful, FALSE - otherwise. -// -static BOOL -WINAPI -KillProcess( - IN DWORD dwProcessId - ) -{ - HANDLE hProcess; - DWORD dwError; - - // first try to obtain handle to the process without the use of any - // additional privileges - hProcess = OpenProcess(PROCESS_TERMINATE, FALSE, dwProcessId); - if (hProcess == NULL) - { - if (GetLastError() != ERROR_ACCESS_DENIED) - return FALSE; - - OSVERSIONINFO osvi; - - // determine operating system version - osvi.dwOSVersionInfoSize = sizeof(osvi); - GetVersionEx(&osvi); - - // we cannot do anything else if this is not Windows NT - if (osvi.dwPlatformId != VER_PLATFORM_WIN32_NT) - return SetLastError(ERROR_ACCESS_DENIED), FALSE; - - // enable SE_DEBUG_NAME privilege and try again - - TOKEN_PRIVILEGES Priv, PrivOld; - DWORD cbPriv = sizeof(PrivOld); - HANDLE hToken; - - // obtain the token of the current thread - if (!OpenThreadToken(GetCurrentThread(), - TOKEN_QUERY|TOKEN_ADJUST_PRIVILEGES, - FALSE, &hToken)) - { - if (GetLastError() != ERROR_NO_TOKEN) - return FALSE; - - // revert to the process token - if (!OpenProcessToken(GetCurrentProcess(), - TOKEN_QUERY|TOKEN_ADJUST_PRIVILEGES, - &hToken)) - return FALSE; - } - - if(!(ANYSIZE_ARRAY > 0)) - { - return 0; - } - - Priv.PrivilegeCount = 1; - Priv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; - LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &Priv.Privileges[0].Luid); - - // try to enable the privilege - if (!AdjustTokenPrivileges(hToken, FALSE, &Priv, sizeof(Priv), - &PrivOld, &cbPriv)) - { - dwError = GetLastError(); - CloseHandle(hToken); - return SetLastError(dwError), FALSE; - } - - if (GetLastError() == ERROR_NOT_ALL_ASSIGNED) - { - // the SE_DEBUG_NAME privilege is not present in the caller's - // token - CloseHandle(hToken); - return SetLastError(ERROR_ACCESS_DENIED), FALSE; - } - - // try to open process handle again - hProcess = OpenProcess(PROCESS_TERMINATE, FALSE, dwProcessId); - dwError = GetLastError(); - - // restore the original state of the privilege - AdjustTokenPrivileges(hToken, FALSE, &PrivOld, sizeof(PrivOld), - NULL, NULL); - CloseHandle(hToken); - - if (hProcess == NULL) - return SetLastError(FALSE), NULL; - } - - // terminate the process - if (!TerminateProcess(hProcess, (UINT)-1)) - { - dwError = GetLastError(); - CloseHandle(hProcess); - return SetLastError(dwError), FALSE; - } - - CloseHandle(hProcess); - - // completed successfully - return TRUE; -} - -typedef LONG NTSTATUS; -typedef LONG KPRIORITY; - -#define NT_SUCCESS(Status) ((NTSTATUS)(Status) >= 0) - -#define STATUS_INFO_LENGTH_MISMATCH ((NTSTATUS)0xC0000004L) - -#define SystemProcessesAndThreadsInformation 5 - -typedef struct _CLIENT_ID { - DWORD UniqueProcess; - DWORD UniqueThread; -} CLIENT_ID; - -typedef struct _UNICODE_STRING { - USHORT Length; - USHORT MaximumLength; - PWSTR Buffer; -} UNICODE_STRING; - -typedef struct _VM_COUNTERS { - SIZE_T PeakVirtualSize; - SIZE_T VirtualSize; - ULONG PageFaultCount; - SIZE_T PeakWorkingSetSize; - SIZE_T WorkingSetSize; - SIZE_T QuotaPeakPagedPoolUsage; - SIZE_T QuotaPagedPoolUsage; - SIZE_T QuotaPeakNonPagedPoolUsage; - SIZE_T QuotaNonPagedPoolUsage; - SIZE_T PagefileUsage; - SIZE_T PeakPagefileUsage; -} VM_COUNTERS; - -typedef struct _SYSTEM_THREADS { - LARGE_INTEGER KernelTime; - LARGE_INTEGER UserTime; - LARGE_INTEGER CreateTime; - ULONG WaitTime; - PVOID StartAddress; - CLIENT_ID ClientId; - KPRIORITY Priority; - KPRIORITY BasePriority; - ULONG ContextSwitchCount; - LONG State; - LONG WaitReason; -} SYSTEM_THREADS, * PSYSTEM_THREADS; - -// Note that the size of the SYSTEM_PROCESSES structure is different on -// NT 4 and Win2K, but we don't care about it, since we don't access neither -// IoCounters member nor Threads array - -typedef struct _SYSTEM_PROCESSES { - ULONG NextEntryDelta; - ULONG ThreadCount; - ULONG Reserved1[6]; - LARGE_INTEGER CreateTime; - LARGE_INTEGER UserTime; - LARGE_INTEGER KernelTime; - UNICODE_STRING ProcessName; - KPRIORITY BasePriority; - ULONG ProcessId; - ULONG InheritedFromProcessId; - ULONG HandleCount; - ULONG Reserved2[2]; - VM_COUNTERS VmCounters; -#if _WIN32_WINNT >= 0x500 - IO_COUNTERS IoCounters; -#endif - SYSTEM_THREADS Threads[1]; -} SYSTEM_PROCESSES, * PSYSTEM_PROCESSES; - -//--------------------------------------------------------------------------- -// KillProcessTreeNtHelper -// -// This is a recursive helper function that terminates all the processes -// started by the specified process and them terminates the process itself -// -// Parameters: -// pInfo - processes information -// dwProcessId - identifier of the process to terminate -// -// Returns: -// Win32 error code. -// -static -BOOL -WINAPI -KillProcessTreeNtHelper( - IN PSYSTEM_PROCESSES pInfo, - IN DWORD dwProcessId - ) -{ - if(!pInfo) - { - return 0; - } - - PSYSTEM_PROCESSES p = pInfo; - - // kill all children first - for (;;) - { - if (p->InheritedFromProcessId == dwProcessId) - KillProcessTreeNtHelper(pInfo, p->ProcessId); - - if (p->NextEntryDelta == 0) - break; - - // find the address of the next process structure - p = (PSYSTEM_PROCESSES)(((LPBYTE)p) + p->NextEntryDelta); - } - - // kill the process itself - if (!KillProcess(dwProcessId)) - return GetLastError(); - - return 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")); - if(!hKernel) - { - return 0; - } - - // 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. -// -static 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")); - if(!hNtDll) - { - return 0; - } - - // 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; -} - -extern "C" { -int kwsysProcessWin32Kill(int pid) -{ - return KillProcessEx(pid, 1)? 1:0; -} -}