xref: /reactos/drivers/bus/acpi/compbatt/comppnp.c (revision c2c66aff)
1*c2c66affSColin Finck /*
2*c2c66affSColin Finck  * PROJECT:         ReactOS Composite Battery Driver
3*c2c66affSColin Finck  * LICENSE:         BSD - See COPYING.ARM in the top level directory
4*c2c66affSColin Finck  * FILE:            boot/drivers/bus/acpi/compbatt/comppnp.c
5*c2c66affSColin Finck  * PURPOSE:         Plug-and-Play IOCTL/IRP Handling
6*c2c66affSColin Finck  * PROGRAMMERS:     ReactOS Portable Systems Group
7*c2c66affSColin Finck  */
8*c2c66affSColin Finck 
9*c2c66affSColin Finck /* INCLUDES *******************************************************************/
10*c2c66affSColin Finck 
11*c2c66affSColin Finck #include "compbatt.h"
12*c2c66affSColin Finck 
13*c2c66affSColin Finck #include <wdmguid.h>
14*c2c66affSColin Finck 
15*c2c66affSColin Finck /* FUNCTIONS ******************************************************************/
16*c2c66affSColin Finck 
17*c2c66affSColin Finck NTSTATUS
18*c2c66affSColin Finck NTAPI
CompBattPowerDispatch(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)19*c2c66affSColin Finck CompBattPowerDispatch(IN PDEVICE_OBJECT DeviceObject,
20*c2c66affSColin Finck                       IN PIRP Irp)
21*c2c66affSColin Finck {
22*c2c66affSColin Finck     PCOMPBATT_DEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
23*c2c66affSColin Finck     if (CompBattDebug & 1) DbgPrint("CompBatt: PowerDispatch received power IRP.\n");
24*c2c66affSColin Finck 
25*c2c66affSColin Finck     /* Start the next IRP */
26*c2c66affSColin Finck     PoStartNextPowerIrp(Irp);
27*c2c66affSColin Finck 
28*c2c66affSColin Finck     /* Call the next driver in the stack */
29*c2c66affSColin Finck     IoSkipCurrentIrpStackLocation(Irp);
30*c2c66affSColin Finck     return PoCallDriver(DeviceExtension->AttachedDevice, Irp);
31*c2c66affSColin Finck }
32*c2c66affSColin Finck 
33*c2c66affSColin Finck PCOMPBATT_BATTERY_DATA
34*c2c66affSColin Finck NTAPI
RemoveBatteryFromList(IN PCUNICODE_STRING BatteryName,IN PCOMPBATT_DEVICE_EXTENSION DeviceExtension)35*c2c66affSColin Finck RemoveBatteryFromList(IN PCUNICODE_STRING BatteryName,
36*c2c66affSColin Finck                       IN PCOMPBATT_DEVICE_EXTENSION DeviceExtension)
37*c2c66affSColin Finck {
38*c2c66affSColin Finck     PLIST_ENTRY ListHead, NextEntry;
39*c2c66affSColin Finck     PCOMPBATT_BATTERY_DATA BatteryData;
40*c2c66affSColin Finck     if (CompBattDebug & 1)
41*c2c66affSColin Finck         DbgPrint("CompBatt: ENTERING RemoveBatteryFromList\n");
42*c2c66affSColin Finck 
43*c2c66affSColin Finck     /* Loop the battery list */
44*c2c66affSColin Finck     ExAcquireFastMutex(&DeviceExtension->Lock);
45*c2c66affSColin Finck     ListHead = &DeviceExtension->BatteryList;
46*c2c66affSColin Finck     NextEntry = ListHead->Flink;
47*c2c66affSColin Finck     while (NextEntry != ListHead)
48*c2c66affSColin Finck     {
49*c2c66affSColin Finck         /* Get the battery information and compare the name */
50*c2c66affSColin Finck         BatteryData = CONTAINING_RECORD(NextEntry, COMPBATT_BATTERY_DATA, BatteryLink);
51*c2c66affSColin Finck         if (!RtlCompareUnicodeString(BatteryName, &BatteryData->BatteryName, TRUE))
52*c2c66affSColin Finck         {
53*c2c66affSColin Finck             /* Flush pending deletes and any lock waiters */
54*c2c66affSColin Finck             IoAcquireRemoveLock(&BatteryData->RemoveLock, 0);
55*c2c66affSColin Finck             ExReleaseFastMutex(&DeviceExtension->Lock);
56*c2c66affSColin Finck             IoReleaseRemoveLockAndWait(&BatteryData->RemoveLock, 0);
57*c2c66affSColin Finck 
58*c2c66affSColin Finck             /* Remove the entry from the list */
59*c2c66affSColin Finck             ExAcquireFastMutex(&DeviceExtension->Lock);
60*c2c66affSColin Finck             RemoveEntryList(&BatteryData->BatteryLink);
61*c2c66affSColin Finck             ExReleaseFastMutex(&DeviceExtension->Lock);
62*c2c66affSColin Finck             return BatteryData;
63*c2c66affSColin Finck         }
64*c2c66affSColin Finck 
65*c2c66affSColin Finck         /* Next */
66*c2c66affSColin Finck         NextEntry = NextEntry->Flink;
67*c2c66affSColin Finck     }
68*c2c66affSColin Finck 
69*c2c66affSColin Finck     /* Done */
70*c2c66affSColin Finck     ExReleaseFastMutex(&DeviceExtension->Lock);
71*c2c66affSColin Finck     if (CompBattDebug & 1) DbgPrint("CompBatt: EXITING RemoveBatteryFromList\n");
72*c2c66affSColin Finck     return NULL;
73*c2c66affSColin Finck }
74*c2c66affSColin Finck 
75*c2c66affSColin Finck BOOLEAN
76*c2c66affSColin Finck NTAPI
IsBatteryAlreadyOnList(IN PCUNICODE_STRING BatteryName,IN PCOMPBATT_DEVICE_EXTENSION DeviceExtension)77*c2c66affSColin Finck IsBatteryAlreadyOnList(IN PCUNICODE_STRING BatteryName,
78*c2c66affSColin Finck                        IN PCOMPBATT_DEVICE_EXTENSION DeviceExtension)
79*c2c66affSColin Finck {
80*c2c66affSColin Finck     PLIST_ENTRY ListHead, NextEntry;
81*c2c66affSColin Finck     PCOMPBATT_BATTERY_DATA BatteryData;
82*c2c66affSColin Finck     BOOLEAN Found = FALSE;
83*c2c66affSColin Finck     if (CompBattDebug & 1)
84*c2c66affSColin Finck         DbgPrint("CompBatt: ENTERING IsBatteryAlreadyOnList\n");
85*c2c66affSColin Finck 
86*c2c66affSColin Finck     /* Loop the battery list */
87*c2c66affSColin Finck     ExAcquireFastMutex(&DeviceExtension->Lock);
88*c2c66affSColin Finck     ListHead = &DeviceExtension->BatteryList;
89*c2c66affSColin Finck     NextEntry = ListHead->Flink;
90*c2c66affSColin Finck     while (NextEntry != ListHead)
91*c2c66affSColin Finck     {
92*c2c66affSColin Finck         /* Get the battery information and compare the name */
93*c2c66affSColin Finck         BatteryData = CONTAINING_RECORD(NextEntry, COMPBATT_BATTERY_DATA, BatteryLink);
94*c2c66affSColin Finck         if (!RtlCompareUnicodeString(BatteryName, &BatteryData->BatteryName, TRUE))
95*c2c66affSColin Finck         {
96*c2c66affSColin Finck             /* Got it */
97*c2c66affSColin Finck             Found = TRUE;
98*c2c66affSColin Finck             break;
99*c2c66affSColin Finck         }
100*c2c66affSColin Finck 
101*c2c66affSColin Finck         /* Next */
102*c2c66affSColin Finck         NextEntry = NextEntry->Flink;
103*c2c66affSColin Finck     }
104*c2c66affSColin Finck 
105*c2c66affSColin Finck     /* Release the lock and return search status */
106*c2c66affSColin Finck     ExReleaseFastMutex(&DeviceExtension->Lock);
107*c2c66affSColin Finck     if (CompBattDebug & 1) DbgPrint("CompBatt: EXITING IsBatteryAlreadyOnList\n");
108*c2c66affSColin Finck     return Found;
109*c2c66affSColin Finck }
110*c2c66affSColin Finck 
111*c2c66affSColin Finck NTSTATUS
112*c2c66affSColin Finck NTAPI
CompBattAddNewBattery(IN PUNICODE_STRING BatteryName,IN PCOMPBATT_DEVICE_EXTENSION DeviceExtension)113*c2c66affSColin Finck CompBattAddNewBattery(IN PUNICODE_STRING BatteryName,
114*c2c66affSColin Finck                       IN PCOMPBATT_DEVICE_EXTENSION DeviceExtension)
115*c2c66affSColin Finck {
116*c2c66affSColin Finck     NTSTATUS Status = STATUS_SUCCESS;
117*c2c66affSColin Finck     PCOMPBATT_BATTERY_DATA BatteryData;
118*c2c66affSColin Finck     PIRP Irp;
119*c2c66affSColin Finck     PIO_STACK_LOCATION IoStackLocation;
120*c2c66affSColin Finck     PFILE_OBJECT FileObject;
121*c2c66affSColin Finck     PAGED_CODE();
122*c2c66affSColin Finck     if (CompBattDebug & 1)
123*c2c66affSColin Finck         DbgPrint("CompBatt: ENTERING AddNewBattery \"%w\" \n", BatteryName->Buffer);
124*c2c66affSColin Finck 
125*c2c66affSColin Finck     /* Is this a new battery? */
126*c2c66affSColin Finck     if (!IsBatteryAlreadyOnList(BatteryName, DeviceExtension))
127*c2c66affSColin Finck     {
128*c2c66affSColin Finck         /* Allocate battery data */
129*c2c66affSColin Finck         BatteryData = ExAllocatePoolWithTag(NonPagedPool,
130*c2c66affSColin Finck                                             sizeof(COMPBATT_BATTERY_DATA) +
131*c2c66affSColin Finck                                             BatteryName->Length,
132*c2c66affSColin Finck                                             'CtaB');
133*c2c66affSColin Finck         if (BatteryData)
134*c2c66affSColin Finck         {
135*c2c66affSColin Finck             /* Initialize the data and write the battery name */
136*c2c66affSColin Finck             RtlZeroMemory(BatteryData, sizeof(COMPBATT_BATTERY_DATA));
137*c2c66affSColin Finck             BatteryData->Tag = 0;
138*c2c66affSColin Finck             BatteryData->BatteryName.MaximumLength = BatteryName->Length;
139*c2c66affSColin Finck             BatteryData->BatteryName.Buffer = (PWCHAR)(BatteryData + 1);
140*c2c66affSColin Finck             RtlCopyUnicodeString(&BatteryData->BatteryName, BatteryName);
141*c2c66affSColin Finck 
142*c2c66affSColin Finck             /* Get the device object */
143*c2c66affSColin Finck             Status = CompBattGetDeviceObjectPointer(BatteryName,
144*c2c66affSColin Finck                                                     FILE_ALL_ACCESS,
145*c2c66affSColin Finck                                                     &FileObject,
146*c2c66affSColin Finck                                                     &BatteryData->DeviceObject);
147*c2c66affSColin Finck             if (NT_SUCCESS(Status))
148*c2c66affSColin Finck             {
149*c2c66affSColin Finck                 /* Reference the DO and drop the FO */
150*c2c66affSColin Finck                 ObReferenceObject(BatteryData->DeviceObject);
151*c2c66affSColin Finck                 ObDereferenceObject(FileObject);
152*c2c66affSColin Finck 
153*c2c66affSColin Finck                 /* Allocate the battery IRP */
154*c2c66affSColin Finck                 Irp = IoAllocateIrp(BatteryData->DeviceObject->StackSize + 1, 0);
155*c2c66affSColin Finck                 if (Irp)
156*c2c66affSColin Finck                 {
157*c2c66affSColin Finck                     /* Save it */
158*c2c66affSColin Finck                     BatteryData->Irp = Irp;
159*c2c66affSColin Finck 
160*c2c66affSColin Finck                     /* Setup the stack location */
161*c2c66affSColin Finck                     IoStackLocation = IoGetNextIrpStackLocation(Irp);
162*c2c66affSColin Finck                     IoStackLocation->Parameters.Others.Argument1 = DeviceExtension;
163*c2c66affSColin Finck                     IoStackLocation->Parameters.Others.Argument2 = BatteryData;
164*c2c66affSColin Finck 
165*c2c66affSColin Finck                     /* Set IRP data */
166*c2c66affSColin Finck                     IoSetNextIrpStackLocation(Irp);
167*c2c66affSColin Finck                     Irp->IoStatus.Status = STATUS_DEVICE_NOT_CONNECTED;
168*c2c66affSColin Finck                     BatteryData->WaitFlag = 0;
169*c2c66affSColin Finck 
170*c2c66affSColin Finck                     /* Insert this battery in the list */
171*c2c66affSColin Finck                     ExAcquireFastMutex(&DeviceExtension->Lock);
172*c2c66affSColin Finck                     InsertTailList(&DeviceExtension->BatteryList,
173*c2c66affSColin Finck                                    &BatteryData->BatteryLink);
174*c2c66affSColin Finck                     ExReleaseFastMutex(&DeviceExtension->Lock);
175*c2c66affSColin Finck 
176*c2c66affSColin Finck                     /* Initialize the work item and delete lock */
177*c2c66affSColin Finck                     IoInitializeRemoveLock(&BatteryData->RemoveLock, 0, 0, 0);
178*c2c66affSColin Finck                     ExInitializeWorkItem(&BatteryData->WorkItem,
179*c2c66affSColin Finck                                          (PVOID)CompBattMonitorIrpCompleteWorker,
180*c2c66affSColin Finck                                          BatteryData);
181*c2c66affSColin Finck 
182*c2c66affSColin Finck                     /* Setup the IRP work entry */
183*c2c66affSColin Finck                     CompBattMonitorIrpComplete(BatteryData->DeviceObject, Irp, 0);
184*c2c66affSColin Finck                     Status = STATUS_SUCCESS;
185*c2c66affSColin Finck                 }
186*c2c66affSColin Finck                 else
187*c2c66affSColin Finck                 {
188*c2c66affSColin Finck                     /* Fail, no memory */
189*c2c66affSColin Finck                     if (CompBattDebug & 8)
190*c2c66affSColin Finck                         DbgPrint("CompBatt: Couldn't allocate new battery Irp\n");
191*c2c66affSColin Finck                     Status = STATUS_INSUFFICIENT_RESOURCES;
192*c2c66affSColin Finck                     ObDereferenceObject(BatteryData->DeviceObject);
193*c2c66affSColin Finck                 }
194*c2c66affSColin Finck             }
195*c2c66affSColin Finck             else if (CompBattDebug & 8)
196*c2c66affSColin Finck             {
197*c2c66affSColin Finck                 /* Fail */
198*c2c66affSColin Finck                 DbgPrint("CompBattAddNewBattery: Failed to get device Object. status = %lx\n",
199*c2c66affSColin Finck                          Status);
200*c2c66affSColin Finck             }
201*c2c66affSColin Finck 
202*c2c66affSColin Finck             /* Free the battery data */
203*c2c66affSColin Finck             ExFreePool(BatteryData);
204*c2c66affSColin Finck         }
205*c2c66affSColin Finck         else
206*c2c66affSColin Finck         {
207*c2c66affSColin Finck             /* Fail, no memory */
208*c2c66affSColin Finck             if (CompBattDebug & 8)
209*c2c66affSColin Finck                 DbgPrint("CompBatt: Couldn't allocate new battery node\n");
210*c2c66affSColin Finck             Status = STATUS_INSUFFICIENT_RESOURCES;
211*c2c66affSColin Finck         }
212*c2c66affSColin Finck     }
213*c2c66affSColin Finck 
214*c2c66affSColin Finck     /* We're done */
215*c2c66affSColin Finck     if (CompBattDebug & 1) DbgPrint("CompBatt: EXITING AddNewBattery\n");
216*c2c66affSColin Finck     return Status;
217*c2c66affSColin Finck }
218*c2c66affSColin Finck 
219*c2c66affSColin Finck NTSTATUS
220*c2c66affSColin Finck NTAPI
CompBattRemoveBattery(IN PCUNICODE_STRING BatteryName,IN PCOMPBATT_DEVICE_EXTENSION DeviceExtension)221*c2c66affSColin Finck CompBattRemoveBattery(IN PCUNICODE_STRING BatteryName,
222*c2c66affSColin Finck                       IN PCOMPBATT_DEVICE_EXTENSION DeviceExtension)
223*c2c66affSColin Finck {
224*c2c66affSColin Finck     PCOMPBATT_BATTERY_DATA BatteryData;
225*c2c66affSColin Finck     if (CompBattDebug & 1) DbgPrint("CompBatt: RemoveBattery\n");
226*c2c66affSColin Finck 
227*c2c66affSColin Finck     /* Remove the entry */
228*c2c66affSColin Finck     BatteryData = RemoveBatteryFromList(BatteryName, DeviceExtension);
229*c2c66affSColin Finck     if (BatteryData)
230*c2c66affSColin Finck     {
231*c2c66affSColin Finck         /* Dereference and free it */
232*c2c66affSColin Finck         ObDereferenceObject(BatteryData->DeviceObject);
233*c2c66affSColin Finck         ExFreePool(BatteryData);
234*c2c66affSColin Finck 
235*c2c66affSColin Finck         /* Notify class driver */
236*c2c66affSColin Finck         DeviceExtension->Flags = 0;
237*c2c66affSColin Finck         BatteryClassStatusNotify(DeviceExtension->ClassData);
238*c2c66affSColin Finck     }
239*c2c66affSColin Finck 
240*c2c66affSColin Finck     /* It's done */
241*c2c66affSColin Finck     return STATUS_SUCCESS;
242*c2c66affSColin Finck }
243*c2c66affSColin Finck 
244*c2c66affSColin Finck NTSTATUS
245*c2c66affSColin Finck NTAPI
CompBattGetBatteries(IN PCOMPBATT_DEVICE_EXTENSION DeviceExtension)246*c2c66affSColin Finck CompBattGetBatteries(IN PCOMPBATT_DEVICE_EXTENSION DeviceExtension)
247*c2c66affSColin Finck {
248*c2c66affSColin Finck     PWCHAR p;
249*c2c66affSColin Finck     NTSTATUS Status;
250*c2c66affSColin Finck     PWCHAR LinkList;
251*c2c66affSColin Finck     UNICODE_STRING LinkString;
252*c2c66affSColin Finck     if (CompBattDebug & 1) DbgPrint("CompBatt: ENTERING GetBatteries\n");
253*c2c66affSColin Finck 
254*c2c66affSColin Finck     /* Get all battery links */
255*c2c66affSColin Finck     Status = IoGetDeviceInterfaces(&GUID_DEVICE_BATTERY, NULL, 0, &LinkList);
256*c2c66affSColin Finck     p = LinkList;
257*c2c66affSColin Finck     if (NT_SUCCESS(Status))
258*c2c66affSColin Finck     {
259*c2c66affSColin Finck         /* Loop all strings inside */
260*c2c66affSColin Finck         while (TRUE)
261*c2c66affSColin Finck         {
262*c2c66affSColin Finck             /* Create the string */
263*c2c66affSColin Finck             RtlInitUnicodeString(&LinkString, p);
264*c2c66affSColin Finck             if (!LinkString.Length) break;
265*c2c66affSColin Finck 
266*c2c66affSColin Finck             /* Add this battery and move on */
267*c2c66affSColin Finck             Status = CompBattAddNewBattery(&LinkString, DeviceExtension);
268*c2c66affSColin Finck             p += (LinkString.Length / sizeof(WCHAR)) + sizeof(UNICODE_NULL);
269*c2c66affSColin Finck         }
270*c2c66affSColin Finck 
271*c2c66affSColin Finck         /* Parsing complete, clean up buffer */
272*c2c66affSColin Finck         ExFreePool(LinkList);
273*c2c66affSColin Finck     }
274*c2c66affSColin Finck     else if (CompBattDebug & 8)
275*c2c66affSColin Finck     {
276*c2c66affSColin Finck         /* Fail */
277*c2c66affSColin Finck         DbgPrint("CompBatt: Couldn't get list of batteries\n");
278*c2c66affSColin Finck     }
279*c2c66affSColin Finck 
280*c2c66affSColin Finck     /* Done */
281*c2c66affSColin Finck     if (CompBattDebug & 1) DbgPrint("CompBatt: EXITING GetBatteries\n");
282*c2c66affSColin Finck     return Status;
283*c2c66affSColin Finck }
284*c2c66affSColin Finck 
285*c2c66affSColin Finck NTSTATUS
286*c2c66affSColin Finck NTAPI
CompBattPnpEventHandler(IN PDEVICE_INTERFACE_CHANGE_NOTIFICATION Notification,IN PCOMPBATT_DEVICE_EXTENSION DeviceExtension)287*c2c66affSColin Finck CompBattPnpEventHandler(IN PDEVICE_INTERFACE_CHANGE_NOTIFICATION Notification,
288*c2c66affSColin Finck                         IN PCOMPBATT_DEVICE_EXTENSION DeviceExtension)
289*c2c66affSColin Finck {
290*c2c66affSColin Finck     if (CompBattDebug & 1) DbgPrint("CompBatt: ENTERING PnpEventHandler\n");
291*c2c66affSColin Finck     if (CompBattDebug & 2) DbgPrint("CompBatt: Received device interface change notification\n");
292*c2c66affSColin Finck 
293*c2c66affSColin Finck     /* Check what happened */
294*c2c66affSColin Finck     if (IsEqualGUIDAligned(&Notification->Event, &GUID_DEVICE_INTERFACE_ARRIVAL))
295*c2c66affSColin Finck     {
296*c2c66affSColin Finck         /* Add the new battery */
297*c2c66affSColin Finck         if (CompBattDebug & 2)
298*c2c66affSColin Finck             DbgPrint("CompBatt: Received notification of battery arrival\n");
299*c2c66affSColin Finck         CompBattAddNewBattery(Notification->SymbolicLinkName, DeviceExtension);
300*c2c66affSColin Finck     }
301*c2c66affSColin Finck     else if (IsEqualGUIDAligned(&Notification->Event, &GUID_DEVICE_INTERFACE_REMOVAL))
302*c2c66affSColin Finck     {
303*c2c66affSColin Finck         /* Don't do anything */
304*c2c66affSColin Finck         if (CompBattDebug & 2)
305*c2c66affSColin Finck             DbgPrint("CompBatt: Received notification of battery removal\n");
306*c2c66affSColin Finck     }
307*c2c66affSColin Finck     else
308*c2c66affSColin Finck     {
309*c2c66affSColin Finck         /* Shouldn't happen */
310*c2c66affSColin Finck         if (CompBattDebug & 2) DbgPrint("CompBatt: Received unhandled PnP event\n");
311*c2c66affSColin Finck     }
312*c2c66affSColin Finck 
313*c2c66affSColin Finck     /* Done, return success */
314*c2c66affSColin Finck     if (CompBattDebug & 1) DbgPrint("CompBatt: EXITING PnpEventHandler\n");
315*c2c66affSColin Finck     return STATUS_SUCCESS;
316*c2c66affSColin Finck }
317*c2c66affSColin Finck 
318*c2c66affSColin Finck NTSTATUS
319*c2c66affSColin Finck NTAPI
CompBattAddDevice(IN PDRIVER_OBJECT DriverObject,IN PDEVICE_OBJECT PdoDeviceObject)320*c2c66affSColin Finck CompBattAddDevice(IN PDRIVER_OBJECT DriverObject,
321*c2c66affSColin Finck                   IN PDEVICE_OBJECT PdoDeviceObject)
322*c2c66affSColin Finck {
323*c2c66affSColin Finck     NTSTATUS Status;
324*c2c66affSColin Finck     UNICODE_STRING DeviceName;
325*c2c66affSColin Finck     PCOMPBATT_DEVICE_EXTENSION DeviceExtension;
326*c2c66affSColin Finck     PDEVICE_OBJECT DeviceObject;
327*c2c66affSColin Finck     UNICODE_STRING SymbolicLinkName;
328*c2c66affSColin Finck     BATTERY_MINIPORT_INFO MiniportInfo;
329*c2c66affSColin Finck     if (CompBattDebug & 2) DbgPrint("CompBatt: Got an AddDevice - %x\n", PdoDeviceObject);
330*c2c66affSColin Finck 
331*c2c66affSColin Finck     /* Create the device */
332*c2c66affSColin Finck     RtlInitUnicodeString(&DeviceName, L"\\Device\\CompositeBattery");
333*c2c66affSColin Finck     Status = IoCreateDevice(DriverObject,
334*c2c66affSColin Finck                             sizeof(COMPBATT_DEVICE_EXTENSION),
335*c2c66affSColin Finck                             &DeviceName,
336*c2c66affSColin Finck                             FILE_DEVICE_BATTERY,
337*c2c66affSColin Finck                             FILE_DEVICE_SECURE_OPEN,
338*c2c66affSColin Finck                             FALSE,
339*c2c66affSColin Finck                             &DeviceObject);
340*c2c66affSColin Finck     if (!NT_SUCCESS(Status)) return Status;
341*c2c66affSColin Finck 
342*c2c66affSColin Finck     /* Setup symbolic link for Win32 access */
343*c2c66affSColin Finck     RtlInitUnicodeString(&SymbolicLinkName, L"\\DosDevices\\CompositeBattery");
344*c2c66affSColin Finck     IoCreateSymbolicLink(&SymbolicLinkName, &DeviceName);
345*c2c66affSColin Finck 
346*c2c66affSColin Finck     /* Initialize the device extension */
347*c2c66affSColin Finck     DeviceExtension = DeviceObject->DeviceExtension;
348*c2c66affSColin Finck     RtlZeroMemory(DeviceExtension, sizeof(COMPBATT_DEVICE_EXTENSION));
349*c2c66affSColin Finck 
350*c2c66affSColin Finck     /* Attach to device stack and set DO pointers */
351*c2c66affSColin Finck     DeviceExtension->AttachedDevice = IoAttachDeviceToDeviceStack(DeviceObject,
352*c2c66affSColin Finck                                                                   PdoDeviceObject);
353*c2c66affSColin Finck     DeviceExtension->DeviceObject = DeviceObject;
354*c2c66affSColin Finck     if (!DeviceExtension->AttachedDevice)
355*c2c66affSColin Finck     {
356*c2c66affSColin Finck         /* Fail */
357*c2c66affSColin Finck         if (CompBattDebug & 8)
358*c2c66affSColin Finck             DbgPrint("CompBattAddDevice: Could not attach to LowerDevice.\n");
359*c2c66affSColin Finck         IoDeleteDevice(DeviceObject);
360*c2c66affSColin Finck         return STATUS_UNSUCCESSFUL;
361*c2c66affSColin Finck     }
362*c2c66affSColin Finck 
363*c2c66affSColin Finck     /* Set device object flags */
364*c2c66affSColin Finck     DeviceObject->Flags |= (DO_POWER_PAGABLE | DO_BUFFERED_IO);
365*c2c66affSColin Finck     DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
366*c2c66affSColin Finck 
367*c2c66affSColin Finck     /* Setup the device extension */
368*c2c66affSColin Finck     ExInitializeFastMutex(&DeviceExtension->Lock);
369*c2c66affSColin Finck     InitializeListHead(&DeviceExtension->BatteryList);
370*c2c66affSColin Finck     DeviceExtension->Flags = 0;
371*c2c66affSColin Finck     DeviceExtension->NextTag = 1;
372*c2c66affSColin Finck 
373*c2c66affSColin Finck     /* Setup the miniport data */
374*c2c66affSColin Finck     RtlZeroMemory(&MiniportInfo, sizeof(MiniportInfo));
375*c2c66affSColin Finck     MiniportInfo.MajorVersion = BATTERY_CLASS_MAJOR_VERSION;
376*c2c66affSColin Finck     MiniportInfo.MinorVersion = BATTERY_CLASS_MINOR_VERSION;
377*c2c66affSColin Finck     MiniportInfo.Context = DeviceExtension;
378*c2c66affSColin Finck     MiniportInfo.DeviceName = &DeviceName;
379*c2c66affSColin Finck     MiniportInfo.QueryTag = (BCLASS_QUERY_TAG)CompBattQueryTag;
380*c2c66affSColin Finck     MiniportInfo.QueryInformation = (BCLASS_QUERY_INFORMATION)CompBattQueryInformation;
381*c2c66affSColin Finck     MiniportInfo.SetInformation = NULL;
382*c2c66affSColin Finck     MiniportInfo.QueryStatus = (BCLASS_QUERY_STATUS)CompBattQueryStatus;
383*c2c66affSColin Finck     MiniportInfo.SetStatusNotify = (BCLASS_SET_STATUS_NOTIFY)CompBattSetStatusNotify;
384*c2c66affSColin Finck     MiniportInfo.DisableStatusNotify = (BCLASS_DISABLE_STATUS_NOTIFY)CompBattDisableStatusNotify;
385*c2c66affSColin Finck     MiniportInfo.Pdo = NULL;
386*c2c66affSColin Finck 
387*c2c66affSColin Finck     /* Register with the class driver */
388*c2c66affSColin Finck     Status = BatteryClassInitializeDevice(&MiniportInfo,
389*c2c66affSColin Finck                                           &DeviceExtension->ClassData);
390*c2c66affSColin Finck     if (!NT_SUCCESS(Status))
391*c2c66affSColin Finck     {
392*c2c66affSColin Finck         /* Undo everything */
393*c2c66affSColin Finck         IoDetachDevice(DeviceExtension->AttachedDevice);
394*c2c66affSColin Finck         IoDeleteDevice(DeviceObject);
395*c2c66affSColin Finck     }
396*c2c66affSColin Finck 
397*c2c66affSColin Finck     /* Return status */
398*c2c66affSColin Finck     return Status;
399*c2c66affSColin Finck }
400*c2c66affSColin Finck 
401*c2c66affSColin Finck NTSTATUS
402*c2c66affSColin Finck NTAPI
CompBattPnpDispatch(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)403*c2c66affSColin Finck CompBattPnpDispatch(IN PDEVICE_OBJECT DeviceObject,
404*c2c66affSColin Finck                     IN PIRP Irp)
405*c2c66affSColin Finck {
406*c2c66affSColin Finck     PIO_STACK_LOCATION IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
407*c2c66affSColin Finck     NTSTATUS Status;
408*c2c66affSColin Finck     PCOMPBATT_DEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
409*c2c66affSColin Finck     if (CompBattDebug & 1) DbgPrint("CompBatt: ENTERING PnpDispatch\n");
410*c2c66affSColin Finck 
411*c2c66affSColin Finck     /* Set default error */
412*c2c66affSColin Finck     Status = STATUS_NOT_SUPPORTED;
413*c2c66affSColin Finck 
414*c2c66affSColin Finck     /* Check what kind of PnP function this is */
415*c2c66affSColin Finck     switch (IoStackLocation->MinorFunction)
416*c2c66affSColin Finck     {
417*c2c66affSColin Finck         case IRP_MN_START_DEVICE:
418*c2c66affSColin Finck 
419*c2c66affSColin Finck             /* Device is starting, register for new batteries and pick up current ones */
420*c2c66affSColin Finck             Status = IoRegisterPlugPlayNotification(EventCategoryDeviceInterfaceChange,
421*c2c66affSColin Finck                                                     0,
422*c2c66affSColin Finck                                                     (PVOID)&GUID_DEVICE_BATTERY,
423*c2c66affSColin Finck                                                     DeviceObject->DriverObject,
424*c2c66affSColin Finck                                                     (PDRIVER_NOTIFICATION_CALLBACK_ROUTINE)CompBattPnpEventHandler,
425*c2c66affSColin Finck                                                     DeviceExtension,
426*c2c66affSColin Finck                                                     &DeviceExtension->NotificationEntry);
427*c2c66affSColin Finck             if (NT_SUCCESS(Status))
428*c2c66affSColin Finck             {
429*c2c66affSColin Finck                 /* Now go get the batteries */
430*c2c66affSColin Finck                 if (CompBattDebug & 2)
431*c2c66affSColin Finck                     DbgPrint("CompBatt: Successfully registered for PnP notification\n");
432*c2c66affSColin Finck                 Status = CompBattGetBatteries(DeviceExtension);
433*c2c66affSColin Finck             }
434*c2c66affSColin Finck             else
435*c2c66affSColin Finck             {
436*c2c66affSColin Finck                 /* We failed */
437*c2c66affSColin Finck                 if (CompBattDebug & 8)
438*c2c66affSColin Finck                     DbgPrint("CompBatt: Couldn't register for PnP notification - %x\n",
439*c2c66affSColin Finck                              Status);
440*c2c66affSColin Finck             }
441*c2c66affSColin Finck              break;
442*c2c66affSColin Finck         case IRP_MN_CANCEL_STOP_DEVICE:
443*c2c66affSColin Finck 
444*c2c66affSColin Finck             /* Explicitly say ok */
445*c2c66affSColin Finck             Status = STATUS_SUCCESS;
446*c2c66affSColin Finck             break;
447*c2c66affSColin Finck 
448*c2c66affSColin Finck         case IRP_MN_CANCEL_REMOVE_DEVICE:
449*c2c66affSColin Finck 
450*c2c66affSColin Finck             /* Explicitly say ok */
451*c2c66affSColin Finck             Status = STATUS_SUCCESS;
452*c2c66affSColin Finck             break;
453*c2c66affSColin Finck 
454*c2c66affSColin Finck         case IRP_MN_SURPRISE_REMOVAL:
455*c2c66affSColin Finck 
456*c2c66affSColin Finck             /* Explicitly say ok */
457*c2c66affSColin Finck             Status = STATUS_SUCCESS;
458*c2c66affSColin Finck             break;
459*c2c66affSColin Finck 
460*c2c66affSColin Finck         case IRP_MN_QUERY_PNP_DEVICE_STATE:
461*c2c66affSColin Finck 
462*c2c66affSColin Finck             /* Add this in */
463*c2c66affSColin Finck             Irp->IoStatus.Information |= PNP_DEVICE_NOT_DISABLEABLE;
464*c2c66affSColin Finck             Status = STATUS_SUCCESS;
465*c2c66affSColin Finck             break;
466*c2c66affSColin Finck 
467*c2c66affSColin Finck         default:
468*c2c66affSColin Finck 
469*c2c66affSColin Finck             /* Not supported */
470*c2c66affSColin Finck             Status = STATUS_INVALID_DEVICE_REQUEST;
471*c2c66affSColin Finck             break;
472*c2c66affSColin Finck     }
473*c2c66affSColin Finck 
474*c2c66affSColin Finck     /* Set IRP status if we have one */
475*c2c66affSColin Finck     if (Status != STATUS_NOT_SUPPORTED) Irp->IoStatus.Status = Status;
476*c2c66affSColin Finck 
477*c2c66affSColin Finck     /* Did someone pick it up? */
478*c2c66affSColin Finck     if ((NT_SUCCESS(Status)) || (Status == STATUS_NOT_SUPPORTED))
479*c2c66affSColin Finck     {
480*c2c66affSColin Finck         /* Still unsupported, try ACPI */
481*c2c66affSColin Finck         IoSkipCurrentIrpStackLocation(Irp);
482*c2c66affSColin Finck         Status = IoCallDriver(DeviceExtension->AttachedDevice, Irp);
483*c2c66affSColin Finck     }
484*c2c66affSColin Finck     else
485*c2c66affSColin Finck     {
486*c2c66affSColin Finck         /* Complete the request */
487*c2c66affSColin Finck         Status = Irp->IoStatus.Status;
488*c2c66affSColin Finck         IoCompleteRequest(Irp, IO_NO_INCREMENT);
489*c2c66affSColin Finck     }
490*c2c66affSColin Finck 
491*c2c66affSColin Finck     /* Release the remove lock and return status */
492*c2c66affSColin Finck     if (CompBattDebug & 1) DbgPrint("CompBatt: EXITING PnpDispatch\n");
493*c2c66affSColin Finck     return Status;
494*c2c66affSColin Finck }
495*c2c66affSColin Finck 
496*c2c66affSColin Finck /* EOF */
497