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 /* The DeviceObject can be NULL, so use the one we stored */
68 DeviceObject
= SysButtonContext
->DeviceObject
;
70 /* FIXME: What do do with the sys button event? */
71 SysButton
= *(PULONG
)Irp
->AssociatedIrp
.SystemBuffer
;
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");
80 if (SysButton
& SYS_BUTTON_POWER
)
82 /* FIXME: Read registry for the action we should perform here */
83 DPRINT1("Initiating shutdown after power button event\n");
85 ZwShutdownSystem(ShutdownNoReboot
);
89 /* Allocate a new workitem to send the next IOCTL_GET_SYS_BUTTON_EVENT */
90 SysButtonContext
->WorkItem
= IoAllocateWorkItem(DeviceObject
);
91 if (!SysButtonContext
->WorkItem
)
93 DPRINT("IoAllocateWorkItem() failed\n");
94 ExFreePoolWithTag(SysButtonContext
, 'IWOP');
95 return STATUS_SUCCESS
;
97 IoQueueWorkItem(SysButtonContext
->WorkItem
,
102 return STATUS_SUCCESS
/* STATUS_CONTINUE_COMPLETION */;
108 IN PDEVICE_OBJECT DeviceObject
,
111 PSYS_BUTTON_CONTEXT SysButtonContext
= Context
;
112 PIO_WORKITEM CurrentWorkItem
= SysButtonContext
->WorkItem
;
115 /* Get button pressed (IOCTL_GET_SYS_BUTTON_EVENT) */
116 KeInitializeEvent(&SysButtonContext
->Event
, NotificationEvent
, FALSE
);
117 Irp
= IoBuildDeviceIoControlRequest(IOCTL_GET_SYS_BUTTON_EVENT
,
121 &SysButtonContext
->SysButton
,
122 sizeof(SysButtonContext
->SysButton
),
124 &SysButtonContext
->Event
,
125 &SysButtonContext
->IoStatusBlock
);
128 IoSetCompletionRoutine(Irp
,
129 PopGetSysButtonCompletion
,
134 IoCallDriver(DeviceObject
, Irp
);
138 DPRINT1("IoBuildDeviceIoControlRequest() failed\n");
139 ExFreePoolWithTag(SysButtonContext
, 'IWOP');
142 IoFreeWorkItem(CurrentWorkItem
);
147 PopAddRemoveSysCapsCallback(IN PVOID NotificationStructure
,
150 PDEVICE_INTERFACE_CHANGE_NOTIFICATION Notification
;
151 PSYS_BUTTON_CONTEXT SysButtonContext
;
152 OBJECT_ATTRIBUTES ObjectAttributes
;
154 PDEVICE_OBJECT DeviceObject
;
155 PFILE_OBJECT FileObject
;
157 IO_STATUS_BLOCK IoStatusBlock
;
162 POP_POLICY_DEVICE_TYPE DeviceType
= (POP_POLICY_DEVICE_TYPE
)(ULONG_PTR
)Context
;
164 DPRINT("PopAddRemoveSysCapsCallback(%p %p)\n",
165 NotificationStructure
, Context
);
167 Notification
= (PDEVICE_INTERFACE_CHANGE_NOTIFICATION
)NotificationStructure
;
168 if (Notification
->Version
!= 1)
169 return STATUS_REVISION_MISMATCH
;
170 if (Notification
->Size
!= sizeof(DEVICE_INTERFACE_CHANGE_NOTIFICATION
))
171 return STATUS_INVALID_PARAMETER
;
172 if (RtlCompareMemory(&Notification
->Event
, &GUID_DEVICE_INTERFACE_ARRIVAL
, sizeof(GUID
)) == sizeof(GUID
))
174 else if (RtlCompareMemory(&Notification
->Event
, &GUID_DEVICE_INTERFACE_REMOVAL
, sizeof(GUID
)) == sizeof(GUID
))
177 return STATUS_INVALID_PARAMETER
;
179 if (Arrival
&& DeviceType
== PolicyDeviceBattery
)
181 PopCapabilities
.SystemBatteriesPresent
= TRUE
;
182 return STATUS_SUCCESS
;
187 DPRINT("Arrival of %wZ\n", Notification
->SymbolicLinkName
);
189 /* Open the device */
190 InitializeObjectAttributes(&ObjectAttributes
,
191 Notification
->SymbolicLinkName
,
195 Status
= ZwOpenFile(&FileHandle
,
199 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
201 if (!NT_SUCCESS(Status
))
203 DPRINT1("ZwOpenFile() failed with status 0x%08lx\n", Status
);
206 Status
= ObReferenceObjectByHandle(FileHandle
,
212 if (!NT_SUCCESS(Status
))
214 DPRINT1("ObReferenceObjectByHandle() failed with status 0x%08lx\n", Status
);
218 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
219 ObDereferenceObject(FileObject
);
221 /* Get capabilities (IOCTL_GET_SYS_BUTTON_CAPS) */
222 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
223 Irp
= IoBuildDeviceIoControlRequest(IOCTL_GET_SYS_BUTTON_CAPS
,
234 DPRINT1("IoBuildDeviceIoControlRequest() failed\n");
236 return STATUS_INSUFFICIENT_RESOURCES
;
238 Status
= IoCallDriver(DeviceObject
, Irp
);
239 if (Status
== STATUS_PENDING
)
241 DPRINT("IOCTL_GET_SYS_BUTTON_CAPS pending\n");
242 KeWaitForSingleObject(&Event
, Suspended
, KernelMode
, FALSE
, NULL
);
243 Status
= IoStatusBlock
.Status
;
245 if (!NT_SUCCESS(Status
))
247 DPRINT1("Sending IOCTL_GET_SYS_BUTTON_CAPS failed with status 0x%08x\n", Status
);
249 return STATUS_INSUFFICIENT_RESOURCES
;
252 DPRINT("Device capabilities: 0x%x\n", Caps
);
253 if (Caps
& SYS_BUTTON_POWER
)
255 DPRINT("POWER button present\n");
256 PopCapabilities
.PowerButtonPresent
= TRUE
;
259 if (Caps
& SYS_BUTTON_SLEEP
)
261 DPRINT("SLEEP button present\n");
262 PopCapabilities
.SleepButtonPresent
= TRUE
;
265 if (Caps
& SYS_BUTTON_LID
)
267 DPRINT("LID present\n");
268 PopCapabilities
.LidPresent
= TRUE
;
271 SysButtonContext
= ExAllocatePoolWithTag(NonPagedPool
,
272 sizeof(SYS_BUTTON_CONTEXT
),
274 if (!SysButtonContext
)
276 DPRINT1("ExAllocatePoolWithTag() failed\n");
278 return STATUS_INSUFFICIENT_RESOURCES
;
281 /* Queue a work item to get sys button event */
282 SysButtonContext
->WorkItem
= IoAllocateWorkItem(DeviceObject
);
283 SysButtonContext
->DeviceObject
= DeviceObject
;
284 if (!SysButtonContext
->WorkItem
)
286 DPRINT1("IoAllocateWorkItem() failed\n");
288 ExFreePoolWithTag(SysButtonContext
, 'IWOP');
289 return STATUS_INSUFFICIENT_RESOURCES
;
291 IoQueueWorkItem(SysButtonContext
->WorkItem
,
297 return STATUS_SUCCESS
;
301 DPRINT1("Removal of a power capable device not implemented\n");
302 return STATUS_NOT_IMPLEMENTED
;