ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

events.c
Go to the documentation of this file.
00001 /*
00002  * PROJECT:         ReactOS Kernel
00003  * LICENSE:         GPL - See COPYING in the top level directory
00004  * FILE:            ntoskrnl/po/events.c
00005  * PURPOSE:         Power Manager
00006  * PROGRAMMERS:     Hervé Poussineau (hpoussin@reactos.org)
00007  */
00008 
00009 /* INCLUDES ******************************************************************/
00010 
00011 #include <ntoskrnl.h>
00012 #define NDEBUG
00013 #include <debug.h>
00014 
00015 /* GLOBALS *******************************************************************/
00016 
00017 typedef struct _SYS_BUTTON_CONTEXT
00018 {
00019     PDEVICE_OBJECT DeviceObject;
00020     PIO_WORKITEM WorkItem;
00021     KEVENT Event;
00022     IO_STATUS_BLOCK IoStatusBlock;
00023     ULONG SysButton;
00024 } SYS_BUTTON_CONTEXT, *PSYS_BUTTON_CONTEXT;
00025 
00026 static VOID
00027 NTAPI
00028 PopGetSysButton(
00029     IN PDEVICE_OBJECT DeviceObject,
00030     IN PVOID Context);
00031 
00032 PKWIN32_POWEREVENT_CALLOUT PopEventCallout;
00033 extern PCALLBACK_OBJECT SetSystemTimeCallback;
00034 
00035 /* FUNCTIONS *****************************************************************/
00036 
00037 VOID
00038 NTAPI
00039 PoNotifySystemTimeSet(VOID)
00040 {
00041     KIRQL OldIrql;
00042 
00043     /* Check if Win32k registered a notification callback */
00044     if (PopEventCallout)
00045     {
00046         /* Raise to dispatch */
00047         KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
00048 
00049         /* Notify the callback */
00050         ExNotifyCallback(SetSystemTimeCallback, NULL, NULL);
00051 
00052         /* Lower IRQL back */
00053         KeLowerIrql(OldIrql);
00054     }
00055 }
00056 
00057 static NTSTATUS
00058 NTAPI
00059 PopGetSysButtonCompletion(
00060     IN PDEVICE_OBJECT DeviceObject,
00061     IN PIRP Irp,
00062     IN PVOID Context)
00063 {
00064     PSYS_BUTTON_CONTEXT SysButtonContext = Context;
00065     ULONG SysButton;
00066 
00067     /* The DeviceObject can be NULL, so use the one we stored */
00068     DeviceObject = SysButtonContext->DeviceObject;
00069 
00070     /* FIXME: What do do with the sys button event? */
00071     SysButton = *(PULONG)Irp->AssociatedIrp.SystemBuffer;
00072     {
00073         DPRINT1("A device reported the event 0x%x (", SysButton);
00074         if (SysButton & SYS_BUTTON_POWER) DbgPrint(" POWER");
00075         if (SysButton & SYS_BUTTON_SLEEP) DbgPrint(" SLEEP");
00076         if (SysButton & SYS_BUTTON_LID) DbgPrint(" LID");
00077         if (SysButton == 0) DbgPrint(" WAKE");
00078         DbgPrint(" )\n");
00079         
00080         if (SysButton & SYS_BUTTON_POWER)
00081         {
00082             /* FIXME: Read registry for the action we should perform here */
00083             DPRINT1("Initiating shutdown after power button event\n");
00084             
00085             ZwShutdownSystem(ShutdownNoReboot);
00086         }
00087     }
00088 
00089     /* Allocate a new workitem to send the next IOCTL_GET_SYS_BUTTON_EVENT */
00090     SysButtonContext->WorkItem = IoAllocateWorkItem(DeviceObject);
00091     if (!SysButtonContext->WorkItem)
00092     {
00093         DPRINT("IoAllocateWorkItem() failed\n");
00094         ExFreePool(SysButtonContext);
00095         return STATUS_SUCCESS;
00096     }
00097     IoQueueWorkItem(
00098         SysButtonContext->WorkItem,
00099         PopGetSysButton,
00100         DelayedWorkQueue,
00101         SysButtonContext);
00102 
00103     return STATUS_SUCCESS /* STATUS_CONTINUE_COMPLETION */;
00104 }
00105 
00106 static VOID
00107 NTAPI
00108 PopGetSysButton(
00109     IN PDEVICE_OBJECT DeviceObject,
00110     IN PVOID Context)
00111 {
00112     PSYS_BUTTON_CONTEXT SysButtonContext = Context;
00113     PIO_WORKITEM CurrentWorkItem = SysButtonContext->WorkItem;
00114     PIRP Irp;
00115 
00116     /* Get button pressed (IOCTL_GET_SYS_BUTTON_EVENT) */
00117     KeInitializeEvent(&SysButtonContext->Event, NotificationEvent, FALSE);
00118     Irp = IoBuildDeviceIoControlRequest(
00119         IOCTL_GET_SYS_BUTTON_EVENT,
00120         DeviceObject,
00121         NULL,
00122         0,
00123         &SysButtonContext->SysButton,
00124         sizeof(SysButtonContext->SysButton),
00125         FALSE,
00126         &SysButtonContext->Event,
00127         &SysButtonContext->IoStatusBlock);
00128     if (Irp)
00129     {
00130         IoSetCompletionRoutine(
00131             Irp,
00132             PopGetSysButtonCompletion,
00133             SysButtonContext,
00134             TRUE,
00135             FALSE,
00136             FALSE);
00137         IoCallDriver(DeviceObject, Irp);
00138     }
00139     else
00140     {
00141         DPRINT1("IoBuildDeviceIoControlRequest() failed\n");
00142         ExFreePool(SysButtonContext);
00143     }
00144 
00145     IoFreeWorkItem(CurrentWorkItem);
00146 }
00147 
00148 NTSTATUS
00149 NTAPI
00150 PopAddRemoveSysCapsCallback(IN PVOID NotificationStructure,
00151                             IN PVOID Context)
00152 {
00153     PDEVICE_INTERFACE_CHANGE_NOTIFICATION Notification;
00154     PSYS_BUTTON_CONTEXT SysButtonContext;
00155     OBJECT_ATTRIBUTES ObjectAttributes;
00156     HANDLE FileHandle;
00157     PDEVICE_OBJECT DeviceObject;
00158     PFILE_OBJECT FileObject;
00159     PIRP Irp;
00160     IO_STATUS_BLOCK IoStatusBlock;
00161     KEVENT Event;
00162     BOOLEAN Arrival;
00163     ULONG Caps;
00164     NTSTATUS Status;
00165     UNICODE_STRING DeviceName;
00166     UNICODE_STRING DeviceNamePrefix = RTL_CONSTANT_STRING(L"\\??\\");
00167 
00168     DPRINT("PopAddRemoveSysCapsCallback(%p %p)\n",
00169         NotificationStructure, Context);
00170 
00171     Notification = (PDEVICE_INTERFACE_CHANGE_NOTIFICATION)NotificationStructure;
00172     if (Notification->Version != 1)
00173         return STATUS_REVISION_MISMATCH;
00174     if (Notification->Size != sizeof(DEVICE_INTERFACE_CHANGE_NOTIFICATION))
00175         return STATUS_INVALID_PARAMETER;
00176     if (RtlCompareMemory(&Notification->Event, &GUID_DEVICE_INTERFACE_ARRIVAL, sizeof(GUID)) == sizeof(GUID))
00177         Arrival = TRUE;
00178     else if (RtlCompareMemory(&Notification->Event, &GUID_DEVICE_INTERFACE_REMOVAL, sizeof(GUID)) == sizeof(GUID))
00179         Arrival = FALSE;
00180     else
00181         return STATUS_INVALID_PARAMETER;
00182 
00183     if (Arrival)
00184     {
00185         DPRINT("Arrival of %wZ\n", Notification->SymbolicLinkName);
00186 
00187         DeviceName.Length = 0;
00188         DeviceName.MaximumLength = Notification->SymbolicLinkName->MaximumLength + DeviceNamePrefix.MaximumLength;
00189         DeviceName.Buffer = ExAllocatePool(PagedPool, DeviceName.MaximumLength);
00190         if (!DeviceName.Buffer) return STATUS_INSUFFICIENT_RESOURCES;
00191 
00192         RtlCopyUnicodeString(&DeviceName, &DeviceNamePrefix);
00193         RtlAppendUnicodeStringToString(&DeviceName, Notification->SymbolicLinkName);
00194 
00195         DPRINT("Opening handle to %wZ\n", &DeviceName);
00196 
00197         /* Open the device */
00198         InitializeObjectAttributes(
00199             &ObjectAttributes,
00200             &DeviceName,
00201             OBJ_KERNEL_HANDLE,
00202             NULL,
00203             NULL);
00204         Status = ZwOpenFile(
00205             &FileHandle,
00206             FILE_READ_DATA,
00207             &ObjectAttributes,
00208             &IoStatusBlock,
00209             FILE_SHARE_READ | FILE_SHARE_WRITE,
00210             0);
00211         RtlFreeUnicodeString(&DeviceName);
00212         if (!NT_SUCCESS(Status))
00213         {
00214             DPRINT1("ZwOpenFile() failed with status 0x%08lx\n", Status);
00215             return Status;
00216         }
00217         Status = ObReferenceObjectByHandle(
00218             FileHandle,
00219             FILE_READ_DATA,
00220             IoFileObjectType,
00221             KernelMode,
00222             (PVOID*)&FileObject,
00223             NULL);
00224         if (!NT_SUCCESS(Status))
00225         {
00226             DPRINT1("ObReferenceObjectByHandle() failed with status 0x%08lx\n", Status);
00227             ZwClose(FileHandle);
00228             return Status;
00229         }
00230         DeviceObject = IoGetRelatedDeviceObject(FileObject);
00231         ObDereferenceObject(FileObject);
00232 
00233         /* Get capabilities (IOCTL_GET_SYS_BUTTON_CAPS) */
00234         KeInitializeEvent(&Event, NotificationEvent, FALSE);
00235         Irp = IoBuildDeviceIoControlRequest(
00236             IOCTL_GET_SYS_BUTTON_CAPS,
00237             DeviceObject,
00238             NULL,
00239             0,
00240             &Caps,
00241             sizeof(Caps),
00242             FALSE,
00243             &Event,
00244             &IoStatusBlock);
00245         if (!Irp)
00246         {
00247             DPRINT1("IoBuildDeviceIoControlRequest() failed\n");
00248             ZwClose(FileHandle);
00249             return STATUS_INSUFFICIENT_RESOURCES;
00250         }
00251         Status = IoCallDriver(DeviceObject, Irp);
00252         if (Status == STATUS_PENDING)
00253         {
00254             DPRINT("IOCTL_GET_SYS_BUTTON_CAPS pending\n");
00255             KeWaitForSingleObject(&Event, Suspended, KernelMode, FALSE, NULL);
00256             Status = IoStatusBlock.Status;
00257         }
00258         if (!NT_SUCCESS(Status))
00259         {
00260             DPRINT1("Sending IOCTL_GET_SYS_BUTTON_CAPS failed with status 0x%08x\n", Status);
00261             ZwClose(FileHandle);
00262             return STATUS_INSUFFICIENT_RESOURCES;
00263         }
00264 
00265         /* FIXME: What do do with the capabilities? */
00266         {
00267             DPRINT1("Device capabilities: 0x%x (", Caps);
00268             if (Caps & SYS_BUTTON_POWER) DbgPrint(" POWER");
00269             if (Caps & SYS_BUTTON_SLEEP) DbgPrint(" SLEEP");
00270             if (Caps & SYS_BUTTON_LID) DbgPrint(" LID");
00271             DbgPrint(" )\n");
00272         }
00273 
00274         SysButtonContext = ExAllocatePool(NonPagedPool, sizeof(SYS_BUTTON_CONTEXT));
00275         if (!SysButtonContext)
00276         {
00277             DPRINT1("ExAllocatePool() failed\n");
00278             ZwClose(FileHandle);
00279             return STATUS_INSUFFICIENT_RESOURCES;
00280         }
00281 
00282         /* Queue a work item to get sys button event */
00283         SysButtonContext->WorkItem = IoAllocateWorkItem(DeviceObject);
00284         SysButtonContext->DeviceObject = DeviceObject;
00285         if (!SysButtonContext->WorkItem)
00286         {
00287             DPRINT1("IoAllocateWorkItem() failed\n");
00288             ZwClose(FileHandle);
00289             ExFreePool(SysButtonContext);
00290             return STATUS_INSUFFICIENT_RESOURCES;
00291         }
00292         IoQueueWorkItem(
00293             SysButtonContext->WorkItem,
00294             PopGetSysButton,
00295             DelayedWorkQueue,
00296             SysButtonContext);
00297 
00298         ZwClose(FileHandle);
00299         return STATUS_SUCCESS;
00300     }
00301     else
00302     {
00303         DPRINT1("Removal of a power capable device not implemented\n");
00304         return STATUS_NOT_IMPLEMENTED;
00305     }
00306 }

Generated on Sun May 27 2012 04:25:16 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.