Leaked source code of windows server 2003
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.

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