ReactOS 0.4.17-dev-684-ga6524ef
kill.c File Reference
#include <ntoskrnl.h>
#include <debug.h>
Include dependency graph for kill.c:

Go to the source code of this file.

Macros

#define NDEBUG
 

Functions

VOID NTAPI PspCatchCriticalBreak (IN PCHAR Message, IN PVOID ProcessOrThread, IN PCHAR ImageName)
 
NTSTATUS NTAPI PspTerminateProcess (IN PEPROCESS Process, IN NTSTATUS ExitStatus)
 
NTSTATUS NTAPI PsTerminateProcess (IN PEPROCESS Process, IN NTSTATUS ExitStatus)
 
VOID NTAPI PspShutdownProcessManager (VOID)
 
VOID NTAPI PspExitApcRundown (IN PKAPC Apc)
 
VOID NTAPI PspReapRoutine (IN PVOID Context)
 
VOID NTAPI PspDeleteProcess (IN PVOID ObjectBody)
 
VOID NTAPI PspDeleteThread (IN PVOID ObjectBody)
 
VOID NTAPI PspExitThread (IN NTSTATUS ExitStatus)
 
VOID NTAPI PsExitSpecialApc (IN PKAPC Apc, IN OUT PKNORMAL_ROUTINE *NormalRoutine, IN OUT PVOID *NormalContext, IN OUT PVOID *SystemArgument1, IN OUT PVOID *SystemArgument2)
 
VOID NTAPI PspExitNormalApc (IN PVOID NormalContext, IN PVOID SystemArgument1, IN PVOID SystemArgument2)
 
NTSTATUS NTAPI PspTerminateThreadByPointer (IN PETHREAD Thread, IN NTSTATUS ExitStatus, IN BOOLEAN bSelf)
 
BOOLEAN NTAPI PspIsProcessExiting (IN PEPROCESS Process)
 
VOID NTAPI PspExitProcess (IN BOOLEAN LastThread, IN PEPROCESS Process)
 
NTSTATUS NTAPI PsTerminateSystemThread (IN NTSTATUS ExitStatus)
 
NTSTATUS NTAPI NtTerminateProcess (IN HANDLE ProcessHandle OPTIONAL, IN NTSTATUS ExitStatus)
 
NTSTATUS NTAPI NtTerminateThread (IN HANDLE ThreadHandle, IN NTSTATUS ExitStatus)
 
NTSTATUS NTAPI NtRegisterThreadTerminatePort (IN HANDLE PortHandle)
 

Variables

LIST_ENTRY PspReaperListHead = { NULL, NULL }
 
WORK_QUEUE_ITEM PspReaperWorkItem
 
LARGE_INTEGER ShortTime = {{-10 * 100 * 1000, -1}}
 

Macro Definition Documentation

◆ NDEBUG

#define NDEBUG

Definition at line 14 of file kill.c.

Function Documentation

◆ NtRegisterThreadTerminatePort()

NTSTATUS NTAPI NtRegisterThreadTerminatePort ( IN HANDLE  PortHandle)

Definition at line 1361 of file kill.c.

1362{
1364 PTERMINATION_PORT TerminationPort;
1365 PVOID TerminationLpcPort;
1367 PAGED_CODE();
1368 PSTRACE(PS_KILL_DEBUG, "PortHandle: %p\n", PortHandle);
1369
1370 /* Get the Port */
1371 Status = ObReferenceObjectByHandle(PortHandle,
1375 &TerminationLpcPort,
1376 NULL);
1377 if (!NT_SUCCESS(Status)) return(Status);
1378
1379 /* Allocate the Port and make sure it suceeded */
1380 TerminationPort = ExAllocatePoolWithTag(NonPagedPool,
1381 sizeof(TERMINATION_PORT),
1382 '=TsP');
1383 if(TerminationPort)
1384 {
1385 /* Associate the Port */
1387 TerminationPort->Port = TerminationLpcPort;
1388 TerminationPort->Next = Thread->TerminationPort;
1389 Thread->TerminationPort = TerminationPort;
1390
1391 /* Return success */
1392 return STATUS_SUCCESS;
1393 }
1394
1395 /* Dereference and Fail */
1396 ObDereferenceObject(TerminationLpcPort);
1398}
#define PAGED_CODE()
LONG NTSTATUS
Definition: precomp.h:26
#define NULL
Definition: types.h:112
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define PsGetCurrentThread()
Definition: env_spec_w32.h:81
#define NonPagedPool
Definition: env_spec_w32.h:307
_In_opt_ PFILE_OBJECT _In_opt_ PETHREAD Thread
Definition: fltkernel.h:2653
Status
Definition: gdiplustypes.h:24
POBJECT_TYPE LpcPortObjectType
Definition: port.c:17
#define PORT_ALL_ACCESS
Definition: lpctypes.h:51
#define KeGetPreviousMode()
Definition: ketypes.h:1115
NTSTATUS NTAPI ObReferenceObjectByHandle(IN HANDLE Handle, IN ACCESS_MASK DesiredAccess, IN POBJECT_TYPE ObjectType, IN KPROCESSOR_MODE AccessMode, OUT PVOID *Object, OUT POBJECT_HANDLE_INFORMATION HandleInformation OPTIONAL)
Definition: obref.c:493
#define PS_KILL_DEBUG
Definition: ps.h:25
#define PSTRACE(x, fmt,...)
Definition: ps.h:57
#define STATUS_SUCCESS
Definition: shellext.h:65
struct _TERMINATION_PORT * TerminationPort
Definition: pstypes.h:1214
struct _TERMINATION_PORT * Next
Definition: pstypes.h:1175
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
#define ObDereferenceObject
Definition: obfuncs.h:203

Referenced by CsrNewThread().

◆ NtTerminateProcess()

NTSTATUS NTAPI NtTerminateProcess ( IN HANDLE ProcessHandle  OPTIONAL,
IN NTSTATUS  ExitStatus 
)

Definition at line 1180 of file kill.c.

1182{
1184 PEPROCESS Process, CurrentProcess = PsGetCurrentProcess();
1185 PETHREAD Thread, CurrentThread = PsGetCurrentThread();
1186 BOOLEAN KillByHandle;
1187 PAGED_CODE();
1189 "ProcessHandle: %p ExitStatus: %d\n", ProcessHandle, ExitStatus);
1190
1191 /* Were we passed a process handle? */
1192 if (ProcessHandle)
1193 {
1194 /* Yes we were, use it */
1195 KillByHandle = TRUE;
1196 }
1197 else
1198 {
1199 /* We weren't... we assume this is suicide */
1200 KillByHandle = FALSE;
1202 }
1203
1204 /* Get the Process Object */
1209 (PVOID*)&Process,
1210 NULL);
1211 if (!NT_SUCCESS(Status)) return(Status);
1212
1213 /* Check if this is a Critical Process, and Bugcheck */
1214 if (Process->BreakOnTermination)
1215 {
1216 /* Break to debugger */
1217 PspCatchCriticalBreak("Terminating critical process 0x%p (%s)\n",
1218 Process,
1219 Process->ImageFileName);
1220 }
1221
1222 /* Lock the Process */
1223 if (!ExAcquireRundownProtection(&Process->RundownProtect))
1224 {
1225 /* Failed to lock, fail */
1228 }
1229
1230 /* Set the delete flag, unless the process is comitting suicide */
1232
1233 /* Get the first thread */
1236 if (Thread)
1237 {
1238 /* We know we have at least a thread */
1240
1241 /* Loop and kill the others */
1242 do
1243 {
1244 /* Ensure it's not ours*/
1245 if (Thread != CurrentThread)
1246 {
1247 /* Kill it */
1249 }
1250
1251 /* Move to the next thread */
1253 } while (Thread);
1254 }
1255
1256 /* Unlock the process */
1257 ExReleaseRundownProtection(&Process->RundownProtect);
1258
1259 /* Check if we are killing ourselves */
1260 if (Process == CurrentProcess)
1261 {
1262 /* Also make sure the caller gave us our handle */
1263 if (KillByHandle)
1264 {
1265 /* Dereference the process */
1267
1268 /* Terminate ourselves */
1270 }
1271 }
1273 {
1274 /* Disable debugging on this process */
1276 }
1277
1278 /* Check if there was nothing to terminate, or if we have a Debug Port */
1280 ((Process->DebugPort) && (KillByHandle)))
1281 {
1282 /* Clear the handle table */
1284
1285 /* Return status now */
1287 }
1288
1289 /* Decrease the reference count we added */
1291
1292 /* Return status */
1293 return Status;
1294}
unsigned char BOOLEAN
Definition: actypes.h:127
NTSTATUS NTAPI DbgkClearProcessDebugObject(IN PEPROCESS Process, IN PDEBUG_OBJECT SourceDebugObject OPTIONAL)
Definition: dbgkobj.c:1410
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define ExReleaseRundownProtection
Definition: ex.h:139
#define ExAcquireRundownProtection
Definition: ex.h:138
_Must_inspect_result_ _In_ PLARGE_INTEGER _In_ PLARGE_INTEGER _In_ ULONG _In_ PFILE_OBJECT _In_ PVOID Process
Definition: fsrtlfuncs.h:223
#define PROCESS_TERMINATE
Definition: pstypes.h:153
#define PSF_PROCESS_DELETE_BIT
Definition: pstypes.h:272
_In_ HANDLE ProcessHandle
Definition: mmfuncs.h:407
_In_ NTSTATUS ExitStatus
Definition: psfuncs.h:868
#define NtCurrentProcess()
Definition: nt_native.h:1660
VOID NTAPI PspCatchCriticalBreak(IN PCHAR Message, IN PVOID ProcessOrThread, IN PCHAR ImageName)
Definition: kill.c:27
NTSTATUS NTAPI PspTerminateThreadByPointer(IN PETHREAD Thread, IN NTSTATUS ExitStatus, IN BOOLEAN bSelf)
Definition: kill.c:1007
POBJECT_TYPE PsProcessType
Definition: process.c:20
#define DBG_TERMINATE_PROCESS
Definition: ntstatus.h:102
#define STATUS_PROCESS_IS_TERMINATING
Definition: ntstatus.h:596
#define STATUS_NOTHING_TO_TERMINATE
Definition: ntstatus.h:159
VOID NTAPI ObClearProcessHandleTable(IN PEPROCESS Process)
Definition: obhandle.c:2049
PETHREAD NTAPI PsGetNextProcessThread(IN PEPROCESS Process, IN PETHREAD Thread OPTIONAL)
Definition: process.c:75
#define PspSetProcessFlag(Process, Flag)
Definition: ps_x.h:33
#define PsGetCurrentProcess
Definition: psfuncs.h:17

◆ NtTerminateThread()

NTSTATUS NTAPI NtTerminateThread ( IN HANDLE ThreadHandle  OPTIONAL,
IN NTSTATUS  ExitStatus 
)

Definition at line 1298 of file kill.c.

1300{
1302 PETHREAD CurrentThread = PsGetCurrentThread();
1304 PAGED_CODE();
1306 "ThreadHandle: %p ExitStatus: %d\n", ThreadHandle, ExitStatus);
1307
1308 /* Handle the special NULL case */
1309 if (!ThreadHandle)
1310 {
1311 /* Check if we're the only thread left */
1312 if (PsGetCurrentProcess()->ActiveThreads == 1)
1313 {
1314 /* This is invalid */
1316 }
1317
1318 /* Terminate us directly */
1319 goto TerminateSelf;
1320 }
1321 else if (ThreadHandle == NtCurrentThread())
1322 {
1323TerminateSelf:
1324 /* Terminate this thread */
1325 return PspTerminateThreadByPointer(CurrentThread,
1326 ExitStatus,
1327 TRUE);
1328 }
1329
1330 /* We are terminating another thread, get the Thread Object */
1331 Status = ObReferenceObjectByHandle(ThreadHandle,
1335 (PVOID*)&Thread,
1336 NULL);
1337 if (!NT_SUCCESS(Status)) return Status;
1338
1339 /* Check to see if we're running in the same thread */
1340 if (Thread != CurrentThread)
1341 {
1342 /* Terminate it */
1344
1345 /* Dereference the Thread and return */
1347 }
1348 else
1349 {
1350 /* Dereference the thread and terminate ourselves */
1352 goto TerminateSelf;
1353 }
1354
1355 /* Return status */
1356 return Status;
1357}
#define THREAD_TERMINATE
Definition: nt_native.h:1339
POBJECT_TYPE PsThreadType
Definition: thread.c:20
#define STATUS_CANT_TERMINATE_SELF
Definition: ntstatus.h:549
#define NtCurrentThread()
Definition: winternl.h:5372

Referenced by _main(), BaseSrvBSMThread(), CreateRemoteThread(), CsrApiRequestThread(), CsrpCheckRequestThreads(), DummyThread(), ExitThread(), InitializeUserModePnpManager(), PnpEventThread(), RtlExitUserThread(), RtlpExitThread(), TerminateThread(), TerminateUserModePnpManager(), test_notifications(), Test_ThreadHideFromDebuggerClass(), Test_ThreadNameInformation(), TestThreadProc(), and wWinMain().

◆ PsExitSpecialApc()

VOID NTAPI PsExitSpecialApc ( IN PKAPC  Apc,
IN OUT PKNORMAL_ROUTINE NormalRoutine,
IN OUT PVOID NormalContext,
IN OUT PVOID SystemArgument1,
IN OUT PVOID SystemArgument2 
)

Definition at line 941 of file kill.c.

946{
948 PAGED_CODE();
950 "Apc: %p SystemArgument2: %p\n", Apc, SystemArgument2);
951
952 /* Don't do anything unless we are in User-Mode */
953 if (Apc->SystemArgument2)
954 {
955 /* Free the APC */
956 Status = PtrToUlong(Apc->NormalContext);
958
959 /* Terminate the Thread */
961 }
962}
#define PtrToUlong(u)
Definition: config.h:107
VOID NTAPI PspExitThread(IN NTSTATUS ExitStatus)
Definition: kill.c:469
VOID NTAPI PspExitApcRundown(IN PKAPC Apc)
Definition: kill.c:157
_In_opt_ PVOID _In_opt_ PVOID _In_opt_ PVOID SystemArgument2
Definition: ketypes.h:757

Referenced by PspExitNormalApc(), and PspTerminateThreadByPointer().

◆ PspCatchCriticalBreak()

VOID NTAPI PspCatchCriticalBreak ( IN PCHAR  Message,
IN PVOID  ProcessOrThread,
IN PCHAR  ImageName 
)

Definition at line 27 of file kill.c.

30{
31 CHAR Action[2];
33 PAGED_CODE();
34
35 /* Check if a debugger is enabled */
37 {
38 /* Print out the message */
39 DbgPrint(Message, ProcessOrThread, ImageName);
40 do
41 {
42 /* If a debugger isn't present, don't prompt */
43 if (KdDebuggerNotPresent) break;
44
45 /* A debugger is active, prompt for action */
46 DbgPrompt("Break, or Ignore (bi)? ", Action, sizeof(Action));
47 switch (Action[0])
48 {
49 /* Break */
50 case 'B': case 'b':
52 /* Fall through */
53
54 /* Ignore: Handle it */
55 case 'I': case 'i':
56 Handled = TRUE;
57
58 /* Unrecognized: Prompt again */
59 default:
60 break;
61 }
62 } while (!Handled);
63 }
64
65 /* Did we ultimately handle this? */
66 if (!Handled)
67 {
68 /* We didn't, bugcheck */
69 KeBugCheckEx(CRITICAL_OBJECT_TERMINATION,
70 ((PKPROCESS)ProcessOrThread)->Header.Type,
71 (ULONG_PTR)ProcessOrThread,
74 }
75}
DECLSPEC_NORETURN VOID NTAPI KeBugCheckEx(IN ULONG BugCheckCode, IN ULONG_PTR BugCheckParameter1, IN ULONG_PTR BugCheckParameter2, IN ULONG_PTR BugCheckParameter3, IN ULONG_PTR BugCheckParameter4)
Definition: debug.c:485
Definition: Header.h:9
static const WCHAR Message[]
Definition: register.c:74
#define DbgPrint
Definition: hal.h:12
BOOLEAN KdDebuggerNotPresent
Definition: kddata.c:81
BOOLEAN KdDebuggerEnabled
Definition: kddata.c:82
static const char * ImageName
Definition: image.c:34
NTSYSAPI ULONG NTAPI DbgPrompt(_In_z_ PCCH Prompt, _Out_writes_bytes_(MaximumResponseLength) PCH Response, _In_ ULONG MaximumResponseLength)
char CHAR
Definition: pedump.c:57
uint32_t ULONG_PTR
Definition: typedefs.h:65
_In_ WDFIOTARGET _In_ _Strict_type_match_ WDF_IO_TARGET_SENT_IO_ACTION Action
Definition: wdfiotarget.h:510
NTSYSAPI void WINAPI DbgBreakPoint(void)
_In_ BOOLEAN Handled
Definition: ketypes.h:401

Referenced by NtTerminateProcess(), PspExitThread(), PspTerminateProcess(), and PspTerminateThreadByPointer().

◆ PspDeleteProcess()

VOID NTAPI PspDeleteProcess ( IN PVOID  ObjectBody)

Definition at line 253 of file kill.c.

254{
255 PEPROCESS Process = (PEPROCESS)ObjectBody;
257 PAGED_CODE();
258 PSTRACE(PS_KILL_DEBUG, "ObjectBody: %p\n", ObjectBody);
260
261 /* Check if it has an Active Process Link */
262 if (Process->ActiveProcessLinks.Flink)
263 {
264 /* Remove it from the Active List */
266 RemoveEntryList(&Process->ActiveProcessLinks);
267 Process->ActiveProcessLinks.Flink = NULL;
268 Process->ActiveProcessLinks.Blink = NULL;
270 }
271
272 /* Check for Auditing information */
273 if (Process->SeAuditProcessCreationInfo.ImageFileName)
274 {
275 /* Free it */
276 ExFreePoolWithTag(Process->SeAuditProcessCreationInfo.ImageFileName,
277 TAG_SEPA);
278 Process->SeAuditProcessCreationInfo.ImageFileName = NULL;
279 }
280
281 /* Check if we have a job */
282 if (Process->Job)
283 {
284 /* Remove the process from the job */
286
287 /* Dereference it */
289 Process->Job = NULL;
290 }
291
292 /* Increase the stack count */
293 Process->Pcb.StackCount++;
294
295 /* Check if we have a debug port */
296 if (Process->DebugPort)
297 {
298 /* Deference the Debug Port */
299 ObDereferenceObject(Process->DebugPort);
300 Process->DebugPort = NULL;
301 }
302
303 /* Check if we have an exception port */
304 if (Process->ExceptionPort)
305 {
306 /* Deference the Exception Port */
307 ObDereferenceObject(Process->ExceptionPort);
308 Process->ExceptionPort = NULL;
309 }
310
311 /* Check if we have a section object */
312 if (Process->SectionObject)
313 {
314 /* Deference the Section Object */
315 ObDereferenceObject(Process->SectionObject);
316 Process->SectionObject = NULL;
317 }
318
319#if defined(_X86_)
320 /* Clean Ldt and Vdm objects */
323#endif
324
325 /* Delete the Object Table */
326 if (Process->ObjectTable)
327 {
328 /* Attach to the process */
330
331 /* Kill the Object Info */
333
334 /* Detach */
336 }
337
338 /* Check if we have an address space, and clean it */
339 if (Process->HasAddressSpace)
340 {
341 /* Attach to the process */
343
344 /* Clean the Address Space */
346
347 /* Detach */
349
350 /* Completely delete the Address Space */
352 }
353
354 /* See if we have a PID */
355 if (Process->UniqueProcessId)
356 {
357 /* Delete the PID */
358 if (!(ExDestroyHandle(PspCidTable, Process->UniqueProcessId, NULL)))
359 {
360 /* Something wrong happened, bugcheck */
361 KeBugCheck(CID_HANDLE_DELETION);
362 }
363 }
364
365 /* Cleanup security information */
367
368 /* Check if we have kept information on the Working Set */
369 if (Process->WorkingSetWatch)
370 {
371 /* Free it */
372 ExFreePool(Process->WorkingSetWatch);
373
374 /* And return the quota it was taking up */
376 }
377
378 /* Dereference the Device Map */
380
381#if defined(_WIN64) && defined(BUILD_WOW64_ENABLED)
382 /* Check if this is a WOW64 process */
383 if (Process->Wow64Process && !IS_WOW64_PROCESS_INITIALIZING(Process))
384 {
385 /* Free WOW64_PROCESS structure */
386 ExFreePoolWithTag(Process->Wow64Process, TAG_PS_WOW64);
387
389 }
390#endif
391
392 /*
393 * Dereference the quota block, the function
394 * will invoke a quota block cleanup if the
395 * block itself is no longer used by anybody.
396 */
398}
DECLSPEC_NORETURN VOID NTAPI KeBugCheck(ULONG BugCheckCode)
Definition: bug.c:1434
#define RemoveEntryList(Entry)
Definition: env_spec_w32.h:986
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
VOID FASTCALL KeReleaseGuardedMutex(IN OUT PKGUARDED_MUTEX GuardedMutex)
Definition: gmutex.c:53
VOID FASTCALL KeAcquireGuardedMutex(IN PKGUARDED_MUTEX GuardedMutex)
Definition: gmutex.c:42
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1109
struct _EPROCESS * PEPROCESS
Definition: nt_native.h:30
BOOLEAN NTAPI ExDestroyHandle(IN PHANDLE_TABLE HandleTable, IN HANDLE Handle, IN PHANDLE_TABLE_ENTRY HandleTableEntry OPTIONAL)
Definition: handle.c:984
VOID NTAPI MmDeleteProcessAddressSpace(IN PEPROCESS Process)
Definition: procsup.c:1413
_Out_ PKAPC_STATE ApcState
Definition: mm.h:1769
VOID NTAPI PspExitProcess(IN BOOLEAN LastThread, IN PEPROCESS Process)
Definition: kill.c:1094
VOID NTAPI ObKillProcess(IN PEPROCESS Process)
Definition: obhandle.c:2182
VOID NTAPI ObDereferenceDeviceMap(IN PEPROCESS Process)
Definition: devicemap.c:456
VOID NTAPI KeStackAttachProcess(IN PKPROCESS Process, OUT PRKAPC_STATE ApcState)
Definition: procobj.c:704
VOID NTAPI KeUnstackDetachProcess(IN PRKAPC_STATE ApcState)
Definition: procobj.c:756
VOID NTAPI PspRemoveProcessFromJob(IN PEPROCESS Process, IN PEJOB Job)
Definition: job.c:138
#define PSREFTRACE(x)
Definition: ps.h:58
PHANDLE_TABLE PspCidTable
Definition: psmgr.c:48
VOID NTAPI PspDereferenceQuotaBlock(_In_opt_ PEPROCESS Process, _In_ PEPROCESS_QUOTA_BLOCK QuotaBlock)
De-references a quota block when quotas have been returned back because of an object de-allocation or...
Definition: quota.c:553
VOID NTAPI PspDeleteProcessSecurity(IN PEPROCESS Process)
Definition: security.c:30
KGUARDED_MUTEX PspActiveProcessMutex
Definition: process.c:23
VOID NTAPI PspDeleteLdt(PEPROCESS Process)
Definition: psldt.c:19
VOID NTAPI PspDeleteVdmObjects(PEPROCESS Process)
Definition: psldt.c:27
VOID NTAPI PsReturnProcessNonPagedPoolQuota(_In_ PEPROCESS Process, _In_ SIZE_T Amount)
Returns the non paged quota pool that the process was taking up.
Definition: quota.c:938
#define TAG_SEPA
Definition: tag.h:158
#define TAG_PS_WOW64
Definition: tag.h:141
KAPC_STATE
Definition: ketypes.h:1727

Referenced by PspInitPhase0().

◆ PspDeleteThread()

VOID NTAPI PspDeleteThread ( IN PVOID  ObjectBody)

Definition at line 402 of file kill.c.

403{
404 PETHREAD Thread = (PETHREAD)ObjectBody;
405 PEPROCESS Process = Thread->ThreadsProcess;
406 PAGED_CODE();
407 PSTRACE(PS_KILL_DEBUG, "ObjectBody: %p\n", ObjectBody);
410
411 /* Check if we have a stack */
413 {
414 /* Release it */
416 Thread->Tcb.LargeStack);
417 }
418
419 /* Check if we have a CID Handle */
421 {
422 /* Delete the CID Handle */
424 {
425 /* Something wrong happened, bugcheck */
426 KeBugCheck(CID_HANDLE_DELETION);
427 }
428 }
429
430 /* Cleanup impersonation information */
432
433 /* Free the thread name if set */
434 if (Thread->ThreadName)
435 {
438 }
439
440 /* Make sure the thread was inserted, before continuing */
441 if (!Process)
442 return;
443
444 /* Check if the thread list is valid */
446 {
447 /* Lock the thread's process */
449 ExAcquirePushLockExclusive(&Process->ProcessLock);
450
451 /* Remove us from the list */
453
454 /* Release the lock */
455 ExReleasePushLockExclusive(&Process->ProcessLock);
457 }
458
459 /* Dereference the Process */
461}
FORCEINLINE VOID ExAcquirePushLockExclusive(PEX_PUSH_LOCK PushLock)
Definition: ex.h:1039
FORCEINLINE VOID ExReleasePushLockExclusive(PEX_PUSH_LOCK PushLock)
Definition: ex.h:1255
#define KeLeaveCriticalRegion()
Definition: ke_x.h:119
#define KeEnterCriticalRegion()
Definition: ke_x.h:88
#define ASSERT(a)
Definition: mode.c:44
struct _ETHREAD * PETHREAD
Definition: nt_native.h:29
VOID NTAPI MmDeleteKernelStack(PVOID Stack, BOOLEAN GuiStack)
VOID NTAPI PspDeleteThreadSecurity(IN PETHREAD Thread)
Definition: security.c:46
HANDLE UniqueThread
Definition: compat.h:826
KTHREAD Tcb
Definition: pstypes.h:1198
CLIENT_ID Cid
Definition: pstypes.h:1223
PUNICODE_STRING ThreadName
Definition: pstypes.h:1352
LIST_ENTRY ThreadListEntry
Definition: pstypes.h:1253
PVOID InitialStack
Definition: ketypes.h:1811
PVOID Win32Thread
Definition: ketypes.h:2013
PVOID StackBase
Definition: ketypes.h:1813
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
#define TAG_THREAD_NAME
Definition: tag.h:140

Referenced by PspInitPhase0().

◆ PspExitApcRundown()

VOID NTAPI PspExitApcRundown ( IN PKAPC  Apc)

Definition at line 157 of file kill.c.

158{
159 PAGED_CODE();
160
161 /* Free the APC */
162 ExFreePool(Apc);
163}

Referenced by PsExitSpecialApc(), PspExitNormalApc(), and PspTerminateThreadByPointer().

◆ PspExitNormalApc()

VOID NTAPI PspExitNormalApc ( IN PVOID  NormalContext,
IN PVOID  SystemArgument1,
IN PVOID  SystemArgument2 
)

Definition at line 966 of file kill.c.

969{
972 PAGED_CODE();
973 PSTRACE(PS_KILL_DEBUG, "SystemArgument2: %p\n", SystemArgument2);
974
975 /* This should never happen */
977
978 /* If we're here, this is not a System Thread, so kill it from User-Mode */
979 KeInitializeApc(Apc,
980 &Thread->Tcb,
985 UserMode,
986 NormalContext);
987
988 /* Now insert the APC with the User-Mode Flag */
989 if (!(KeInsertQueueApc(Apc,
990 Apc,
992 2)))
993 {
994 /* Failed to insert, free the APC */
996 }
997
998 /* Set the APC Pending flag */
999 Thread->Tcb.ApcState.UserApcPending = TRUE;
1000}
#define UserMode
Definition: asm.h:39
@ OriginalApcEnvironment
Definition: ketypes.h:911
BOOLEAN NTAPI KeInsertQueueApc(IN PKAPC Apc, IN PVOID SystemArgument1, IN PVOID SystemArgument2, IN KPRIORITY PriorityBoost)
Definition: apc.c:735
VOID NTAPI KeInitializeApc(IN PKAPC Apc, IN PKTHREAD Thread, IN KAPC_ENVIRONMENT TargetEnvironment, IN PKKERNEL_ROUTINE KernelRoutine, IN PKRUNDOWN_ROUTINE RundownRoutine OPTIONAL, IN PKNORMAL_ROUTINE NormalRoutine, IN KPROCESSOR_MODE Mode, IN PVOID Context)
Definition: apc.c:651
VOID NTAPI PspExitNormalApc(IN PVOID NormalContext, IN PVOID SystemArgument1, IN PVOID SystemArgument2)
Definition: kill.c:966
VOID NTAPI PsExitSpecialApc(IN PKAPC Apc, IN OUT PKNORMAL_ROUTINE *NormalRoutine, IN OUT PVOID *NormalContext, IN OUT PVOID *SystemArgument1, IN OUT PVOID *SystemArgument2)
Definition: kill.c:941
Definition: ketypes.h:615
KAPC_STATE ApcState
Definition: ketypes.h:1925
_In_opt_ PVOID _In_opt_ PVOID SystemArgument1
Definition: ketypes.h:756
struct _KAPC * PKAPC

Referenced by PspExitNormalApc(), and PspTerminateThreadByPointer().

◆ PspExitProcess()

VOID NTAPI PspExitProcess ( IN BOOLEAN  LastThread,
IN PEPROCESS  Process 
)

Definition at line 1094 of file kill.c.

1096{
1097 ULONG Actual;
1098 PAGED_CODE();
1100 "LastThread: %u Process: %p\n", LastThread, Process);
1102
1103 /* Set Process Exit flag */
1105
1106 /* Check if we are the last thread */
1107 if (LastThread)
1108 {
1109 /* Notify the WMI Process Callback */
1110 //WmiTraceProcess(Process, FALSE);
1111
1112 /* Run the Notification Routines */
1114 }
1115
1116 /* Cleanup the power state */
1117 PopCleanupPowerState((PPOWER_STATE)&Process->Pcb.PowerState);
1118
1119 /* Clear the security port */
1120 if (!Process->SecurityPort)
1121 {
1122 /* So we don't double-dereference */
1123 Process->SecurityPort = (PVOID)1;
1124 }
1125 else if (Process->SecurityPort != (PVOID)1)
1126 {
1127 /* Dereference it */
1128 ObDereferenceObject(Process->SecurityPort);
1129 Process->SecurityPort = (PVOID)1;
1130 }
1131
1132 /* Check if we are the last thread */
1133 if (LastThread)
1134 {
1135 /* Check if we have to set the Timer Resolution */
1136 if (Process->SetTimerResolution)
1137 {
1138 /* Set it to default */
1140 }
1141
1142 /* Check if we are part of a Job that has a completion port */
1143 if ((Process->Job) && (Process->Job->CompletionPort))
1144 {
1145 /* FIXME: Check job status code and do I/O completion if needed */
1146 }
1147
1148 /* FIXME: Notify the Prefetcher */
1149 }
1150 else
1151 {
1152 /* Clear process' address space here */
1154 }
1155}
#define PSF_PROCESS_EXITING_BIT
Definition: pstypes.h:271
#define InterlockedOr
Definition: interlocked.h:239
NTSYSAPI NTSTATUS NTAPI ZwSetTimerResolution(_In_ ULONG RequestedResolution, _In_ BOOLEAN SetOrUnset, _Out_ PULONG ActualResolution)
VOID NTAPI MmCleanProcessAddressSpace(IN PEPROCESS Process)
Definition: procsup.c:1319
ULONG KeMaximumIncrement
Definition: clock.c:20
PETHREAD LastThread
Definition: pinsup.c:109
VOID NTAPI PopCleanupPowerState(IN PPOWER_STATE PowerState)
Definition: power.c:164
FORCEINLINE VOID PspRunCreateProcessNotifyRoutines(IN PEPROCESS CurrentProcess, IN BOOLEAN Create)
Definition: ps_x.h:62
void * PVOID
Definition: typedefs.h:50
int32_t * PLONG
Definition: typedefs.h:58
uint32_t ULONG
Definition: typedefs.h:59

Referenced by PspDeleteProcess(), and PspExitThread().

◆ PspExitThread()

VOID NTAPI PspExitThread ( IN NTSTATUS  ExitStatus)

Definition at line 469 of file kill.c.

470{
471 CLIENT_DIED_MSG TerminationMsg;
473 PTEB Teb;
474 PEPROCESS CurrentProcess;
475 PETHREAD Thread, OtherThread, PreviousThread = NULL;
476 PVOID DeallocationStack;
477 SIZE_T Dummy;
478 BOOLEAN Last = FALSE;
479 PTERMINATION_PORT TerminationPort, NextPort;
480 PLIST_ENTRY FirstEntry, CurrentEntry;
481 PKAPC Apc;
482 PTOKEN PrimaryToken;
483 PAGED_CODE();
484 PSTRACE(PS_KILL_DEBUG, "ExitStatus: %d\n", ExitStatus);
485
486 /* Get the Current Thread and Process */
488 CurrentProcess = Thread->ThreadsProcess;
490
491 /* Can't terminate a thread if it attached another process */
493 {
494 /* Bugcheck */
495 KeBugCheckEx(INVALID_PROCESS_ATTACH_ATTEMPT,
496 (ULONG_PTR)CurrentProcess,
497 (ULONG_PTR)Thread->Tcb.ApcState.Process,
500 }
501
502 /* Lower to Passive Level */
504
505 /* Can't be a worker thread */
507 {
508 /* Bugcheck */
509 KeBugCheckEx(ACTIVE_EX_WORKER_THREAD_TERMINATION,
511 0,
512 0,
513 0);
514 }
515
516 /* Can't have pending APCs */
517 if (Thread->Tcb.CombinedApcDisable != 0)
518 {
519 /* Bugcheck */
520 KeBugCheckEx(KERNEL_APC_PENDING_DURING_EXIT,
521 0,
523 0,
524 1);
525 }
526
527 /* Lock the thread */
529
530 /* Cleanup the power state */
532
533 /* Call the WMI Callback for Threads */
534 //WmiTraceThread(Thread, NULL, FALSE);
535
536 /* Run Thread Notify Routines before we desintegrate the thread */
538
539 /* Lock the Process before we modify its thread entries */
541 ExAcquirePushLockExclusive(&CurrentProcess->ProcessLock);
542
543 /* Decrease the active thread count, and check if it's 0 */
544 if (!(--CurrentProcess->ActiveThreads))
545 {
546 /* Set the delete flag */
548
549 /* Remember we are last */
550 Last = TRUE;
551
552 /* Check if this termination is due to the thread dying */
554 {
555 /* Check if the last thread was pending */
556 if (CurrentProcess->ExitStatus == STATUS_PENDING)
557 {
558 /* Use the last exit status */
559 CurrentProcess->ExitStatus = CurrentProcess->
560 LastThreadExitStatus;
561 }
562 }
563 else
564 {
565 /* Just a normal exit, write the code */
566 CurrentProcess->ExitStatus = ExitStatus;
567 }
568
569 /* Loop all the current threads */
570 FirstEntry = &CurrentProcess->ThreadListHead;
571 CurrentEntry = FirstEntry->Flink;
572 while (FirstEntry != CurrentEntry)
573 {
574 /* Get the thread on the list */
575 OtherThread = CONTAINING_RECORD(CurrentEntry,
576 ETHREAD,
577 ThreadListEntry);
578
579 /* Check if it's a thread that's still alive */
580 if ((OtherThread != Thread) &&
581 !(KeReadStateThread(&OtherThread->Tcb)) &&
582 (ObReferenceObjectSafe(OtherThread)))
583 {
584 /* It's a live thread and we referenced it, unlock process */
585 ExReleasePushLockExclusive(&CurrentProcess->ProcessLock);
587
588 /* Wait on the thread */
589 KeWaitForSingleObject(OtherThread,
590 Executive,
592 FALSE,
593 NULL);
594
595 /* Check if we had a previous thread to dereference */
596 if (PreviousThread) ObDereferenceObject(PreviousThread);
597
598 /* Remember the thread and re-lock the process */
599 PreviousThread = OtherThread;
601 ExAcquirePushLockExclusive(&CurrentProcess->ProcessLock);
602 }
603
604 /* Go to the next thread */
605 CurrentEntry = CurrentEntry->Flink;
606 }
607 }
609 {
610 /* Write down the exit status of the last thread to get killed */
611 CurrentProcess->LastThreadExitStatus = ExitStatus;
612 }
613
614 /* Unlock the Process */
615 ExReleasePushLockExclusive(&CurrentProcess->ProcessLock);
617
618 /* Check if we had a previous thread to dereference */
619 if (PreviousThread) ObDereferenceObject(PreviousThread);
620
621 /* Check if the process has a debug port and if this is a user thread */
622 if ((CurrentProcess->DebugPort) && !(Thread->SystemThread))
623 {
624 /* Notify the Debug API. */
625 Last ? DbgkExitProcess(CurrentProcess->ExitStatus) :
627 }
628
629 /* Check if this is a Critical Thread */
631 {
632 /* Break to debugger */
633 PspCatchCriticalBreak("Critical thread 0x%p (in %s) exited\n",
634 Thread,
635 CurrentProcess->ImageFileName);
636 }
637
638 /* Check if it's the last thread and this is a Critical Process */
639 if ((Last) && (CurrentProcess->BreakOnTermination))
640 {
641 /* Check if a debugger is here to handle this */
643 {
644 /* Break to debugger */
645 PspCatchCriticalBreak("Critical process 0x%p (%s) exited\n",
646 CurrentProcess,
647 CurrentProcess->ImageFileName);
648 }
649 else
650 {
651 /* Bugcheck, we can't allow this */
652 KeBugCheckEx(CRITICAL_PROCESS_DIED,
653 (ULONG_PTR)CurrentProcess,
654 0,
655 0,
656 0);
657 }
658 }
659
660 /* Sanity check */
662
663 /* Process the Termination Ports */
664 TerminationPort = Thread->TerminationPort;
665 if (TerminationPort)
666 {
667 /* Setup the message header */
668 TerminationMsg.h.u2.ZeroInit = 0;
669 TerminationMsg.h.u2.s2.Type = LPC_CLIENT_DIED;
670 TerminationMsg.h.u1.s1.TotalLength = sizeof(TerminationMsg);
671 TerminationMsg.h.u1.s1.DataLength = sizeof(TerminationMsg) -
672 sizeof(PORT_MESSAGE);
673
674 /* Loop each port */
675 do
676 {
677 /* Save the Create Time */
678 TerminationMsg.CreateTime = Thread->CreateTime;
679
680 /* Loop trying to send message */
681 while (TRUE)
682 {
683 /* Send the LPC Message */
684 Status = LpcRequestPort(TerminationPort->Port,
685 &TerminationMsg.h);
686 if ((Status == STATUS_NO_MEMORY) ||
688 {
689 /* Wait a bit and try again */
691 continue;
692 }
693 break;
694 }
695
696 /* Dereference this LPC Port */
697 ObDereferenceObject(TerminationPort->Port);
698
699 /* Move to the next one */
700 NextPort = TerminationPort->Next;
701
702 /* Free the Termination Port Object */
703 ExFreePoolWithTag(TerminationPort, '=TsP');
704
705 /* Keep looping as long as there is a port */
706 TerminationPort = NextPort;
707 } while (TerminationPort);
708 }
710 (Thread->DeadThread)) ||
711 !(Thread->DeadThread))
712 {
713 /*
714 * This case is special and deserves some extra comments. What
715 * basically happens here is that this thread doesn't have a termination
716 * port, which means that it died before being fully created. Since we
717 * still have to notify an LPC Server, we'll use the exception port,
718 * which we know exists. However, we need to know how far the thread
719 * actually got created. We have three possibilities:
720 *
721 * - NtCreateThread returned an error really early: DeadThread is set.
722 * - NtCreateThread managed to create the thread: DeadThread is off.
723 * - NtCreateThread was creating the thread (with DeadThread set,
724 * but the thread got killed prematurely: STATUS_THREAD_IS_TERMINATING
725 * is our exit code.)
726 *
727 * For the 2 & 3rd scenarios, the thread has been created far enough to
728 * warrant notification to the LPC Server.
729 */
730
731 /* Setup the message header */
732 TerminationMsg.h.u2.ZeroInit = 0;
733 TerminationMsg.h.u2.s2.Type = LPC_CLIENT_DIED;
734 TerminationMsg.h.u1.s1.TotalLength = sizeof(TerminationMsg);
735 TerminationMsg.h.u1.s1.DataLength = sizeof(TerminationMsg) -
736 sizeof(PORT_MESSAGE);
737
738 /* Make sure the process has an exception port */
739 if (CurrentProcess->ExceptionPort)
740 {
741 /* Save the Create Time */
742 TerminationMsg.CreateTime = Thread->CreateTime;
743
744 /* Loop trying to send message */
745 while (TRUE)
746 {
747 /* Send the LPC Message */
748 Status = LpcRequestPort(CurrentProcess->ExceptionPort,
749 &TerminationMsg.h);
750 if ((Status == STATUS_NO_MEMORY) ||
752 {
753 /* Wait a bit and try again */
755 continue;
756 }
757 break;
758 }
759 }
760 }
761
762 /* Rundown Win32 Thread if there is one */
765
766 /* If we are the last thread and have a W32 Process */
767 if ((Last) && (CurrentProcess->Win32Process))
768 {
769 /* Run it down too */
770 PspW32ProcessCallout(CurrentProcess, FALSE);
771 }
772
773 /* Make sure Stack Swap is enabled */
775 {
776 /* Stack swap really shouldn't be disabled during exit! */
777 KeBugCheckEx(KERNEL_STACK_LOCKED_AT_EXIT, 0, 0, 0, 0);
778 }
779
780 /* Cancel I/O for the thread. */
782
783 /* Rundown Timers */
785
786 /* FIXME: Rundown Registry Notifications (NtChangeNotify)
787 CmNotifyRunDown(Thread); */
788
789 /* Rundown Mutexes */
791
792 /* Check if we have a TEB */
793 Teb = Thread->Tcb.Teb;
794 if (Teb)
795 {
796 /* Check if the thread is still alive */
797 if (!Thread->DeadThread)
798 {
799 /* Check if we need to free its stack */
800 if (Teb->FreeStackOnTermination)
801 {
802 /* Set the TEB's Deallocation Stack as the Base Address */
803 Dummy = 0;
804 DeallocationStack = Teb->DeallocationStack;
805
806 /* Free the Thread's Stack */
807 ZwFreeVirtualMemory(NtCurrentProcess(),
808 &DeallocationStack,
809 &Dummy,
811 }
812
813 /* Free the debug handle */
814 if (Teb->DbgSsReserved[1]) ObCloseHandle(Teb->DbgSsReserved[1],
815 UserMode);
816 }
817
818 /* Decommit the TEB */
819 MmDeleteTeb(CurrentProcess, Teb);
820 Thread->Tcb.Teb = NULL;
821 }
822
823 /* Free LPC Data */
825
826 /* Save the exit status and exit time */
829
830 /* Sanity check */
832
833 /* Check if this is the final thread or not */
834 if (Last)
835 {
836 /* Set the process exit time */
837 CurrentProcess->ExitTime = Thread->ExitTime;
838
839 /* Exit the process */
840 PspExitProcess(TRUE, CurrentProcess);
841
842 /* Get the process token and check if we need to audit */
843 PrimaryToken = PsReferencePrimaryToken(CurrentProcess);
844 if (SeDetailedAuditingWithToken(PrimaryToken))
845 {
846 /* Audit the exit */
847 SeAuditProcessExit(CurrentProcess);
848 }
849
850 /* Dereference the process token */
851 ObFastDereferenceObject(&CurrentProcess->Token, PrimaryToken);
852
853 /* Check if this is a VDM Process and rundown the VDM DPCs if so */
854 if (CurrentProcess->VdmObjects) { /* VdmRundownDpcs(CurrentProcess); */ }
855
856 /* Kill the process in the Object Manager */
857 ObKillProcess(CurrentProcess);
858
859 /* Check if we have a section object */
860 if (CurrentProcess->SectionObject)
861 {
862 /* Dereference and clear the Section Object */
863 ObDereferenceObject(CurrentProcess->SectionObject);
864 CurrentProcess->SectionObject = NULL;
865 }
866
867 /* Check if the process is part of a job */
868 if (CurrentProcess->Job)
869 {
870 /* Remove the process from the job */
871 PspExitProcessFromJob(CurrentProcess->Job, CurrentProcess);
872 }
873 }
874
875 /* Disable APCs */
877
878 /* Disable APC queueing, force a resumption */
881
882 /* Re-enable APCs */
884
885 /* Flush the User APCs */
886 FirstEntry = KeFlushQueueApc(&Thread->Tcb, UserMode);
887 if (FirstEntry)
888 {
889 /* Start with the first entry */
890 CurrentEntry = FirstEntry;
891 do
892 {
893 /* Get the APC */
894 Apc = CONTAINING_RECORD(CurrentEntry, KAPC, ApcListEntry);
895
896 /* Move to the next one */
897 CurrentEntry = CurrentEntry->Flink;
898
899 /* Rundown the APC or de-allocate it */
900 if (Apc->RundownRoutine)
901 {
902 /* Call its own routine */
903 Apc->RundownRoutine(Apc);
904 }
905 else
906 {
907 /* Do it ourselves */
908 ExFreePool(Apc);
909 }
910 }
911 while (CurrentEntry != FirstEntry);
912 }
913
914 /* Clean address space if this was the last thread */
915 if (Last) MmCleanProcessAddressSpace(CurrentProcess);
916
917 /* Call the Lego routine */
919
920 /* Flush the APC queue, which should be empty */
921 FirstEntry = KeFlushQueueApc(&Thread->Tcb, KernelMode);
922 if ((FirstEntry) || (Thread->Tcb.CombinedApcDisable != 0))
923 {
924 /* Bugcheck time */
925 KeBugCheckEx(KERNEL_APC_PENDING_DURING_EXIT,
926 (ULONG_PTR)FirstEntry,
929 0);
930 }
931
932 /* Signal the process if this was the last thread */
933 if (Last) KeSetProcess(&CurrentProcess->Pcb, 0, FALSE);
934
935 /* Terminate the Thread from the Scheduler */
937}
#define STATUS_NO_MEMORY
Definition: d3dkmdt.h:51
VOID NTAPI DbgkExitThread(IN NTSTATUS ExitStatus)
Definition: dbgkutil.c:340
VOID NTAPI DbgkExitProcess(IN NTSTATUS ExitStatus)
Definition: dbgkutil.c:304
#define PASSIVE_LEVEL
Definition: env_spec_w32.h:693
#define KeWaitForSingleObject(pEvt, foo, a, b, c)
Definition: env_spec_w32.h:478
#define KeLowerIrql(oldIrql)
Definition: env_spec_w32.h:602
#define KeQuerySystemTime(t)
Definition: env_spec_w32.h:570
#define KeGetCurrentIrql()
Definition: env_spec_w32.h:706
#define KeDelayExecutionThread(mode, foo, t)
Definition: env_spec_w32.h:484
#define ExWaitForRundownProtectionRelease
Definition: ex.h:141
@ PsW32ThreadCalloutExit
Definition: pstypes.h:534
VOID NTAPI LpcExitThread(IN PETHREAD Thread)
Definition: close.c:19
#define LPC_CLIENT_DIED
Definition: port.c:98
#define KernelMode
Definition: asm.h:38
#define MEM_RELEASE
Definition: nt_native.h:1319
VOID NTAPI ExTimerRundown(VOID)
Definition: timer.c:43
VOID NTAPI IoCancelThreadIo(IN PETHREAD Thread)
Definition: irp.c:1178
ULONG NTAPI KeForceResumeThread(IN PKTHREAD Thread)
Definition: thrdobj.c:267
ULONG NTAPI KeSetProcess(struct _KPROCESS *Process, KPRIORITY Increment, BOOLEAN InWait)
PLIST_ENTRY NTAPI KeFlushQueueApc(IN PKTHREAD Thread, IN KPROCESSOR_MODE PreviousMode)
Definition: apc.c:793
VOID NTAPI KeRundownThread(VOID)
Definition: thrdobj.c:430
BOOLEAN NTAPI KeReadStateThread(IN PKTHREAD Thread)
Definition: thrdobj.c:42
VOID NTAPI MmDeleteTeb(struct _EPROCESS *Process, PTEB Teb)
VOID NTAPI SeAuditProcessExit(_In_ PEPROCESS Process)
Peforms a security auditing against a process that is about to be terminated.
Definition: audit.c:77
BOOLEAN NTAPI SeDetailedAuditingWithToken(_In_ PTOKEN Token)
Peforms a detailed security auditing with an access token.
Definition: audit.c:34
NTSTATUS NTAPI LpcRequestPort(IN PVOID PortObject, IN PPORT_MESSAGE LpcMessage)
Definition: send.c:22
LARGE_INTEGER ShortTime
Definition: kill.c:21
PACCESS_TOKEN NTAPI PsReferencePrimaryToken(PEPROCESS Process)
Definition: security.c:440
#define STATUS_THREAD_IS_TERMINATING
Definition: ntstatus.h:405
BOOLEAN FASTCALL ObReferenceObjectSafe(IN PVOID Object)
Definition: obref.c:22
VOID FASTCALL ObFastDereferenceObject(IN PEX_FAST_REF FastRef, IN PVOID Object)
Definition: obref.c:167
NTSTATUS NTAPI ObCloseHandle(IN HANDLE Handle, IN KPROCESSOR_MODE AccessMode)
Definition: obhandle.c:3406
BOOLEAN NTAPI KeIsAttachedProcess(VOID)
Definition: procobj.c:693
PKWIN32_THREAD_CALLOUT PspW32ThreadCallout
Definition: win32.c:19
VOID NTAPI PspExitProcessFromJob(IN PEJOB Job, IN PEPROCESS Process)
Definition: job.c:146
PKWIN32_PROCESS_CALLOUT PspW32ProcessCallout
Definition: win32.c:18
FORCEINLINE VOID PspRunLegoRoutine(IN PKTHREAD Thread)
Definition: ps_x.h:103
FORCEINLINE VOID PspRunCreateThreadNotifyRoutines(IN PETHREAD CurrentThread, IN BOOLEAN Create)
Definition: ps_x.h:40
PORT_MESSAGE h
Definition: lpctypes.h:273
LARGE_INTEGER CreateTime
Definition: lpctypes.h:274
PVOID SectionObject
Definition: pstypes.h:1411
LIST_ENTRY ThreadListHead
Definition: pstypes.h:1436
PVOID VdmObjects
Definition: pstypes.h:1419
NTSTATUS ExitStatus
Definition: pstypes.h:1544
PVOID DebugPort
Definition: pstypes.h:1382
KPROCESS Pcb
Definition: pstypes.h:1369
EX_FAST_REF Token
Definition: pstypes.h:1394
struct _EJOB * Job
Definition: pstypes.h:1410
EX_PUSH_LOCK ProcessLock
Definition: pstypes.h:1370
ULONG Flags
Definition: pstypes.h:1542
PVOID * Win32Process
Definition: pstypes.h:1409
NTSTATUS LastThreadExitStatus
Definition: pstypes.h:1450
CHAR ImageFileName[16]
Definition: pstypes.h:1433
LARGE_INTEGER ExitTime
Definition: pstypes.h:1372
ULONG BreakOnTermination
Definition: pstypes.h:1512
ULONG ActiveThreads
Definition: pstypes.h:1443
LARGE_INTEGER ExitTime
Definition: pstypes.h:1202
NTSTATUS ExitStatus
Definition: pstypes.h:1208
EX_RUNDOWN_REF RundownProtect
Definition: pstypes.h:1254
ULONG ActiveExWorker
Definition: pstypes.h:1295
LARGE_INTEGER CreateTime
Definition: pstypes.h:1199
ULONG BreakOnTermination
Definition: pstypes.h:1279
ULONG SystemThread
Definition: pstypes.h:1277
ULONG CombinedApcDisable
Definition: ketypes.h:2030
UCHAR ApcStateIndex
Definition: ketypes.h:2089
PVOID Teb
Definition: ketypes.h:1954
PVOID LegoData
Definition: ketypes.h:2144
ULONG EnableStackSwap
Definition: ketypes.h:1876
ULONG ApcQueueable
Definition: ketypes.h:1858
Definition: typedefs.h:120
Definition: compat.h:836
PVOID DbgSsReserved[2]
Definition: compat.h:883
PVOID DeallocationStack
Definition: compat.h:878
#define STATUS_PENDING
Definition: telnetd.h:14
VOID NTAPI KeTerminateThread(IN KPRIORITY Increment)
Definition: thrdobj.c:1348
ULONG_PTR SIZE_T
Definition: typedefs.h:80
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
@ Executive
Definition: ketypes.h:467

Referenced by PsExitSpecialApc(), and PspTerminateThreadByPointer().

◆ PspIsProcessExiting()

BOOLEAN NTAPI PspIsProcessExiting ( IN PEPROCESS  Process)

Definition at line 1087 of file kill.c.

1088{
1089 return Process->Flags & PSF_PROCESS_EXITING_BIT;
1090}

Referenced by MmpPageOutPhysicalAddress().

◆ PspReapRoutine()

VOID NTAPI PspReapRoutine ( IN PVOID  Context)

Definition at line 167 of file kill.c.

168{
169 PSINGLE_LIST_ENTRY NextEntry;
171 PSTRACE(PS_KILL_DEBUG, "Context: %p\n", Context);
172
173 /* Start main loop */
174 do
175 {
176 /* Write magic value and return the next entry to process */
178 (PVOID)1);
179 ASSERT((NextEntry != NULL) && (NextEntry != (PVOID)1));
180
181 /* Start inner loop */
182 do
183 {
184 /* Get the first Thread Entry */
185 Thread = CONTAINING_RECORD(NextEntry, ETHREAD, ReaperLink);
186
187 /* Delete this entry's kernel stack */
189 Thread->Tcb.LargeStack);
191
192 /* Move to the next entry */
193 NextEntry = NextEntry->Next;
194
195 /* Dereference this thread */
197 } while ((NextEntry != NULL) && (NextEntry != (PVOID)1));
198
199 /* Remove magic value, keep looping if it got changed */
201 NULL,
202 (PVOID)1) != (PVOID)1);
203}
#define InterlockedExchangePointer(Target, Value)
Definition: dshow.h:45
#define InterlockedCompareExchangePointer
Definition: interlocked.h:144
LIST_ENTRY PspReaperListHead
Definition: kill.c:19
_In_ PVOID Context
Definition: storport.h:2269
Definition: ntbasedef.h:640
struct _SINGLE_LIST_ENTRY * Next
Definition: ntbasedef.h:641

Referenced by PspInitPhase0().

◆ PspShutdownProcessManager()

VOID NTAPI PspShutdownProcessManager ( VOID  )

Definition at line 135 of file kill.c.

136{
138
139 /* Loop every process */
141 while (Process)
142 {
143 /* Make sure this isn't the idle or initial process */
145 {
146 /* Kill it */
148 }
149
150 /* Get the next process */
152 }
153}
NTSTATUS NTAPI PspTerminateProcess(IN PEPROCESS Process, IN NTSTATUS ExitStatus)
Definition: kill.c:79
#define STATUS_SYSTEM_SHUTDOWN
Definition: ntstatus.h:981
PEPROCESS NTAPI PsGetNextProcess(IN PEPROCESS OldProcess OPTIONAL)
Definition: process.c:128
PEPROCESS PsIdleProcess
Definition: psmgr.c:51
PEPROCESS PsInitialSystemProcess
Definition: psmgr.c:50

◆ PspTerminateProcess()

NTSTATUS NTAPI PspTerminateProcess ( IN PEPROCESS  Process,
IN NTSTATUS  ExitStatus 
)

Definition at line 79 of file kill.c.

81{
84 PAGED_CODE();
86 "Process: %p ExitStatus: %d\n", Process, ExitStatus);
88
89 /* Check if this is a Critical Process */
90 if (Process->BreakOnTermination)
91 {
92 /* Break to debugger */
93 PspCatchCriticalBreak("Terminating critical process 0x%p (%s)\n",
94 Process,
95 Process->ImageFileName);
96 }
97
98 /* Set the delete flag */
100
101 /* Get the first thread */
103 while (Thread)
104 {
105 /* Kill it */
108
109 /* We had at least one thread, so termination is OK */
111 }
112
113 /* Check if there was nothing to terminate or if we have a debug port */
114 if ((Status == STATUS_NOTHING_TO_TERMINATE) || (Process->DebugPort))
115 {
116 /* Clear the handle table anyway */
118 }
119
120 /* Return status */
121 return Status;
122}

Referenced by PspShutdownProcessManager(), and PsTerminateProcess().

◆ PspTerminateThreadByPointer()

NTSTATUS NTAPI PspTerminateThreadByPointer ( IN PETHREAD  Thread,
IN NTSTATUS  ExitStatus,
IN BOOLEAN  bSelf 
)

Definition at line 1007 of file kill.c.

1010{
1011 PKAPC Apc;
1013 ULONG Flags;
1014 PAGED_CODE();
1015 PSTRACE(PS_KILL_DEBUG, "Thread: %p ExitStatus: %d\n", Thread, ExitStatus);
1017
1018 /* Check if this is a Critical Thread, and Bugcheck */
1020 {
1021 /* Break to debugger */
1022 PspCatchCriticalBreak("Terminating critical thread 0x%p (in %s)\n",
1023 Thread,
1024 Thread->ThreadsProcess->ImageFileName);
1025 }
1026
1027 /* Check if we are already inside the thread */
1028 if ((bSelf) || (PsGetCurrentThread() == Thread))
1029 {
1030 /* This should only happen at passive */
1032
1033 /* Mark it as terminated */
1035
1036 /* Directly terminate the thread */
1038 }
1039
1040 /* This shouldn't be a system thread */
1042
1043 /* Allocate the APC */
1045 if (!Apc) return STATUS_INSUFFICIENT_RESOURCES;
1046
1047 /* Set the Terminated Flag */
1049
1050 /* Set it, and check if it was already set while we were running */
1053 {
1054 /* Initialize a Kernel Mode APC to Kill the Thread */
1055 KeInitializeApc(Apc,
1056 &Thread->Tcb,
1061 KernelMode,
1063
1064 /* Insert it into the APC Queue */
1065 if (!KeInsertQueueApc(Apc, Apc, NULL, 2))
1066 {
1067 /* The APC was already in the queue, fail */
1069 }
1070 else
1071 {
1072 /* Forcefully resume the thread and return */
1074 return Status;
1075 }
1076 }
1077
1078 /* We failed, free the APC */
1080
1081 /* Return Status */
1082 return Status;
1083}
#define InterlockedExchange
Definition: armddk.h:54
#define ASSERT_IRQL_EQUAL(x)
Definition: debug.h:43
#define UlongToPtr(u)
Definition: config.h:106
#define CT_TERMINATED_BIT
Definition: pstypes.h:234
#define PspSetCrossThreadFlag(Thread, Flag)
Definition: ps_x.h:25
ULONG CrossThreadFlags
Definition: pstypes.h:1289
#define TAG_TERMINATE_APC
Definition: tag.h:135
#define STATUS_ACCESS_DENIED
Definition: udferr_usr.h:145
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170

Referenced by NtTerminateProcess(), NtTerminateThread(), PspSystemThreadStartup(), PspTerminateProcess(), PspUserThreadStartup(), and PsTerminateSystemThread().

◆ PsTerminateProcess()

NTSTATUS NTAPI PsTerminateProcess ( IN PEPROCESS  Process,
IN NTSTATUS  ExitStatus 
)

Definition at line 126 of file kill.c.

128{
129 /* Call the internal API */
131}

Referenced by DbgkpCloseObject(), and ExpDebuggerWorker().

◆ PsTerminateSystemThread()

Variable Documentation

◆ PspReaperListHead

LIST_ENTRY PspReaperListHead = { NULL, NULL }

Definition at line 19 of file kill.c.

Referenced by KeTerminateThread(), and PspReapRoutine().

◆ PspReaperWorkItem

WORK_QUEUE_ITEM PspReaperWorkItem

Definition at line 20 of file kill.c.

Referenced by KeTerminateThread(), and PspInitPhase0().

◆ ShortTime

LARGE_INTEGER ShortTime = {{-10 * 100 * 1000, -1}}

Definition at line 21 of file kill.c.

Referenced by PspExitThread().