mirror of
https://github.com/reactos/CMake.git
synced 2025-02-20 11:52:04 +00:00
ENH: Adding native windows process tree kill to ProcessWin32.c. This replaces the ProcessWin32Kill.c implementation.
This commit is contained in:
parent
dd70c8f82d
commit
6c4ab7ec52
@ -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)
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
@ -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
|
Loading…
x
Reference in New Issue
Block a user