diff options
author | Brad King <brad.king@kitware.com> | 2004-05-10 18:54:22 (GMT) |
---|---|---|
committer | Brad King <brad.king@kitware.com> | 2004-05-10 18:54:22 (GMT) |
commit | 6c4ab7ec52025971d8a038eb8485d6722cbe7011 (patch) | |
tree | 813215de7559ec4f99700a88e9889815cfbfa682 /Source/kwsys | |
parent | dd70c8f82d5101fa4ec49c379fdbbdda14fe9a3b (diff) | |
download | CMake-6c4ab7ec52025971d8a038eb8485d6722cbe7011.zip CMake-6c4ab7ec52025971d8a038eb8485d6722cbe7011.tar.gz CMake-6c4ab7ec52025971d8a038eb8485d6722cbe7011.tar.bz2 |
ENH: Adding native windows process tree kill to ProcessWin32.c. This replaces the ProcessWin32Kill.c implementation.
Diffstat (limited to 'Source/kwsys')
-rw-r--r-- | Source/kwsys/CMakeLists.txt | 2 | ||||
-rw-r--r-- | Source/kwsys/ProcessWin32.c | 408 | ||||
-rw-r--r-- | Source/kwsys/ProcessWin32Kill.c | 453 | ||||
-rw-r--r-- | Source/kwsys/ProcessWin32Kill.h.in | 46 |
4 files changed, 403 insertions, 506 deletions
diff --git a/Source/kwsys/CMakeLists.txt b/Source/kwsys/CMakeLists.txt index e253027..16c73d5 100644 --- a/Source/kwsys/CMakeLists.txt +++ b/Source/kwsys/CMakeLists.txt @@ -274,8 +274,6 @@ IF(KWSYS_USE_Process) SET_SOURCE_FILES_PROPERTIES( ${PROJECT_BINARY_DIR}/${KWSYS_NAMESPACE}ProcessFwd9xEnc.c PROPERTIES GENERATED 1) - SET(KWSYS_H_FILES ${KWSYS_H_FILES} ProcessWin32Kill) - 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/ProcessWin32.c b/Source/kwsys/ProcessWin32.c index cdb4e96..a184367 100644 --- a/Source/kwsys/ProcessWin32.c +++ b/Source/kwsys/ProcessWin32.c @@ -14,7 +14,6 @@ #define KWSYS_IN_PROCESS_C #include "kwsysPrivate.h" #include KWSYS_HEADER(Process.h) -#include KWSYS_HEADER(ProcessWin32Kill.h) /* @@ -102,6 +101,7 @@ static int kwsysProcessTimeLess(kwsysProcessTime in1, kwsysProcessTime in2); static kwsysProcessTime kwsysProcessTimeAdd(kwsysProcessTime in1, kwsysProcessTime in2); static kwsysProcessTime kwsysProcessTimeSubtract(kwsysProcessTime in1, kwsysProcessTime in2); static void kwsysProcessSetExitException(kwsysProcess* cp, int code); +static void kwsysProcessKillTree(int pid); extern kwsysEXPORT int kwsysEncodedWriteArrayProcessFwd9x(const char* fname); /*--------------------------------------------------------------------------*/ @@ -1405,10 +1405,7 @@ void kwsysProcess_Kill(kwsysProcess* cp) /* Not Windows 9x. Just terminate the children. */ for(i=0; i < cp->NumberOfCommands; ++i) { - if(!kwsysProcessWin32Kill(cp->ProcessInformation[i].dwProcessId)) - { - TerminateProcess(cp->ProcessInformation[i].hProcess, 255); - } + kwsysProcessKillTree(cp->ProcessInformation[i].dwProcessId); } } @@ -2141,3 +2138,404 @@ static void kwsysProcessSetExitException(kwsysProcess* cp, int code) } #undef KWSYSPE_CASE +typedef struct kwsysProcess_List_s kwsysProcess_List; +static kwsysProcess_List* kwsysProcess_List_New(); +static void kwsysProcess_List_Delete(kwsysProcess_List* self); +static int kwsysProcess_List_Update(kwsysProcess_List* self); +static int kwsysProcess_List_NextProcess(kwsysProcess_List* self); +static int kwsysProcess_List_GetCurrentProcessId(kwsysProcess_List* self); +static int kwsysProcess_List_GetCurrentParentId(kwsysProcess_List* self); + +/*--------------------------------------------------------------------------*/ +/* Windows NT 4 API definitions. */ +#define STATUS_INFO_LENGTH_MISMATCH ((NTSTATUS)0xC0000004L) +typedef LONG NTSTATUS; +typedef LONG KPRIORITY; +typedef struct _UNICODE_STRING UNICODE_STRING; +struct _UNICODE_STRING +{ + USHORT Length; + USHORT MaximumLength; + PWSTR Buffer; +}; + +/* The process information structure. Declare only enough to get + process identifiers. The rest may be ignored because we use the + NextEntryDelta to move through an array of instances. */ +typedef struct _SYSTEM_PROCESS_INFORMATION SYSTEM_PROCESS_INFORMATION; +typedef SYSTEM_PROCESS_INFORMATION* PSYSTEM_PROCESS_INFORMATION; +struct _SYSTEM_PROCESS_INFORMATION +{ + 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; +}; + +/*--------------------------------------------------------------------------*/ +/* Toolhelp32 API definitions. */ +#define TH32CS_SNAPPROCESS 0x00000002 +typedef struct tagPROCESSENTRY32 PROCESSENTRY32; +typedef PROCESSENTRY32* LPPROCESSENTRY32; +struct tagPROCESSENTRY32 +{ + DWORD dwSize; + DWORD cntUsage; + DWORD th32ProcessID; + DWORD th32DefaultHeapID; + DWORD th32ModuleID; + DWORD cntThreads; + DWORD th32ParentProcessID; + LONG pcPriClassBase; + DWORD dwFlags; + char szExeFile[MAX_PATH]; +}; + +/*--------------------------------------------------------------------------*/ +/* Windows API function types. */ +typedef HANDLE (WINAPI* CreateToolhelp32SnapshotType)(DWORD, DWORD); +typedef BOOL (WINAPI* Process32FirstType)(HANDLE, LPPROCESSENTRY32); +typedef BOOL (WINAPI* Process32NextType)(HANDLE, LPPROCESSENTRY32); +typedef NTSTATUS (WINAPI* ZwQuerySystemInformationType)(ULONG, PVOID, + ULONG, PULONG); + + +/*--------------------------------------------------------------------------*/ +static int kwsysProcess_List__New_NT4(kwsysProcess_List* self); +static int kwsysProcess_List__New_Snapshot(kwsysProcess_List* self); +static void kwsysProcess_List__Delete_NT4(kwsysProcess_List* self); +static void kwsysProcess_List__Delete_Snapshot(kwsysProcess_List* self); +static int kwsysProcess_List__Update_NT4(kwsysProcess_List* self); +static int kwsysProcess_List__Update_Snapshot(kwsysProcess_List* self); +static int kwsysProcess_List__Next_NT4(kwsysProcess_List* self); +static int kwsysProcess_List__Next_Snapshot(kwsysProcess_List* self); +static int kwsysProcess_List__GetProcessId_NT4(kwsysProcess_List* self); +static int kwsysProcess_List__GetProcessId_Snapshot(kwsysProcess_List* self); +static int kwsysProcess_List__GetParentId_NT4(kwsysProcess_List* self); +static int kwsysProcess_List__GetParentId_Snapshot(kwsysProcess_List* self); + +struct kwsysProcess_List_s +{ + /* Implementation switches at runtime based on version of Windows. */ + int NT4; + + /* Implementation functions and data for NT 4. */ + ZwQuerySystemInformationType P_ZwQuerySystemInformation; + char* Buffer; + int BufferSize; + PSYSTEM_PROCESS_INFORMATION CurrentInfo; + + /* Implementation functions and data for other Windows versions. */ + CreateToolhelp32SnapshotType P_CreateToolhelp32Snapshot; + Process32FirstType P_Process32First; + Process32NextType P_Process32Next; + HANDLE Snapshot; + PROCESSENTRY32 CurrentEntry; +}; + +/*--------------------------------------------------------------------------*/ +static kwsysProcess_List* kwsysProcess_List_New() +{ + OSVERSIONINFO osv; + kwsysProcess_List* self; + + /* Allocate and initialize the list object. */ + if(!(self = (kwsysProcess_List*)malloc(sizeof(kwsysProcess_List)))) + { + return 0; + } + memset(self, 0, sizeof(*self)); + + /* Select an implementation. */ + ZeroMemory(&osv, sizeof(osv)); + osv.dwOSVersionInfoSize = sizeof(osv); + GetVersionEx(&osv); + self->NT4 = (osv.dwPlatformId == VER_PLATFORM_WIN32_NT && + osv.dwMajorVersion < 5)? 1:0; + + /* Initialize the selected implementation. */ + if(!(self->NT4? + kwsysProcess_List__New_NT4(self) : + kwsysProcess_List__New_Snapshot(self))) + { + kwsysProcess_List_Delete(self); + return 0; + } + + /* Update to the current set of processes. */ + if(!kwsysProcess_List_Update(self)) + { + kwsysProcess_List_Delete(self); + return 0; + } + return self; +} + +/*--------------------------------------------------------------------------*/ +static void kwsysProcess_List_Delete(kwsysProcess_List* self) +{ + if(self) + { + if(self->NT4) + { + kwsysProcess_List__Delete_NT4(self); + } + else + { + kwsysProcess_List__Delete_Snapshot(self); + } + free(self); + } +} + +/*--------------------------------------------------------------------------*/ +static int kwsysProcess_List_Update(kwsysProcess_List* self) +{ + return self? (self->NT4? + kwsysProcess_List__Update_NT4(self) : + kwsysProcess_List__Update_Snapshot(self)) : 0; +} + +/*--------------------------------------------------------------------------*/ +static int kwsysProcess_List_GetCurrentProcessId(kwsysProcess_List* self) +{ + return self? (self->NT4? + kwsysProcess_List__GetProcessId_NT4(self) : + kwsysProcess_List__GetProcessId_Snapshot(self)) : -1; + +} + +/*--------------------------------------------------------------------------*/ +static int kwsysProcess_List_GetCurrentParentId(kwsysProcess_List* self) +{ + return self? (self->NT4? + kwsysProcess_List__GetParentId_NT4(self) : + kwsysProcess_List__GetParentId_Snapshot(self)) : -1; + +} + +/*--------------------------------------------------------------------------*/ +static int kwsysProcess_List_NextProcess(kwsysProcess_List* self) +{ + return (self? (self->NT4? + kwsysProcess_List__Next_NT4(self) : + kwsysProcess_List__Next_Snapshot(self)) : 0); +} + +/*--------------------------------------------------------------------------*/ +static int kwsysProcess_List__New_NT4(kwsysProcess_List* self) +{ + HANDLE hNT = GetModuleHandle("ntdll.dll"); + if(hNT) + { + /* Get pointers to the needed API functions. */ + self->P_ZwQuerySystemInformation = + ((ZwQuerySystemInformationType) + GetProcAddress(hNT, "ZwQuerySystemInformation")); + CloseHandle(hNT); + } + if(!self->P_ZwQuerySystemInformation) + { + return 0; + } + + /* Allocate an initial process information buffer. */ + self->BufferSize = 32768; + self->Buffer = (char*)malloc(self->BufferSize); + return self->Buffer? 1:0; +} + +/*--------------------------------------------------------------------------*/ +static void kwsysProcess_List__Delete_NT4(kwsysProcess_List* self) +{ + /* Free the process information buffer. */ + if(self->Buffer) + { + free(self->Buffer); + } +} + +/*--------------------------------------------------------------------------*/ +static int kwsysProcess_List__Update_NT4(kwsysProcess_List* self) +{ + self->CurrentInfo = 0; + while(1) + { + /* Query number 5 is for system process list. */ + NTSTATUS status = + self->P_ZwQuerySystemInformation(5, self->Buffer, self->BufferSize, 0); + if(status == STATUS_INFO_LENGTH_MISMATCH) + { + /* The query requires a bigger buffer. */ + int newBufferSize = self->BufferSize * 2; + char* newBuffer = (char*)malloc(newBufferSize); + if(newBuffer) + { + free(self->Buffer); + self->Buffer = newBuffer; + self->BufferSize = newBufferSize; + } + else + { + return 0; + } + } + else if(status >= 0) + { + /* The query succeeded. Initialize traversal of the process list. */ + self->CurrentInfo = (PSYSTEM_PROCESS_INFORMATION)self->Buffer; + return 1; + } + else + { + /* The query failed. */ + return 0; + } + } +} + +/*--------------------------------------------------------------------------*/ +static int kwsysProcess_List__Next_NT4(kwsysProcess_List* self) +{ + if(self->CurrentInfo) + { + if(self->CurrentInfo->NextEntryDelta > 0) + { + self->CurrentInfo = ((PSYSTEM_PROCESS_INFORMATION) + ((char*)self->CurrentInfo + + self->CurrentInfo->NextEntryDelta)); + return 1; + } + self->CurrentInfo = 0; + } + return 0; +} + +/*--------------------------------------------------------------------------*/ +static int kwsysProcess_List__GetProcessId_NT4(kwsysProcess_List* self) +{ + return self->CurrentInfo? self->CurrentInfo->ProcessId : -1; +} + +/*--------------------------------------------------------------------------*/ +static int kwsysProcess_List__GetParentId_NT4(kwsysProcess_List* self) +{ + return self->CurrentInfo? self->CurrentInfo->InheritedFromProcessId : -1; +} + +/*--------------------------------------------------------------------------*/ +static int kwsysProcess_List__New_Snapshot(kwsysProcess_List* self) +{ + HANDLE hKernel = GetModuleHandle("kernel32.dll"); + if(hKernel) + { + self->P_CreateToolhelp32Snapshot = + ((CreateToolhelp32SnapshotType) + GetProcAddress(hKernel, "CreateToolhelp32Snapshot")); + self->P_Process32First = + ((Process32FirstType) + GetProcAddress(hKernel, "Process32First")); + self->P_Process32Next = + ((Process32NextType) + GetProcAddress(hKernel, "Process32Next")); + CloseHandle(hKernel); + } + return (self->P_CreateToolhelp32Snapshot && + self->P_Process32First && + self->P_Process32Next)? 1:0; +} + +/*--------------------------------------------------------------------------*/ +static void kwsysProcess_List__Delete_Snapshot(kwsysProcess_List* self) +{ + if(self->Snapshot) + { + CloseHandle(self->Snapshot); + } +} + +/*--------------------------------------------------------------------------*/ +static int kwsysProcess_List__Update_Snapshot(kwsysProcess_List* self) +{ + if(self->Snapshot) + { + CloseHandle(self->Snapshot); + } + if(!(self->Snapshot = + self->P_CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0))) + { + return 0; + } + ZeroMemory(&self->CurrentEntry, sizeof(self->CurrentEntry)); + self->CurrentEntry.dwSize = sizeof(self->CurrentEntry); + if(!self->P_Process32First(self->Snapshot, &self->CurrentEntry)) + { + CloseHandle(self->Snapshot); + self->Snapshot = 0; + return 0; + } + return 1; +} + +/*--------------------------------------------------------------------------*/ +static int kwsysProcess_List__Next_Snapshot(kwsysProcess_List* self) +{ + if(self->Snapshot) + { + if(self->P_Process32Next(self->Snapshot, &self->CurrentEntry)) + { + return 1; + } + CloseHandle(self->Snapshot); + self->Snapshot = 0; + } + return 0; +} + +/*--------------------------------------------------------------------------*/ +static int kwsysProcess_List__GetProcessId_Snapshot(kwsysProcess_List* self) +{ + return self->Snapshot? self->CurrentEntry.th32ProcessID : -1; +} + +/*--------------------------------------------------------------------------*/ +static int kwsysProcess_List__GetParentId_Snapshot(kwsysProcess_List* self) +{ + return self->Snapshot? self->CurrentEntry.th32ParentProcessID : -1; +} + +/*--------------------------------------------------------------------------*/ +static void kwsysProcessKill(DWORD pid) +{ + HANDLE h = OpenProcess(PROCESS_TERMINATE, 0, pid); + if(h) + { + TerminateProcess(h, 255); + WaitForSingleObject(h, INFINITE); + } +} + +/*--------------------------------------------------------------------------*/ +static void kwsysProcessKillTree(int pid) +{ + kwsysProcess_List* plist = kwsysProcess_List_New(); + kwsysProcessKill(pid); + if(plist) + { + do + { + if(kwsysProcess_List_GetCurrentParentId(plist) == pid) + { + int ppid = kwsysProcess_List_GetCurrentProcessId(plist); + kwsysProcessKillTree(ppid); + } + } while(kwsysProcess_List_NextProcess(plist)); + kwsysProcess_List_Delete(plist); + } +} diff --git a/Source/kwsys/ProcessWin32Kill.c b/Source/kwsys/ProcessWin32Kill.c deleted file mode 100644 index 21a1bb8..0000000 --- a/Source/kwsys/ProcessWin32Kill.c +++ /dev/null @@ -1,453 +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) - { - 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.h.in b/Source/kwsys/ProcessWin32Kill.h.in deleted file mode 100644 index 2243600..0000000 --- a/Source/kwsys/ProcessWin32Kill.h.in +++ /dev/null @@ -1,46 +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. - -=========================================================================*/ -#ifndef @KWSYS_NAMESPACE@_ProcessWin32Kill_h -#define @KWSYS_NAMESPACE@_ProcessWin32Kill_h - -#include <@KWSYS_NAMESPACE@/Configure.h> - -/* Redefine all public interface symbol names to be in the proper - namespace. These macros are used internally to kwsys only, and are - not visible to user code. Use kwsysHeaderDump.pl to reproduce - these macros after making changes to the interface. */ -#define kwsys_ns(x) @KWSYS_NAMESPACE@##x -#define kwsysEXPORT @KWSYS_NAMESPACE@_EXPORT -#define kwsysProcessWin32Kill kwsys_ns(ProcessWin32Kill) - -#if defined(__cplusplus) -extern "C" -{ -#endif - -kwsysEXPORT int kwsysProcessWin32Kill(int pid); - -#if defined(__cplusplus) -} /* extern "C" */ -#endif - -/* If we are building a kwsysProcess .c file, let it use these macros. - Otherwise, undefine them to keep the namespace clean. */ -#if !defined(KWSYS_IN_PROCESS_C) -# undef kwsys_ns -# undef kwsysEXPORT -# undef kwsysProcessWin32Kill -#endif - -#endif |