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)
9 /* INCLUDES ******************************************************************/
15 /* GLOBALS *******************************************************************/
17 typedef struct _SYS_BUTTON_CONTEXT
19 PDEVICE_OBJECT DeviceObject
;
20 PIO_WORKITEM WorkItem
;
22 IO_STATUS_BLOCK IoStatusBlock
;
24 } SYS_BUTTON_CONTEXT
, *PSYS_BUTTON_CONTEXT
;
29 IN PDEVICE_OBJECT DeviceObject
,
32 PKWIN32_POWEREVENT_CALLOUT PopEventCallout
;
33 extern PCALLBACK_OBJECT SetSystemTimeCallback
;
35 /* FUNCTIONS *****************************************************************/
39 PoNotifySystemTimeSet(VOID
)
43 /* Check if Win32k registered a notification callback */
46 /* Raise to dispatch */
47 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
49 /* Notify the callback */
50 ExNotifyCallback(SetSystemTimeCallback
, NULL
, NULL
);
59 PopGetSysButtonCompletion(
60 IN PDEVICE_OBJECT DeviceObject
,
64 PSYS_BUTTON_CONTEXT SysButtonContext
= Context
;
67 if (Irp
->PendingReturned
)
68 IoMarkIrpPending(Irp
);
70 /* The DeviceObject can be NULL, so use the one we stored */
71 DeviceObject
= SysButtonContext
->DeviceObject
;
73 /* FIXME: What do do with the sys button event? */
74 SysButton
= *(PULONG
)Irp
->AssociatedIrp
.SystemBuffer
;
76 DPRINT1("A device reported the event 0x%x (", SysButton
);
77 if (SysButton
& SYS_BUTTON_POWER
) DbgPrint(" POWER");
78 if (SysButton
& SYS_BUTTON_SLEEP
) DbgPrint(" SLEEP");
79 if (SysButton
& SYS_BUTTON_LID
) DbgPrint(" LID");
80 if (SysButton
== 0) DbgPrint(" WAKE");
83 if (SysButton
& SYS_BUTTON_POWER
)
85 /* FIXME: Read registry for the action we should perform here */
86 DPRINT1("Initiating shutdown after power button event\n");
88 ZwShutdownSystem(ShutdownNoReboot
);
93 /* Allocate a new workitem to send the next IOCTL_GET_SYS_BUTTON_EVENT */
94 SysButtonContext
->WorkItem
= IoAllocateWorkItem(DeviceObject
);
95 if (!SysButtonContext
->WorkItem
)
97 DPRINT("IoAllocateWorkItem() failed\n");
98 ExFreePool(SysButtonContext
);
99 return STATUS_SUCCESS
;
102 SysButtonContext
->WorkItem
,
107 return STATUS_SUCCESS
/* STATUS_CONTINUE_COMPLETION */;
113 IN PDEVICE_OBJECT DeviceObject
,
116 PSYS_BUTTON_CONTEXT SysButtonContext
= Context
;
117 PIO_WORKITEM CurrentWorkItem
= SysButtonContext
->WorkItem
;
120 /* Get button pressed (IOCTL_GET_SYS_BUTTON_EVENT) */
121 KeInitializeEvent(&SysButtonContext
->Event
, NotificationEvent
, FALSE
);
122 Irp
= IoBuildDeviceIoControlRequest(
123 IOCTL_GET_SYS_BUTTON_EVENT
,
127 &SysButtonContext
->SysButton
,
128 sizeof(SysButtonContext
->SysButton
),
130 &SysButtonContext
->Event
,
131 &SysButtonContext
->IoStatusBlock
);
134 IoSetCompletionRoutine(
136 PopGetSysButtonCompletion
,
141 IoCallDriver(DeviceObject
, Irp
);
145 DPRINT1("IoBuildDeviceIoControlRequest() failed\n");
146 ExFreePool(SysButtonContext
);
149 IoFreeWorkItem(CurrentWorkItem
);
154 PopAddRemoveSysCapsCallback(IN PVOID NotificationStructure
,
157 PDEVICE_INTERFACE_CHANGE_NOTIFICATION Notification
;
158 PSYS_BUTTON_CONTEXT SysButtonContext
;
159 OBJECT_ATTRIBUTES ObjectAttributes
;
161 PDEVICE_OBJECT DeviceObject
;
162 PFILE_OBJECT FileObject
;
164 IO_STATUS_BLOCK IoStatusBlock
;
169 UNICODE_STRING DeviceName
;
170 UNICODE_STRING DeviceNamePrefix
= RTL_CONSTANT_STRING(L
"\\??\\");
172 DPRINT("PopAddRemoveSysCapsCallback(%p %p)\n",
173 NotificationStructure
, Context
);
175 Notification
= (PDEVICE_INTERFACE_CHANGE_NOTIFICATION
)NotificationStructure
;
176 if (Notification
->Version
!= 1)
177 return STATUS_REVISION_MISMATCH
;
178 if (Notification
->Size
!= sizeof(DEVICE_INTERFACE_CHANGE_NOTIFICATION
))
179 return STATUS_INVALID_PARAMETER
;
180 if (RtlCompareMemory(&Notification
->Event
, &GUID_DEVICE_INTERFACE_ARRIVAL
, sizeof(GUID
) == sizeof(GUID
)))
182 else if (RtlCompareMemory(&Notification
->Event
, &GUID_DEVICE_INTERFACE_REMOVAL
, sizeof(GUID
) == sizeof(GUID
)))
185 return STATUS_INVALID_PARAMETER
;
189 DPRINT("Arrival of %wZ\n", Notification
->SymbolicLinkName
);
191 DeviceName
.Length
= 0;
192 DeviceName
.MaximumLength
= Notification
->SymbolicLinkName
->MaximumLength
+ DeviceNamePrefix
.MaximumLength
;
193 DeviceName
.Buffer
= ExAllocatePool(PagedPool
, DeviceName
.MaximumLength
);
194 if (!DeviceName
.Buffer
) return STATUS_INSUFFICIENT_RESOURCES
;
196 RtlCopyUnicodeString(&DeviceName
, &DeviceNamePrefix
);
197 RtlAppendUnicodeStringToString(&DeviceName
, Notification
->SymbolicLinkName
);
199 DPRINT("Opening handle to %wZ\n", &DeviceName
);
201 /* Open the device */
202 InitializeObjectAttributes(
213 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
215 if (!NT_SUCCESS(Status
))
217 DPRINT("ZwOpenFile() failed with status 0x%08lx\n", Status
);
220 Status
= ObReferenceObjectByHandle(
227 if (!NT_SUCCESS(Status
))
229 DPRINT("ObReferenceObjectByHandle() failed with status 0x%08lx\n", Status
);
233 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
234 ObDereferenceObject(FileObject
);
236 /* Get capabilities (IOCTL_GET_SYS_BUTTON_CAPS) */
237 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
238 Irp
= IoBuildDeviceIoControlRequest(
239 IOCTL_GET_SYS_BUTTON_CAPS
,
250 DPRINT("IoBuildDeviceIoControlRequest() failed\n");
252 return STATUS_INSUFFICIENT_RESOURCES
;
254 Status
= IoCallDriver(DeviceObject
, Irp
);
255 if (Status
== STATUS_PENDING
)
257 DPRINT("IOCTL_GET_SYS_BUTTON_CAPS pending\n");
258 KeWaitForSingleObject(&Event
, Suspended
, KernelMode
, FALSE
, NULL
);
259 Status
= IoStatusBlock
.Status
;
261 if (!NT_SUCCESS(Status
))
263 DPRINT("Sending IOCTL_GET_SYS_BUTTON_CAPS failed with status 0x%08x\n", Status
);
265 return STATUS_INSUFFICIENT_RESOURCES
;
268 /* FIXME: What do do with the capabilities? */
270 DPRINT1("Device capabilities: 0x%x (", Caps
);
271 if (Caps
& SYS_BUTTON_POWER
) DbgPrint(" POWER");
272 if (Caps
& SYS_BUTTON_SLEEP
) DbgPrint(" SLEEP");
273 if (Caps
& SYS_BUTTON_LID
) DbgPrint(" LID");
277 SysButtonContext
= ExAllocatePool(NonPagedPool
, sizeof(SYS_BUTTON_CONTEXT
));
278 if (!SysButtonContext
)
280 DPRINT("ExAllocatePool() failed\n");
282 return STATUS_INSUFFICIENT_RESOURCES
;
285 /* Queue a work item to get sys button event */
286 SysButtonContext
->WorkItem
= IoAllocateWorkItem(DeviceObject
);
287 SysButtonContext
->DeviceObject
= DeviceObject
;
288 if (!SysButtonContext
->WorkItem
)
290 DPRINT("IoAllocateWorkItem() failed\n");
292 ExFreePool(SysButtonContext
);
293 return STATUS_INSUFFICIENT_RESOURCES
;
296 SysButtonContext
->WorkItem
,
302 return STATUS_SUCCESS
;
306 DPRINT1("Removal of a power capable device not implemented\n");
307 return STATUS_NOT_IMPLEMENTED
;