Author: hpoussin
Date: Thu Jul 5 18:23:16 2007
New Revision: 27407
URL:
http://svn.reactos.org/svn/reactos?rev=27407&view=rev
Log:
Better support of GUID_DEVICE_SYS_BUTTON interface.
Now, the kernel can receive power events from the keyboard, but only reacts by displaying
a message
Modified:
trunk/reactos/ntoskrnl/po/events.c
Modified: trunk/reactos/ntoskrnl/po/events.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/po/events.c?rev=2…
==============================================================================
--- trunk/reactos/ntoskrnl/po/events.c (original)
+++ trunk/reactos/ntoskrnl/po/events.c Thu Jul 5 18:23:16 2007
@@ -8,11 +8,17 @@
*/
#include <ntoskrnl.h>
-//#define NDEBUG
+#define NDEBUG
#include <internal/debug.h>
PKWIN32_POWEREVENT_CALLOUT PopEventCallout;
extern PCALLBACK_OBJECT SetSystemTimeCallback;
+
+static VOID
+NTAPI
+PopGetSysButton(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PVOID Context);
VOID
NTAPI
@@ -34,6 +40,101 @@
}
}
+typedef struct _SYS_BUTTON_CONTEXT
+{
+ PDEVICE_OBJECT DeviceObject;
+ PIO_WORKITEM WorkItem;
+ KEVENT Event;
+ IO_STATUS_BLOCK IoStatusBlock;
+ ULONG SysButton;
+} SYS_BUTTON_CONTEXT, *PSYS_BUTTON_CONTEXT;
+
+static NTSTATUS
+NTAPI
+PopGetSysButtonCompletion(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp,
+ IN PVOID Context)
+{
+ PSYS_BUTTON_CONTEXT SysButtonContext = Context;
+ ULONG SysButton;
+
+ if (Irp->PendingReturned)
+ IoMarkIrpPending(Irp);
+
+ /* The DeviceObject can be NULL, so use the one we stored */
+ DeviceObject = SysButtonContext->DeviceObject;
+
+ /* FIXME: What do do with the sys button event? */
+ SysButton = *(PULONG)Irp->AssociatedIrp.SystemBuffer;
+ {
+ DPRINT1("A device reported the event 0x%x (", SysButton);
+ if (SysButton & SYS_BUTTON_POWER) DbgPrint(" POWER");
+ if (SysButton & SYS_BUTTON_SLEEP) DbgPrint(" SLEEP");
+ if (SysButton & SYS_BUTTON_LID) DbgPrint(" LID");
+ if (SysButton == 0) DbgPrint(" WAKE");
+ DbgPrint(" )\n");
+ }
+
+ /* Allocate a new workitem to send the next IOCTL_GET_SYS_BUTTON_EVENT */
+ SysButtonContext->WorkItem = IoAllocateWorkItem(DeviceObject);
+ if (!SysButtonContext->WorkItem)
+ {
+ DPRINT("IoAllocateWorkItem() failed\n");
+ ExFreePool(SysButtonContext);
+ return STATUS_SUCCESS;
+ }
+ IoQueueWorkItem(
+ SysButtonContext->WorkItem,
+ PopGetSysButton,
+ DelayedWorkQueue,
+ SysButtonContext);
+
+ return STATUS_SUCCESS /* STATUS_CONTINUE_COMPLETION */;
+}
+
+static VOID
+NTAPI
+PopGetSysButton(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PVOID Context)
+{
+ PSYS_BUTTON_CONTEXT SysButtonContext = Context;
+ PIO_WORKITEM CurrentWorkItem = SysButtonContext->WorkItem;;
+ PIRP Irp;
+
+ /* Get button pressed (IOCTL_GET_SYS_BUTTON_EVENT) */
+ KeInitializeEvent(&SysButtonContext->Event, NotificationEvent, FALSE);
+ Irp = IoBuildDeviceIoControlRequest(
+ IOCTL_GET_SYS_BUTTON_EVENT,
+ DeviceObject,
+ NULL,
+ 0,
+ &SysButtonContext->SysButton,
+ sizeof(SysButtonContext->SysButton),
+ FALSE,
+ &SysButtonContext->Event,
+ &SysButtonContext->IoStatusBlock);
+ if (Irp)
+ {
+ IoSetCompletionRoutine(
+ Irp,
+ PopGetSysButtonCompletion,
+ SysButtonContext,
+ TRUE,
+ FALSE,
+ FALSE);
+ IoCallDriver(DeviceObject, Irp);
+ }
+ else
+ {
+ DPRINT1("IoBuildDeviceIoControlRequest() failed\n");
+ ExFreePool(SysButtonContext);
+ }
+
+ IoFreeWorkItem(CurrentWorkItem);
+}
+
NTSTATUS
NTAPI
PopAddRemoveSysCapsCallback(
@@ -41,9 +142,14 @@
IN PVOID Context)
{
PDEVICE_INTERFACE_CHANGE_NOTIFICATION Notification;
+ PSYS_BUTTON_CONTEXT SysButtonContext;
OBJECT_ATTRIBUTES ObjectAttributes;
- HANDLE DeviceHandle;
+ HANDLE FileHandle;
+ PDEVICE_OBJECT DeviceObject;
+ PFILE_OBJECT FileObject;
+ PIRP Irp;
IO_STATUS_BLOCK IoStatusBlock;
+ KEVENT Event;
BOOLEAN Arrival;
ULONG Caps;
NTSTATUS Status;
@@ -67,7 +173,7 @@
{
DPRINT("Arrival of %wZ\n", Notification->SymbolicLinkName);
- /* Open device */
+ /* Open the device */
InitializeObjectAttributes(
&ObjectAttributes,
Notification->SymbolicLinkName,
@@ -75,7 +181,7 @@
NULL,
NULL);
Status = ZwOpenFile(
- &DeviceHandle,
+ &FileHandle,
FILE_READ_DATA,
&ObjectAttributes,
&IoStatusBlock,
@@ -86,32 +192,89 @@
DPRINT("ZwOpenFile() failed with status 0x%08lx\n", Status);
return Status;
}
-
- /* Send IOCTL_GET_SYS_BUTTON_CAPS to get new caps */
- Status = ZwDeviceIoControlFile(
- DeviceHandle,
- NULL,
- NULL,
- NULL,
- &IoStatusBlock,
+ Status = ObReferenceObjectByHandle(
+ FileHandle,
+ FILE_READ_DATA,
+ IoFileObjectType,
+ ExGetPreviousMode(),
+ (PVOID*)&FileObject,
+ NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT("ObReferenceObjectByHandle() failed with status 0x%08lx\n", Status);
+ ZwClose(FileHandle);
+ return Status;
+ }
+ DeviceObject = IoGetRelatedDeviceObject(FileObject);
+ ObDereferenceObject(FileObject);
+
+ /* Get capabilities (IOCTL_GET_SYS_BUTTON_CAPS) */
+ KeInitializeEvent(&Event, NotificationEvent, FALSE);
+ Irp = IoBuildDeviceIoControlRequest(
IOCTL_GET_SYS_BUTTON_CAPS,
+ DeviceObject,
NULL,
0,
&Caps,
- sizeof(Caps));
+ sizeof(Caps),
+ FALSE,
+ &Event,
+ &IoStatusBlock);
+ if (!Irp)
+ {
+ DPRINT("IoBuildDeviceIoControlRequest() failed\n");
+ ZwClose(FileHandle);
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+ Status = IoCallDriver(DeviceObject, Irp);
+ if (Status == STATUS_PENDING)
+ {
+ DPRINT("IOCTL_GET_SYS_BUTTON_CAPS pending\n");
+ KeWaitForSingleObject(&Event, Suspended, KernelMode, FALSE, NULL);
+ Status = IoStatusBlock.Status;
+ }
if (!NT_SUCCESS(Status))
{
- DPRINT("ZwDeviceIoControlFile(IOCTL_GET_SYS_BUTTON_CAPS) failed with status
0x%08lx\n", Status);
- ZwClose(DeviceHandle);
- return Status;
- }
- /* FIXME: What do do with this? */
- DPRINT1("Device capabilities: 0x%lx\n", Caps);
-
- /* Send IOCTL_GET_SYS_BUTTON_CAPS to get current caps */
- /* FIXME: Set a IO completion routine on it to be able to send a new one */
- DPRINT1("Send a IOCTL_GET_SYS_BUTTON_EVENT\n");
- return ZwClose(DeviceHandle);
+ DPRINT("Sending IOCTL_GET_SYS_BUTTON_CAPS failed with status 0x%08x\n",
Status);
+ ZwClose(FileHandle);
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ /* FIXME: What do do with the capabilities? */
+ {
+ DPRINT1("Device capabilities: 0x%x (", Caps);
+ if (Caps & SYS_BUTTON_POWER) DbgPrint(" POWER");
+ if (Caps & SYS_BUTTON_SLEEP) DbgPrint(" SLEEP");
+ if (Caps & SYS_BUTTON_LID) DbgPrint(" LID");
+ DbgPrint(" )\n");
+ }
+
+ SysButtonContext = ExAllocatePool(NonPagedPool, sizeof(SYS_BUTTON_CONTEXT));
+ if (!SysButtonContext)
+ {
+ DPRINT("ExAllocatePool() failed\n");
+ ZwClose(FileHandle);
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ /* Queue a work item to get sys button event */
+ SysButtonContext->WorkItem = IoAllocateWorkItem(DeviceObject);
+ SysButtonContext->DeviceObject = DeviceObject;
+ if (!SysButtonContext->WorkItem)
+ {
+ DPRINT("IoAllocateWorkItem() failed\n");
+ ZwClose(FileHandle);
+ ExFreePool(SysButtonContext);
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+ IoQueueWorkItem(
+ SysButtonContext->WorkItem,
+ PopGetSysButton,
+ DelayedWorkQueue,
+ SysButtonContext);
+
+ ZwClose(FileHandle);
+ return STATUS_SUCCESS;
}
else
{