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

cmbpnp.c
Go to the documentation of this file.
00001 /*
00002  * PROJECT:         ReactOS ACPI-Compliant Control Method Battery
00003  * LICENSE:         BSD - See COPYING.ARM in the top level directory
00004  * FILE:            boot/drivers/bus/acpi/cmbatt/cmbpnp.c
00005  * PURPOSE:         Plug-and-Play IOCTL/IRP Handling
00006  * PROGRAMMERS:     ReactOS Portable Systems Group
00007  */
00008 
00009 /* INCLUDES *******************************************************************/
00010 
00011 #include "cmbatt.h"
00012 
00013 /* FUNCTIONS ******************************************************************/
00014 
00015 VOID
00016 NTAPI
00017 CmBattWaitWakeLoop(IN PDEVICE_OBJECT DeviceObject,
00018                    IN UCHAR MinorFunction,
00019                    IN POWER_STATE PowerState,
00020                    IN PVOID Context,
00021                    IN PIO_STATUS_BLOCK IoStatusBlock)
00022 {
00023     NTSTATUS Status;
00024     PCMBATT_DEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
00025     if (CmBattDebug & 0x20) DbgPrint("CmBattWaitWakeLoop: Entered.\n");
00026     
00027     /* Check for success */
00028     if ((NT_SUCCESS(IoStatusBlock->Status)) && (DeviceExtension->WaitWakeEnable))
00029     {
00030         /* Request a new power IRP */
00031         if (CmBattDebug & 2) DbgPrint("CmBattWaitWakeLoop: completed successfully\n");
00032         Status = PoRequestPowerIrp(DeviceObject,
00033                                    MinorFunction,
00034                                    PowerState,
00035                                    CmBattWaitWakeLoop,
00036                                    Context,
00037                                    &DeviceExtension->PowerIrp);
00038         if (CmBattDebug & 2)
00039             DbgPrint("CmBattWaitWakeLoop: PoRequestPowerIrp: status = 0x%08x.\n",
00040                      Status);
00041     }
00042     else
00043     {
00044         /* Clear the power IRP, we failed */
00045         if (CmBattDebug & 0xC)
00046             DbgPrint("CmBattWaitWakeLoop: failed: status = 0x%08x.\n",
00047                      IoStatusBlock->Status);
00048         DeviceExtension->PowerIrp = NULL;
00049     }
00050 }
00051  
00052 NTSTATUS
00053 NTAPI
00054 CmBattIoCompletion(IN PDEVICE_OBJECT DeviceObject,
00055                    IN PIRP Irp,
00056                    IN PKEVENT Event)
00057 {
00058     if (CmBattDebug & 2) DbgPrint("CmBattIoCompletion: Event (%x)\n", Event);
00059 
00060     /* Set the completion event */
00061     KeSetEvent(Event, IO_NO_INCREMENT, FALSE);
00062     return STATUS_MORE_PROCESSING_REQUIRED;
00063 }
00064 
00065 NTSTATUS
00066 NTAPI
00067 CmBattGetAcpiInterfaces(IN PDEVICE_OBJECT DeviceObject,
00068                         IN OUT PACPI_INTERFACE_STANDARD AcpiInterface)
00069 {
00070     PIRP Irp;
00071     NTSTATUS Status;
00072     PIO_STACK_LOCATION IoStackLocation;
00073     KEVENT Event;
00074 
00075     /* Allocate the IRP */
00076     Irp = IoAllocateIrp(DeviceObject->StackSize, 0);
00077     if (!Irp)
00078     {
00079         /* Fail */
00080         if (CmBattDebug & 0xC)
00081           DbgPrint("CmBattGetAcpiInterfaces: Failed to allocate Irp\n");
00082         return STATUS_INSUFFICIENT_RESOURCES;
00083     }
00084 
00085     /* Set default error code */
00086     Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
00087 
00088     /* Build the query */
00089     IoStackLocation = IoGetNextIrpStackLocation(Irp);
00090     IoStackLocation->MinorFunction = IRP_MN_QUERY_INTERFACE;
00091     IoStackLocation->Parameters.QueryInterface.InterfaceType = &GUID_ACPI_INTERFACE_STANDARD;
00092     IoStackLocation->Parameters.QueryInterface.Size = sizeof(ACPI_INTERFACE_STANDARD);
00093     IoStackLocation->Parameters.QueryInterface.Version = 1;
00094     IoStackLocation->Parameters.QueryInterface.Interface = (PINTERFACE)AcpiInterface;
00095     IoStackLocation->Parameters.QueryInterface.InterfaceSpecificData = NULL;
00096 
00097     /* Set default ACPI interface data */
00098     AcpiInterface->Size = sizeof(ACPI_INTERFACE_STANDARD);
00099     AcpiInterface->Version = 1;
00100 
00101     /* Initialize our wait event */
00102     KeInitializeEvent(&Event, SynchronizationEvent, 0);
00103     
00104     /* Set the completion routine */
00105     IoCopyCurrentIrpStackLocationToNext(Irp);
00106     IoSetCompletionRoutine(Irp,
00107                            (PVOID)CmBattIoCompletion,
00108                            &Event,
00109                            TRUE,
00110                            TRUE,
00111                            TRUE);
00112  
00113     /* Now call ACPI */
00114     Status = IoCallDriver(DeviceObject, Irp);
00115     if (Status == STATUS_PENDING)
00116     {
00117         /* Wait for completion */
00118         KeWaitForSingleObject(&Event,
00119                               Executive,
00120                               KernelMode,
00121                               FALSE,
00122                               NULL);
00123         Status = Irp->IoStatus.Status;
00124     }
00125     
00126     /* Free the IRP */
00127     IoFreeIrp(Irp);
00128     
00129     /* Return status */
00130     if (!(NT_SUCCESS(Status)) && (CmBattDebug & 0xC))
00131         DbgPrint("CmBattGetAcpiInterfaces: Could not get ACPI driver interfaces, status = %x\n", Status);
00132     return Status;
00133 }
00134 
00135 VOID
00136 NTAPI
00137 CmBattDestroyFdo(IN PDEVICE_OBJECT DeviceObject)
00138 {
00139     PAGED_CODE();
00140     if (CmBattDebug & 0x220) DbgPrint("CmBattDestroyFdo, Battery.\n");
00141 
00142     /* Delete the device */
00143     IoDeleteDevice(DeviceObject);
00144     if (CmBattDebug & 0x220) DbgPrint("CmBattDestroyFdo: done.\n");
00145 }
00146 
00147 NTSTATUS
00148 NTAPI
00149 CmBattRemoveDevice(IN PDEVICE_OBJECT DeviceObject,
00150                    IN PIRP Irp)
00151 {
00152     PCMBATT_DEVICE_EXTENSION DeviceExtension;
00153     PVOID Context;
00154     DeviceExtension = DeviceObject->DeviceExtension;
00155     if (CmBattDebug & 2)
00156         DbgPrint("CmBattRemoveDevice: CmBatt (%x), Type %d, _UID %d\n",
00157                  DeviceExtension,
00158                  DeviceExtension->FdoType,
00159                  DeviceExtension->DeviceId);
00160                  
00161     /* Make sure it's safe to go ahead */
00162     IoReleaseRemoveLockAndWait(&DeviceExtension->RemoveLock, 0);
00163 
00164     /* Check for pending power IRP */
00165     if (DeviceExtension->PowerIrp)
00166     {
00167         /* Cancel and clear */
00168         IoCancelIrp(DeviceExtension->PowerIrp);
00169         DeviceExtension->PowerIrp = NULL;
00170     }
00171     
00172     /* Check what type of FDO is being removed */
00173     Context = DeviceExtension->AcpiInterface.Context;
00174     if (DeviceExtension->FdoType == CmBattBattery)
00175     {
00176         /* Unregister battery FDO */
00177         DeviceExtension->AcpiInterface.UnregisterForDeviceNotifications(Context,
00178                                                                         (PVOID)CmBattNotifyHandler);
00179         CmBattWmiDeRegistration(DeviceExtension);
00180         if (!NT_SUCCESS(BatteryClassUnload(DeviceExtension->ClassData))) ASSERT(FALSE);
00181     }
00182     else
00183     {
00184         /* Unregister AC adapter FDO */
00185         DeviceExtension->AcpiInterface.UnregisterForDeviceNotifications(Context,
00186                                                                         (PVOID)CmBattNotifyHandler);
00187         CmBattWmiDeRegistration(DeviceExtension);
00188         AcAdapterPdo = NULL;
00189     }
00190     
00191     /* Detach and delete */
00192     IoDetachDevice(DeviceExtension->AttachedDevice);
00193     IoDeleteDevice(DeviceExtension->DeviceObject);
00194     return STATUS_SUCCESS;
00195 }
00196 
00197 NTSTATUS
00198 NTAPI
00199 CmBattPowerDispatch(IN PDEVICE_OBJECT DeviceObject,
00200                     IN PIRP Irp)
00201 {
00202     PIO_STACK_LOCATION IoStackLocation;
00203     PCMBATT_DEVICE_EXTENSION DeviceExtension;
00204     NTSTATUS Status;
00205     if (CmBattDebug & 0x210) DbgPrint("CmBattPowerDispatch\n");
00206 
00207     /* Get stack location and device extension */
00208     IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
00209     DeviceExtension = DeviceObject->DeviceExtension;
00210     switch (IoStackLocation->MinorFunction)
00211     {
00212         case IRP_MN_WAIT_WAKE:        
00213             if (CmBattDebug & 0x10)
00214                 DbgPrint("CmBattPowerDispatch: IRP_MN_WAIT_WAKE\n");
00215             break;
00216         
00217         case IRP_MN_POWER_SEQUENCE:
00218             if (CmBattDebug & 0x10)
00219                 DbgPrint("CmBattPowerDispatch: IRP_MN_POWER_SEQUENCE\n");
00220             break;
00221         
00222         case IRP_MN_QUERY_POWER:
00223             if (CmBattDebug & 0x10)
00224                 DbgPrint("CmBattPowerDispatch: IRP_MN_WAIT_WAKE\n");
00225             break;
00226         
00227         case IRP_MN_SET_POWER:
00228             if (CmBattDebug & 0x10)
00229                 DbgPrint("CmBattPowerDispatch: IRP_MN_SET_POWER type: %d, State: %d \n",
00230                          IoStackLocation->Parameters.Power.Type,
00231                          IoStackLocation->Parameters.Power.State);
00232             break;
00233             
00234         default:
00235         
00236             if (CmBattDebug & 1)
00237                 DbgPrint("CmBattPowerDispatch: minor %d\n", IoStackLocation->MinorFunction);
00238             break;
00239     }
00240 
00241     /* Start the next IRP and see if we're attached */
00242     PoStartNextPowerIrp(Irp);
00243     if (DeviceExtension->AttachedDevice)
00244     {
00245         /* Call ACPI */
00246         IoSkipCurrentIrpStackLocation(Irp);
00247         Status = PoCallDriver(DeviceExtension->AttachedDevice, Irp);
00248     }
00249     else
00250     {
00251         /* Complete the request here */
00252         Status = Irp->IoStatus.Status;
00253         IoCompleteRequest(Irp, IO_NO_INCREMENT);
00254     }
00255     
00256     /* Return status */
00257     return Status;
00258 }
00259 
00260 NTSTATUS
00261 NTAPI
00262 CmBattPnpDispatch(IN PDEVICE_OBJECT DeviceObject,
00263                   IN PIRP Irp)
00264 {
00265     PIO_STACK_LOCATION IoStackLocation;
00266     PCMBATT_DEVICE_EXTENSION DeviceExtension;
00267     NTSTATUS Status;
00268     KEVENT Event;
00269     PAGED_CODE();
00270 
00271     /* Get stack location and device extension */
00272     IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
00273     DeviceExtension = DeviceObject->DeviceExtension;
00274     
00275     /* Set default error */
00276     Status = STATUS_NOT_SUPPORTED;
00277 
00278     /* Try to acquire the lock before doing anything */
00279     Status = IoAcquireRemoveLock(&DeviceExtension->RemoveLock, 0);
00280     if (!NT_SUCCESS(Status))
00281     {
00282         /* Complete the request */
00283         Irp->IoStatus.Status = STATUS_DEVICE_REMOVED;
00284         IoCompleteRequest(Irp, IO_NO_INCREMENT);
00285         return STATUS_DEVICE_REMOVED;
00286     }
00287 
00288     /* What's the operation? */
00289     switch (IoStackLocation->MinorFunction)
00290     {            
00291         case IRP_MN_QUERY_PNP_DEVICE_STATE:
00292         
00293             /* Initialize our wait event */
00294             KeInitializeEvent(&Event, SynchronizationEvent, 0);
00295 
00296             /* Set the completion routine */
00297             IoCopyCurrentIrpStackLocationToNext(Irp);
00298             IoSetCompletionRoutine(Irp,
00299                                    (PVOID)CmBattIoCompletion,
00300                                    &Event,
00301                                    TRUE,
00302                                    TRUE,
00303                                    TRUE);
00304 
00305             /* Now call ACPI to inherit its PnP Device State */
00306             Status = IoCallDriver(DeviceExtension->AttachedDevice, Irp);
00307             if (Status == STATUS_PENDING)
00308             {
00309                 /* Wait for completion */
00310                 KeWaitForSingleObject(&Event,
00311                                       Executive,
00312                                       KernelMode,
00313                                       FALSE,
00314                                       NULL);
00315                 Status = Irp->IoStatus.Status;
00316             }
00317 
00318             /* However, a battery CAN be disabled */
00319             Irp->IoStatus.Information &= ~PNP_DEVICE_NOT_DISABLEABLE;
00320 
00321             /* Release the remove lock and complete the request */
00322             IoCompleteRequest(Irp, IO_NO_INCREMENT);
00323             IoReleaseRemoveLock(&DeviceExtension->RemoveLock, Irp);
00324             return Status;
00325         
00326         case IRP_MN_SURPRISE_REMOVAL:
00327             if (CmBattDebug & 0x20)
00328                 DbgPrint("CmBattPnpDispatch: IRP_MN_SURPRISE_REMOVAL\n");
00329                 
00330             /* Lock the device extension and set the handle count to invalid */
00331             ExAcquireFastMutex(&DeviceExtension->FastMutex);
00332             DeviceExtension->HandleCount = -1;
00333             ExReleaseFastMutex(&DeviceExtension->FastMutex);
00334             Status = STATUS_SUCCESS;
00335             break;
00336         
00337         case IRP_MN_START_DEVICE:
00338             if (CmBattDebug & 0x20)
00339                 DbgPrint("CmBattPnpDispatch: IRP_MN_START_DEVICE\n");
00340           
00341             /* Mark the extension as started */
00342             if (DeviceExtension->FdoType == CmBattBattery) DeviceExtension->Started = TRUE;
00343             Status = STATUS_SUCCESS;
00344             break;
00345         
00346         case IRP_MN_STOP_DEVICE:        
00347             if (CmBattDebug & 0x20)
00348                 DbgPrint("CmBattPnpDispatch: IRP_MN_STOP_DEVICE\n");
00349 
00350             /* Mark the extension as stopped */
00351             if (DeviceExtension->FdoType == CmBattBattery) DeviceExtension->Started = FALSE;
00352             Status = STATUS_SUCCESS;
00353             break;
00354         
00355         case IRP_MN_QUERY_REMOVE_DEVICE:
00356             if (CmBattDebug & 0x20)
00357                 DbgPrint("CmBattPnpDispatch: IRP_MN_QUERY_REMOVE_DEVICE\n");
00358 
00359             /* Lock the extension and get the current handle count */
00360             ExAcquireFastMutex(&DeviceExtension->FastMutex);
00361             if (DeviceExtension->HandleCount == 0)
00362             {
00363                 /* No handles. Mark it as invalid since it'll be removed */
00364                 DeviceExtension->HandleCount = -1;
00365                 Status = STATUS_SUCCESS;
00366             }
00367             else if (DeviceExtension->HandleCount == -1)
00368             {
00369                 /* Don't do anything, but this is strange since it's already removed */
00370                 Status = STATUS_SUCCESS;
00371                 if (CmBattDebug & 4)
00372                     DbgPrint("CmBattPnpDispatch: Recieved two consecutive QUERY_REMOVE requests.\n");
00373             }
00374             else
00375             {
00376                 /* Fail because there's still open handles */
00377                 Status = STATUS_UNSUCCESSFUL;
00378             }
00379             
00380             /* Release the lock and return */
00381             ExReleaseFastMutex(&DeviceExtension->FastMutex);
00382             break;
00383         
00384         case IRP_MN_REMOVE_DEVICE:
00385             if (CmBattDebug & 0x20)
00386                 DbgPrint("CmBattPnpDispatch: IRP_MN_REMOVE_DEVICE\n");
00387              
00388             /* Call the remove code */
00389             Status = CmBattRemoveDevice(DeviceObject, Irp);
00390             break;
00391         
00392         case IRP_MN_CANCEL_REMOVE_DEVICE:
00393             if (CmBattDebug & 0x20)
00394                 DbgPrint("CmBattPnpDispatch: IRP_MN_CANCEL_REMOVE_DEVICE\n");
00395             
00396             /* Lock the extension and get the handle count */
00397             ExAcquireFastMutex(&DeviceExtension->FastMutex);
00398             if (DeviceExtension->HandleCount == -1)
00399             {
00400                 /* A remove was in progress, set the handle count back to 0 */
00401                 DeviceExtension->HandleCount = 0;
00402             }
00403             else if (CmBattDebug & 2)
00404             {
00405                 /* Nop, but warn about it */
00406                 DbgPrint("CmBattPnpDispatch: Received CANCEL_REMOVE when OpenCount == %x\n", 
00407                          DeviceExtension->HandleCount);
00408             }
00409             
00410             /* Return success in all cases, and release the lock */
00411             Status = STATUS_SUCCESS;
00412             ExReleaseFastMutex(&DeviceExtension->FastMutex);
00413             break;
00414         
00415         case IRP_MN_QUERY_STOP_DEVICE:
00416             if (CmBattDebug & 0x20)
00417                 DbgPrint("CmBattPnpDispatch: IRP_MN_QUERY_STOP_DEVICE\n");
00418             
00419             /* There's no real support for this */    
00420             Status = STATUS_NOT_IMPLEMENTED;
00421             break;
00422 
00423         case IRP_MN_CANCEL_STOP_DEVICE:
00424             if (CmBattDebug & 0x20)
00425                 DbgPrint("CmBattPnpDispatch: IRP_MN_CANCEL_STOP_DEVICE\n");
00426         
00427             /* There's no real support for this */    
00428             Status = STATUS_NOT_IMPLEMENTED;
00429             break;
00430         
00431         case IRP_MN_QUERY_CAPABILITIES:
00432         
00433             /* Initialize our wait event */
00434             KeInitializeEvent(&Event, SynchronizationEvent, 0);
00435 
00436             /* Set the completion routine */
00437             IoCopyCurrentIrpStackLocationToNext(Irp);
00438             IoSetCompletionRoutine(Irp,
00439                                    (PVOID)CmBattIoCompletion,
00440                                    &Event,
00441                                    TRUE,
00442                                    TRUE,
00443                                    TRUE);
00444 
00445             /* Now call ACPI */
00446             Status = IoCallDriver(DeviceExtension->AttachedDevice, Irp);
00447             if (Status == STATUS_PENDING)
00448             {
00449                 /* Wait for completion */
00450                 KeWaitForSingleObject(&Event,
00451                                       Executive,
00452                                       KernelMode,
00453                                       FALSE,
00454                                       NULL);
00455                 Status = Irp->IoStatus.Status;
00456             }
00457 
00458             /* Get the wake power state */
00459             DeviceExtension->PowerState.SystemState = IoStackLocation->Parameters.DeviceCapabilities.Capabilities->SystemWake;
00460             if (CmBattDebug & 0x20)
00461                 DbgPrint("CmBattPnpDispatch: IRP_MN_QUERY_CAPABILITIES %d Capabilities->SystemWake = %x\n",
00462                          DeviceExtension->FdoType,
00463                          DeviceExtension->PowerState);
00464 
00465             /* Check if it's invalid */
00466             if (DeviceExtension->PowerState.SystemState == PowerSystemUnspecified)
00467             {
00468                 /* Wait wake is not supported in this scenario */
00469                 DeviceExtension->WaitWakeEnable = FALSE;
00470                 if (CmBattDebug & 0x20)
00471                     DbgPrint("CmBattPnpDispatch: IRP_MN_QUERY_CAPABILITIES Wake not supported.\n");
00472             }
00473             else if (!(DeviceExtension->PowerIrp) &&
00474                      (DeviceExtension->WaitWakeEnable))
00475             {
00476                 /* If it was requested in the registry, request the power IRP for it */
00477                 PoRequestPowerIrp(DeviceExtension->DeviceObject,
00478                                   0,
00479                                   DeviceExtension->PowerState,
00480                                   CmBattWaitWakeLoop,
00481                                   0,
00482                                   &DeviceExtension->PowerIrp);
00483                 if (CmBattDebug & 0x20)
00484                     DbgPrint("CmBattPnpDispatch: IRP_MN_QUERY_CAPABILITIES wait/Wake irp sent.\n");
00485             }
00486 
00487             /* Release the remove lock and complete the request */
00488             IoCompleteRequest(Irp, IO_NO_INCREMENT);
00489             IoReleaseRemoveLock(&DeviceExtension->RemoveLock, Irp);
00490             return Status;
00491 
00492         default:
00493             /* Unsupported */
00494             if (CmBattDebug & 0x20)
00495                 DbgPrint("CmBattPnpDispatch: Unimplemented minor %0x\n",
00496                          IoStackLocation->MinorFunction);
00497             break;
00498     }
00499     
00500     /* Release the remove lock */  
00501     IoReleaseRemoveLock(&DeviceExtension->RemoveLock, Irp);
00502 
00503     /* Set IRP status if we have one */
00504     if (Status != STATUS_NOT_SUPPORTED) Irp->IoStatus.Status = Status;
00505 
00506     /* Did someone pick it up? */    
00507     if ((NT_SUCCESS(Status)) || (Status == STATUS_NOT_SUPPORTED))
00508     {
00509         /* Still unsupported, try ACPI */
00510         IoSkipCurrentIrpStackLocation(Irp);
00511         Status = IoCallDriver(DeviceExtension->AttachedDevice, Irp);
00512     }
00513     else
00514     {
00515         /* Complete the request */
00516         Status = Irp->IoStatus.Status;
00517         IoCompleteRequest(Irp, IO_NO_INCREMENT);
00518     }
00519 
00520     /* Release the remove lock and return status */
00521     return Status;
00522 }
00523 
00524 NTSTATUS
00525 NTAPI
00526 CmBattCreateFdo(IN PDRIVER_OBJECT DriverObject,
00527                 IN PDEVICE_OBJECT DeviceObject,
00528                 IN ULONG DeviceExtensionSize,
00529                 IN PDEVICE_OBJECT *NewDeviceObject)
00530 {
00531     PDEVICE_OBJECT FdoDeviceObject;
00532     HANDLE KeyHandle;
00533     PCMBATT_DEVICE_EXTENSION FdoExtension;
00534     UCHAR Buffer[sizeof(KEY_VALUE_PARTIAL_INFORMATION) + sizeof(ULONG)];
00535     PKEY_VALUE_PARTIAL_INFORMATION PartialInfo = (PVOID)Buffer;
00536     NTSTATUS Status;
00537     UNICODE_STRING KeyString;
00538     ULONG UniqueId;
00539     ULONG ResultLength;
00540     PAGED_CODE();
00541     if (CmBattDebug & 0x220) DbgPrint("CmBattCreateFdo: Entered\n");
00542     
00543     /* Get unique ID */
00544     Status = CmBattGetUniqueId(DeviceObject, &UniqueId);
00545     if (!NT_SUCCESS(Status))
00546     {
00547         /* Assume 0 */
00548         UniqueId = 0;
00549         if (CmBattDebug & 2)
00550           DbgPrint("CmBattCreateFdo: Error %x from _UID, assuming unit #0\n", Status);
00551     }
00552     
00553     /* Create the FDO */
00554     Status = IoCreateDevice(DriverObject,
00555                             DeviceExtensionSize,
00556                             0,
00557                             FILE_DEVICE_BATTERY,
00558                             FILE_DEVICE_SECURE_OPEN,
00559                             0,
00560                             &FdoDeviceObject);
00561     if (!NT_SUCCESS(Status))
00562     {
00563         /* Fail */
00564         if (CmBattDebug & 0xC)
00565             DbgPrint("CmBattCreateFdo: error (0x%x) creating device object\n", Status);
00566         return Status;
00567     }
00568     
00569     /* Set FDO flags */
00570     FdoDeviceObject->Flags |= (DO_POWER_PAGABLE | DO_BUFFERED_IO);
00571     FdoDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
00572 
00573     /* Initialize the extension */
00574     FdoExtension = FdoDeviceObject->DeviceExtension;
00575     RtlZeroMemory(FdoExtension, DeviceExtensionSize);
00576     FdoExtension->DeviceObject = FdoDeviceObject;
00577     FdoExtension->FdoDeviceObject = FdoDeviceObject;
00578     FdoExtension->PdoDeviceObject = DeviceObject;
00579     
00580     /* Attach to ACPI */
00581     FdoExtension->AttachedDevice = IoAttachDeviceToDeviceStack(FdoDeviceObject,
00582                                                                DeviceObject);
00583     if (!FdoExtension->AttachedDevice)
00584     {
00585         /* Destroy and fail */
00586         CmBattDestroyFdo(FdoExtension->FdoDeviceObject);
00587         if (CmBattDebug & 0xC)
00588             DbgPrint("CmBattCreateFdo: IoAttachDeviceToDeviceStack failed.\n");
00589         return STATUS_UNSUCCESSFUL;
00590     }
00591     
00592     /* Get ACPI interface for EVAL */
00593     Status = CmBattGetAcpiInterfaces(FdoExtension->AttachedDevice,
00594                                      &FdoExtension->AcpiInterface);
00595     if (!FdoExtension->AttachedDevice)
00596     {
00597         /* Detach, destroy, and fail */
00598         IoDetachDevice(FdoExtension->AttachedDevice);
00599         CmBattDestroyFdo(FdoExtension->FdoDeviceObject);
00600         if (CmBattDebug & 0xC)
00601             DbgPrint("CmBattCreateFdo: Could not get ACPI interfaces: %x\n", Status);
00602         return STATUS_UNSUCCESSFUL;
00603     }
00604 
00605     /* Setup the rest of the extension */
00606     ExInitializeFastMutex(&FdoExtension->FastMutex);
00607     IoInitializeRemoveLock(&FdoExtension->RemoveLock, 0, 0, 0);
00608     FdoExtension->HandleCount = 0;
00609     FdoExtension->WaitWakeEnable = FALSE;
00610     FdoExtension->DeviceId = UniqueId;
00611     FdoExtension->DeviceName = NULL;
00612     FdoExtension->DelayNotification = FALSE;
00613     FdoExtension->ArFlag = 0;
00614     
00615     /* Open the device key */
00616     Status = IoOpenDeviceRegistryKey(DeviceObject,
00617                                      PLUGPLAY_REGKEY_DEVICE,
00618                                      KEY_READ,
00619                                      &KeyHandle);
00620     if (NT_SUCCESS(Status))
00621     {
00622         /* Read wait wake value */
00623         RtlInitUnicodeString(&KeyString, L"WaitWakeEnabled");
00624         Status = ZwQueryValueKey(KeyHandle,
00625                                  &KeyString,
00626                                  KeyValuePartialInformation,
00627                                  PartialInfo,
00628                                  sizeof(Buffer),
00629                                  &ResultLength);
00630         if (NT_SUCCESS(Status))
00631         {
00632             /* Set value */
00633             FdoExtension->WaitWakeEnable = *(PULONG)PartialInfo->Data;
00634         }
00635         
00636         /* Close the handle */
00637         ZwClose(KeyHandle);
00638     }
00639 
00640     /* Return success and the new FDO */
00641     *NewDeviceObject = FdoDeviceObject;
00642     if (CmBattDebug & 0x220)
00643         DbgPrint("CmBattCreateFdo: Created FDO %x\n", FdoDeviceObject);
00644     return STATUS_SUCCESS;
00645 }
00646 
00647 NTSTATUS
00648 NTAPI
00649 CmBattAddBattery(IN PDRIVER_OBJECT DriverObject,
00650                  IN PDEVICE_OBJECT DeviceObject)
00651 {
00652     BATTERY_MINIPORT_INFO MiniportInfo;
00653     NTSTATUS Status;
00654     PDEVICE_OBJECT FdoDeviceObject;
00655     PCMBATT_DEVICE_EXTENSION FdoExtension; 
00656     PAGED_CODE();
00657     if (CmBattDebug & 0x220)
00658         DbgPrint("CmBattAddBattery: pdo %x\n", DeviceObject);
00659 
00660     /* Create the FDO */
00661     Status = CmBattCreateFdo(DriverObject,
00662                              DeviceObject,
00663                              sizeof(CMBATT_DEVICE_EXTENSION),
00664                              &FdoDeviceObject);
00665     if (!NT_SUCCESS(Status))
00666     {
00667         if (CmBattDebug & 0xC)
00668             DbgPrint("CmBattAddBattery: error (0x%x) creating Fdo\n", Status);
00669         return Status;
00670     }
00671 
00672     /* Build the FDO extensio, check if we support trip points */
00673     FdoExtension = FdoDeviceObject->DeviceExtension;
00674     FdoExtension->FdoType = CmBattBattery;
00675     FdoExtension->Started = 0;
00676     FdoExtension->NotifySent = TRUE;
00677     InterlockedExchange(&FdoExtension->ArLockValue, 0);
00678     FdoExtension->TripPointValue = BATTERY_UNKNOWN_CAPACITY;
00679     FdoExtension->Tag = 0;
00680     FdoExtension->InterruptTime = KeQueryInterruptTime();
00681     FdoExtension->TripPointSet = CmBattSetTripPpoint(FdoExtension, 0) !=
00682                                  STATUS_OBJECT_NAME_NOT_FOUND;
00683        
00684     /* Setup the battery miniport information structure */
00685     RtlZeroMemory(&MiniportInfo, sizeof(MiniportInfo));
00686     MiniportInfo.Pdo = DeviceObject;
00687     MiniportInfo.MajorVersion = BATTERY_CLASS_MAJOR_VERSION;
00688     MiniportInfo.MinorVersion = BATTERY_CLASS_MINOR_VERSION;
00689     MiniportInfo.Context = FdoExtension;
00690     MiniportInfo.QueryTag = (PVOID)CmBattQueryTag;
00691     MiniportInfo.QueryInformation = (PVOID)CmBattQueryInformation;
00692     MiniportInfo.SetInformation = NULL;
00693     MiniportInfo.QueryStatus = (PVOID)CmBattQueryStatus;
00694     MiniportInfo.SetStatusNotify = (PVOID)CmBattSetStatusNotify;
00695     MiniportInfo.DisableStatusNotify = (PVOID)CmBattDisableStatusNotify;
00696     MiniportInfo.DeviceName = FdoExtension->DeviceName;
00697  
00698     /* Register with the class driver */
00699     Status = BatteryClassInitializeDevice(&MiniportInfo, &FdoExtension->ClassData);
00700     if (!NT_SUCCESS(Status))
00701     {
00702         IoDetachDevice(FdoExtension->AttachedDevice);
00703         CmBattDestroyFdo(FdoExtension->FdoDeviceObject);
00704         if (CmBattDebug & 0xC)
00705             DbgPrint("CmBattAddBattery: error (0x%x) registering with class\n", Status);
00706         return Status;
00707     }
00708 
00709     /* Register WMI */
00710     Status = CmBattWmiRegistration(FdoExtension);
00711     if (!NT_SUCCESS(Status))
00712     {
00713         if (CmBattDebug & 0xC)
00714             DbgPrint("CmBattAddBattery: Could not register as a WMI provider, status = %Lx\n", Status);
00715         return Status;
00716     }
00717     
00718     /* Register ACPI */
00719     Status = FdoExtension->AcpiInterface.RegisterForDeviceNotifications(FdoExtension->AcpiInterface.Context,
00720                                                                         (PVOID)CmBattNotifyHandler,
00721                                                                         FdoExtension);
00722     if (!NT_SUCCESS(Status))
00723     {
00724         CmBattWmiDeRegistration(FdoExtension);
00725         BatteryClassUnload(FdoExtension->ClassData);
00726         IoDetachDevice(FdoExtension->AttachedDevice);
00727         CmBattDestroyFdo(FdoExtension->FdoDeviceObject);
00728         if (CmBattDebug & 0xC)
00729             DbgPrint("CmBattAddBattery: Could not register for battery notify, status = %Lx\n", Status);
00730     }
00731     
00732     /* Return status */
00733     return Status;
00734 }
00735 
00736 NTSTATUS
00737 NTAPI
00738 CmBattAddAcAdapter(IN PDRIVER_OBJECT DriverObject,
00739                    IN PDEVICE_OBJECT PdoDeviceObject)
00740 {
00741     PDEVICE_OBJECT FdoDeviceObject;
00742     NTSTATUS Status;
00743     PCMBATT_DEVICE_EXTENSION DeviceExtension;
00744     PAGED_CODE();
00745     if (CmBattDebug & 0x220)
00746         DbgPrint("CmBattAddAcAdapter: pdo %x\n", PdoDeviceObject);
00747 
00748     /* Check if we already have an AC adapter */
00749     if (AcAdapterPdo)
00750     {
00751         /* Don't do anything */
00752         if (CmBattDebug & 0xC)
00753             DbgPrint("CmBatt: Second AC adapter found.  Current version of driver only supports 1 aadapter.\n");
00754     }
00755     else
00756     {
00757         /* Set this as the AC adapter's PDO */
00758         AcAdapterPdo = PdoDeviceObject;
00759     }
00760     
00761     /* Create the FDO for the adapter */
00762     Status = CmBattCreateFdo(DriverObject,
00763                              PdoDeviceObject,
00764                              sizeof(CMBATT_DEVICE_EXTENSION),
00765                              &FdoDeviceObject);
00766     if (!NT_SUCCESS(Status))
00767     {
00768         /* Fail */
00769         if (CmBattDebug & 0xC)
00770             DbgPrint("CmBattAddAcAdapter: error (0x%x) creating Fdo\n", Status);
00771         return Status;
00772     }
00773     
00774     /* Set the type and do WMI registration */
00775     DeviceExtension = FdoDeviceObject->DeviceExtension;
00776     DeviceExtension->FdoType = CmBattAcAdapter;
00777     Status = CmBattWmiRegistration(DeviceExtension);
00778     if (!NT_SUCCESS(Status))
00779     {
00780         /* We can go on without WMI */
00781         if (CmBattDebug & 0xC)
00782             DbgPrint("CmBattAddBattery: Could not register as a WMI provider, status = %Lx\n", Status);
00783     }
00784     
00785     /* Register with ACPI */
00786     Status = DeviceExtension->AcpiInterface.RegisterForDeviceNotifications(DeviceExtension->AcpiInterface.Context,
00787                                                                            (PVOID)CmBattNotifyHandler,
00788                                                                            DeviceExtension);
00789     if (!(NT_SUCCESS(Status)) && (CmBattDebug & 0xC))
00790         DbgPrint("CmBattAddAcAdapter: Could not register for power notify, status = %Lx\n", Status);
00791 
00792     /* Send the first manual notification */
00793     CmBattNotifyHandler(DeviceExtension, ACPI_BATT_NOTIFY_STATUS);
00794     return STATUS_SUCCESS;
00795 }
00796 
00797 NTSTATUS
00798 NTAPI
00799 CmBattAddDevice(IN PDRIVER_OBJECT DriverObject,
00800                 IN PDEVICE_OBJECT PdoDeviceObject)
00801 {
00802     NTSTATUS Status;
00803     HANDLE KeyHandle;
00804     ULONG ResultLength;
00805     UNICODE_STRING KeyString;
00806     UCHAR Buffer[sizeof(KEY_VALUE_PARTIAL_INFORMATION) + sizeof(ULONG)];
00807     PKEY_VALUE_PARTIAL_INFORMATION PartialInfo = (PVOID)Buffer;
00808     ULONG PowerSourceType;
00809     PAGED_CODE();
00810     if (CmBattDebug & 0x220)
00811         DbgPrint("CmBattAddDevice: Entered with pdo %x\n", PdoDeviceObject);
00812     
00813     /* Make sure we have a PDO */
00814     if (!PdoDeviceObject)
00815     {
00816         /* Should not be having as one */
00817         if (CmBattDebug & 0x24) DbgPrint("CmBattAddDevice: Asked to do detection\n");
00818         return STATUS_NO_MORE_ENTRIES;
00819     }
00820     
00821     /* Open the driver key */
00822     Status = IoOpenDeviceRegistryKey(PdoDeviceObject,
00823                                      PLUGPLAY_REGKEY_DRIVER,
00824                                      KEY_READ,
00825                                      &KeyHandle);
00826     if (!NT_SUCCESS(Status))
00827     {
00828         if (CmBattDebug & 0xC)
00829             DbgPrint("CmBattAddDevice: Could not get the software branch: %x\n", Status);
00830         return Status;
00831     }
00832 
00833     /* Read the power source type */
00834     RtlInitUnicodeString(&KeyString, L"PowerSourceType");
00835     Status = ZwQueryValueKey(KeyHandle,
00836                              &KeyString,
00837                              KeyValuePartialInformation,
00838                              PartialInfo,
00839                              sizeof(Buffer),
00840                              &ResultLength);
00841     ZwClose(KeyHandle);
00842     if (!NT_SUCCESS(Status))
00843     {
00844         /* We need the data, fail without it */
00845         if (CmBattDebug & 0xC)
00846             DbgPrint("CmBattAddDevice: Could not read the power type identifier: %x\n", Status);
00847         return Status;
00848     }
00849     
00850     /* Check what kind of power source this is */
00851     PowerSourceType = *(PULONG)PartialInfo->Data;
00852     if (PowerSourceType == 1)
00853     {
00854         /* Create an AC adapter */
00855         Status = CmBattAddAcAdapter(DriverObject, PdoDeviceObject);
00856     }
00857     else if (PowerSourceType == 0)
00858     {
00859         /* Create a battery */
00860         Status = CmBattAddBattery(DriverObject, PdoDeviceObject);
00861     }
00862     else
00863     {
00864         /* Unknown type, fail */
00865         if (CmBattDebug & 0xC)
00866             DbgPrint("CmBattAddDevice: Invalid POWER_SOURCE_TYPE == %d \n", PowerSourceType);
00867         return STATUS_UNSUCCESSFUL;
00868     }
00869     
00870     /* Return whatever the FDO creation routine did */
00871     return Status;
00872 }
00873 
00874 /* EOF */

Generated on Sun May 27 2012 04:27:25 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.