summaryrefslogtreecommitdiffstats
path: root/Source/kwsys
diff options
context:
space:
mode:
Diffstat (limited to 'Source/kwsys')
-rw-r--r--Source/kwsys/CMakeLists.txt2
-rw-r--r--Source/kwsys/ProcessWin32Kill.c454
-rw-r--r--Source/kwsys/ProcessWin32Kill.cxx446
3 files changed, 455 insertions, 447 deletions
diff --git a/Source/kwsys/CMakeLists.txt b/Source/kwsys/CMakeLists.txt
index c5abeac..e253027 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 0000000..5ab867a
--- /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 <windows.h>
+#include <tchar.h>
+#include <crtdbg.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <tlhelp32.h>
+
+//---------------------------------------------------------------------------
+// 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 3afe14a..0000000
--- 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 <windows.h>
-#include <tchar.h>
-#include <stdio.h>
-#include <stdarg.h>
-#include <tlhelp32.h>
-
-//---------------------------------------------------------------------------
-// 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;
-}
-}