Sync to trunk head (r47736)
[reactos.git] / ntoskrnl / po / poshtdwn.c
1 /*
2 * PROJECT: ReactOS Kernel
3 * LICENSE: BSD - See COPYING.ARM in the top level directory
4 * FILE: ntoskrnl/po/poshtdwn.c
5 * PURPOSE: Power Manager Shutdown Code
6 * PROGRAMMERS: ReactOS Portable Systems Group
7 */
8
9 /* INCLUDES ******************************************************************/
10
11 #include <ntoskrnl.h>
12 #define NDEBUG
13 #include <debug.h>
14
15 /* GLOBALS *******************************************************************/
16
17 ULONG PopShutdownPowerOffPolicy;
18
19 /* PRIVATE FUNCTIONS *********************************************************/
20
21 VOID
22 NTAPI
23 PopShutdownHandler(VOID)
24 {
25 PUCHAR Logo1, Logo2;
26 ULONG i;
27
28 /* Stop all interrupts */
29 KeRaiseIrqlToDpcLevel();
30 _disable();
31
32 /* Do we have boot video */
33 if (InbvIsBootDriverInstalled())
34 {
35 /* Yes we do, cleanup for shutdown screen */
36 if (!InbvCheckDisplayOwnership()) InbvAcquireDisplayOwnership();
37 InbvResetDisplay();
38 InbvSolidColorFill(0, 0, 639, 479, 0);
39 InbvEnableDisplayString(TRUE);
40 InbvSetScrollRegion(0, 0, 639, 479);
41
42 /* Display shutdown logo and message */
43 Logo1 = InbvGetResourceAddress(IDB_SHUTDOWN_LOGO);
44 Logo2 = InbvGetResourceAddress(IDB_LOGO);
45 if ((Logo1) && (Logo2))
46 {
47 InbvBitBlt(Logo1, 215, 352);
48 InbvBitBlt(Logo2, 217, 111);
49 }
50 }
51 else
52 {
53 /* Do it in text-mode */
54 for (i = 0; i < 25; i++) InbvDisplayString("\n");
55 InbvDisplayString(" ");
56 InbvDisplayString("The system may be powered off now.\n");
57 }
58
59 /* Hang the system */
60 for (;;) HalHaltSystem();
61 }
62
63 VOID
64 NTAPI
65 PopShutdownSystem(IN POWER_ACTION SystemAction)
66 {
67 /* Note should notify caller of NtPowerInformation(PowerShutdownNotification) */
68
69 /* Unload symbols */
70 DPRINT1("It's the final countdown...%lx\n", SystemAction);
71 DbgUnLoadImageSymbols(NULL, (PVOID)-1, 0);
72
73 /* Run the thread on the boot processor */
74 KeSetSystemAffinityThread(1);
75
76 /* Now check what the caller wants */
77 switch (SystemAction)
78 {
79 /* Reset */
80 case PowerActionShutdownReset:
81
82 /* Try platform driver first, then legacy */
83 //PopInvokeSystemStateHandler(PowerStateShutdownReset, NULL);
84 HalReturnToFirmware(HalRebootRoutine);
85 break;
86
87 case PowerActionShutdown:
88
89 /* Check for group policy that says to use "it is now safe" screen */
90 if (PopShutdownPowerOffPolicy)
91 {
92 /* FIXFIX: Switch to legacy shutdown handler */
93 //PopPowerStateHandlers[PowerStateShutdownOff].Handler = PopShutdownHandler;
94 }
95
96 case PowerActionShutdownOff:
97
98 /* Call shutdown handler */
99 //PopInvokeSystemStateHandler(PowerStateShutdownOff, NULL);
100
101 /* ReactOS Hack */
102 PopSetSystemPowerState(PowerSystemShutdown);
103 PopShutdownHandler();
104
105 /* If that didn't work, call the HAL */
106 HalReturnToFirmware(HalPowerDownRoutine);
107 break;
108
109 default:
110 break;
111 }
112
113 /* Anything else should not happen */
114 KeBugCheckEx(INTERNAL_POWER_ERROR, 5, 0, 0, 0);
115 }
116
117 VOID
118 NTAPI
119 PopGracefulShutdown(IN PVOID Context)
120 {
121 PEPROCESS Process = NULL;
122
123 /* Loop every process */
124 Process = PsGetNextProcess(Process);
125 while (Process)
126 {
127 /* Make sure this isn't the idle or initial process */
128 if ((Process != PsInitialSystemProcess) && (Process != PsIdleProcess))
129 {
130 /* Print it */
131 DPRINT1("%15s is still RUNNING (%lx)\n", Process->ImageFileName, Process->UniqueProcessId);
132 }
133
134 /* Get the next process */
135 Process = PsGetNextProcess(Process);
136 }
137
138 /* First, the HAL handles any "end of boot" special functionality */
139 DPRINT1("HAL shutting down\n");
140 HalEndOfBoot();
141
142 /* In this step, the I/O manager does first-chance shutdown notification */
143 DPRINT1("I/O manager shutting down in phase 0\n");
144 IoShutdownSystem(0);
145
146 /* In this step, all workers are killed and hives are flushed */
147 DPRINT1("Configuration Manager shutting down\n");
148 CmShutdownSystem();
149
150 /* Note that modified pages should be written here (MiShutdownSystem) */
151
152 /* In this step, the I/O manager does last-chance shutdown notification */
153 DPRINT1("I/O manager shutting down in phase 1\n");
154 IoShutdownSystem(1);
155 CcWaitForCurrentLazyWriterActivity();
156
157 /* Note that here, we should broadcast the power IRP to devices */
158
159 /* In this step, the HAL disables any wake timers */
160 DPRINT1("Disabling wake timers\n");
161 HalSetWakeEnable(FALSE);
162
163 /* And finally the power request is sent */
164 DPRINT1("Taking the system down\n");
165 PopShutdownSystem(PopAction.Action);
166 }
167
168 VOID
169 NTAPI
170 PopReadShutdownPolicy(VOID)
171 {
172 UNICODE_STRING KeyString;
173 OBJECT_ATTRIBUTES ObjectAttributes;
174 NTSTATUS Status;
175 HANDLE KeyHandle;
176 ULONG Length;
177 UCHAR Buffer[sizeof(KEY_VALUE_PARTIAL_INFORMATION) + sizeof(ULONG)];
178 PKEY_VALUE_PARTIAL_INFORMATION Info = (PVOID)Buffer;
179
180 /* Setup object attributes */
181 RtlInitUnicodeString(&KeyString,
182 L"\\Registry\\Machine\\Software\\Policies\\Microsoft\\Windows NT");
183 InitializeObjectAttributes(&ObjectAttributes,
184 &KeyString,
185 OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
186 NULL,
187 NULL);
188
189 /* Open the key */
190 Status = ZwOpenKey(&KeyHandle, KEY_READ, &ObjectAttributes);
191 if (NT_SUCCESS(Status))
192 {
193 /* Open the policy value and query it */
194 RtlInitUnicodeString(&KeyString, L"DontPowerOffAfterShutdown");
195 Status = ZwQueryValueKey(KeyHandle,
196 &KeyString,
197 KeyValuePartialInformation,
198 &Info,
199 sizeof(Info),
200 &Length);
201 if ((NT_SUCCESS(Status)) && (Info->Type == REG_DWORD))
202 {
203 /* Read the policy */
204 PopShutdownPowerOffPolicy = *Info->Data == 1;
205 }
206
207 /* Close the key */
208 ZwClose(KeyHandle);
209 }
210 }
211
212 /* PUBLIC FUNCTIONS **********************************************************/
213