Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenevents.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
1.7.6.1
|