Skip to content
GitLab
Explore
Sign in
Register
Primary navigation
Search or go to…
Project
K
KWSys
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Deploy
Releases
Container Registry
Model registry
Monitor
Incidents
Service Desk
Analyze
Value stream analytics
Contributor analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Artur Ryt
KWSys
Commits
ebc4e0d2
Commit
ebc4e0d2
authored
20 years ago
by
Bill Hoffman
Browse files
Options
Downloads
Patches
Plain Diff
ENH: change to c code so it can be built with mingw
parent
0fb5c7e9
No related branches found
Branches containing commit
No related tags found
No related merge requests found
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
CMakeLists.txt
+1
-1
1 addition, 1 deletion
CMakeLists.txt
ProcessWin32Kill.c
+454
-0
454 additions, 0 deletions
ProcessWin32Kill.c
ProcessWin32Kill.cxx
+0
-446
0 additions, 446 deletions
ProcessWin32Kill.cxx
with
455 additions
and
447 deletions
CMakeLists.txt
+
1
−
1
View file @
ebc4e0d2
...
...
@@ -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.c
xx
)
SET
(
KWSYS_SRCS
${
KWSYS_SRCS
}
ProcessWin32Kill.c
)
ELSE
(
NOT UNIX
)
# Use the UNIX implementation.
SET
(
KWSYS_SRCS
${
KWSYS_SRCS
}
ProcessUNIX.c
)
...
...
This diff is collapsed.
Click to expand it.
ProcessWin32Kill.c
0 → 100644
+
454
−
0
View file @
ebc4e0d2
/*=========================================================================
Program: KWSys - Kitware System Library
Module: ProcessWin32Kill.c
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
;
}
This diff is collapsed.
Click to expand it.
ProcessWin32Kill.cxx
deleted
100644 → 0
+
0
−
446
View file @
0fb5c7e9
/*=========================================================================
Program: KWSys - Kitware System Library
Module: ProcessWin32Kill.cxx
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
;
}
}
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment