Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenpower.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/power.c 00005 * PURPOSE: Power Manager 00006 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) 00007 * Hervé Poussineau (hpoussin@reactos.com) 00008 */ 00009 00010 /* INCLUDES ******************************************************************/ 00011 00012 #include "initguid.h" 00013 #include <ntoskrnl.h> 00014 #define NDEBUG 00015 #include <debug.h> 00016 00017 /* GLOBALS *******************************************************************/ 00018 00019 typedef struct _REQUEST_POWER_ITEM 00020 { 00021 PREQUEST_POWER_COMPLETE CompletionRoutine; 00022 POWER_STATE PowerState; 00023 PVOID Context; 00024 } REQUEST_POWER_ITEM, *PREQUEST_POWER_ITEM; 00025 00026 typedef struct _POWER_STATE_TRAVERSE_CONTEXT 00027 { 00028 SYSTEM_POWER_STATE SystemPowerState; 00029 POWER_ACTION PowerAction; 00030 PDEVICE_OBJECT PowerDevice; 00031 } POWER_STATE_TRAVERSE_CONTEXT, *PPOWER_STATE_TRAVERSE_CONTEXT; 00032 00033 PDEVICE_NODE PopSystemPowerDeviceNode = NULL; 00034 BOOLEAN PopAcpiPresent = FALSE; 00035 POP_POWER_ACTION PopAction; 00036 WORK_QUEUE_ITEM PopShutdownWorkItem; 00037 00038 /* PRIVATE FUNCTIONS *********************************************************/ 00039 00040 static 00041 NTSTATUS 00042 NTAPI 00043 PopRequestPowerIrpCompletion(IN PDEVICE_OBJECT DeviceObject, 00044 IN PIRP Irp, 00045 IN PVOID Context) 00046 { 00047 PIO_STACK_LOCATION Stack; 00048 PREQUEST_POWER_ITEM RequestPowerItem; 00049 00050 Stack = IoGetNextIrpStackLocation(Irp); 00051 RequestPowerItem = (PREQUEST_POWER_ITEM)Context; 00052 00053 RequestPowerItem->CompletionRoutine(DeviceObject, 00054 Stack->MinorFunction, 00055 RequestPowerItem->PowerState, 00056 RequestPowerItem->Context, 00057 &Irp->IoStatus); 00058 00059 ExFreePool(Context); 00060 00061 IoFreeIrp(Irp); 00062 ObDereferenceObject(DeviceObject); 00063 00064 return STATUS_MORE_PROCESSING_REQUIRED; 00065 } 00066 00067 VOID 00068 NTAPI 00069 PopCleanupPowerState(IN PPOWER_STATE PowerState) 00070 { 00071 //UNIMPLEMENTED; 00072 } 00073 00074 NTSTATUS 00075 PopSendQuerySystemPowerState(PDEVICE_OBJECT DeviceObject, SYSTEM_POWER_STATE SystemState, POWER_ACTION PowerAction) 00076 { 00077 KEVENT Event; 00078 IO_STATUS_BLOCK IoStatusBlock; 00079 PIO_STACK_LOCATION IrpSp; 00080 PIRP Irp; 00081 NTSTATUS Status; 00082 00083 KeInitializeEvent(&Event, 00084 NotificationEvent, 00085 FALSE); 00086 00087 Irp = IoBuildSynchronousFsdRequest(IRP_MJ_POWER, 00088 DeviceObject, 00089 NULL, 00090 0, 00091 NULL, 00092 &Event, 00093 &IoStatusBlock); 00094 00095 IrpSp = IoGetNextIrpStackLocation(Irp); 00096 IrpSp->MinorFunction = IRP_MN_QUERY_POWER; 00097 IrpSp->Parameters.Power.Type = SystemPowerState; 00098 IrpSp->Parameters.Power.State.SystemState = SystemState; 00099 IrpSp->Parameters.Power.ShutdownType = PowerAction; 00100 00101 Status = PoCallDriver(DeviceObject, Irp); 00102 if (Status == STATUS_PENDING) 00103 { 00104 KeWaitForSingleObject(&Event, 00105 Executive, 00106 KernelMode, 00107 FALSE, 00108 NULL); 00109 Status = IoStatusBlock.Status; 00110 } 00111 00112 return Status; 00113 } 00114 00115 NTSTATUS 00116 PopSendSetSystemPowerState(PDEVICE_OBJECT DeviceObject, SYSTEM_POWER_STATE SystemState, POWER_ACTION PowerAction) 00117 { 00118 KEVENT Event; 00119 IO_STATUS_BLOCK IoStatusBlock; 00120 PIO_STACK_LOCATION IrpSp; 00121 PIRP Irp; 00122 NTSTATUS Status; 00123 00124 KeInitializeEvent(&Event, 00125 NotificationEvent, 00126 FALSE); 00127 00128 Irp = IoBuildSynchronousFsdRequest(IRP_MJ_POWER, 00129 DeviceObject, 00130 NULL, 00131 0, 00132 NULL, 00133 &Event, 00134 &IoStatusBlock); 00135 00136 IrpSp = IoGetNextIrpStackLocation(Irp); 00137 IrpSp->MinorFunction = IRP_MN_SET_POWER; 00138 IrpSp->Parameters.Power.Type = SystemPowerState; 00139 IrpSp->Parameters.Power.State.SystemState = SystemState; 00140 IrpSp->Parameters.Power.ShutdownType = PowerAction; 00141 00142 Status = PoCallDriver(DeviceObject, Irp); 00143 if (Status == STATUS_PENDING) 00144 { 00145 KeWaitForSingleObject(&Event, 00146 Executive, 00147 KernelMode, 00148 FALSE, 00149 NULL); 00150 Status = IoStatusBlock.Status; 00151 } 00152 00153 return Status; 00154 } 00155 00156 NTSTATUS 00157 PopQuerySystemPowerStateTraverse(PDEVICE_NODE DeviceNode, 00158 PVOID Context) 00159 { 00160 PPOWER_STATE_TRAVERSE_CONTEXT PowerStateContext = Context; 00161 NTSTATUS Status; 00162 00163 DPRINT("PopQuerySystemPowerStateTraverse(%p, %p)\n", DeviceNode, Context); 00164 00165 if (DeviceNode == IopRootDeviceNode) 00166 return STATUS_SUCCESS; 00167 00168 if (DeviceNode->Flags & DNF_LEGACY_DRIVER) 00169 return STATUS_SUCCESS; 00170 00171 Status = PopSendQuerySystemPowerState(DeviceNode->PhysicalDeviceObject, 00172 PowerStateContext->SystemPowerState, 00173 PowerStateContext->PowerAction); 00174 if (!NT_SUCCESS(Status)) 00175 { 00176 DPRINT1("Device '%wZ' failed IRP_MN_QUERY_POWER\n", &DeviceNode->InstancePath); 00177 } 00178 00179 #if 0 00180 return Status; 00181 #else 00182 return STATUS_SUCCESS; 00183 #endif 00184 } 00185 00186 NTSTATUS 00187 PopSetSystemPowerStateTraverse(PDEVICE_NODE DeviceNode, 00188 PVOID Context) 00189 { 00190 PPOWER_STATE_TRAVERSE_CONTEXT PowerStateContext = Context; 00191 NTSTATUS Status; 00192 00193 DPRINT("PopSetSystemPowerStateTraverse(%p, %p)\n", DeviceNode, Context); 00194 00195 if (DeviceNode == IopRootDeviceNode) 00196 return STATUS_SUCCESS; 00197 00198 if (DeviceNode->PhysicalDeviceObject == PowerStateContext->PowerDevice) 00199 return STATUS_SUCCESS; 00200 00201 if (DeviceNode->Flags & DNF_LEGACY_DRIVER) 00202 return STATUS_SUCCESS; 00203 00204 Status = PopSendSetSystemPowerState(DeviceNode->PhysicalDeviceObject, 00205 PowerStateContext->SystemPowerState, 00206 PowerStateContext->PowerAction); 00207 if (!NT_SUCCESS(Status)) 00208 { 00209 DPRINT1("Device '%wZ' failed IRP_MN_SET_POWER\n", &DeviceNode->InstancePath); 00210 } 00211 00212 #if 0 00213 return Status; 00214 #else 00215 return STATUS_SUCCESS; 00216 #endif 00217 } 00218 00219 NTSTATUS 00220 NTAPI 00221 PopSetSystemPowerState(SYSTEM_POWER_STATE PowerState, POWER_ACTION PowerAction) 00222 { 00223 PDEVICE_OBJECT DeviceObject; 00224 PDEVICE_OBJECT Fdo; 00225 NTSTATUS Status; 00226 DEVICETREE_TRAVERSE_CONTEXT Context; 00227 POWER_STATE_TRAVERSE_CONTEXT PowerContext; 00228 00229 Status = IopGetSystemPowerDeviceObject(&DeviceObject); 00230 if (!NT_SUCCESS(Status)) 00231 { 00232 DPRINT1("No system power driver available\n"); 00233 Fdo = NULL; 00234 } 00235 else 00236 { 00237 Fdo = IoGetAttachedDeviceReference(DeviceObject); 00238 if (Fdo == DeviceObject) 00239 { 00240 DPRINT("An FDO was not attached\n"); 00241 return STATUS_UNSUCCESSFUL; 00242 } 00243 } 00244 00245 /* Set up context */ 00246 PowerContext.PowerAction = PowerAction; 00247 PowerContext.SystemPowerState = PowerState; 00248 PowerContext.PowerDevice = Fdo; 00249 00250 /* Query for system power change */ 00251 IopInitDeviceTreeTraverseContext(&Context, 00252 IopRootDeviceNode, 00253 PopQuerySystemPowerStateTraverse, 00254 &PowerContext); 00255 00256 Status = IopTraverseDeviceTree(&Context); 00257 if (!NT_SUCCESS(Status)) 00258 { 00259 DPRINT1("Query system power state failed; changing state anyway\n"); 00260 } 00261 00262 /* Set system power change */ 00263 IopInitDeviceTreeTraverseContext(&Context, 00264 IopRootDeviceNode, 00265 PopSetSystemPowerStateTraverse, 00266 &PowerContext); 00267 00268 IopTraverseDeviceTree(&Context); 00269 00270 if (!PopAcpiPresent) return STATUS_NOT_IMPLEMENTED; 00271 00272 if (Fdo != NULL) 00273 { 00274 if (PowerAction != PowerActionShutdownReset) 00275 PopSendSetSystemPowerState(Fdo, PowerState, PowerAction); 00276 00277 ObDereferenceObject(Fdo); 00278 } 00279 00280 return Status; 00281 } 00282 00283 BOOLEAN 00284 NTAPI 00285 INIT_FUNCTION 00286 PoInitSystem(IN ULONG BootPhase) 00287 { 00288 PVOID NotificationEntry; 00289 PCHAR CommandLine; 00290 BOOLEAN ForceAcpiDisable = FALSE; 00291 00292 /* Check if this is phase 1 init */ 00293 if (BootPhase == 1) 00294 { 00295 /* Register power button notification */ 00296 IoRegisterPlugPlayNotification(EventCategoryDeviceInterfaceChange, 00297 PNPNOTIFY_DEVICE_INTERFACE_INCLUDE_EXISTING_INTERFACES, 00298 (PVOID)&GUID_DEVICE_SYS_BUTTON, 00299 IopRootDeviceNode-> 00300 PhysicalDeviceObject->DriverObject, 00301 PopAddRemoveSysCapsCallback, 00302 NULL, 00303 &NotificationEntry); 00304 00305 /* Register lid notification */ 00306 IoRegisterPlugPlayNotification(EventCategoryDeviceInterfaceChange, 00307 PNPNOTIFY_DEVICE_INTERFACE_INCLUDE_EXISTING_INTERFACES, 00308 (PVOID)&GUID_DEVICE_LID, 00309 IopRootDeviceNode-> 00310 PhysicalDeviceObject->DriverObject, 00311 PopAddRemoveSysCapsCallback, 00312 NULL, 00313 &NotificationEntry); 00314 return TRUE; 00315 } 00316 00317 /* Get the Command Line */ 00318 CommandLine = KeLoaderBlock->LoadOptions; 00319 00320 /* Upcase it */ 00321 _strupr(CommandLine); 00322 00323 /* Check for ACPI disable */ 00324 if (strstr(CommandLine, "NOACPI")) ForceAcpiDisable = TRUE; 00325 00326 if (ForceAcpiDisable) 00327 { 00328 /* Set the ACPI State to False if it's been forced that way */ 00329 PopAcpiPresent = FALSE; 00330 } 00331 else 00332 { 00333 /* Otherwise check if the LoaderBlock has a ACPI Table */ 00334 PopAcpiPresent = KeLoaderBlock->Extension->AcpiTable != NULL ? TRUE : FALSE; 00335 } 00336 00337 00338 /* Initialize volume support */ 00339 InitializeListHead(&PopVolumeDevices); 00340 KeInitializeGuardedMutex(&PopVolumeLock); 00341 00342 /* Initialize support for dope */ 00343 KeInitializeSpinLock(&PopDopeGlobalLock); 00344 return TRUE; 00345 } 00346 00347 VOID 00348 NTAPI 00349 PopPerfIdle(PPROCESSOR_POWER_STATE PowerState) 00350 { 00351 DPRINT1("PerfIdle function: %p\n", PowerState); 00352 } 00353 00354 VOID 00355 NTAPI 00356 PopPerfIdleDpc(IN PKDPC Dpc, 00357 IN PVOID DeferredContext, 00358 IN PVOID SystemArgument1, 00359 IN PVOID SystemArgument2) 00360 { 00361 /* Call the Perf Idle function */ 00362 PopPerfIdle(&((PKPRCB)DeferredContext)->PowerState); 00363 } 00364 00365 VOID 00366 FASTCALL 00367 PopIdle0(IN PPROCESSOR_POWER_STATE PowerState) 00368 { 00369 /* FIXME: Extremly naive implementation */ 00370 HalProcessorIdle(); 00371 } 00372 00373 VOID 00374 NTAPI 00375 INIT_FUNCTION 00376 PoInitializePrcb(IN PKPRCB Prcb) 00377 { 00378 /* Initialize the Power State */ 00379 RtlZeroMemory(&Prcb->PowerState, sizeof(Prcb->PowerState)); 00380 Prcb->PowerState.Idle0KernelTimeLimit = 0xFFFFFFFF; 00381 Prcb->PowerState.CurrentThrottle = 100; 00382 Prcb->PowerState.CurrentThrottleIndex = 0; 00383 Prcb->PowerState.IdleFunction = PopIdle0; 00384 00385 /* Initialize the Perf DPC and Timer */ 00386 KeInitializeDpc(&Prcb->PowerState.PerfDpc, PopPerfIdleDpc, Prcb); 00387 KeSetTargetProcessorDpc(&Prcb->PowerState.PerfDpc, Prcb->Number); 00388 KeInitializeTimerEx(&Prcb->PowerState.PerfTimer, SynchronizationTimer); 00389 } 00390 00391 /* PUBLIC FUNCTIONS **********************************************************/ 00392 00393 /* 00394 * @unimplemented 00395 */ 00396 NTSTATUS 00397 NTAPI 00398 PoCancelDeviceNotify(IN PVOID NotifyBlock) 00399 { 00400 UNIMPLEMENTED; 00401 return STATUS_NOT_IMPLEMENTED; 00402 } 00403 00404 /* 00405 * @unimplemented 00406 */ 00407 NTSTATUS 00408 NTAPI 00409 PoRegisterDeviceNotify(OUT PVOID Unknown0, 00410 IN ULONG Unknown1, 00411 IN ULONG Unknown2, 00412 IN ULONG Unknown3, 00413 IN PVOID Unknown4, 00414 IN PVOID Unknown5) 00415 { 00416 UNIMPLEMENTED; 00417 return STATUS_NOT_IMPLEMENTED; 00418 } 00419 00420 /* 00421 * @unimplemented 00422 */ 00423 VOID 00424 NTAPI 00425 PoShutdownBugCheck(IN BOOLEAN LogError, 00426 IN ULONG BugCheckCode, 00427 IN ULONG_PTR BugCheckParameter1, 00428 IN ULONG_PTR BugCheckParameter2, 00429 IN ULONG_PTR BugCheckParameter3, 00430 IN ULONG_PTR BugCheckParameter4) 00431 { 00432 DPRINT1("PoShutdownBugCheck called\n"); 00433 00434 /* FIXME: Log error if requested */ 00435 /* FIXME: Initiate a shutdown */ 00436 00437 /* Bugcheck the system */ 00438 KeBugCheckEx(BugCheckCode, 00439 BugCheckParameter1, 00440 BugCheckParameter2, 00441 BugCheckParameter3, 00442 BugCheckParameter4); 00443 } 00444 00445 /* 00446 * @unimplemented 00447 */ 00448 NTSTATUS 00449 NTAPI 00450 PoRequestShutdownEvent(OUT PVOID *Event) 00451 { 00452 UNIMPLEMENTED; 00453 return STATUS_NOT_IMPLEMENTED; 00454 } 00455 00456 /* 00457 * @unimplemented 00458 */ 00459 VOID 00460 NTAPI 00461 PoSetHiberRange(IN PVOID HiberContext, 00462 IN ULONG Flags, 00463 IN OUT PVOID StartPage, 00464 IN ULONG Length, 00465 IN ULONG PageTag) 00466 { 00467 UNIMPLEMENTED; 00468 return; 00469 } 00470 00471 /* 00472 * @implemented 00473 */ 00474 NTSTATUS 00475 NTAPI 00476 PoCallDriver(IN PDEVICE_OBJECT DeviceObject, 00477 IN OUT PIRP Irp) 00478 { 00479 NTSTATUS Status; 00480 00481 /* Forward to Io -- FIXME! */ 00482 Status = IoCallDriver(DeviceObject, Irp); 00483 00484 /* Return status */ 00485 return Status; 00486 } 00487 00488 /* 00489 * @unimplemented 00490 */ 00491 PULONG 00492 NTAPI 00493 PoRegisterDeviceForIdleDetection(IN PDEVICE_OBJECT DeviceObject, 00494 IN ULONG ConservationIdleTime, 00495 IN ULONG PerformanceIdleTime, 00496 IN DEVICE_POWER_STATE State) 00497 { 00498 UNIMPLEMENTED; 00499 return NULL; 00500 } 00501 00502 /* 00503 * @unimplemented 00504 */ 00505 PVOID 00506 NTAPI 00507 PoRegisterSystemState(IN PVOID StateHandle, 00508 IN EXECUTION_STATE Flags) 00509 { 00510 UNIMPLEMENTED; 00511 return NULL; 00512 } 00513 00514 /* 00515 * @implemented 00516 */ 00517 NTSTATUS 00518 NTAPI 00519 PoRequestPowerIrp(IN PDEVICE_OBJECT DeviceObject, 00520 IN UCHAR MinorFunction, 00521 IN POWER_STATE PowerState, 00522 IN PREQUEST_POWER_COMPLETE CompletionFunction, 00523 IN PVOID Context, 00524 OUT PIRP *pIrp OPTIONAL) 00525 { 00526 PDEVICE_OBJECT TopDeviceObject; 00527 PIO_STACK_LOCATION Stack; 00528 PIRP Irp; 00529 PREQUEST_POWER_ITEM RequestPowerItem; 00530 00531 if (MinorFunction != IRP_MN_QUERY_POWER 00532 && MinorFunction != IRP_MN_SET_POWER 00533 && MinorFunction != IRP_MN_WAIT_WAKE) 00534 return STATUS_INVALID_PARAMETER_2; 00535 00536 RequestPowerItem = ExAllocatePool(NonPagedPool, sizeof(REQUEST_POWER_ITEM)); 00537 if (!RequestPowerItem) 00538 return STATUS_INSUFFICIENT_RESOURCES; 00539 00540 /* Always call the top of the device stack */ 00541 TopDeviceObject = IoGetAttachedDeviceReference(DeviceObject); 00542 00543 Irp = IoBuildAsynchronousFsdRequest(IRP_MJ_POWER, 00544 TopDeviceObject, 00545 NULL, 00546 0, 00547 NULL, 00548 NULL); 00549 if (!Irp) 00550 { 00551 ObDereferenceObject(TopDeviceObject); 00552 ExFreePool(RequestPowerItem); 00553 return STATUS_INSUFFICIENT_RESOURCES; 00554 } 00555 00556 /* POWER IRPs are always initialized with a status code of 00557 STATUS_NOT_IMPLEMENTED */ 00558 Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED; 00559 Irp->IoStatus.Information = 0; 00560 00561 Stack = IoGetNextIrpStackLocation(Irp); 00562 Stack->MinorFunction = MinorFunction; 00563 if (MinorFunction == IRP_MN_WAIT_WAKE) 00564 Stack->Parameters.WaitWake.PowerState = PowerState.SystemState; 00565 else 00566 { 00567 Stack->Parameters.Power.Type = DevicePowerState; 00568 Stack->Parameters.Power.State = PowerState; 00569 } 00570 00571 RequestPowerItem->CompletionRoutine = CompletionFunction; 00572 RequestPowerItem->PowerState = PowerState; 00573 RequestPowerItem->Context = Context; 00574 00575 if (pIrp != NULL) 00576 *pIrp = Irp; 00577 00578 IoSetCompletionRoutine(Irp, PopRequestPowerIrpCompletion, RequestPowerItem, TRUE, TRUE, TRUE); 00579 PoCallDriver(TopDeviceObject, Irp); 00580 00581 /* Always return STATUS_PENDING. The completion routine 00582 * will call CompletionFunction and complete the Irp. 00583 */ 00584 return STATUS_PENDING; 00585 } 00586 00587 /* 00588 * @unimplemented 00589 */ 00590 POWER_STATE 00591 NTAPI 00592 PoSetPowerState(IN PDEVICE_OBJECT DeviceObject, 00593 IN POWER_STATE_TYPE Type, 00594 IN POWER_STATE State) 00595 { 00596 POWER_STATE ps; 00597 00598 ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL); 00599 00600 ps.SystemState = PowerSystemWorking; // Fully on 00601 ps.DeviceState = PowerDeviceD0; // Fully on 00602 00603 return ps; 00604 } 00605 00606 /* 00607 * @unimplemented 00608 */ 00609 VOID 00610 NTAPI 00611 PoSetSystemState(IN EXECUTION_STATE Flags) 00612 { 00613 UNIMPLEMENTED; 00614 } 00615 00616 /* 00617 * @unimplemented 00618 */ 00619 VOID 00620 NTAPI 00621 PoStartNextPowerIrp(IN PIRP Irp) 00622 { 00623 UNIMPLEMENTED; 00624 } 00625 00626 /* 00627 * @unimplemented 00628 */ 00629 VOID 00630 NTAPI 00631 PoUnregisterSystemState(IN PVOID StateHandle) 00632 { 00633 UNIMPLEMENTED; 00634 } 00635 00636 /* 00637 * @unimplemented 00638 */ 00639 NTSTATUS 00640 NTAPI 00641 PoQueueShutdownWorkItem(IN PWORK_QUEUE_ITEM WorkItem) 00642 { 00643 PAGED_CODE(); 00644 00645 UNIMPLEMENTED; 00646 return STATUS_NOT_IMPLEMENTED; 00647 } 00648 00649 /* 00650 * @unimplemented 00651 */ 00652 NTSTATUS 00653 NTAPI 00654 NtInitiatePowerAction (IN POWER_ACTION SystemAction, 00655 IN SYSTEM_POWER_STATE MinSystemState, 00656 IN ULONG Flags, 00657 IN BOOLEAN Asynchronous) 00658 { 00659 UNIMPLEMENTED; 00660 return STATUS_NOT_IMPLEMENTED; 00661 } 00662 00663 /* 00664 * @unimplemented 00665 */ 00666 NTSTATUS 00667 NTAPI 00668 NtPowerInformation(IN POWER_INFORMATION_LEVEL PowerInformationLevel, 00669 IN PVOID InputBuffer OPTIONAL, 00670 IN ULONG InputBufferLength, 00671 OUT PVOID OutputBuffer OPTIONAL, 00672 IN ULONG OutputBufferLength) 00673 { 00674 NTSTATUS Status; 00675 00676 PAGED_CODE(); 00677 00678 DPRINT("NtPowerInformation(PowerInformationLevel 0x%x, InputBuffer 0x%x, " 00679 "InputBufferLength 0x%x, OutputBuffer 0x%x, OutputBufferLength 0x%x)\n", 00680 PowerInformationLevel, 00681 InputBuffer, InputBufferLength, 00682 OutputBuffer, OutputBufferLength); 00683 00684 switch (PowerInformationLevel) 00685 { 00686 case SystemBatteryState: 00687 { 00688 PSYSTEM_BATTERY_STATE BatteryState = (PSYSTEM_BATTERY_STATE)OutputBuffer; 00689 00690 if (InputBuffer != NULL) 00691 return STATUS_INVALID_PARAMETER; 00692 if (OutputBufferLength < sizeof(SYSTEM_BATTERY_STATE)) 00693 return STATUS_BUFFER_TOO_SMALL; 00694 00695 /* Just zero the struct (and thus set BatteryState->BatteryPresent = FALSE) */ 00696 RtlZeroMemory(BatteryState, sizeof(SYSTEM_BATTERY_STATE)); 00697 BatteryState->EstimatedTime = MAXULONG; 00698 00699 Status = STATUS_SUCCESS; 00700 break; 00701 } 00702 case SystemPowerCapabilities: 00703 { 00704 PSYSTEM_POWER_CAPABILITIES PowerCapabilities = (PSYSTEM_POWER_CAPABILITIES)OutputBuffer; 00705 00706 if (InputBuffer != NULL) 00707 return STATUS_INVALID_PARAMETER; 00708 if (OutputBufferLength < sizeof(SYSTEM_POWER_CAPABILITIES)) 00709 return STATUS_BUFFER_TOO_SMALL; 00710 00711 /* Just zero the struct (and thus set BatteryState->BatteryPresent = FALSE) */ 00712 RtlZeroMemory(PowerCapabilities, sizeof(SYSTEM_POWER_CAPABILITIES)); 00713 //PowerCapabilities->SystemBatteriesPresent = 0; 00714 00715 Status = STATUS_SUCCESS; 00716 break; 00717 } 00718 00719 default: 00720 Status = STATUS_NOT_IMPLEMENTED; 00721 DPRINT1("PowerInformationLevel 0x%x is UNIMPLEMENTED! Have a nice day.\n", 00722 PowerInformationLevel); 00723 break; 00724 } 00725 00726 return Status; 00727 } 00728 00729 NTSTATUS 00730 NTAPI 00731 NtGetDevicePowerState(IN HANDLE Device, 00732 IN PDEVICE_POWER_STATE PowerState) 00733 { 00734 UNIMPLEMENTED; 00735 return STATUS_NOT_IMPLEMENTED; 00736 } 00737 00738 BOOLEAN 00739 NTAPI 00740 NtIsSystemResumeAutomatic(VOID) 00741 { 00742 UNIMPLEMENTED; 00743 return FALSE; 00744 } 00745 00746 NTSTATUS 00747 NTAPI 00748 NtRequestWakeupLatency(IN LATENCY_TIME Latency) 00749 { 00750 UNIMPLEMENTED; 00751 return STATUS_NOT_IMPLEMENTED; 00752 } 00753 00754 NTSTATUS 00755 NTAPI 00756 NtSetThreadExecutionState(IN EXECUTION_STATE esFlags, 00757 OUT EXECUTION_STATE *PreviousFlags) 00758 { 00759 PKTHREAD Thread = KeGetCurrentThread(); 00760 KPROCESSOR_MODE PreviousMode = KeGetPreviousMode(); 00761 EXECUTION_STATE PreviousState; 00762 PAGED_CODE(); 00763 00764 /* Validate flags */ 00765 if (esFlags & ~(ES_CONTINUOUS | ES_USER_PRESENT)) 00766 { 00767 /* Fail the request */ 00768 return STATUS_INVALID_PARAMETER; 00769 } 00770 00771 /* Check for user parameters */ 00772 if (PreviousMode != KernelMode) 00773 { 00774 /* Protect the probes */ 00775 _SEH2_TRY 00776 { 00777 /* Check if the pointer is valid */ 00778 ProbeForWriteUlong(PreviousFlags); 00779 } 00780 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 00781 { 00782 /* It isn't -- fail */ 00783 _SEH2_YIELD(return _SEH2_GetExceptionCode()); 00784 } 00785 _SEH2_END; 00786 } 00787 00788 /* Save the previous state, always masking in the continous flag */ 00789 PreviousState = Thread->PowerState | ES_CONTINUOUS; 00790 00791 /* Check if we need to update the power state */ 00792 if (esFlags & ES_CONTINUOUS) Thread->PowerState = (UCHAR)esFlags; 00793 00794 /* Protect the write back to user mode */ 00795 _SEH2_TRY 00796 { 00797 /* Return the previous flags */ 00798 *PreviousFlags = PreviousState; 00799 } 00800 _SEH2_EXCEPT(ExSystemExceptionFilter()) 00801 { 00802 /* Something's wrong, fail */ 00803 _SEH2_YIELD(return _SEH2_GetExceptionCode()); 00804 } 00805 _SEH2_END; 00806 00807 /* All is good */ 00808 return STATUS_SUCCESS; 00809 } 00810 00811 NTSTATUS 00812 NTAPI 00813 NtSetSystemPowerState(IN POWER_ACTION SystemAction, 00814 IN SYSTEM_POWER_STATE MinSystemState, 00815 IN ULONG Flags) 00816 { 00817 KPROCESSOR_MODE PreviousMode = KeGetPreviousMode(); 00818 POP_POWER_ACTION Action = {0}; 00819 NTSTATUS Status; 00820 ULONG Dummy; 00821 00822 /* Check for invalid parameter combinations */ 00823 if ((MinSystemState >= PowerSystemMaximum) || 00824 (MinSystemState <= PowerSystemUnspecified) || 00825 (SystemAction > PowerActionWarmEject) || 00826 (SystemAction < PowerActionReserved) || 00827 (Flags & ~(POWER_ACTION_QUERY_ALLOWED | 00828 POWER_ACTION_UI_ALLOWED | 00829 POWER_ACTION_OVERRIDE_APPS | 00830 POWER_ACTION_LIGHTEST_FIRST | 00831 POWER_ACTION_LOCK_CONSOLE | 00832 POWER_ACTION_DISABLE_WAKES | 00833 POWER_ACTION_CRITICAL))) 00834 { 00835 DPRINT1("NtSetSystemPowerState: Bad parameters!\n"); 00836 DPRINT1(" SystemAction: 0x%x\n", SystemAction); 00837 DPRINT1(" MinSystemState: 0x%x\n", MinSystemState); 00838 DPRINT1(" Flags: 0x%x\n", Flags); 00839 return STATUS_INVALID_PARAMETER; 00840 } 00841 00842 /* Check for user caller */ 00843 if (PreviousMode != KernelMode) 00844 { 00845 /* Check for shutdown permission */ 00846 if (!SeSinglePrivilegeCheck(SeShutdownPrivilege, PreviousMode)) 00847 { 00848 /* Not granted */ 00849 DPRINT1("ERROR: Privilege not held for shutdown\n"); 00850 //return STATUS_PRIVILEGE_NOT_HELD; HACK! 00851 } 00852 00853 /* Do it as a kernel-mode caller for consistency with system state */ 00854 return ZwSetSystemPowerState (SystemAction, MinSystemState, Flags); 00855 } 00856 00857 /* Read policy settings (partial shutdown vs. full shutdown) */ 00858 if (SystemAction == PowerActionShutdown) PopReadShutdownPolicy(); 00859 00860 /* Disable lazy flushing of registry */ 00861 DPRINT1("Stopping lazy flush\n"); 00862 CmSetLazyFlushState(FALSE); 00863 00864 /* Setup the power action */ 00865 Action.Action = SystemAction; 00866 Action.Flags = Flags; 00867 00868 /* Notify callbacks */ 00869 DPRINT1("Notifying callbacks\n"); 00870 ExNotifyCallback(PowerStateCallback, (PVOID)3, NULL); 00871 00872 /* Swap in any worker thread stacks */ 00873 DPRINT1("Swapping worker threads\n"); 00874 ExSwapinWorkerThreads(FALSE); 00875 00876 /* Make our action global */ 00877 PopAction = Action; 00878 00879 /* Start power loop */ 00880 Status = STATUS_CANCELLED; 00881 while (TRUE) 00882 { 00883 /* Break out if there's nothing to do */ 00884 if (Action.Action == PowerActionNone) break; 00885 00886 /* Check for first-pass or restart */ 00887 if (Status == STATUS_CANCELLED) 00888 { 00889 /* Check for shutdown action */ 00890 if ((PopAction.Action == PowerActionShutdown) || 00891 (PopAction.Action == PowerActionShutdownReset) || 00892 (PopAction.Action == PowerActionShutdownOff)) 00893 { 00894 /* Set the action */ 00895 PopAction.Shutdown = TRUE; 00896 } 00897 00898 /* Now we are good to go */ 00899 Status = STATUS_SUCCESS; 00900 } 00901 00902 /* Check if we're still in an invalid status */ 00903 if (!NT_SUCCESS(Status)) break; 00904 00905 #ifndef NEWCC 00906 /* Flush dirty cache pages */ 00907 CcRosFlushDirtyPages(-1, &Dummy, FALSE); //HACK: We really should wait here! 00908 #else 00909 Dummy = 0; 00910 #endif 00911 00912 /* Flush all volumes and the registry */ 00913 DPRINT1("Flushing volumes, cache flushed %d pages\n", Dummy); 00914 PopFlushVolumes(PopAction.Shutdown); 00915 00916 /* Set IRP for drivers */ 00917 PopAction.IrpMinor = IRP_MN_SET_POWER; 00918 if (PopAction.Shutdown) 00919 { 00920 DPRINT1("Queueing shutdown thread\n"); 00921 /* Check if we are running in the system context */ 00922 if (PsGetCurrentProcess() != PsInitialSystemProcess) 00923 { 00924 /* We're not, so use a worker thread for shutdown */ 00925 ExInitializeWorkItem(&PopShutdownWorkItem, 00926 &PopGracefulShutdown, 00927 NULL); 00928 00929 ExQueueWorkItem(&PopShutdownWorkItem, CriticalWorkQueue); 00930 00931 /* Spend us -- when we wake up, the system is good to go down */ 00932 KeSuspendThread(KeGetCurrentThread()); 00933 Status = STATUS_SYSTEM_SHUTDOWN; 00934 goto Exit; 00935 00936 } 00937 else 00938 { 00939 /* Do the shutdown inline */ 00940 PopGracefulShutdown(NULL); 00941 } 00942 } 00943 00944 /* You should not have made it this far */ 00945 ASSERT(FALSE && "System is still up and running?!"); 00946 break; 00947 } 00948 00949 Exit: 00950 /* We're done, return */ 00951 return Status; 00952 } Generated on Fri May 25 2012 04:22:22 for ReactOS by
1.7.6.1
|