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

power.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 doxygen 1.7.6.1

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