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

comppnp.c
Go to the documentation of this file.
00001 /*
00002  * PROJECT:         ReactOS Composite Battery Driver
00003  * LICENSE:         BSD - See COPYING.ARM in the top level directory
00004  * FILE:            boot/drivers/bus/acpi/compbatt/comppnp.c
00005  * PURPOSE:         Plug-and-Play IOCTL/IRP Handling
00006  * PROGRAMMERS:     ReactOS Portable Systems Group
00007  */
00008 
00009 /* INCLUDES *******************************************************************/
00010 
00011 #include "compbatt.h"
00012 
00013 /* FUNCTIONS ******************************************************************/
00014  
00015 NTSTATUS
00016 NTAPI
00017 CompBattPowerDispatch(IN PDEVICE_OBJECT DeviceObject,
00018                       IN PIRP Irp)
00019 {
00020     PCOMPBATT_DEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
00021     if (CompBattDebug & 1) DbgPrint("CompBatt: PowerDispatch recieved power IRP.\n");
00022      
00023     /* Start the next IRP */
00024     PoStartNextPowerIrp(Irp);
00025     
00026     /* Call the next driver in the stack */
00027     IoSkipCurrentIrpStackLocation(Irp);
00028     return PoCallDriver(DeviceExtension->AttachedDevice, Irp);
00029 }
00030 
00031 PCOMPBATT_BATTERY_DATA
00032 NTAPI
00033 RemoveBatteryFromList(IN PCUNICODE_STRING BatteryName,
00034                       IN PCOMPBATT_DEVICE_EXTENSION DeviceExtension)
00035 {
00036     PLIST_ENTRY ListHead, NextEntry;
00037     PCOMPBATT_BATTERY_DATA BatteryData;
00038     if (CompBattDebug & 1)
00039         DbgPrint("CompBatt: ENTERING RemoveBatteryFromList\n");
00040 
00041     /* Loop the battery list */
00042     ExAcquireFastMutex(&DeviceExtension->Lock);
00043     ListHead = &DeviceExtension->BatteryList;
00044     NextEntry = ListHead->Flink;
00045     while (NextEntry != ListHead)
00046     {
00047         /* Get the battery information and compare the name */
00048         BatteryData = CONTAINING_RECORD(NextEntry, COMPBATT_BATTERY_DATA, BatteryLink);
00049         if (!RtlCompareUnicodeString(BatteryName, &BatteryData->BatteryName, TRUE))
00050         {
00051             /* Flush pending deletes and any lock waiters */
00052             IoAcquireRemoveLock(&BatteryData->RemoveLock, 0);
00053             ExReleaseFastMutex(&DeviceExtension->Lock);
00054             IoReleaseRemoveLockAndWait(&BatteryData->RemoveLock, 0);
00055           
00056             /* Remove the entry from the list */
00057             ExAcquireFastMutex(&DeviceExtension->Lock);
00058             RemoveEntryList(&BatteryData->BatteryLink);
00059             ExReleaseFastMutex(&DeviceExtension->Lock);
00060             return BatteryData;
00061         }
00062         
00063         /* Next */
00064         NextEntry = NextEntry->Flink;
00065     }
00066     
00067     /* Done */
00068     ExReleaseFastMutex(&DeviceExtension->Lock);
00069     if (CompBattDebug & 1) DbgPrint("CompBatt: EXITING RemoveBatteryFromList\n");
00070     return STATUS_SUCCESS;
00071 }
00072 
00073 BOOLEAN
00074 NTAPI
00075 IsBatteryAlreadyOnList(IN PCUNICODE_STRING BatteryName,
00076                        IN PCOMPBATT_DEVICE_EXTENSION DeviceExtension)
00077 {
00078     PLIST_ENTRY ListHead, NextEntry;
00079     PCOMPBATT_BATTERY_DATA BatteryData;
00080     BOOLEAN Found = FALSE;
00081     if (CompBattDebug & 1)
00082         DbgPrint("CompBatt: ENTERING IsBatteryAlreadyOnList\n");
00083     
00084     /* Loop the battery list */
00085     ExAcquireFastMutex(&DeviceExtension->Lock);
00086     ListHead = &DeviceExtension->BatteryList;
00087     NextEntry = ListHead->Flink;
00088     while (NextEntry != ListHead)
00089     {
00090         /* Get the battery information and compare the name */
00091         BatteryData = CONTAINING_RECORD(NextEntry, COMPBATT_BATTERY_DATA, BatteryLink);
00092         if (!RtlCompareUnicodeString(BatteryName, &BatteryData->BatteryName, TRUE))
00093         {
00094             /* Got it */
00095             Found = TRUE;
00096             break;
00097         }
00098 
00099         /* Next */
00100         NextEntry = NextEntry->Flink;
00101     }
00102     
00103     /* Release the lock and return search status */
00104     ExReleaseFastMutex(&DeviceExtension->Lock);
00105     if (CompBattDebug & 1) DbgPrint("CompBatt: EXITING IsBatteryAlreadyOnList\n");
00106     return Found;
00107 }
00108 
00109 NTSTATUS
00110 NTAPI
00111 CompBattAddNewBattery(IN PUNICODE_STRING BatteryName,
00112                       IN PCOMPBATT_DEVICE_EXTENSION DeviceExtension)
00113 {
00114     NTSTATUS Status = STATUS_SUCCESS;
00115     PCOMPBATT_BATTERY_DATA BatteryData;
00116     PIRP Irp;
00117     PIO_STACK_LOCATION IoStackLocation;
00118     PFILE_OBJECT FileObject;
00119     PAGED_CODE();
00120     if (CompBattDebug & 1)
00121         DbgPrint("CompBatt: ENTERING AddNewBattery \"%w\" \n", BatteryName->Buffer);
00122     
00123     /* Is this a new battery? */
00124     if (!IsBatteryAlreadyOnList(BatteryName, DeviceExtension))
00125     {
00126         /* Allocate battery data */
00127         BatteryData = ExAllocatePoolWithTag(NonPagedPool,
00128                                             sizeof(COMPBATT_BATTERY_DATA) +
00129                                             BatteryName->Length,
00130                                             'CtaB');
00131         if (BatteryData)
00132         {
00133             /* Initialize the data and write the battery name */
00134             RtlZeroMemory(BatteryData, sizeof(COMPBATT_BATTERY_DATA));
00135             BatteryData->Tag = 0;
00136             BatteryData->BatteryName.MaximumLength = BatteryName->Length;
00137             BatteryData->BatteryName.Buffer = (PWCHAR)(BatteryData + 1);
00138             RtlCopyUnicodeString(&BatteryData->BatteryName, BatteryName);
00139             
00140             /* Get the device object */
00141             Status = CompBattGetDeviceObjectPointer(BatteryName,
00142                                                     FILE_ALL_ACCESS,
00143                                                     &FileObject,
00144                                                     &BatteryData->DeviceObject);
00145             if (NT_SUCCESS(Status))
00146             {
00147                 /* Reference the DO and drop the FO */
00148                 ObReferenceObject(BatteryData->DeviceObject);
00149                 ObDereferenceObject(FileObject);
00150                 
00151                 /* Allocate the battery IRP */            
00152                 Irp = IoAllocateIrp(BatteryData->DeviceObject->StackSize + 1, 0);
00153                 if (Irp)
00154                 {
00155                     /* Save it */
00156                     BatteryData->Irp = Irp;
00157                     
00158                     /* Setup the stack location */
00159                     IoStackLocation = IoGetNextIrpStackLocation(Irp);
00160                     IoStackLocation->Parameters.Others.Argument1 = DeviceExtension;
00161                     IoStackLocation->Parameters.Others.Argument2 = BatteryData;
00162 
00163                     /* Set IRP data */
00164                     IoSetNextIrpStackLocation(Irp);
00165                     Irp->IoStatus.Status = STATUS_DEVICE_NOT_CONNECTED;
00166                     BatteryData->WaitFlag = 0;
00167 
00168                     /* Insert this battery in the list */
00169                     ExAcquireFastMutex(&DeviceExtension->Lock);
00170                     InsertTailList(&DeviceExtension->BatteryList,
00171                                    &BatteryData->BatteryLink);
00172                     ExReleaseFastMutex(&DeviceExtension->Lock);
00173 
00174                     /* Initialize the work item and delete lock */
00175                     IoInitializeRemoveLock(&BatteryData->RemoveLock, 0, 0, 0);
00176                     ExInitializeWorkItem(&BatteryData->WorkItem,
00177                                          (PVOID)CompBattMonitorIrpCompleteWorker,
00178                                          BatteryData);
00179                     
00180                     /* Setup the IRP work entry */
00181                     CompBattMonitorIrpComplete(BatteryData->DeviceObject, Irp, 0);
00182                     Status = STATUS_SUCCESS;
00183                 }
00184                 else
00185                 {
00186                     /* Fail, no memory */
00187                     if (CompBattDebug & 8)
00188                         DbgPrint("CompBatt: Couldn't allocate new battery Irp\n");
00189                     Status = STATUS_INSUFFICIENT_RESOURCES;
00190                     ObDereferenceObject(BatteryData->DeviceObject);
00191                 }
00192             }
00193             else if (CompBattDebug & 8)
00194             {
00195                 /* Fail */
00196                 DbgPrint("CompBattAddNewBattery: Failed to get device Object. status = %lx\n", 
00197                          Status);
00198             }
00199             
00200             /* Free the battery data */
00201             ExFreePool(BatteryData);
00202         }
00203         else
00204         {
00205             /* Fail, no memory */
00206             if (CompBattDebug & 8)
00207                 DbgPrint("CompBatt: Couldn't allocate new battery node\n");
00208             Status = STATUS_INSUFFICIENT_RESOURCES;
00209         }
00210     }
00211 
00212     /* We're done */
00213     if (CompBattDebug & 1) DbgPrint("CompBatt: EXITING AddNewBattery\n");
00214     return Status;
00215 }
00216 
00217 NTSTATUS
00218 NTAPI
00219 CompBattRemoveBattery(IN PCUNICODE_STRING BatteryName,
00220                       IN PCOMPBATT_DEVICE_EXTENSION DeviceExtension)
00221 {
00222     PCOMPBATT_BATTERY_DATA BatteryData;
00223     if (CompBattDebug & 1) DbgPrint("CompBatt: RemoveBattery\n");
00224 
00225     /* Remove the entry */
00226     BatteryData = RemoveBatteryFromList(BatteryName, DeviceExtension);
00227     if (BatteryData)
00228     {
00229         /* Dereference and free it */
00230         ObDereferenceObject(BatteryData->DeviceObject);
00231         ExFreePool(BatteryData);
00232         
00233         /* Notify class driver */
00234         DeviceExtension->Flags = 0;
00235         BatteryClassStatusNotify(DeviceExtension->ClassData);
00236     }
00237 
00238     /* It's done */
00239     return STATUS_SUCCESS;
00240 }
00241 
00242 NTSTATUS
00243 NTAPI
00244 CompBattGetBatteries(IN PCOMPBATT_DEVICE_EXTENSION DeviceExtension)
00245 {
00246     PWCHAR p;
00247     NTSTATUS Status;
00248     PWCHAR LinkList;
00249     UNICODE_STRING LinkString;
00250     if (CompBattDebug & 1) DbgPrint("CompBatt: ENTERING GetBatteries\n");
00251     
00252     /* Get all battery links */
00253     Status = IoGetDeviceInterfaces(&GUID_DEVICE_BATTERY, NULL, 0, &LinkList);
00254     p = LinkList;
00255     if (NT_SUCCESS(Status))
00256     {
00257         /* Loop all strings inside */
00258         while (TRUE)
00259         {
00260             /* Create the string */
00261             RtlInitUnicodeString(&LinkString, p);
00262             if (!LinkString.Length) break;
00263             
00264             /* Add this battery and move on */
00265             Status = CompBattAddNewBattery(&LinkString, DeviceExtension);
00266             p += (LinkString.Length / sizeof(WCHAR)) + sizeof(UNICODE_NULL);
00267         }
00268       
00269         /* Parsing complete, clean up buffer */
00270         ExFreePool(LinkList);
00271     }
00272     else if (CompBattDebug & 8)
00273     {
00274         /* Fail */
00275         DbgPrint("CompBatt: Couldn't get list of batteries\n");
00276     }
00277     
00278     /* Done */
00279     if (CompBattDebug & 1) DbgPrint("CompBatt: EXITING GetBatteries\n");
00280     return Status;
00281 }
00282 
00283 NTSTATUS
00284 NTAPI
00285 CompBattPnpEventHandler(IN PDEVICE_INTERFACE_CHANGE_NOTIFICATION Notification,
00286                         IN PCOMPBATT_DEVICE_EXTENSION DeviceExtension)
00287 {
00288     if (CompBattDebug & 1) DbgPrint("CompBatt: ENTERING PnpEventHandler\n");
00289     if (CompBattDebug & 2) DbgPrint("CompBatt: Received device interface change notification\n");
00290 
00291     /* Check what happened */
00292     if (IsEqualGUIDAligned(&Notification->Event, &GUID_DEVICE_INTERFACE_ARRIVAL))
00293     {
00294         /* Add the new battery */
00295         if (CompBattDebug & 2)
00296             DbgPrint("CompBatt: Received notification of battery arrival\n");
00297         CompBattAddNewBattery(Notification->SymbolicLinkName, DeviceExtension);
00298     }
00299     else if (IsEqualGUIDAligned(&Notification->Event, &GUID_DEVICE_INTERFACE_REMOVAL))
00300     {
00301         /* Don't do anything */
00302         if (CompBattDebug & 2)
00303             DbgPrint("CompBatt: Received notification of battery removal\n");
00304     }
00305     else
00306     {
00307         /* Shouldn't happen */
00308         if (CompBattDebug & 2) DbgPrint("CompBatt: Received unhandled PnP event\n");
00309     }
00310 
00311     /* Done, return success */
00312     if (CompBattDebug & 1) DbgPrint("CompBatt: EXITING PnpEventHandler\n");
00313     return STATUS_SUCCESS;
00314 }
00315 
00316 NTSTATUS
00317 NTAPI
00318 CompBattAddDevice(IN PDRIVER_OBJECT DriverObject,
00319                   IN PDEVICE_OBJECT PdoDeviceObject)
00320 {
00321     NTSTATUS Status;
00322     UNICODE_STRING DeviceName;
00323     PCOMPBATT_DEVICE_EXTENSION DeviceExtension;
00324     PDEVICE_OBJECT DeviceObject;
00325     UNICODE_STRING SymbolicLinkName;
00326     BATTERY_MINIPORT_INFO MiniportInfo;
00327     if (CompBattDebug & 2) DbgPrint("CompBatt: Got an AddDevice - %x\n", PdoDeviceObject);
00328     
00329     /* Create the device */
00330     RtlInitUnicodeString(&DeviceName, L"\\Device\\CompositeBattery");
00331     Status = IoCreateDevice(DriverObject,
00332                             sizeof(COMPBATT_DEVICE_EXTENSION),
00333                             &DeviceName, 
00334                             FILE_DEVICE_BATTERY,
00335                             FILE_DEVICE_SECURE_OPEN,
00336                             FALSE,
00337                             &DeviceObject);
00338     if (!NT_SUCCESS(Status)) return Status;
00339 
00340     /* Setup symbolic link for Win32 access */
00341     RtlInitUnicodeString(&SymbolicLinkName, L"\\DosDevices\\CompositeBattery");
00342     IoCreateSymbolicLink(&SymbolicLinkName, &DeviceName);
00343     
00344     /* Initialize the device extension */
00345     DeviceExtension = DeviceObject->DeviceExtension;
00346     RtlZeroMemory(DeviceExtension, 0x1B0u);
00347     
00348     /* Attach to device stack and set DO pointers */
00349     DeviceExtension->AttachedDevice = IoAttachDeviceToDeviceStack(DeviceObject,
00350                                                                   PdoDeviceObject);
00351     DeviceExtension->DeviceObject = DeviceObject;
00352     if (!DeviceExtension->AttachedDevice)
00353     {
00354         /* Fail */
00355         if (CompBattDebug & 8)
00356             DbgPrint("CompBattAddDevice: Could not attach to LowerDevice.\n");
00357         IoDeleteDevice(DeviceObject);
00358         return STATUS_UNSUCCESSFUL; 
00359     }
00360 
00361     /* Set device object flags */
00362     DeviceObject->Flags |= (DO_POWER_PAGABLE | DO_BUFFERED_IO);
00363     DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
00364 
00365     /* Setup the device extension */
00366     ExInitializeFastMutex(&DeviceExtension->Lock);
00367     InitializeListHead(&DeviceExtension->BatteryList);
00368     DeviceExtension->Flags = 0;
00369     DeviceExtension->NextTag = 1;
00370     
00371     /* Setup the miniport data */
00372     RtlZeroMemory(&MiniportInfo, sizeof(MiniportInfo));
00373     MiniportInfo.MajorVersion = BATTERY_CLASS_MAJOR_VERSION;
00374     MiniportInfo.MinorVersion = BATTERY_CLASS_MINOR_VERSION;
00375     MiniportInfo.Context = DeviceExtension;
00376     MiniportInfo.DeviceName = &DeviceName;
00377     MiniportInfo.QueryTag = (BCLASS_QUERY_TAG)CompBattQueryTag;
00378     MiniportInfo.QueryInformation = (BCLASS_QUERY_INFORMATION)CompBattQueryInformation;
00379     MiniportInfo.SetInformation = NULL;
00380     MiniportInfo.QueryStatus = (BCLASS_QUERY_STATUS)CompBattQueryStatus;
00381     MiniportInfo.SetStatusNotify = (BCLASS_SET_STATUS_NOTIFY)CompBattSetStatusNotify;
00382     MiniportInfo.DisableStatusNotify = (BCLASS_DISABLE_STATUS_NOTIFY)CompBattDisableStatusNotify;
00383     MiniportInfo.Pdo = NULL;
00384     
00385     /* Register with the class driver */
00386     Status = BatteryClassInitializeDevice(&MiniportInfo,
00387                                           &DeviceExtension->ClassData);
00388     if (!NT_SUCCESS(Status))
00389     {
00390         /* Undo everything */
00391         IoDetachDevice(DeviceExtension->AttachedDevice);
00392         IoDeleteDevice(DeviceObject);
00393     }
00394 
00395     /* Return status */
00396     return Status;
00397 }
00398 
00399 NTSTATUS
00400 NTAPI
00401 CompBattPnpDispatch(IN PDEVICE_OBJECT DeviceObject,
00402                     IN PIRP Irp)
00403 {
00404     PIO_STACK_LOCATION IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
00405     NTSTATUS Status;
00406     PCOMPBATT_DEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
00407     if (CompBattDebug & 1) DbgPrint("CompBatt: ENTERING PnpDispatch\n");
00408 
00409     /* Set default error */
00410     Status = STATUS_NOT_SUPPORTED;
00411 
00412     /* Check what kind of PnP function this is */
00413     switch (IoStackLocation->MinorFunction)
00414     {
00415         case IRP_MN_START_DEVICE:
00416         
00417             /* Device is starting, register for new batteries and pick up current ones */
00418             Status = IoRegisterPlugPlayNotification(EventCategoryDeviceInterfaceChange,
00419                                                     0,
00420                                                     (PVOID)&GUID_DEVICE_BATTERY,
00421                                                     DeviceObject->DriverObject,
00422                                                     (PDRIVER_NOTIFICATION_CALLBACK_ROUTINE)CompBattPnpEventHandler,
00423                                                     DeviceExtension,
00424                                                     &DeviceExtension->NotificationEntry);
00425             if (NT_SUCCESS(Status))
00426             {
00427                 /* Now go get the batteries */
00428                 if (CompBattDebug & 2)
00429                     DbgPrint("CompBatt: Successfully registered for PnP notification\n");
00430                 Status = CompBattGetBatteries(DeviceExtension);
00431             }
00432             else
00433             {
00434                 /* We failed */
00435                 if (CompBattDebug & 8)
00436                     DbgPrint("CompBatt: Couldn't register for PnP notification - %x\n",
00437                              Status);
00438             }
00439              break;
00440         case IRP_MN_CANCEL_STOP_DEVICE:
00441         
00442             /* Explicitly say ok */
00443             Status = STATUS_SUCCESS;
00444             break;
00445             
00446         case IRP_MN_CANCEL_REMOVE_DEVICE:
00447 
00448             /* Explicitly say ok */
00449             Status = STATUS_SUCCESS;
00450             break;
00451             
00452         case IRP_MN_SURPRISE_REMOVAL:
00453         
00454             /* Explicitly say ok */
00455             Status = STATUS_SUCCESS;
00456             break;
00457             
00458         case IRP_MN_QUERY_PNP_DEVICE_STATE:
00459         
00460             /* Add this in */
00461             Irp->IoStatus.Information |= PNP_DEVICE_NOT_DISABLEABLE;
00462             Status = STATUS_SUCCESS;
00463             break;
00464             
00465         default:
00466         
00467             /* Not supported */
00468             Status = STATUS_INVALID_DEVICE_REQUEST;
00469             break;
00470     }
00471 
00472     /* Set IRP status if we have one */
00473     if (Status != STATUS_NOT_SUPPORTED) Irp->IoStatus.Status = Status;
00474 
00475     /* Did someone pick it up? */    
00476     if ((NT_SUCCESS(Status)) || (Status == STATUS_NOT_SUPPORTED))
00477     {
00478         /* Still unsupported, try ACPI */
00479         IoSkipCurrentIrpStackLocation(Irp);
00480         Status = IoCallDriver(DeviceExtension->AttachedDevice, Irp);
00481     }
00482     else
00483     {
00484         /* Complete the request */
00485         Status = Irp->IoStatus.Status;
00486         IoCompleteRequest(Irp, IO_NO_INCREMENT);
00487     }
00488 
00489     /* Release the remove lock and return status */
00490     if (CompBattDebug & 1) DbgPrint("CompBatt: EXITING PnpDispatch\n");
00491     return Status;
00492 }
00493 
00494 /* 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.