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.

429 lines
10 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. poshtdwn.c
  5. Abstract:
  6. Shutdown-related routines and structures
  7. Author:
  8. Rob Earhart (earhart) 01-Feb-2000
  9. Revision History:
  10. --*/
  11. #include "pop.h"
  12. #if DBG
  13. BOOLEAN
  14. PopDumpFileObject(
  15. IN PVOID Object,
  16. IN PUNICODE_STRING ObjectName,
  17. IN ULONG HandleCount,
  18. IN ULONG PointerCount,
  19. IN PVOID Parameter
  20. );
  21. #endif
  22. #ifdef ALLOC_PRAGMA
  23. #pragma alloc_text(INIT, PopInitShutdownList)
  24. #pragma alloc_text(PAGE, PoRequestShutdownEvent)
  25. #pragma alloc_text(PAGE, PoRequestShutdownWait)
  26. #pragma alloc_text(PAGE, PoQueueShutdownWorkItem)
  27. #pragma alloc_text(PAGELK, PopGracefulShutdown)
  28. #if DBG
  29. #pragma alloc_text(PAGELK, PopDumpFileObject)
  30. #endif
  31. #endif
  32. KEVENT PopShutdownEvent;
  33. FAST_MUTEX PopShutdownListMutex;
  34. #ifdef ALLOC_DATA_PRAGMA
  35. #pragma data_seg("PAGEDATA")
  36. #endif
  37. BOOLEAN PopShutdownListAvailable = FALSE;
  38. SINGLE_LIST_ENTRY PopShutdownThreadList;
  39. LIST_ENTRY PopShutdownQueue;
  40. typedef struct _PoShutdownThreadListEntry {
  41. SINGLE_LIST_ENTRY ShutdownThreadList;
  42. PETHREAD Thread;
  43. } POSHUTDOWNLISTENTRY, *PPOSHUTDOWNLISTENTRY;
  44. NTSTATUS
  45. PopInitShutdownList(
  46. VOID
  47. )
  48. {
  49. PAGED_CODE();
  50. KeInitializeEvent(&PopShutdownEvent,
  51. NotificationEvent,
  52. FALSE);
  53. PopShutdownThreadList.Next = NULL;
  54. InitializeListHead(&PopShutdownQueue);
  55. ExInitializeFastMutex(&PopShutdownListMutex);
  56. PopShutdownListAvailable = TRUE;
  57. return STATUS_SUCCESS;
  58. }
  59. NTSTATUS
  60. PoRequestShutdownWait(
  61. IN PETHREAD Thread
  62. )
  63. {
  64. PPOSHUTDOWNLISTENTRY Entry;
  65. PAGED_CODE();
  66. Entry = (PPOSHUTDOWNLISTENTRY)
  67. ExAllocatePoolWithTag(PagedPool|POOL_COLD_ALLOCATION,
  68. sizeof(POSHUTDOWNLISTENTRY),
  69. 'LSoP');
  70. if (! Entry) {
  71. return STATUS_NO_MEMORY;
  72. }
  73. Entry->Thread = Thread;
  74. ObReferenceObject(Thread);
  75. ExAcquireFastMutex(&PopShutdownListMutex);
  76. if (! PopShutdownListAvailable) {
  77. ObDereferenceObject(Thread);
  78. ExFreePool(Entry);
  79. ExReleaseFastMutex(&PopShutdownListMutex);
  80. return STATUS_UNSUCCESSFUL;
  81. }
  82. PushEntryList(&PopShutdownThreadList,
  83. &Entry->ShutdownThreadList);
  84. ExReleaseFastMutex(&PopShutdownListMutex);
  85. return STATUS_SUCCESS;
  86. }
  87. NTSTATUS
  88. PoRequestShutdownEvent(
  89. OUT PVOID *Event
  90. )
  91. {
  92. NTSTATUS Status;
  93. PAGED_CODE();
  94. if (Event != NULL) {
  95. *Event = NULL;
  96. }
  97. Status = PoRequestShutdownWait(PsGetCurrentThread());
  98. if (!NT_SUCCESS(Status)) {
  99. return Status;
  100. }
  101. if (Event != NULL) {
  102. *Event = &PopShutdownEvent;
  103. }
  104. return STATUS_SUCCESS;
  105. }
  106. NTKERNELAPI
  107. NTSTATUS
  108. PoQueueShutdownWorkItem(
  109. IN PWORK_QUEUE_ITEM WorkItem
  110. )
  111. {
  112. NTSTATUS Status;
  113. PAGED_CODE();
  114. ExAcquireFastMutex(&PopShutdownListMutex);
  115. if (PopShutdownListAvailable) {
  116. InsertTailList(&PopShutdownQueue,
  117. &WorkItem->List);
  118. Status = STATUS_SUCCESS;
  119. } else {
  120. Status = STATUS_SYSTEM_SHUTDOWN;
  121. }
  122. ExReleaseFastMutex(&PopShutdownListMutex);
  123. return Status;
  124. }
  125. #if DBG
  126. extern POBJECT_TYPE IoFileObjectType;
  127. BOOLEAN
  128. PopDumpFileObject(
  129. IN PVOID Object,
  130. IN PUNICODE_STRING ObjectName,
  131. IN ULONG HandleCount,
  132. IN ULONG PointerCount,
  133. IN PVOID Parameter
  134. )
  135. {
  136. PFILE_OBJECT File;
  137. PULONG NumberOfFilesFound;
  138. UNREFERENCED_PARAMETER(ObjectName);
  139. ASSERT(Object);
  140. ASSERT(Parameter);
  141. File = (PFILE_OBJECT) Object;
  142. NumberOfFilesFound = (PULONG) Parameter;
  143. ++*NumberOfFilesFound;
  144. DbgPrint("\t0x%0p : HC %d, PC %d, Name %.*ls\n",
  145. Object, HandleCount, PointerCount,
  146. File->FileName.Length,
  147. File->FileName.Buffer);
  148. return TRUE;
  149. }
  150. #endif // DBG
  151. VOID
  152. PopGracefulShutdown (
  153. IN PVOID WorkItemParameter
  154. )
  155. /*++
  156. Routine Description:
  157. This function is only called as a HyperCritical work queue item.
  158. It's responsible for gracefully shutting down the system.
  159. Return Value:
  160. This function never returns.
  161. --*/
  162. {
  163. PVOID Context;
  164. LARGE_INTEGER Timeout;
  165. HANDLE ShutdownReqThreadHandle;
  166. NTSTATUS Status;
  167. UNREFERENCED_PARAMETER(WorkItemParameter);
  168. //
  169. // Shutdown executive components (there's no turning back after this).
  170. //
  171. PERFINFO_SHUTDOWN_LOG_LAST_MEMORY_SNAPSHOT();
  172. if (!PopAction.ShutdownBugCode) {
  173. HalEndOfBoot();
  174. }
  175. if (PoCleanShutdownEnabled()) {
  176. //
  177. // Terminate all processes. This will close all the handles and delete
  178. // all the address spaces. Note the system process is kept alive.
  179. //
  180. PsShutdownSystem ();
  181. //
  182. // Notify every system thread that we're shutting things
  183. // down...
  184. //
  185. KeSetEvent(&PopShutdownEvent, 0, FALSE);
  186. //
  187. // ... and give all threads which requested notification a
  188. // chance to clean up and exit.
  189. //
  190. ExAcquireFastMutex(&PopShutdownListMutex);
  191. PopShutdownListAvailable = FALSE;
  192. ExReleaseFastMutex(&PopShutdownListMutex);
  193. {
  194. PLIST_ENTRY Next;
  195. PWORK_QUEUE_ITEM WorkItem;
  196. while (PopShutdownQueue.Flink != &PopShutdownQueue) {
  197. Next = RemoveHeadList(&PopShutdownQueue);
  198. WorkItem = CONTAINING_RECORD(Next,
  199. WORK_QUEUE_ITEM,
  200. List);
  201. WorkItem->WorkerRoutine(WorkItem->Parameter);
  202. }
  203. }
  204. {
  205. PSINGLE_LIST_ENTRY Next;
  206. PPOSHUTDOWNLISTENTRY ShutdownEntry;
  207. while (TRUE) {
  208. Next = PopEntryList(&PopShutdownThreadList);
  209. if (! Next) {
  210. break;
  211. }
  212. ShutdownEntry = CONTAINING_RECORD(Next,
  213. POSHUTDOWNLISTENTRY,
  214. ShutdownThreadList);
  215. KeWaitForSingleObject(ShutdownEntry->Thread,
  216. Executive,
  217. KernelMode,
  218. FALSE,
  219. NULL);
  220. ObDereferenceObject(ShutdownEntry->Thread);
  221. ExFreePool(ShutdownEntry);
  222. }
  223. }
  224. }
  225. //
  226. // Terminate Plug-N-Play.
  227. //
  228. PpShutdownSystem (TRUE, 0, &Context);
  229. ExShutdownSystem (0);
  230. //
  231. // Send shutdown IRPs to all drivers that asked for it.
  232. //
  233. IoShutdownSystem (0);
  234. if (PoCleanShutdownEnabled()) {
  235. //
  236. // Wait for all the user mode processes to exit.
  237. //
  238. PsWaitForAllProcesses ();
  239. }
  240. //
  241. // Scrub the object directories
  242. //
  243. if (PoCleanShutdownEnabled() & PO_CLEAN_SHUTDOWN_OB) {
  244. ObShutdownSystem (0);
  245. }
  246. //
  247. // Close the registry and the associated handles/file objects.
  248. //
  249. CmShutdownSystem ();
  250. //
  251. // Check for open handles
  252. //
  253. if (PoCleanShutdownEnabled() & PO_CLEAN_SHUTDOWN_OB) {
  254. ObShutdownSystem (1);
  255. }
  256. //
  257. // This call to MmShutdownSystem will flush all the mapped data and empty
  258. // the cache. This gets the data out and dereferences all the file objects
  259. // so the drivers (ie: the network stack) can be cleanly unloaded.
  260. // Note that the drivers in the paging path will (and must) remain as the
  261. // pagefile handle has not yet been closed.
  262. //
  263. MmShutdownSystem (0);
  264. //
  265. // Inform drivers of the system shutdown state.
  266. // This will finish shutting down Io and Mm.
  267. // After this is complete,
  268. // NO MORE REFERENCES TO PAGABLE CODE OR DATA MAY BE MADE.
  269. //
  270. // ISSUE-2000/03/14-earhart: shutdown filesystems in dev shutdown
  271. IoConfigureCrashDump(CrashDumpDisable);
  272. CcWaitForCurrentLazyWriterActivity();
  273. ExShutdownSystem(1);
  274. IoShutdownSystem(1);
  275. MmShutdownSystem(1);
  276. #if DBG
  277. if (PoCleanShutdownEnabled()) {
  278. ULONG NumberOfFilesFoundAtShutdown = 0;
  279. // As of this time, no files should be open.
  280. DbgPrint("Looking for open files...\n");
  281. ObEnumerateObjectsByType(IoFileObjectType,
  282. &PopDumpFileObject,
  283. &NumberOfFilesFoundAtShutdown);
  284. DbgPrint("Found %d open files.\n", NumberOfFilesFoundAtShutdown);
  285. ASSERT(NumberOfFilesFoundAtShutdown == 0);
  286. }
  287. #endif
  288. // This prevents us from making any more calls out to GDI.
  289. PopFullWake = 0;
  290. ASSERT(PopAction.DevState);
  291. PopAction.DevState->Thread = KeGetCurrentThread();
  292. PopSetDevicesSystemState(FALSE);
  293. IoFreePoDeviceNotifyList(&PopAction.DevState->Order);
  294. //
  295. // Disable any wake alarms.
  296. //
  297. HalSetWakeEnable(FALSE);
  298. //
  299. // If this is a controlled shutdown bugcheck sequence, issue the
  300. // bugcheck now
  301. // ISSUE-2000/01/30-earhart Placement of ShutdownBugCode BugCheck
  302. // I dislike the fact that we're doing this controlled shutdown
  303. // bugcheck so late in the shutdown process; at this stage, too
  304. // much state has been torn down for this to be really useful.
  305. // Maybe if there's a debugger attached, we could shut down
  306. // sooner...
  307. if (PopAction.ShutdownBugCode) {
  308. KeBugCheckEx (PopAction.ShutdownBugCode->Code,
  309. PopAction.ShutdownBugCode->Parameter1,
  310. PopAction.ShutdownBugCode->Parameter2,
  311. PopAction.ShutdownBugCode->Parameter3,
  312. PopAction.ShutdownBugCode->Parameter4);
  313. }
  314. PERFINFO_SHUTDOWN_DUMP_PERF_BUFFER();
  315. PpShutdownSystem (TRUE, 1, &Context);
  316. ExShutdownSystem (2);
  317. if (PoCleanShutdownEnabled() & PO_CLEAN_SHUTDOWN_OB) {
  318. ObShutdownSystem (2);
  319. }
  320. //
  321. // Any allocated pool left at this point is a leak.
  322. //
  323. MmShutdownSystem (2);
  324. //
  325. // Implement shutdown style action -
  326. // N.B. does not return (will bugcheck in preference to returning).
  327. //
  328. PopShutdownSystem(PopAction.Action);
  329. }