[STORPORT] Fix x64 build
[reactos.git] / ntoskrnl / po / events.c
1 /*
2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: ntoskrnl/po/events.c
5 * PURPOSE: Power Manager
6 * PROGRAMMERS: Hervé Poussineau (hpoussin@reactos.org)
7 */
8
9 /* INCLUDES ******************************************************************/
10
11 #include <ntoskrnl.h>
12 #define NDEBUG
13 #include <debug.h>
14
15 /* GLOBALS *******************************************************************/
16
17 typedef struct _SYS_BUTTON_CONTEXT
18 {
19 PDEVICE_OBJECT DeviceObject;
20 PIO_WORKITEM WorkItem;
21 KEVENT Event;
22 IO_STATUS_BLOCK IoStatusBlock;
23 ULONG SysButton;
24 } SYS_BUTTON_CONTEXT, *PSYS_BUTTON_CONTEXT;
25
26 static VOID
27 NTAPI
28 PopGetSysButton(
29 IN PDEVICE_OBJECT DeviceObject,
30 IN PVOID Context);
31
32 PKWIN32_POWEREVENT_CALLOUT PopEventCallout;
33 extern PCALLBACK_OBJECT SetSystemTimeCallback;
34
35 /* FUNCTIONS *****************************************************************/
36
37 VOID
38 NTAPI
39 PoNotifySystemTimeSet(VOID)
40 {
41 KIRQL OldIrql;
42
43 /* Check if Win32k registered a notification callback */
44 if (PopEventCallout)
45 {
46 /* Raise to dispatch */
47 KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
48
49 /* Notify the callback */
50 ExNotifyCallback(SetSystemTimeCallback, NULL, NULL);
51
52 /* Lower IRQL back */
53 KeLowerIrql(OldIrql);
54 }
55 }
56
57 static NTSTATUS
58 NTAPI
59 PopGetSysButtonCompletion(
60 IN PDEVICE_OBJECT DeviceObject,
61 IN PIRP Irp,
62 IN PVOID Context)
63 {
64 PSYS_BUTTON_CONTEXT SysButtonContext = Context;
65 ULONG SysButton;
66
67 /* The DeviceObject can be NULL, so use the one we stored */
68 DeviceObject = SysButtonContext->DeviceObject;
69
70 /* FIXME: What do do with the sys button event? */
71 SysButton = *(PULONG)Irp->AssociatedIrp.SystemBuffer;
72 {
73 DPRINT1("A device reported the event 0x%x (", SysButton);
74 if (SysButton & SYS_BUTTON_POWER) DbgPrint(" POWER");
75 if (SysButton & SYS_BUTTON_SLEEP) DbgPrint(" SLEEP");
76 if (SysButton & SYS_BUTTON_LID) DbgPrint(" LID");
77 if (SysButton == 0) DbgPrint(" WAKE");
78 DbgPrint(" )\n");
79
80 if (SysButton & SYS_BUTTON_POWER)
81 {
82 /* FIXME: Read registry for the action we should perform here */
83 DPRINT1("Initiating shutdown after power button event\n");
84
85 ZwShutdownSystem(ShutdownNoReboot);
86 }
87 }
88
89 /* Allocate a new workitem to send the next IOCTL_GET_SYS_BUTTON_EVENT */
90 SysButtonContext->WorkItem = IoAllocateWorkItem(DeviceObject);
91 if (!SysButtonContext->WorkItem)
92 {
93 DPRINT("IoAllocateWorkItem() failed\n");
94 ExFreePoolWithTag(SysButtonContext, 'IWOP');
95 return STATUS_SUCCESS;
96 }
97 IoQueueWorkItem(SysButtonContext->WorkItem,
98 PopGetSysButton,
99 DelayedWorkQueue,
100 SysButtonContext);
101
102 return STATUS_SUCCESS /* STATUS_CONTINUE_COMPLETION */;
103 }
104
105 static VOID
106 NTAPI
107 PopGetSysButton(
108 IN PDEVICE_OBJECT DeviceObject,
109 IN PVOID Context)
110 {
111 PSYS_BUTTON_CONTEXT SysButtonContext = Context;
112 PIO_WORKITEM CurrentWorkItem = SysButtonContext->WorkItem;
113 PIRP Irp;
114
115 /* Get button pressed (IOCTL_GET_SYS_BUTTON_EVENT) */
116 KeInitializeEvent(&SysButtonContext->Event, NotificationEvent, FALSE);
117 Irp = IoBuildDeviceIoControlRequest(IOCTL_GET_SYS_BUTTON_EVENT,
118 DeviceObject,
119 NULL,
120 0,
121 &SysButtonContext->SysButton,
122 sizeof(SysButtonContext->SysButton),
123 FALSE,
124 &SysButtonContext->Event,
125 &SysButtonContext->IoStatusBlock);
126 if (Irp)
127 {
128 IoSetCompletionRoutine(Irp,
129 PopGetSysButtonCompletion,
130 SysButtonContext,
131 TRUE,
132 FALSE,
133 FALSE);
134 IoCallDriver(DeviceObject, Irp);
135 }
136 else
137 {
138 DPRINT1("IoBuildDeviceIoControlRequest() failed\n");
139 ExFreePoolWithTag(SysButtonContext, 'IWOP');
140 }
141
142 IoFreeWorkItem(CurrentWorkItem);
143 }
144
145 NTSTATUS
146 NTAPI
147 PopAddRemoveSysCapsCallback(IN PVOID NotificationStructure,
148 IN PVOID Context)
149 {
150 PDEVICE_INTERFACE_CHANGE_NOTIFICATION Notification;
151 PSYS_BUTTON_CONTEXT SysButtonContext;
152 OBJECT_ATTRIBUTES ObjectAttributes;
153 HANDLE FileHandle;
154 PDEVICE_OBJECT DeviceObject;
155 PFILE_OBJECT FileObject;
156 PIRP Irp;
157 IO_STATUS_BLOCK IoStatusBlock;
158 KEVENT Event;
159 BOOLEAN Arrival;
160 ULONG Caps;
161 NTSTATUS Status;
162
163 DPRINT("PopAddRemoveSysCapsCallback(%p %p)\n",
164 NotificationStructure, Context);
165
166 Notification = (PDEVICE_INTERFACE_CHANGE_NOTIFICATION)NotificationStructure;
167 if (Notification->Version != 1)
168 return STATUS_REVISION_MISMATCH;
169 if (Notification->Size != sizeof(DEVICE_INTERFACE_CHANGE_NOTIFICATION))
170 return STATUS_INVALID_PARAMETER;
171 if (RtlCompareMemory(&Notification->Event, &GUID_DEVICE_INTERFACE_ARRIVAL, sizeof(GUID)) == sizeof(GUID))
172 Arrival = TRUE;
173 else if (RtlCompareMemory(&Notification->Event, &GUID_DEVICE_INTERFACE_REMOVAL, sizeof(GUID)) == sizeof(GUID))
174 Arrival = FALSE;
175 else
176 return STATUS_INVALID_PARAMETER;
177
178 if (Arrival)
179 {
180 DPRINT("Arrival of %wZ\n", Notification->SymbolicLinkName);
181
182 /* Open the device */
183 InitializeObjectAttributes(&ObjectAttributes,
184 Notification->SymbolicLinkName,
185 OBJ_KERNEL_HANDLE,
186 NULL,
187 NULL);
188 Status = ZwOpenFile(&FileHandle,
189 FILE_READ_DATA,
190 &ObjectAttributes,
191 &IoStatusBlock,
192 FILE_SHARE_READ | FILE_SHARE_WRITE,
193 0);
194 if (!NT_SUCCESS(Status))
195 {
196 DPRINT1("ZwOpenFile() failed with status 0x%08lx\n", Status);
197 return Status;
198 }
199 Status = ObReferenceObjectByHandle(FileHandle,
200 FILE_READ_DATA,
201 IoFileObjectType,
202 KernelMode,
203 (PVOID*)&FileObject,
204 NULL);
205 if (!NT_SUCCESS(Status))
206 {
207 DPRINT1("ObReferenceObjectByHandle() failed with status 0x%08lx\n", Status);
208 ZwClose(FileHandle);
209 return Status;
210 }
211 DeviceObject = IoGetRelatedDeviceObject(FileObject);
212 ObDereferenceObject(FileObject);
213
214 /* Get capabilities (IOCTL_GET_SYS_BUTTON_CAPS) */
215 KeInitializeEvent(&Event, NotificationEvent, FALSE);
216 Irp = IoBuildDeviceIoControlRequest(IOCTL_GET_SYS_BUTTON_CAPS,
217 DeviceObject,
218 NULL,
219 0,
220 &Caps,
221 sizeof(Caps),
222 FALSE,
223 &Event,
224 &IoStatusBlock);
225 if (!Irp)
226 {
227 DPRINT1("IoBuildDeviceIoControlRequest() failed\n");
228 ZwClose(FileHandle);
229 return STATUS_INSUFFICIENT_RESOURCES;
230 }
231 Status = IoCallDriver(DeviceObject, Irp);
232 if (Status == STATUS_PENDING)
233 {
234 DPRINT("IOCTL_GET_SYS_BUTTON_CAPS pending\n");
235 KeWaitForSingleObject(&Event, Suspended, KernelMode, FALSE, NULL);
236 Status = IoStatusBlock.Status;
237 }
238 if (!NT_SUCCESS(Status))
239 {
240 DPRINT1("Sending IOCTL_GET_SYS_BUTTON_CAPS failed with status 0x%08x\n", Status);
241 ZwClose(FileHandle);
242 return STATUS_INSUFFICIENT_RESOURCES;
243 }
244
245 /* FIXME: What do do with the capabilities? */
246 {
247 DPRINT("Device capabilities: 0x%x (", Caps);
248 if (Caps & SYS_BUTTON_POWER) DPRINT(" POWER");
249 if (Caps & SYS_BUTTON_SLEEP) DPRINT(" SLEEP");
250 if (Caps & SYS_BUTTON_LID) DPRINT(" LID");
251 DPRINT(" )\n");
252 }
253
254 SysButtonContext = ExAllocatePoolWithTag(NonPagedPool,
255 sizeof(SYS_BUTTON_CONTEXT),
256 'IWOP');
257 if (!SysButtonContext)
258 {
259 DPRINT1("ExAllocatePoolWithTag() failed\n");
260 ZwClose(FileHandle);
261 return STATUS_INSUFFICIENT_RESOURCES;
262 }
263
264 /* Queue a work item to get sys button event */
265 SysButtonContext->WorkItem = IoAllocateWorkItem(DeviceObject);
266 SysButtonContext->DeviceObject = DeviceObject;
267 if (!SysButtonContext->WorkItem)
268 {
269 DPRINT1("IoAllocateWorkItem() failed\n");
270 ZwClose(FileHandle);
271 ExFreePoolWithTag(SysButtonContext, 'IWOP');
272 return STATUS_INSUFFICIENT_RESOURCES;
273 }
274 IoQueueWorkItem(SysButtonContext->WorkItem,
275 PopGetSysButton,
276 DelayedWorkQueue,
277 SysButtonContext);
278
279 ZwClose(FileHandle);
280 return STATUS_SUCCESS;
281 }
282 else
283 {
284 DPRINT1("Removal of a power capable device not implemented\n");
285 return STATUS_NOT_IMPLEMENTED;
286 }
287 }