Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2188 lines
58 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. psdelete.c
  5. Abstract:
  6. This module implements process and thread object termination and
  7. deletion.
  8. Author:
  9. Mark Lucovsky (markl) 01-May-1989
  10. Revision History:
  11. --*/
  12. #include "psp.h"
  13. extern PEPROCESS ExpDefaultErrorPortProcess;
  14. #ifdef ALLOC_PRAGMA
  15. NTSTATUS
  16. PspFreezeProcessWorker (
  17. PEPROCESS Process,
  18. PVOID Context
  19. );
  20. VOID
  21. PspCatchCriticalBreak(
  22. IN PCHAR Msg,
  23. IN PVOID Object,
  24. IN PUCHAR ImageFileName
  25. );
  26. #pragma alloc_text(PAGE, PsSetLegoNotifyRoutine)
  27. #pragma alloc_text(PAGE, PspTerminateThreadByPointer)
  28. #pragma alloc_text(PAGE, NtTerminateProcess)
  29. #pragma alloc_text(PAGE, PsTerminateProcess)
  30. #pragma alloc_text(PAGE, PspWaitForUsermodeExit)
  31. #pragma alloc_text(PAGE, NtTerminateThread)
  32. #pragma alloc_text(PAGE, PsTerminateSystemThread)
  33. #pragma alloc_text(PAGE, PspNullSpecialApc)
  34. #pragma alloc_text(PAGE, PsExitSpecialApc)
  35. #pragma alloc_text(PAGE, PspExitApcRundown)
  36. #pragma alloc_text(PAGE, PspExitNormalApc)
  37. #pragma alloc_text(PAGE, PspCatchCriticalBreak)
  38. #pragma alloc_text(PAGE, PspExitThread)
  39. #pragma alloc_text(PAGE, PspExitProcess)
  40. #pragma alloc_text(PAGE, PspProcessDelete)
  41. #pragma alloc_text(PAGE, PspThreadDelete)
  42. #pragma alloc_text(PAGE, NtRegisterThreadTerminatePort)
  43. #pragma alloc_text(PAGE, PsGetProcessExitTime)
  44. #pragma alloc_text(PAGE, PsShutdownSystem)
  45. #pragma alloc_text(PAGE, PsWaitForAllProcesses)
  46. #pragma alloc_text(PAGE, PspFreezeProcessWorker)
  47. #pragma alloc_text(PAGE, PspTerminateProcess)
  48. #endif
  49. #ifdef ALLOC_DATA_PRAGMA
  50. #pragma data_seg("PAGEDATA")
  51. #endif
  52. PLEGO_NOTIFY_ROUTINE PspLegoNotifyRoutine = NULL;
  53. ULONG
  54. PsSetLegoNotifyRoutine(
  55. PLEGO_NOTIFY_ROUTINE LegoNotifyRoutine
  56. )
  57. {
  58. PAGED_CODE();
  59. PspLegoNotifyRoutine = LegoNotifyRoutine;
  60. return FIELD_OFFSET(KTHREAD,LegoData);
  61. }
  62. VOID
  63. PspReaper(
  64. IN PVOID Context
  65. )
  66. /*++
  67. Routine Description:
  68. This routine implements the thread reaper. The reaper is responsible
  69. for processing terminated threads. This includes:
  70. - deallocating their kernel stacks
  71. - releasing their process' CreateDelete lock
  72. - dereferencing their process
  73. - dereferencing themselves
  74. Arguments:
  75. Context - NOT USED
  76. Return Value:
  77. None.
  78. --*/
  79. {
  80. KIRQL OldIrql;
  81. PETHREAD Thread, NextThread;
  82. UNREFERENCED_PARAMETER (Context);
  83. //
  84. // Remove the current list of threads from the reaper list, acquire
  85. // the context swap lock, and then release the both the context
  86. // swap dispatcher database locks.
  87. //
  88. //
  89. // N.B. The dispatcher database lock is used to synchronize access to
  90. // the reaper list. This is done to avoid a race condition with
  91. // the thread termination code.
  92. //
  93. //
  94. while (1) {
  95. KiLockDispatcherDatabase (&OldIrql);
  96. Thread = PsReaperList;
  97. PsReaperList = NULL;
  98. if (Thread == NULL) {
  99. //
  100. // Set the reaper not active and return.
  101. //
  102. PsReaperActive = FALSE;
  103. KiUnlockDispatcherDatabase (OldIrql);
  104. return;
  105. } else {
  106. KiUnlockDispatcherDatabase (OldIrql);
  107. //
  108. // The context swap lock is acquired and immediately released.
  109. // This is necessary to ensure that the respective thread has
  110. // completely passed through the context switch code before it
  111. // is terminated.
  112. //
  113. #if !defined (NT_UP)
  114. KiLockContextSwap (&OldIrql);
  115. KiUnlockContextSwap (OldIrql);
  116. #endif
  117. }
  118. //
  119. // Delete the kernel stack and dereference the thread.
  120. //
  121. do {
  122. MmDeleteKernelStack (Thread->Tcb.StackBase,
  123. (BOOLEAN)Thread->Tcb.LargeStack);
  124. Thread->Tcb.InitialStack = NULL;
  125. NextThread = Thread->ReaperLink;
  126. ObDereferenceObject (Thread);
  127. Thread = NextThread;
  128. } while (Thread != NULL);
  129. }
  130. return;
  131. }
  132. NTSTATUS
  133. PspTerminateThreadByPointer(
  134. IN PETHREAD Thread,
  135. IN NTSTATUS ExitStatus
  136. )
  137. /*++
  138. Routine Description:
  139. This function causes the specified thread to terminate.
  140. Arguments:
  141. ThreadHandle - Supplies a referenced pointer to the thread to terminate.
  142. ExitStatus - Supplies the exit status associated with the thread.
  143. Return Value:
  144. TBD
  145. --*/
  146. {
  147. NTSTATUS Status;
  148. PKAPC ExitApc=NULL;
  149. ULONG OldMask;
  150. LARGE_INTEGER ShortTime = {(ULONG)(-10 * 1000 * 100), -1}; // 100 milliseconds
  151. PAGED_CODE();
  152. if (Thread->CrossThreadFlags
  153. & PS_CROSS_THREAD_FLAGS_BREAK_ON_TERMINATION) {
  154. PspCatchCriticalBreak("Terminating critical thread 0x%p (in %s)\n",
  155. Thread,
  156. THREAD_TO_PROCESS(Thread)->ImageFileName);
  157. }
  158. if (Thread == PsGetCurrentThread()) {
  159. PS_SET_BITS (&Thread->CrossThreadFlags, PS_CROSS_THREAD_FLAGS_TERMINATED);
  160. PspExitThread (ExitStatus);
  161. //
  162. // Never Returns
  163. //
  164. } else {
  165. //
  166. // Cross thread deletion of system threads won't work.
  167. //
  168. if (IS_SYSTEM_THREAD (Thread)) {
  169. return STATUS_ACCESS_DENIED;
  170. }
  171. Status = STATUS_SUCCESS;
  172. while (1) {
  173. ExitApc = (PKAPC) ExAllocatePoolWithTag (NonPagedPool,
  174. sizeof(KAPC),
  175. 'xEsP');
  176. if (ExitApc != NULL) {
  177. break;
  178. }
  179. KeDelayExecutionThread(KernelMode, FALSE, &ShortTime);
  180. }
  181. //
  182. // Mark the thread as terminating and call the exit function.
  183. //
  184. OldMask = PS_TEST_SET_BITS (&Thread->CrossThreadFlags, PS_CROSS_THREAD_FLAGS_TERMINATED);
  185. //
  186. // If we are the first to set the terminating flag then queue the APC
  187. //
  188. if ((OldMask & PS_CROSS_THREAD_FLAGS_TERMINATED) == 0) {
  189. KeInitializeApc (ExitApc,
  190. PsGetKernelThread (Thread),
  191. OriginalApcEnvironment,
  192. PsExitSpecialApc,
  193. PspExitApcRundown,
  194. PspExitNormalApc,
  195. KernelMode,
  196. ULongToPtr (ExitStatus));
  197. if (!KeInsertQueueApc (ExitApc, ExitApc, NULL, 2)) {
  198. // Note that we'll get here if APC queueing has been
  199. // disabled -- on the other hand, in that case, the thread
  200. // is exiting anyway.
  201. ExFreePool (ExitApc);
  202. Status = STATUS_UNSUCCESSFUL;
  203. } else {
  204. //
  205. // We queued the APC to the thread. Wake up the thread if it was suspened.
  206. //
  207. KeForceResumeThread (&Thread->Tcb);
  208. }
  209. } else {
  210. ExFreePool (ExitApc);
  211. }
  212. }
  213. return Status;
  214. }
  215. NTSTATUS
  216. NtTerminateProcess(
  217. IN HANDLE ProcessHandle OPTIONAL,
  218. IN NTSTATUS ExitStatus
  219. )
  220. /*++
  221. Routine Description:
  222. This function causes the specified process and all of
  223. its threads to terminate.
  224. Arguments:
  225. ProcessHandle - Supplies a handle to the process to terminate.
  226. ExitStatus - Supplies the exit status associated with the process.
  227. Return Value:
  228. NTSTATUS - Status of operation
  229. --*/
  230. {
  231. PETHREAD Thread, Self;
  232. PEPROCESS Process;
  233. PEPROCESS CurrentProcess;
  234. NTSTATUS st;
  235. BOOLEAN ProcessHandleSpecified;
  236. PAGED_CODE();
  237. Self = PsGetCurrentThread();
  238. CurrentProcess = PsGetCurrentProcessByThread (Self);
  239. if (ARGUMENT_PRESENT (ProcessHandle)) {
  240. ProcessHandleSpecified = TRUE;
  241. } else {
  242. ProcessHandleSpecified = FALSE;
  243. ProcessHandle = NtCurrentProcess();
  244. }
  245. st = ObReferenceObjectByHandle (ProcessHandle,
  246. PROCESS_TERMINATE,
  247. PsProcessType,
  248. KeGetPreviousModeByThread(&Self->Tcb),
  249. &Process,
  250. NULL);
  251. if (!NT_SUCCESS (st)) {
  252. return(st);
  253. }
  254. if (Process->Flags & PS_PROCESS_FLAGS_BREAK_ON_TERMINATION) {
  255. PspCatchCriticalBreak ("Terminating critical process 0x%p (%s)\n",
  256. Process,
  257. Process->ImageFileName);
  258. }
  259. //
  260. // Acquire rundown protection just so we can give the right errors
  261. //
  262. if (!ExAcquireRundownProtection (&Process->RundownProtect)) {
  263. ObDereferenceObject (Process);
  264. return STATUS_PROCESS_IS_TERMINATING;
  265. }
  266. //
  267. // Mark process as deleting except for the obscure delete self case.
  268. //
  269. if (ProcessHandleSpecified) {
  270. PS_SET_BITS (&Process->Flags, PS_PROCESS_FLAGS_PROCESS_DELETE);
  271. }
  272. st = STATUS_NOTHING_TO_TERMINATE;
  273. for (Thread = PsGetNextProcessThread (Process, NULL);
  274. Thread != NULL;
  275. Thread = PsGetNextProcessThread (Process, Thread)) {
  276. st = STATUS_SUCCESS;
  277. if (Thread != Self) {
  278. PspTerminateThreadByPointer (Thread, ExitStatus);
  279. }
  280. }
  281. ExReleaseRundownProtection (&Process->RundownProtect);
  282. if (Process == CurrentProcess) {
  283. if (ProcessHandleSpecified) {
  284. ObDereferenceObject (Process);
  285. //
  286. // Never Returns
  287. //
  288. PspTerminateThreadByPointer (Self, ExitStatus);
  289. }
  290. } else if (ExitStatus == DBG_TERMINATE_PROCESS) {
  291. DbgkClearProcessDebugObject (Process, NULL);
  292. }
  293. //
  294. // If there are no threads in this process then clear out its handle table.
  295. // Do the same for processes being debugged. This is so a process can never lock itself into the system
  296. // by debugging itself or have a handle open to itself.
  297. //
  298. if (st == STATUS_NOTHING_TO_TERMINATE || (Process->DebugPort != NULL && ProcessHandleSpecified)) {
  299. ObClearProcessHandleTable (Process);
  300. st = STATUS_SUCCESS;
  301. }
  302. ObDereferenceObject(Process);
  303. return st;
  304. }
  305. NTSTATUS
  306. PsTerminateProcess(
  307. PEPROCESS Process,
  308. NTSTATUS Status
  309. )
  310. {
  311. return PspTerminateProcess (Process, Status);
  312. }
  313. NTSTATUS
  314. PspTerminateProcess(
  315. PEPROCESS Process,
  316. NTSTATUS ExitStatus
  317. )
  318. /*++
  319. Routine Description:
  320. This function causes the specified process and all of
  321. its threads to terminate.
  322. Arguments:
  323. ProcessHandle - Supplies a handle to the process to terminate.
  324. ExitStatus - Supplies the exit status associated with the process.
  325. Return Value:
  326. TBD
  327. --*/
  328. {
  329. PETHREAD Thread;
  330. NTSTATUS st;
  331. PAGED_CODE();
  332. if (Process == PsGetCurrentProcess ()) {
  333. return STATUS_INVALID_PARAMETER;
  334. }
  335. if (Process->Flags
  336. & PS_PROCESS_FLAGS_BREAK_ON_TERMINATION) {
  337. PspCatchCriticalBreak("Terminating critical process 0x%p (%s)\n",
  338. Process,
  339. Process->ImageFileName);
  340. }
  341. //
  342. // Mark process as deleting
  343. //
  344. PS_SET_BITS (&Process->Flags, PS_PROCESS_FLAGS_PROCESS_DELETE);
  345. st = STATUS_NOTHING_TO_TERMINATE;
  346. for (Thread = PsGetNextProcessThread (Process, NULL);
  347. Thread != NULL;
  348. Thread = PsGetNextProcessThread (Process, Thread)) {
  349. st = STATUS_SUCCESS;
  350. PspTerminateThreadByPointer (Thread, ExitStatus);
  351. }
  352. //
  353. // If there are no threads in this process then clear out its handle table.
  354. // Do the same for processes being debugged. This is so a process can never lock itself into the system
  355. // by debugging itself or have a handle open to itself.
  356. //
  357. if (st == STATUS_NOTHING_TO_TERMINATE || Process->DebugPort != NULL) {
  358. ObClearProcessHandleTable (Process);
  359. st = STATUS_SUCCESS;
  360. }
  361. return st;
  362. }
  363. NTSTATUS
  364. PspWaitForUsermodeExit(
  365. IN PEPROCESS Process
  366. )
  367. /*++
  368. Routine Description:
  369. This function waits for a process's usermode threads to terminate.
  370. Arguments:
  371. Process - Supplies a pointer to the process to wait for
  372. WaitMode - Supplies the mode to wait in
  373. LockMode - Supplies the way to wait for the process lock
  374. Return Value:
  375. NTSTATUS - Status of call
  376. --*/
  377. {
  378. BOOLEAN GotAThread;
  379. PETHREAD Thread;
  380. do {
  381. GotAThread = FALSE;
  382. for (Thread = PsGetNextProcessThread (Process, NULL);
  383. Thread != NULL;
  384. Thread = PsGetNextProcessThread (Process, Thread)) {
  385. if (!IS_SYSTEM_THREAD (Thread) && !KeReadStateThread (&Thread->Tcb)) {
  386. ObReferenceObject (Thread);
  387. PsQuitNextProcessThread (Thread);
  388. GotAThread = TRUE;
  389. break;
  390. }
  391. }
  392. if (GotAThread) {
  393. KeWaitForSingleObject (Thread,
  394. Executive,
  395. KernelMode,
  396. FALSE,
  397. NULL);
  398. ObDereferenceObject (Thread);
  399. }
  400. } while (GotAThread);
  401. return STATUS_SUCCESS;
  402. }
  403. NTSTATUS
  404. NtTerminateThread(
  405. IN HANDLE ThreadHandle OPTIONAL,
  406. IN NTSTATUS ExitStatus
  407. )
  408. /*++
  409. Routine Description:
  410. This function causes the specified thread to terminate.
  411. Arguments:
  412. ThreadHandle - Supplies a handle to the thread to terminate.
  413. ExitStatus - Supplies the exit status associated with the thread.
  414. Return Value:
  415. TBD
  416. --*/
  417. {
  418. PETHREAD Thread=NULL, ThisThread;
  419. PEPROCESS ThisProcess;
  420. NTSTATUS Status = STATUS_SUCCESS;
  421. BOOLEAN Self = TRUE;
  422. PAGED_CODE();
  423. ThisThread = PsGetCurrentThread ();
  424. if (!ARGUMENT_PRESENT (ThreadHandle)) {
  425. //
  426. // This is part of the strange linkage between base\win32 and the kernel.
  427. // This routine gets called this way first and if it returns the base
  428. // code does an exit process call.
  429. //
  430. ThisProcess = PsGetCurrentProcessByThread (ThisThread);
  431. if (ThisProcess->ActiveThreads == 1) {
  432. return STATUS_CANT_TERMINATE_SELF;
  433. }
  434. Self = TRUE;
  435. } else {
  436. if (ThreadHandle != NtCurrentThread ()) {
  437. Status = ObReferenceObjectByHandle (ThreadHandle,
  438. THREAD_TERMINATE,
  439. PsThreadType,
  440. KeGetPreviousModeByThread(&ThisThread->Tcb),
  441. &Thread,
  442. NULL);
  443. if (!NT_SUCCESS (Status)) {
  444. return Status;
  445. }
  446. if (Thread == ThisThread) {
  447. ObDereferenceObject (Thread);
  448. } else {
  449. Self = FALSE;
  450. }
  451. }
  452. }
  453. if (Self) {
  454. PspTerminateThreadByPointer (ThisThread, ExitStatus);
  455. } else {
  456. Status = PspTerminateThreadByPointer (Thread, ExitStatus);
  457. ObDereferenceObject (Thread);
  458. }
  459. return Status;
  460. }
  461. NTSTATUS
  462. PsTerminateSystemThread(
  463. IN NTSTATUS ExitStatus
  464. )
  465. /*++
  466. Routine Description:
  467. This function causes the current thread, which must be a system
  468. thread, to terminate.
  469. Arguments:
  470. ExitStatus - Supplies the exit status associated with the thread.
  471. Return Value:
  472. NTSTATUS - Status of call
  473. --*/
  474. {
  475. PETHREAD Thread = PsGetCurrentThread();
  476. if (!IS_SYSTEM_THREAD (Thread)) {
  477. return STATUS_INVALID_PARAMETER;
  478. }
  479. return PspTerminateThreadByPointer (Thread, ExitStatus);
  480. }
  481. VOID
  482. PspNullSpecialApc(
  483. IN PKAPC Apc,
  484. IN PKNORMAL_ROUTINE *NormalRoutine,
  485. IN PVOID *NormalContext,
  486. IN PVOID *SystemArgument1,
  487. IN PVOID *SystemArgument2
  488. )
  489. {
  490. PAGED_CODE();
  491. UNREFERENCED_PARAMETER(NormalRoutine);
  492. UNREFERENCED_PARAMETER(NormalContext);
  493. UNREFERENCED_PARAMETER(SystemArgument1);
  494. UNREFERENCED_PARAMETER(SystemArgument2);
  495. ExFreePool (Apc);
  496. }
  497. VOID
  498. PsExitSpecialApc(
  499. IN PKAPC Apc,
  500. IN PKNORMAL_ROUTINE *NormalRoutine,
  501. IN PVOID *NormalContext,
  502. IN PVOID *SystemArgument1,
  503. IN PVOID *SystemArgument2
  504. )
  505. {
  506. NTSTATUS ExitStatus;
  507. PETHREAD Thread;
  508. PAGED_CODE();
  509. UNREFERENCED_PARAMETER(NormalRoutine);
  510. UNREFERENCED_PARAMETER(NormalContext);
  511. UNREFERENCED_PARAMETER(SystemArgument1);
  512. UNREFERENCED_PARAMETER(SystemArgument2);
  513. Thread = PsGetCurrentThread();
  514. if (((ULONG_PTR)Apc->SystemArgument2) & 1) {
  515. ExitStatus = (NTSTATUS)((LONG_PTR)Apc->NormalContext);
  516. PspExitApcRundown (Apc);
  517. PspExitThread (ExitStatus);
  518. }
  519. }
  520. VOID
  521. PspExitApcRundown(
  522. IN PKAPC Apc
  523. )
  524. {
  525. PAGED_CODE();
  526. ExFreePool(Apc);
  527. }
  528. VOID
  529. PspExitNormalApc(
  530. IN PVOID NormalContext,
  531. IN PVOID SystemArgument1,
  532. IN PVOID SystemArgument2
  533. )
  534. {
  535. PETHREAD Thread;
  536. PKAPC ExitApc;
  537. PAGED_CODE();
  538. ASSERT (!(((ULONG_PTR)SystemArgument2) & 1));
  539. Thread = PsGetCurrentThread();
  540. ExitApc = (PKAPC) SystemArgument1;
  541. KeInitializeApc (ExitApc,
  542. PsGetKernelThread(Thread),
  543. OriginalApcEnvironment,
  544. PsExitSpecialApc,
  545. PspExitApcRundown,
  546. PspExitNormalApc,
  547. UserMode,
  548. NormalContext);
  549. if (!KeInsertQueueApc (ExitApc, ExitApc,
  550. (PVOID)((ULONG_PTR)SystemArgument2 | 1),
  551. 2)) {
  552. // Note that we'll get here if APC queueing has been
  553. // disabled -- on the other hand, in that case, the thread
  554. // is exiting anyway.
  555. PspExitApcRundown (ExitApc);
  556. }
  557. //
  558. // We just queued a user APC to this thread. User APC won't fire until we do an
  559. // alertable wait so we need to set this flag here.
  560. //
  561. Thread->Tcb.ApcState.UserApcPending = TRUE;
  562. }
  563. VOID
  564. PspCatchCriticalBreak(
  565. IN PCHAR Msg,
  566. IN PVOID Object,
  567. IN PUCHAR ImageFileName
  568. )
  569. {
  570. // The object is critical to the OS -- ask to break in, or bugcheck.
  571. char Response[2];
  572. BOOLEAN Handled;
  573. PAGED_CODE();
  574. Handled = FALSE;
  575. if (KdDebuggerEnabled) {
  576. DbgPrint(Msg,
  577. Object,
  578. ImageFileName);
  579. while (! Handled
  580. && ! KdDebuggerNotPresent) {
  581. DbgPrompt("Break, or Ignore (bi)? ",
  582. Response,
  583. sizeof(Response));
  584. switch (Response[0]) {
  585. case 'b':
  586. case 'B':
  587. DbgBreakPoint();
  588. // Fall through
  589. case 'i':
  590. case 'I':
  591. Handled = TRUE;
  592. break;
  593. default:
  594. break;
  595. }
  596. }
  597. }
  598. if (! Handled) {
  599. //
  600. // No debugger -- bugcheck immediately
  601. //
  602. KeBugCheckEx(CRITICAL_OBJECT_TERMINATION,
  603. (ULONG_PTR) ((DISPATCHER_HEADER *)Object)->Type,
  604. (ULONG_PTR) Object,
  605. (ULONG_PTR) ImageFileName,
  606. (ULONG_PTR) Msg);
  607. }
  608. }
  609. DECLSPEC_NORETURN
  610. VOID
  611. PspExitThread(
  612. IN NTSTATUS ExitStatus
  613. )
  614. /*++
  615. Routine Description:
  616. This function causes the currently executing thread to terminate. This
  617. function is only called from within the process structure. It is called
  618. either from mainline exit code to exit the current thread, or from
  619. PsExitSpecialApc (as a piggyback to user-mode PspExitNormalApc).
  620. Arguments:
  621. ExitStatus - Supplies the exit status associated with the current thread.
  622. Return Value:
  623. None.
  624. --*/
  625. {
  626. PETHREAD Thread;
  627. PETHREAD WaitThread;
  628. PETHREAD DerefThread;
  629. PEPROCESS Process;
  630. PKAPC Apc;
  631. PLIST_ENTRY Entry, FirstEntry;
  632. PTERMINATION_PORT TerminationPort, NextPort;
  633. LPC_CLIENT_DIED_MSG CdMsg;
  634. BOOLEAN LastThread;
  635. PTEB Teb;
  636. PPEB Peb;
  637. PAGED_CODE();
  638. Thread = PsGetCurrentThread();
  639. Process = THREAD_TO_PROCESS(Thread);
  640. if (Process != PsGetCurrentProcessByThread (Thread)) {
  641. KeBugCheckEx (INVALID_PROCESS_ATTACH_ATTEMPT,
  642. (ULONG_PTR)Process,
  643. (ULONG_PTR)Thread->Tcb.ApcState.Process,
  644. (ULONG)Thread->Tcb.ApcStateIndex,
  645. (ULONG_PTR)Thread);
  646. }
  647. KeLowerIrql(PASSIVE_LEVEL);
  648. if (Thread->ActiveExWorker) {
  649. KeBugCheckEx (ACTIVE_EX_WORKER_THREAD_TERMINATION,
  650. (ULONG_PTR)Thread,
  651. 0,
  652. 0,
  653. 0);
  654. }
  655. if (Thread->Tcb.Priority < LOW_REALTIME_PRIORITY) {
  656. KeSetPriorityThread (&Thread->Tcb, LOW_REALTIME_PRIORITY);
  657. }
  658. //
  659. // Its time to start turning off various cross thread references.
  660. // Mark the thread as rundown and wait for accessors to exit.
  661. //
  662. ExWaitForRundownProtectionRelease (&Thread->RundownProtect);
  663. //
  664. // Clear any execution state associated with the thread
  665. //
  666. PoRundownThread(Thread);
  667. //
  668. // Notify registered callout routines of thread deletion.
  669. //
  670. PERFINFO_THREAD_DELETE(Thread);
  671. if (PspCreateThreadNotifyRoutineCount != 0) {
  672. ULONG i;
  673. PEX_CALLBACK_ROUTINE_BLOCK CallBack;
  674. PCREATE_THREAD_NOTIFY_ROUTINE Rtn;
  675. for (i=0; i < PSP_MAX_CREATE_THREAD_NOTIFY; i++) {
  676. CallBack = ExReferenceCallBackBlock (&PspCreateThreadNotifyRoutine[i]);
  677. if (CallBack != NULL) {
  678. Rtn = (PCREATE_THREAD_NOTIFY_ROUTINE) ExGetCallBackBlockRoutine (CallBack);
  679. Rtn (Process->UniqueProcessId,
  680. Thread->Cid.UniqueThread,
  681. FALSE);
  682. ExDereferenceCallBackBlock (&PspCreateThreadNotifyRoutine[i],
  683. CallBack);
  684. }
  685. }
  686. }
  687. LastThread = FALSE;
  688. DerefThread = NULL;
  689. PspLockProcessExclusive (Process, Thread);
  690. //
  691. // Say one less active thread. If we are the last then block creates and wait for the other threads to exit.
  692. //
  693. Process->ActiveThreads--;
  694. if (Process->ActiveThreads == 0) {
  695. PS_SET_BITS (&Process->Flags, PS_PROCESS_FLAGS_PROCESS_DELETE);
  696. LastThread = TRUE;
  697. if (ExitStatus == STATUS_THREAD_IS_TERMINATING) {
  698. if (Process->ExitStatus == STATUS_PENDING) {
  699. Process->ExitStatus = Process->LastThreadExitStatus;
  700. }
  701. } else {
  702. Process->ExitStatus = ExitStatus;
  703. }
  704. //
  705. // We are the last thread to leave the process. We have to wait till all the other threads have exited before we do.
  706. //
  707. for (Entry = Process->ThreadListHead.Flink;
  708. Entry != &Process->ThreadListHead;
  709. Entry = Entry->Flink) {
  710. WaitThread = CONTAINING_RECORD (Entry, ETHREAD, ThreadListEntry);
  711. if (WaitThread != Thread &&
  712. !KeReadStateThread (&WaitThread->Tcb) &&
  713. ObReferenceObjectSafe (WaitThread)) {
  714. PspUnlockProcessExclusive (Process, Thread);
  715. KeWaitForSingleObject (WaitThread,
  716. Executive,
  717. KernelMode,
  718. FALSE,
  719. NULL);
  720. if (DerefThread != NULL) {
  721. ObDereferenceObject (DerefThread);
  722. }
  723. DerefThread = WaitThread;
  724. PspLockProcessExclusive (Process, Thread);
  725. }
  726. }
  727. } else {
  728. if (ExitStatus != STATUS_THREAD_IS_TERMINATING) {
  729. Process->LastThreadExitStatus = ExitStatus;
  730. }
  731. }
  732. PspUnlockProcessExclusive (Process, Thread);
  733. if (DerefThread != NULL) {
  734. ObDereferenceObject (DerefThread);
  735. }
  736. //
  737. // If we need to send debug messages then do so.
  738. //
  739. if (Process->DebugPort != NULL) {
  740. //
  741. // Don't report system thread exit to the debugger as we don't report them.
  742. //
  743. if (!IS_SYSTEM_THREAD (Thread)) {
  744. if (LastThread) {
  745. DbgkExitProcess (ExitStatus);
  746. } else {
  747. DbgkExitThread (ExitStatus);
  748. }
  749. }
  750. }
  751. if (KD_DEBUGGER_ENABLED) {
  752. if (Thread->CrossThreadFlags & PS_CROSS_THREAD_FLAGS_BREAK_ON_TERMINATION) {
  753. PspCatchCriticalBreak ("Critical thread 0x%p (in %s) exited\n",
  754. Thread,
  755. Process->ImageFileName);
  756. }
  757. } // End of critical thread/process exit detect
  758. if (LastThread &&
  759. (Process->Flags & PS_PROCESS_FLAGS_BREAK_ON_TERMINATION)) {
  760. if (KD_DEBUGGER_ENABLED) {
  761. PspCatchCriticalBreak ("Critical process 0x%p (%s) exited\n",
  762. Process,
  763. Process->ImageFileName);
  764. } else {
  765. KeBugCheckEx (CRITICAL_PROCESS_DIED,
  766. (ULONG_PTR)Process,
  767. 0,
  768. 0,
  769. 0);
  770. }
  771. }
  772. ASSERT(Thread->Tcb.KernelApcDisable == 0);
  773. //
  774. // Process the TerminationPort. This is only accessed from this thread
  775. //
  776. TerminationPort = Thread->TerminationPort;
  777. if (TerminationPort != NULL) {
  778. CdMsg.PortMsg.u1.s1.DataLength = sizeof(LARGE_INTEGER);
  779. CdMsg.PortMsg.u1.s1.TotalLength = sizeof(LPC_CLIENT_DIED_MSG);
  780. CdMsg.PortMsg.u2.s2.Type = LPC_CLIENT_DIED;
  781. CdMsg.PortMsg.u2.s2.DataInfoOffset = 0;
  782. do {
  783. CdMsg.CreateTime.QuadPart = PS_GET_THREAD_CREATE_TIME (Thread);
  784. LpcRequestPort (TerminationPort->Port, (PPORT_MESSAGE)&CdMsg);
  785. ObDereferenceObject (TerminationPort->Port);
  786. NextPort = TerminationPort->Next;
  787. ExFreePoolWithTag (TerminationPort, 'pTsP'|PROTECTED_POOL);
  788. TerminationPort = NextPort;
  789. } while (TerminationPort != NULL);
  790. } else {
  791. //
  792. // If there are no ports to send notifications to,
  793. // but there is an exception port, then we have to
  794. // send a client died message through the exception
  795. // port. This will allow a server a chance to get notification
  796. // if an app/thread dies before it even starts
  797. //
  798. //
  799. // We only send the exception if the thread creation really worked.
  800. // DeadThread is set when an NtCreateThread returns an error, but
  801. // the thread will actually execute this path. If DeadThread is not
  802. // set than the thread creation succeeded. The other place DeadThread
  803. // is set is when we were terminated without having any chance to move.
  804. // in this case, DeadThread is set and the exit status is set to
  805. // STATUS_THREAD_IS_TERMINATING
  806. //
  807. if ((ExitStatus == STATUS_THREAD_IS_TERMINATING &&
  808. (Thread->CrossThreadFlags&PS_CROSS_THREAD_FLAGS_DEADTHREAD)) ||
  809. !(Thread->CrossThreadFlags&PS_CROSS_THREAD_FLAGS_DEADTHREAD)) {
  810. CdMsg.PortMsg.u1.s1.DataLength = sizeof (LARGE_INTEGER);
  811. CdMsg.PortMsg.u1.s1.TotalLength = sizeof (LPC_CLIENT_DIED_MSG);
  812. CdMsg.PortMsg.u2.s2.Type = LPC_CLIENT_DIED;
  813. CdMsg.PortMsg.u2.s2.DataInfoOffset = 0;
  814. if (Process->ExceptionPort != NULL) {
  815. CdMsg.CreateTime.QuadPart = PS_GET_THREAD_CREATE_TIME (Thread);
  816. LpcRequestPort (Process->ExceptionPort, (PPORT_MESSAGE)&CdMsg);
  817. }
  818. }
  819. }
  820. //
  821. // rundown the Win32 structures
  822. //
  823. if (Thread->Tcb.Win32Thread) {
  824. (PspW32ThreadCallout) (Thread, PsW32ThreadCalloutExit);
  825. }
  826. if (LastThread && Process->Win32Process) {
  827. (PspW32ProcessCallout) (Process, FALSE);
  828. }
  829. //
  830. // User/Gdi has been given a chance to clean up. Now make sure they didn't
  831. // leave the kernel stack locked which would happen if data was still live on
  832. // this stack, but was being used by another thread
  833. //
  834. if (!Thread->Tcb.EnableStackSwap) {
  835. KeBugCheckEx (KERNEL_STACK_LOCKED_AT_EXIT, 0, 0, 0, 0);
  836. }
  837. //
  838. // Rundown The Lists:
  839. //
  840. // - Cancel Io By Thread
  841. // - Cancel Timers
  842. // - Cancel Registry Notify Requests pending against this thread
  843. // - Perform kernel thread rundown
  844. //
  845. IoCancelThreadIo (Thread);
  846. ExTimerRundown ();
  847. CmNotifyRunDown (Thread);
  848. KeRundownThread ();
  849. //
  850. // Delete the thread's TEB. If the address of the TEB is in user
  851. // space, then this is a real user mode TEB. If the address is in
  852. // system space, then this is a special system thread TEB allocated
  853. // from paged or nonpaged pool.
  854. //
  855. Teb = Thread->Tcb.Teb;
  856. if (Teb != NULL) {
  857. PRTL_CRITICAL_SECTION Cs;
  858. int DecrementCount;
  859. Peb = Process->Peb;
  860. try {
  861. //
  862. // The thread is a user-mode thread. Look to see if the thread
  863. // owns the loader lock (and any other key peb-based critical
  864. // sections. If so, do our best to release the locks.
  865. //
  866. // Since the LoaderLock used to be a mutant, releasing the lock
  867. // like this is very similar to mutant abandonment and the loader
  868. // never did anything with abandoned status anyway
  869. //
  870. Cs = Peb->LoaderLock;
  871. if (Cs != NULL) {
  872. ProbeForRead(Cs,sizeof(*Cs),4);
  873. if (Cs->OwningThread == Thread->Cid.UniqueThread) {
  874. //
  875. // x86 uses a 1 based recursion count
  876. //
  877. #if defined(_X86_)
  878. DecrementCount = Cs->RecursionCount;
  879. #else
  880. DecrementCount = Cs->RecursionCount + 1;
  881. #endif
  882. Cs->RecursionCount = 0;
  883. Cs->OwningThread = 0;
  884. //
  885. // undo lock count increments for recursion cases
  886. //
  887. while(DecrementCount > 1) {
  888. InterlockedDecrement (&Cs->LockCount);
  889. DecrementCount--;
  890. }
  891. //
  892. // undo final lock count
  893. //
  894. if (InterlockedDecrement (&Cs->LockCount) >= 0) {
  895. NtSetEvent (Cs->LockSemaphore, NULL);
  896. }
  897. } else if (Teb->WaitingOnLoaderLock) {
  898. //
  899. // if the thread exited while waiting on the loader
  900. // lock clean it up. There is still a potential race
  901. // here since we can not safely know what happens to
  902. // a thread after it interlocked increments the lock count
  903. // but before it sets the waiting on loader lock flag. On the
  904. // release side, it it safe since we mark ownership of the lock
  905. // before clearing the flag. This triggers the first part of this
  906. // test. The only thing out of whack is the recursion count, but this
  907. // is also safe since in this state, recursion count is 0.
  908. //
  909. //
  910. // This code isn't right. We need to bump down our lock count
  911. // increment.
  912. //
  913. // A few cases to consider:
  914. //
  915. // Another thread releases the lock signals the event.
  916. // We take the wait and then die before setting our ID.
  917. // I doubt very much that this can happen because right
  918. // after we come out of the wait, we set the owner Id
  919. // (meaning that we would go through the other part of the if).
  920. // Bottom line is that we should just decrement our lock count
  921. // and get out of the way. There is no need to set the event.
  922. // In the RAS stress failure, I saw us setting the event
  923. // just because the lock count was >= 0. The lock was already held
  924. // by another thread so setting the event let yet another thread
  925. // also own the lock. Last one to release would get a
  926. // not owner critical section failure
  927. //
  928. //
  929. // if ( InterlockedDecrement(&Cs->LockCount) >= 0 ){
  930. // NtSetEvent(Cs->LockSemaphore,NULL);
  931. // }
  932. //
  933. InterlockedDecrement (&Cs->LockCount);
  934. }
  935. }
  936. #if defined(_WIN64)
  937. if (Process->Wow64Process) {
  938. // Do the same thing for the 32-bit PEB->Ldr
  939. PRTL_CRITICAL_SECTION32 Cs32;
  940. PPEB32 Peb32;
  941. Peb32 = Process->Wow64Process->Wow64;
  942. Cs32 = (PRTL_CRITICAL_SECTION32)ULongToPtr (Peb32->LoaderLock);
  943. if (Cs32 != NULL) {
  944. ProbeForRead (Cs32, sizeof(*Cs32), 4);
  945. if (Cs32->OwningThread == PtrToUlong(Thread->Cid.UniqueThread)) {
  946. //
  947. // x86 uses a 1 based recursion count, so the
  948. // IA64 kernel needs to do the same, since
  949. // the critsect is really implemented by IA32
  950. // usermode.
  951. //
  952. DecrementCount = Cs32->RecursionCount;
  953. Cs32->RecursionCount = 0;
  954. Cs32->OwningThread = 0;
  955. //
  956. // undo lock count increments for recursion cases
  957. //
  958. while(DecrementCount > 1) {
  959. InterlockedDecrement(&Cs32->LockCount);
  960. DecrementCount--;
  961. }
  962. //
  963. // undo final lock count
  964. //
  965. if (InterlockedDecrement (&Cs32->LockCount) >= 0){
  966. NtSetEvent (LongToHandle (Cs32->LockSemaphore),NULL);
  967. }
  968. } else {
  969. PTEB32 Teb32 = WOW64_GET_TEB32(Teb);
  970. ProbeForRead (Teb32,sizeof (*Teb32), 4);
  971. if (Teb32->WaitingOnLoaderLock) {
  972. InterlockedDecrement(&Cs32->LockCount);
  973. }
  974. }
  975. }
  976. }
  977. #endif
  978. //
  979. // Free the user mode stack on termination if we need to.
  980. //
  981. if (Teb->FreeStackOnTermination &&
  982. (Thread->CrossThreadFlags&PS_CROSS_THREAD_FLAGS_DEADTHREAD) == 0) {
  983. SIZE_T Zero = 0;
  984. PVOID BaseAddress = Teb->DeallocationStack;
  985. ZwFreeVirtualMemory (NtCurrentProcess (),
  986. &BaseAddress,
  987. &Zero,
  988. MEM_RELEASE);
  989. }
  990. //
  991. // Close the debugger object associated with this thread if there is one.
  992. //
  993. if (Teb->DbgSsReserved[1] != NULL) {
  994. ObCloseHandle (Teb->DbgSsReserved[1], UserMode);
  995. }
  996. } except (EXCEPTION_EXECUTE_HANDLER) {
  997. }
  998. MmDeleteTeb (Process, Teb);
  999. Thread->Tcb.Teb = NULL;
  1000. }
  1001. //
  1002. // Let LPC component deal with message stack in Thread->LpcReplyMessage
  1003. // but do it after the client ID becomes invalid.
  1004. //
  1005. LpcExitThread (Thread);
  1006. Thread->ExitStatus = ExitStatus;
  1007. KeQuerySystemTime (&Thread->ExitTime);
  1008. ASSERT (Thread->Tcb.KernelApcDisable == 0);
  1009. if (LastThread) {
  1010. Process->ExitTime = Thread->ExitTime;
  1011. PspExitProcess (TRUE, Process);
  1012. if (SeDetailedAuditing && !ExFastRefObjectNull (Process->Token)) {
  1013. SeAuditProcessExit (Process);
  1014. }
  1015. #if defined(_X86_)
  1016. //
  1017. // Rundown VDM DPCs
  1018. //
  1019. if (Process->VdmObjects != NULL) {
  1020. VdmRundownDpcs (Process);
  1021. }
  1022. #endif
  1023. //
  1024. // Rundown the handle table
  1025. //
  1026. ObKillProcess (Process);
  1027. //
  1028. // Release the image section
  1029. //
  1030. if (Process->SectionObject != NULL) {
  1031. ObDereferenceObject (Process->SectionObject);
  1032. Process->SectionObject = NULL;
  1033. }
  1034. if (Process->Job != NULL) {
  1035. //
  1036. // Now we can fold the process accounting into the job. Don't need to wait for
  1037. // the delete routine.
  1038. //
  1039. PspExitProcessFromJob (Process->Job, Process);
  1040. }
  1041. //
  1042. // Signal the process
  1043. //
  1044. KeSetProcess (&Process->Pcb, 0, FALSE);
  1045. }
  1046. //
  1047. // Rundown pending APCs. Protect against being frozen after we raise IRQL but before dispatcher lock is taken.
  1048. //
  1049. KeEnterCriticalRegionThread (&Thread->Tcb);
  1050. KeDisableApcQueuingThread (&Thread->Tcb);
  1051. //
  1052. // At this point we may have been frozen and the APC is pending. First we remove the suspend/freeze bias that
  1053. // may exist and then drop IRQL. The suspend APC if present will fire and drop through. No futher suspends are
  1054. // allowed as the thread is marked to prevent APC's
  1055. //
  1056. KeForceResumeThread (&Thread->Tcb);
  1057. KeLeaveCriticalRegionThread (&Thread->Tcb);
  1058. //
  1059. // flush user-mode APC queue
  1060. //
  1061. FirstEntry = KeFlushQueueApc (&Thread->Tcb, UserMode);
  1062. if (FirstEntry != NULL) {
  1063. Entry = FirstEntry;
  1064. do {
  1065. Apc = CONTAINING_RECORD (Entry, KAPC, ApcListEntry);
  1066. Entry = Entry->Flink;
  1067. //
  1068. // If the APC has a rundown routine then call it. Otherwise
  1069. // deallocate the APC
  1070. //
  1071. if (Apc->RundownRoutine) {
  1072. (Apc->RundownRoutine) (Apc);
  1073. } else {
  1074. ExFreePool (Apc);
  1075. }
  1076. } while (Entry != FirstEntry);
  1077. }
  1078. if (LastThread) {
  1079. MmCleanProcessAddressSpace (Process);
  1080. }
  1081. if (Thread->Tcb.LegoData && PspLegoNotifyRoutine) {
  1082. (PspLegoNotifyRoutine) (&Thread->Tcb);
  1083. }
  1084. //
  1085. // flush kernel-mode APC queue
  1086. // There should never be any kernel mode APCs found this far
  1087. // into thread termination. Since we go to PASSIVE_LEVEL upon
  1088. // entering exit.
  1089. //
  1090. FirstEntry = KeFlushQueueApc (&Thread->Tcb, KernelMode);
  1091. if (FirstEntry != NULL) {
  1092. KeBugCheckEx (KERNEL_APC_PENDING_DURING_EXIT,
  1093. (ULONG_PTR)FirstEntry,
  1094. (ULONG_PTR)Thread->Tcb.KernelApcDisable,
  1095. (ULONG_PTR)KeGetCurrentIrql(),
  1096. 0);
  1097. }
  1098. //
  1099. // Terminate the thread.
  1100. //
  1101. // N.B. There is no return from this call.
  1102. //
  1103. // N.B. The kernel inserts the current thread in the reaper list and
  1104. // activates a thread, if necessary, to reap the terminating thread.
  1105. //
  1106. KeTerminateThread (0L);
  1107. }
  1108. VOID
  1109. PspExitProcess(
  1110. IN BOOLEAN LastThreadExit,
  1111. IN PEPROCESS Process
  1112. )
  1113. {
  1114. ULONG ActualTime;
  1115. PEJOB Job;
  1116. PETHREAD CurrentThread;
  1117. PAGED_CODE();
  1118. PS_SET_BITS (&Process->Flags, PS_PROCESS_FLAGS_PROCESS_EXITING);
  1119. if (LastThreadExit) {
  1120. PERFINFO_PROCESS_DELETE(Process);
  1121. if (PspCreateProcessNotifyRoutineCount != 0) {
  1122. ULONG i;
  1123. PEX_CALLBACK_ROUTINE_BLOCK CallBack;
  1124. PCREATE_PROCESS_NOTIFY_ROUTINE Rtn;
  1125. for (i = 0; i < PSP_MAX_CREATE_PROCESS_NOTIFY; i++) {
  1126. CallBack = ExReferenceCallBackBlock (&PspCreateProcessNotifyRoutine[i]);
  1127. if (CallBack != NULL) {
  1128. Rtn = (PCREATE_PROCESS_NOTIFY_ROUTINE) ExGetCallBackBlockRoutine (CallBack);
  1129. Rtn (Process->InheritedFromUniqueProcessId,
  1130. Process->UniqueProcessId,
  1131. FALSE);
  1132. ExDereferenceCallBackBlock (&PspCreateProcessNotifyRoutine[i],
  1133. CallBack);
  1134. }
  1135. }
  1136. }
  1137. }
  1138. PoRundownProcess (Process);
  1139. //
  1140. // Dereference (close) the security port. This will stop any authentication
  1141. // or EFS requests from this process to the LSA process. The "well known"
  1142. // value of 1 will prevent the security system from try to re-establish the
  1143. // connection during the process shutdown (e.g. when the rdr deletes a handle)
  1144. //
  1145. if (Process->SecurityPort) {
  1146. if (Process->SecurityPort != ((PVOID) 1)) {
  1147. ObDereferenceObject (Process->SecurityPort);
  1148. Process->SecurityPort = (PVOID) 1 ;
  1149. }
  1150. }
  1151. if (LastThreadExit) {
  1152. //
  1153. // If the current process has previously set the timer resolution,
  1154. // then reset it.
  1155. //
  1156. if ((Process->Flags&PS_PROCESS_FLAGS_SET_TIMER_RESOLUTION) != 0) {
  1157. ZwSetTimerResolution (KeMaximumIncrement, FALSE, &ActualTime);
  1158. }
  1159. Job = Process->Job;
  1160. if (Job != NULL && Job->CompletionPort != NULL &&
  1161. !(Process->JobStatus & PS_JOB_STATUS_NOT_REALLY_ACTIVE) &&
  1162. !(Process->JobStatus & PS_JOB_STATUS_EXIT_PROCESS_REPORTED)) {
  1163. ULONG_PTR ExitMessageId;
  1164. switch (Process->ExitStatus) {
  1165. case STATUS_GUARD_PAGE_VIOLATION :
  1166. case STATUS_DATATYPE_MISALIGNMENT :
  1167. case STATUS_BREAKPOINT :
  1168. case STATUS_SINGLE_STEP :
  1169. case STATUS_ACCESS_VIOLATION :
  1170. case STATUS_IN_PAGE_ERROR :
  1171. case STATUS_ILLEGAL_INSTRUCTION :
  1172. case STATUS_NONCONTINUABLE_EXCEPTION :
  1173. case STATUS_INVALID_DISPOSITION :
  1174. case STATUS_ARRAY_BOUNDS_EXCEEDED :
  1175. case STATUS_FLOAT_DENORMAL_OPERAND :
  1176. case STATUS_FLOAT_DIVIDE_BY_ZERO :
  1177. case STATUS_FLOAT_INEXACT_RESULT :
  1178. case STATUS_FLOAT_INVALID_OPERATION :
  1179. case STATUS_FLOAT_OVERFLOW :
  1180. case STATUS_FLOAT_STACK_CHECK :
  1181. case STATUS_FLOAT_UNDERFLOW :
  1182. case STATUS_INTEGER_DIVIDE_BY_ZERO :
  1183. case STATUS_INTEGER_OVERFLOW :
  1184. case STATUS_PRIVILEGED_INSTRUCTION :
  1185. case STATUS_STACK_OVERFLOW :
  1186. case STATUS_CONTROL_C_EXIT :
  1187. case STATUS_FLOAT_MULTIPLE_FAULTS :
  1188. case STATUS_FLOAT_MULTIPLE_TRAPS :
  1189. case STATUS_REG_NAT_CONSUMPTION :
  1190. ExitMessageId = JOB_OBJECT_MSG_ABNORMAL_EXIT_PROCESS;
  1191. break;
  1192. default:
  1193. ExitMessageId = JOB_OBJECT_MSG_EXIT_PROCESS;
  1194. break;
  1195. }
  1196. PS_SET_CLEAR_BITS (&Process->JobStatus,
  1197. PS_JOB_STATUS_EXIT_PROCESS_REPORTED,
  1198. PS_JOB_STATUS_LAST_REPORT_MEMORY);
  1199. CurrentThread = PsGetCurrentThread ();
  1200. KeEnterCriticalRegionThread (&CurrentThread->Tcb);
  1201. ExAcquireResourceSharedLite (&Job->JobLock, TRUE);
  1202. if (Job->CompletionPort != NULL) {
  1203. IoSetIoCompletion (Job->CompletionPort,
  1204. Job->CompletionKey,
  1205. (PVOID)Process->UniqueProcessId,
  1206. STATUS_SUCCESS,
  1207. ExitMessageId,
  1208. FALSE);
  1209. }
  1210. ExReleaseResourceLite (&Job->JobLock);
  1211. KeLeaveCriticalRegionThread (&CurrentThread->Tcb);
  1212. }
  1213. if (CCPF_IS_PREFETCHER_ACTIVE ()) {
  1214. //
  1215. // Let prefetcher know that this process is exiting.
  1216. //
  1217. CcPfProcessExitNotification (Process);
  1218. }
  1219. } else {
  1220. MmCleanProcessAddressSpace (Process);
  1221. }
  1222. }
  1223. VOID
  1224. PspProcessDelete(
  1225. IN PVOID Object
  1226. )
  1227. {
  1228. PEPROCESS Process;
  1229. PETHREAD CurrentThread;
  1230. KAPC_STATE ApcState;
  1231. PAGED_CODE();
  1232. Process = (PEPROCESS)Object;
  1233. //
  1234. // Remove the process from the global list
  1235. //
  1236. if (Process->ActiveProcessLinks.Flink != NULL) {
  1237. CurrentThread = PsGetCurrentThread ();
  1238. PspLockProcessList (CurrentThread);
  1239. RemoveEntryList (&Process->ActiveProcessLinks);
  1240. PspUnlockProcessList (CurrentThread);
  1241. }
  1242. if (Process->SeAuditProcessCreationInfo.ImageFileName != NULL) {
  1243. ExFreePool (Process->SeAuditProcessCreationInfo.ImageFileName);
  1244. Process->SeAuditProcessCreationInfo.ImageFileName = NULL;
  1245. }
  1246. if (Process->Job != NULL) {
  1247. PspRemoveProcessFromJob (Process->Job, Process);
  1248. ObDereferenceObjectDeferDelete (Process->Job);
  1249. Process->Job = NULL;
  1250. }
  1251. KeTerminateProcess (&Process->Pcb);
  1252. if (Process->DebugPort != NULL) {
  1253. ObDereferenceObject (Process->DebugPort);
  1254. Process->DebugPort = NULL;
  1255. }
  1256. if (Process->ExceptionPort != NULL) {
  1257. ObDereferenceObject (Process->ExceptionPort);
  1258. Process->ExceptionPort = NULL;
  1259. }
  1260. if (Process->SectionObject != NULL) {
  1261. ObDereferenceObject (Process->SectionObject);
  1262. Process->SectionObject = NULL;
  1263. }
  1264. PspDeleteLdt (Process );
  1265. PspDeleteVdmObjects (Process);
  1266. if (Process->ObjectTable != NULL) {
  1267. KeStackAttachProcess (&Process->Pcb, &ApcState);
  1268. ObKillProcess (Process);
  1269. KeUnstackDetachProcess (&ApcState);
  1270. }
  1271. if (Process->Flags&PS_PROCESS_FLAGS_HAS_ADDRESS_SPACE) {
  1272. //
  1273. // Clean address space of the process
  1274. //
  1275. KeStackAttachProcess (&Process->Pcb, &ApcState);
  1276. PspExitProcess (FALSE, Process);
  1277. KeUnstackDetachProcess (&ApcState);
  1278. MmDeleteProcessAddressSpace (Process);
  1279. }
  1280. if (Process->UniqueProcessId) {
  1281. if (!(ExDestroyHandle (PspCidTable, Process->UniqueProcessId, NULL))) {
  1282. KeBugCheck (CID_HANDLE_DELETION);
  1283. }
  1284. }
  1285. PspDeleteProcessSecurity (Process);
  1286. if (Process->WorkingSetWatch != NULL) {
  1287. ExFreePool (Process->WorkingSetWatch);
  1288. PsReturnProcessNonPagedPoolQuota (Process, WS_CATCH_SIZE);
  1289. }
  1290. ObDereferenceDeviceMap (Process);
  1291. PspDereferenceQuota (Process);
  1292. #if !defined(_X86_)
  1293. {
  1294. //
  1295. // Free any alignment exception tracking structures that might
  1296. // have been around to support a user-mode debugger.
  1297. //
  1298. PALIGNMENT_EXCEPTION_TABLE ExceptionTable;
  1299. PALIGNMENT_EXCEPTION_TABLE NextExceptionTable;
  1300. ExceptionTable = Process->Pcb.AlignmentExceptionTable;
  1301. while (ExceptionTable != NULL) {
  1302. NextExceptionTable = ExceptionTable->Next;
  1303. ExFreePool( ExceptionTable );
  1304. ExceptionTable = NextExceptionTable;
  1305. }
  1306. }
  1307. #endif
  1308. }
  1309. VOID
  1310. PspThreadDelete(
  1311. IN PVOID Object
  1312. )
  1313. {
  1314. PETHREAD Thread;
  1315. PETHREAD CurrentThread;
  1316. PEPROCESS Process;
  1317. PAGED_CODE();
  1318. Thread = (PETHREAD) Object;
  1319. ASSERT(Thread->Tcb.Win32Thread == NULL);
  1320. if (Thread->Tcb.InitialStack) {
  1321. MmDeleteKernelStack(Thread->Tcb.StackBase,
  1322. (BOOLEAN)Thread->Tcb.LargeStack);
  1323. }
  1324. if (Thread->Cid.UniqueThread != NULL) {
  1325. if (!ExDestroyHandle (PspCidTable, Thread->Cid.UniqueThread, NULL)) {
  1326. KeBugCheck(CID_HANDLE_DELETION);
  1327. }
  1328. }
  1329. PspDeleteThreadSecurity (Thread);
  1330. Process = THREAD_TO_PROCESS(Thread);
  1331. if (Process) {
  1332. //
  1333. // Remove the thread from the process if it was ever inserted.
  1334. //
  1335. if (Thread->ThreadListEntry.Flink != NULL) {
  1336. CurrentThread = PsGetCurrentThread ();
  1337. PspLockProcessExclusive (Process, CurrentThread);
  1338. RemoveEntryList (&Thread->ThreadListEntry);
  1339. PspUnlockProcessExclusive (Process, CurrentThread);
  1340. }
  1341. ObDereferenceObject(Process);
  1342. }
  1343. }
  1344. NTSTATUS
  1345. NtRegisterThreadTerminatePort(
  1346. IN HANDLE PortHandle
  1347. )
  1348. /*++
  1349. Routine Description:
  1350. This API allows a thread to register a port to be notified upon
  1351. thread termination.
  1352. Arguments:
  1353. PortHandle - Supplies an open handle to a port object that will be
  1354. sent a termination message when the thread terminates.
  1355. Return Value:
  1356. TBD
  1357. --*/
  1358. {
  1359. PVOID Port;
  1360. PTERMINATION_PORT TerminationPort;
  1361. NTSTATUS st;
  1362. PETHREAD Thread;
  1363. PAGED_CODE();
  1364. Thread = PsGetCurrentThread ();
  1365. st = ObReferenceObjectByHandle (PortHandle,
  1366. 0,
  1367. LpcPortObjectType,
  1368. KeGetPreviousModeByThread(&Thread->Tcb),
  1369. &Port,
  1370. NULL);
  1371. if (!NT_SUCCESS (st)) {
  1372. return st;
  1373. }
  1374. TerminationPort = ExAllocatePoolWithQuotaTag (PagedPool|POOL_QUOTA_FAIL_INSTEAD_OF_RAISE,
  1375. sizeof(TERMINATION_PORT),
  1376. 'pTsP'|PROTECTED_POOL);
  1377. if (TerminationPort == NULL) {
  1378. ObDereferenceObject (Port);
  1379. return STATUS_INSUFFICIENT_RESOURCES;
  1380. }
  1381. TerminationPort->Port = Port;
  1382. TerminationPort->Next = Thread->TerminationPort;
  1383. Thread->TerminationPort = TerminationPort;
  1384. return STATUS_SUCCESS;
  1385. }
  1386. LARGE_INTEGER
  1387. PsGetProcessExitTime(
  1388. VOID
  1389. )
  1390. /*++
  1391. Routine Description:
  1392. This routine returns the exit time for the current process.
  1393. Arguments:
  1394. None.
  1395. Return Value:
  1396. The function value is the exit time for the current process.
  1397. Note:
  1398. This routine assumes that the caller wants an error log entry within the
  1399. bounds of the maximum size.
  1400. --*/
  1401. {
  1402. PAGED_CODE();
  1403. //
  1404. // Simply return the exit time for this process.
  1405. //
  1406. return PsGetCurrentProcess()->ExitTime;
  1407. }
  1408. #undef PsIsThreadTerminating
  1409. BOOLEAN
  1410. PsIsThreadTerminating(
  1411. IN PETHREAD Thread
  1412. )
  1413. /*++
  1414. Routine Description:
  1415. This routine returns TRUE if the specified thread is in the process of
  1416. terminating.
  1417. Arguments:
  1418. Thread - Supplies a pointer to the thread to be checked for termination.
  1419. Return Value:
  1420. TRUE is returned if the thread is terminating, else FALSE is returned.
  1421. --*/
  1422. {
  1423. //
  1424. // Simply return whether or not the thread is in the process of terminating.
  1425. //
  1426. if (Thread->CrossThreadFlags&PS_CROSS_THREAD_FLAGS_TERMINATED) {
  1427. return TRUE;
  1428. } else {
  1429. return FALSE;
  1430. }
  1431. }
  1432. NTSTATUS
  1433. PspFreezeProcessWorker (
  1434. PEPROCESS Process,
  1435. PVOID Context
  1436. )
  1437. /*++
  1438. Routine Description:
  1439. This function is the enumeration worker to suspend all processes.
  1440. Arguments:
  1441. Process - Current process being enumerated
  1442. Context - Unused context value
  1443. Return Value:
  1444. NTSTATUS - Always returns true to continue enumeration
  1445. --*/
  1446. {
  1447. UNREFERENCED_PARAMETER (Context);
  1448. if (Process != PsInitialSystemProcess &&
  1449. Process != PsIdleProcess &&
  1450. Process != ExpDefaultErrorPortProcess) {
  1451. if (Process->ExceptionPort != NULL) {
  1452. LpcDisconnectPort (Process->ExceptionPort);
  1453. }
  1454. if ((Process->Flags&PS_PROCESS_FLAGS_PROCESS_EXITING) == 0) {
  1455. PsSuspendProcess (Process);
  1456. }
  1457. }
  1458. return STATUS_SUCCESS;
  1459. }
  1460. BOOLEAN PsContinueWaiting = FALSE;
  1461. LOGICAL
  1462. PsShutdownSystem (
  1463. VOID
  1464. )
  1465. /*++
  1466. Routine Description:
  1467. This function shuts down ps, killing all non-system threads.
  1468. Arguments:
  1469. None.
  1470. Return Value:
  1471. Returns TRUE if all processes were terminated, FALSE if not.
  1472. --*/
  1473. {
  1474. PEPROCESS Process;
  1475. PETHREAD Thread;
  1476. ULONG NumProcs;
  1477. ULONG i;
  1478. ULONG MaxPasses;
  1479. NTSTATUS Status;
  1480. LARGE_INTEGER Timeout = {(ULONG)(-10 * 1000 * 1000 * 100), -1};
  1481. LOGICAL Retval;
  1482. #define WAIT_BATCH THREAD_WAIT_OBJECTS
  1483. PKPROCESS WaitProcs[WAIT_BATCH];
  1484. BOOLEAN First;
  1485. PAGED_CODE();
  1486. Retval = TRUE;
  1487. //
  1488. // Some processes wait for other processes to die and then initiate actions.
  1489. // Killing all processes without letting any execute any usermode code
  1490. // prevents any unwanted initiated actions.
  1491. //
  1492. Thread = PsGetCurrentThread();
  1493. if (InterlockedCompareExchangePointer(&PspShutdownThread,
  1494. Thread,
  1495. 0) != 0) {
  1496. // Some other thread is already in shutdown -- bail
  1497. return FALSE;
  1498. }
  1499. PsEnumProcesses (PspFreezeProcessWorker, NULL);
  1500. //
  1501. // This loop kills all the processes and then waits for one of a subset
  1502. // of them to die. They must all be killed first (before any can be waited
  1503. // on) so that any process like a debuggee that is waiting for a debugger
  1504. // won't stall us.
  1505. //
  1506. // Driver unload won't occur until the last handle goes away for a device.
  1507. //
  1508. MaxPasses = 0;
  1509. First = TRUE;
  1510. do {
  1511. NumProcs = 0;
  1512. Status = STATUS_SUCCESS;
  1513. for (Process = PsGetNextProcess (NULL);
  1514. Process != NULL;
  1515. Process = PsGetNextProcess (Process)) {
  1516. if (Process != PsInitialSystemProcess &&
  1517. Process != PsIdleProcess &&
  1518. Process != ExpDefaultErrorPortProcess) {
  1519. ASSERT (MmGetSessionId (Process) == 0);
  1520. Status = PsTerminateProcess (Process,
  1521. STATUS_SYSTEM_SHUTDOWN);
  1522. //
  1523. // If there is space save the referenced process away so
  1524. // we can wait on it. Don't wait on processes with no
  1525. // threads as they will only exit when the last handle goes.
  1526. //
  1527. if ((Process->Flags&PS_PROCESS_FLAGS_PROCESS_EXITING) == 0 &&
  1528. Status != STATUS_NOTHING_TO_TERMINATE &&
  1529. NumProcs < WAIT_BATCH) {
  1530. ObReferenceObject (Process);
  1531. WaitProcs[NumProcs++] = &Process->Pcb;
  1532. }
  1533. }
  1534. }
  1535. First = FALSE;
  1536. //
  1537. // Wait for one of a small set of the processes to exit.
  1538. //
  1539. if (NumProcs != 0) {
  1540. Status = KeWaitForMultipleObjects (NumProcs,
  1541. WaitProcs,
  1542. WaitAny,
  1543. Executive,
  1544. KernelMode,
  1545. FALSE,
  1546. &Timeout,
  1547. NULL);
  1548. for (i = 0; i < NumProcs; i++) {
  1549. Process = CONTAINING_RECORD(WaitProcs[i],
  1550. EPROCESS,
  1551. Pcb);
  1552. ObDereferenceObject (Process);
  1553. }
  1554. }
  1555. //
  1556. // Don't let an unkillable process stop shutdown from finishing.
  1557. // ASSERT on checked builds so the faulty component causing this
  1558. // can be debugged and fixed.
  1559. //
  1560. if (NumProcs > 0 && Status == STATUS_TIMEOUT) {
  1561. MaxPasses += 1;
  1562. if (MaxPasses > 10) {
  1563. ASSERT (FALSE);
  1564. if (!PsContinueWaiting) {
  1565. Retval = FALSE;
  1566. break;
  1567. }
  1568. }
  1569. } else {
  1570. MaxPasses = 0;
  1571. }
  1572. } while (NumProcs > 0);
  1573. if (PoCleanShutdownEnabled() && ExpDefaultErrorPortProcess) {
  1574. // Explicitly kill csrss -- we don't want to do this in the loop,
  1575. // because we don't want to wait on it, because it has system
  1576. // threads which will exit later. But we can terminate the user
  1577. // threads, now that everything else has died (we can't terminate
  1578. // them earlier, because DestroyWindowStation()/TerminateConsole()
  1579. // depends on them being around).
  1580. PsTerminateProcess(ExpDefaultErrorPortProcess,
  1581. STATUS_SYSTEM_SHUTDOWN);
  1582. // Now, make sure that csrss's usermode threads have gotten a
  1583. // chance to terminate.
  1584. PspWaitForUsermodeExit(ExpDefaultErrorPortProcess);
  1585. }
  1586. // And we're done.
  1587. PspShutdownJobLimits();
  1588. MmUnmapViewOfSection(PsInitialSystemProcess, PspSystemDll.DllBase);
  1589. ObDereferenceObject(PspSystemDll.Section);
  1590. ZwClose(PspInitialSystemProcessHandle);
  1591. PspInitialSystemProcessHandle = NULL;
  1592. // Disconnect the system process's LSA security port
  1593. if (PsInitialSystemProcess->SecurityPort) {
  1594. if (PsInitialSystemProcess->SecurityPort != ((PVOID) 1 ))
  1595. {
  1596. ObDereferenceObject(PsInitialSystemProcess->SecurityPort);
  1597. PsInitialSystemProcess->SecurityPort = (PVOID) 1 ;
  1598. }
  1599. }
  1600. return Retval;
  1601. }
  1602. BOOLEAN
  1603. PsWaitForAllProcesses (
  1604. VOID)
  1605. /*++
  1606. Routine Description:
  1607. This function waits for all the processes to terminate.
  1608. Arguments:
  1609. None.
  1610. Return Value:
  1611. Returns TRUE if all processes were terminated, FALSE if not.
  1612. --*/
  1613. {
  1614. NTSTATUS Status;
  1615. LARGE_INTEGER Timeout = {(ULONG)-(100 * 1000), -1};
  1616. ULONG MaxPasses;
  1617. BOOLEAN Wait;
  1618. PEPROCESS Process;
  1619. PEPROCESS WaitProcess=NULL;
  1620. MaxPasses = 0;
  1621. while (1) {
  1622. Wait = FALSE;
  1623. for (Process = PsGetNextProcess (NULL);
  1624. Process != NULL;
  1625. Process = PsGetNextProcess (Process)) {
  1626. if (Process != PsInitialSystemProcess &&
  1627. Process != PsIdleProcess &&
  1628. (Process->Flags&PS_PROCESS_FLAGS_PROCESS_EXITING) != 0) {
  1629. if (Process->ObjectTable != NULL) {
  1630. Wait = TRUE;
  1631. WaitProcess = Process;
  1632. ObReferenceObject (WaitProcess);
  1633. PsQuitNextProcess (WaitProcess);
  1634. break;
  1635. }
  1636. }
  1637. }
  1638. if (Wait) {
  1639. Status = KeWaitForSingleObject (WaitProcess,
  1640. Executive,
  1641. KernelMode,
  1642. FALSE,
  1643. &Timeout);
  1644. ObDereferenceObject (WaitProcess);
  1645. if (Status == STATUS_TIMEOUT) {
  1646. MaxPasses += 1;
  1647. Timeout.QuadPart *= 2;
  1648. if (MaxPasses > 13) {
  1649. KdPrint (("PS: %d process left in the system after termination\n",
  1650. PsProcessType->TotalNumberOfObjects));
  1651. // ASSERT (PsProcessType->TotalNumberOfObjects == 0);
  1652. return FALSE;
  1653. }
  1654. }
  1655. } else {
  1656. return TRUE;
  1657. }
  1658. }
  1659. return TRUE;
  1660. }