ReactOS 0.4.16-dev-522-gb68104a
compbatt.c
Go to the documentation of this file.
1/*
2 * PROJECT: ReactOS Composite Battery Driver
3 * LICENSE: MIT (https://spdx.org/licenses/MIT)
4 * PURPOSE: Main Initialization Code and IRP Handling
5 * COPYRIGHT: Copyright 2010 ReactOS Portable Systems Group <ros.arm@reactos.org>
6 * Copyright 2024 George Bișoc <george.bisoc@reactos.org>
7 */
8
9/* INCLUDES *******************************************************************/
10
11#include "compbatt.h"
12
13#include <debug.h>
14
15/* GLOBALS ********************************************************************/
16
18
19/* FUNCTIONS ******************************************************************/
20
26{
27 PAGED_CODE();
28 if (CompBattDebug & COMPBATT_DEBUG_TRACE) DbgPrint("CompBatt: ENTERING OpenClose\n");
29
30 /* Complete the IRP with success */
31 Irp->IoStatus.Status = STATUS_SUCCESS;
32 Irp->IoStatus.Information = 0;
34
35 /* Return success */
36 if (CompBattDebug & COMPBATT_DEBUG_TRACE) DbgPrint("CompBatt: Exiting OpenClose\n");
37 return STATUS_SUCCESS;
38}
39
45{
46 PCOMPBATT_DEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
48 PAGED_CODE();
49 if (CompBattDebug & COMPBATT_DEBUG_TRACE) DbgPrint("CompBatt: ENTERING System Control\n");
50
51 /* Are we attached yet? */
52 if (DeviceExtension->AttachedDevice)
53 {
54 /* Send it up the stack */
56 Status = IoCallDriver(DeviceExtension->AttachedDevice, Irp);
57 }
58 else
59 {
60 /* We don't support WMI */
62 Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
64 }
65
66 /* Return status */
67 return Status;
68}
69
96{
97 PIO_STACK_LOCATION IoStackLocation;
98 PCOMPBATT_BATTERY_DATA BatteryData;
99
100 /* We do not care about the device object */
102
103 /* Grab the composite battery data from the I/O stack packet */
104 IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
105 BatteryData = IoStackLocation->Parameters.Others.Argument2;
106
107 /* Request the IRP complete worker to do the deed */
110}
111
123VOID
124NTAPI
126 _In_ PCOMPBATT_BATTERY_DATA BatteryData)
127{
129 PIRP Irp;
130 UCHAR Mode;
131 ULONG PrevPowerState;
134 PIO_STACK_LOCATION IoStackLocation;
135 PCOMPBATT_DEVICE_EXTENSION DeviceExtension;
136
137 /* Cache the necessary battery data */
138 Irp = BatteryData->Irp;
139 DeviceObject = BatteryData->DeviceObject;
140 IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
141 DeviceExtension = IoStackLocation->Parameters.Others.Argument1;
142
143 /* Switch to the next stack as we have to setup the control function data there */
144 IoStackLocation = IoGetNextIrpStackLocation(Irp);
145
146 /* Has the I/O composite battery request succeeded? */
147 Status = Irp->IoStatus.Status;
149 {
150 /*
151 * This battery is being removed from the composite, perform
152 * cleanups and do not inquire I/O requests again on this battery.
153 */
155 {
157 DbgPrint("CompBatt: Battery (0x%p) is being removed from composite battery\n", BatteryData);
158
159 IoFreeIrp(Irp);
160 CompBattRemoveBattery(&BatteryData->BatteryName, DeviceExtension);
161 return;
162 }
163
164 /*
165 * This is the first time a battery is being added into the composite
166 * (we understand that if Status was STATUS_DEVICE_NOT_CONNECTED).
167 * We must invalidate the composite tag and request a recalculation
168 * of the battery tag.
169 */
171 DbgPrint("CompBatt: Battery arrived for first time or disappeared (Status 0x%08lx)\n", Status);
172
173 BatteryData->Tag = BATTERY_TAG_INVALID;
174
175 /*
176 * Invalidate the last read status interrupt time as well since the last
177 * battery status data no longer applies. Same for the composite battery
178 * as well.
179 */
180 BatteryData->InterruptTime = 0;
181 DeviceExtension->InterruptTime = 0;
182
183 /* Notify Battery Class the battery status incurs in a change */
184 BatteryClassStatusNotify(DeviceExtension->ClassData);
185
186 /* Setup the necessary I/O data to query the battery tag */
187 IoStackLocation->Parameters.DeviceIoControl.IoControlCode = IOCTL_BATTERY_QUERY_TAG;
188 IoStackLocation->Parameters.DeviceIoControl.InputBufferLength = sizeof(ULONG);
189 IoStackLocation->Parameters.DeviceIoControl.OutputBufferLength = sizeof(ULONG);
190 BatteryData->Mode = COMPBATT_QUERY_TAG;
191 BatteryData->WorkerBuffer.WorkerTag = 0xFFFFFFFF;
192
193 /* Dispatch our request now to the battery's driver */
194 goto DispatchRequest;
195 }
196
197 /* Our I/O request has been completed successfully, check what did we get */
198 Mode = BatteryData->Mode;
199 switch (Mode)
200 {
202 {
203 /*
204 * This battery has just gotten a tag, acknowledge the composite battery
205 * about that so it can recalculate its own composite tag.
206 */
208 DbgPrint("CompBatt: Battery (Device 0x%p) has a tag of %lu\n", DeviceObject, BatteryData->WorkerBuffer.WorkerTag);
209
210 /* Ensure the battery tag is not bogus, getting a tag of 0 is illegal */
211 ASSERT(BatteryData->WorkerBuffer.WorkerTag != 0);
212
213 /* Assign the battery tag */
214 BatteryData->Tag = BatteryData->WorkerBuffer.WorkerTag;
215 BatteryData->Flags |= COMPBATT_TAG_ASSIGNED;
216
217 /* Punt the composite battery flags, as the previous cached data no longer applies */
218 DeviceExtension->Flags = 0;
219
220 /* Notify the Battery Class driver this battery has got a tag */
221 BatteryClassStatusNotify(DeviceExtension->ClassData);
222 break;
223 }
224
226 {
227 /*
228 * Read the battery status only if the IRP has not been cancelled,
229 * otherwise the request must be re-issued again. This typically
230 * happens if the wait values are in conflict which it might
231 * end up in inconsistent battery status results.
232 */
233 if (Status != STATUS_CANCELLED && !Irp->Cancel)
234 {
235 /*
236 * If we reach here then the battery has entered into a change of
237 * power state or its charge capacity has changed.
238 */
240 DbgPrint("CompBatt: Battery state (Device 0x%p) has changed\n", DeviceObject);
241
242 /* Copy the battery status of this battery */
243 RtlCopyMemory(&BatteryData->BatteryStatus,
244 &BatteryData->WorkerBuffer.WorkerStatus,
245 sizeof(BatteryData->BatteryStatus));
246
247 /* Update the interrupt time as this is the most recent read of the battery status */
248 BatteryData->InterruptTime = KeQueryInterruptTime();
249
250 /*
251 * Ensure we have not gotten unknown capacities while we waited for new
252 * battery status. The battery might have malfunctioned or something.
253 */
254 if (BatteryData->WorkerBuffer.WorkerStatus.Capacity == BATTERY_UNKNOWN_CAPACITY)
255 {
256 /* We do not know the capacity of this battery, default the low and high capacities */
257 BatteryData->WaitStatus.LowCapacity = BATTERY_UNKNOWN_CAPACITY;
258 BatteryData->WaitStatus.HighCapacity = BATTERY_UNKNOWN_CAPACITY;
259 }
260 else
261 {
262 /* We know the capacity, adjust the low and high capacities accordingly */
263 if (BatteryData->WaitStatus.LowCapacity >
264 BatteryData->WorkerBuffer.WorkerStatus.Capacity)
265 {
266 BatteryData->WaitStatus.LowCapacity = BatteryData->WorkerBuffer.WorkerStatus.Capacity;
267 }
268
269 if (BatteryData->WaitStatus.HighCapacity <
270 BatteryData->WorkerBuffer.WorkerStatus.Capacity)
271 {
272 BatteryData->WaitStatus.HighCapacity = BatteryData->WorkerBuffer.WorkerStatus.Capacity;
273 }
274 }
275
276 /* Copy the current last read power state for the next wait */
277 BatteryData->WaitStatus.PowerState = BatteryData->WorkerBuffer.WorkerStatus.PowerState;
278
279 /*
280 * Cache the previous power state of the composite battery and invalidate
281 * the last computed battery status interrupt time. This is because,
282 * logically, this specific battery incurred in a state change therefore
283 * the previous composite status is no longer consistent.
284 */
285 PrevPowerState = DeviceExtension->BatteryStatus.PowerState;
286 DeviceExtension->InterruptTime = 0;
287
288 /* Compute a new battery status for the composite battery */
289 Status = CompBattQueryStatus(DeviceExtension,
290 DeviceExtension->Tag,
292
293 /* Print out the current battery status of the composite to the debugger */
295 DbgPrint("CompBatt: Latest composite battery status\n"
296 " PowerState -> 0x%lx\n"
297 " Capacity -> %u\n"
298 " Voltage -> %u\n"
299 " Rate -> %d\n",
304
305 /*
306 * Now determine whether should we notify the Battery Class driver due to
307 * changes in power state settings in the composite battery. This could
308 * happen in two following conditions:
309 *
310 * 1. The status notify flag was set for the respective power notification
311 * settings, and the composite battery incurred in a change of such
312 * settings. In this case we have to probe the current settings that
313 * they have changed.
314 *
315 * 2. The status notify flag was not set, therefore we do not know the
316 * exact configuration of the notification settings. We only care that
317 * the power state has changed at this point.
318 *
319 * Why do we have to do this is because we have to warn the Battery Class
320 * about the data that has changed.
321 */
322 if (!(DeviceExtension->Flags & COMPBATT_STATUS_NOTIFY_SET))
323 {
324 if (PrevPowerState != DeviceExtension->BatteryStatus.PowerState)
325 {
326 /* The previous power state is no longer valid, notify Battery Class */
327 BatteryClassStatusNotify(DeviceExtension->ClassData);
328 }
329 }
330 else
331 {
332 /*
333 * Unlike the condition above, we check for power state change against
334 * the current notify wait set since the notify set flag bit is assigned.
335 */
336 if (DeviceExtension->WaitNotifyStatus.PowerState != DeviceExtension->BatteryStatus.PowerState ||
337 DeviceExtension->WaitNotifyStatus.LowCapacity > DeviceExtension->BatteryStatus.Capacity ||
338 DeviceExtension->WaitNotifyStatus.HighCapacity < DeviceExtension->BatteryStatus.Capacity)
339 {
340 /* The following configuration settings have changed, notify Battery Class */
341 BatteryClassStatusNotify(DeviceExtension->ClassData);
342 }
343 }
344 }
345
346 break;
347 }
348
349 default:
350 {
351 ASSERTMSG("CompBatt: BAD!!! WE SHOULD NOT BE HERE!\n", FALSE);
353 }
354 }
355
356 /* Setup the necessary data to read battery status */
357 BatteryData->WaitStatus.BatteryTag = BatteryData->Tag;
358 BatteryData->WaitStatus.Timeout = 3000; // FIXME: Hardcoded (wait for 3 seconds) because we do not have ACPI notifications implemented yet...
359
360 RtlCopyMemory(&BatteryData->WorkerBuffer.WorkerWaitStatus,
361 &BatteryData->WaitStatus,
362 sizeof(BatteryData->WaitStatus));
363
364 IoStackLocation->Parameters.DeviceIoControl.IoControlCode = IOCTL_BATTERY_QUERY_STATUS;
365 IoStackLocation->Parameters.DeviceIoControl.InputBufferLength = sizeof(BatteryData->WorkerBuffer.WorkerWaitStatus);
366 IoStackLocation->Parameters.DeviceIoControl.OutputBufferLength = sizeof(BatteryData->WorkerBuffer.WorkerStatus);
367 BatteryData->Mode = COMPBATT_READ_STATUS;
368
369DispatchRequest:
370 /* Setup the system buffer to that of the battery data which it will hold the returned data */
371 IoStackLocation->MajorFunction = IRP_MJ_DEVICE_CONTROL;
372 Irp->AssociatedIrp.SystemBuffer = &BatteryData->WorkerBuffer;
373 Irp->Cancel = FALSE;
374 Irp->PendingReturned = FALSE;
375
376 /* Setup the worker completion routine which it will invoke the worker later on */
379 NULL,
380 TRUE,
381 TRUE,
382 TRUE);
383
384 /* Dispatch the I/O request now */
386}
387
388VOID
389NTAPI
391 _In_ PCOMPBATT_DEVICE_EXTENSION DeviceExtension)
392{
393 PCOMPBATT_BATTERY_DATA BatteryData;
394 ULONG Tag;
395 PLIST_ENTRY ListHead, NextEntry;
396 if (CompBattDebug & COMPBATT_DEBUG_TRACE) DbgPrint("CompBatt: ENTERING CompBattRecalculateTag\n");
397
398 /* Loop the battery list */
399 ExAcquireFastMutex(&DeviceExtension->Lock);
400 ListHead = &DeviceExtension->BatteryList;
401 NextEntry = ListHead->Flink;
402 while (NextEntry != ListHead)
403 {
404 /* Get the battery information and check if it has a tag */
405 BatteryData = CONTAINING_RECORD(NextEntry, COMPBATT_BATTERY_DATA, BatteryLink);
406 if (BatteryData->Flags & COMPBATT_TAG_ASSIGNED)
407 {
408 /* Generate the next tag and exit */
409 Tag = DeviceExtension->NextTag;
410 DeviceExtension->Flags |= COMPBATT_TAG_ASSIGNED;
411 DeviceExtension->Tag = Tag;
412 DeviceExtension->NextTag = Tag + 1;
413 break;
414 }
415
416 /* No tag for this device extension, clear it */
417 DeviceExtension->Tag = BATTERY_TAG_INVALID;
418 NextEntry = NextEntry->Flink;
419 }
420
421 /* We're done */
422 ExReleaseFastMutex(&DeviceExtension->Lock);
423 if (CompBattDebug & COMPBATT_DEBUG_TRACE) DbgPrint("CompBatt: EXITING CompBattRecalculateTag\n");
424}
425
427NTAPI
430 _In_ PIRP Irp)
431{
432 PCOMPBATT_DEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
434 if (CompBattDebug & COMPBATT_DEBUG_TRACE) DbgPrint("CompBatt: ENTERING Ioctl\n");
435
436 /* Let the class driver handle it */
437 Status = BatteryClassIoctl(DeviceExtension->ClassData, Irp);
439 {
440 /* It failed, try the next driver up the stack */
441 Irp->IoStatus.Status = Status;
443 Status = IoCallDriver(DeviceExtension->AttachedDevice, Irp);
444 }
445
446 /* Return status */
447 if (CompBattDebug & COMPBATT_DEBUG_TRACE) DbgPrint("CompBatt: EXITING Ioctl\n");
448 return Status;
449}
450
452NTAPI
454 _In_ PCOMPBATT_DEVICE_EXTENSION DeviceExtension,
456{
458 PAGED_CODE();
459 if (CompBattDebug & COMPBATT_DEBUG_TRACE) DbgPrint("CompBatt: ENTERING QueryTag\n");
460
461 /* Was a tag assigned? */
462 if (!(DeviceExtension->Flags & COMPBATT_TAG_ASSIGNED))
463 {
464 /* Assign one */
465 CompBattRecalculateTag(DeviceExtension);
466 }
467
468 /* Do we have a tag now? */
469 if ((DeviceExtension->Flags & COMPBATT_TAG_ASSIGNED) && DeviceExtension->Tag != BATTERY_TAG_INVALID)
470 {
471 /* Return the tag */
472 *Tag = DeviceExtension->Tag;
474 }
475 else
476 {
477 /* No tag */
480 }
481
482 /* Return status */
483 if (CompBattDebug & COMPBATT_DEBUG_TRACE) DbgPrint("CompBatt: EXITING QueryTag\n");
484 return Status;
485}
486
488NTAPI
490 _In_ PCOMPBATT_DEVICE_EXTENSION DeviceExtension)
491{
492 PCOMPBATT_BATTERY_DATA BatteryData;
493 PLIST_ENTRY ListHead, NextEntry;
494 if (CompBattDebug & COMPBATT_DEBUG_TRACE) DbgPrint("CompBatt: ENTERING DisableStatusNotify\n");
495
496 /* Loop the battery list */
497 ExAcquireFastMutex(&DeviceExtension->Lock);
498 ListHead = &DeviceExtension->BatteryList;
499 NextEntry = ListHead->Flink;
500 while (NextEntry != ListHead)
501 {
502 /* Get the battery information and clear capacity data */
503 BatteryData = CONTAINING_RECORD(NextEntry, COMPBATT_BATTERY_DATA, BatteryLink);
504 BatteryData->WaitStatus.LowCapacity = 0;
505 BatteryData->WaitStatus.HighCapacity = 0x7FFFFFFF;
506 NextEntry = NextEntry->Flink;
507 }
508
509 /* Done */
510 ExReleaseFastMutex(&DeviceExtension->Lock);
511 if (CompBattDebug & COMPBATT_DEBUG_TRACE) DbgPrint("CompBatt: EXITING DisableStatusNotify\n");
512 return STATUS_SUCCESS;
513}
514
538static
541 _In_ PCOMPBATT_DEVICE_EXTENSION DeviceExtension,
542 _Out_ PULONG TotalRate,
543 _Out_ PULONG BatteriesCount)
544{
545 PCOMPBATT_BATTERY_DATA BatteryData;
546 PLIST_ENTRY ListHead, NextEntry;
547 BOOLEAN BadBattery = FALSE;
548 ULONG LinkedBatteries = 0;
549 ULONG BadBatteriesCount = 0;
550 ULONG ComputedRate = 0;
551
552 /* Loop over the linked batteries and sum up the total capacity rate */
553 ExAcquireFastMutex(&DeviceExtension->Lock);
554 ListHead = &DeviceExtension->BatteryList;
555 for (NextEntry = ListHead->Flink;
556 NextEntry != ListHead;
557 NextEntry = NextEntry->Flink)
558 {
559 /* Acquire the remove lock so this battery does not disappear under us */
560 BatteryData = CONTAINING_RECORD(NextEntry, COMPBATT_BATTERY_DATA, BatteryLink);
561 if (!NT_SUCCESS(IoAcquireRemoveLock(&BatteryData->RemoveLock, BatteryData->Irp)))
562 continue;
563
564 /*
565 * Ensure this battery has a valid tag and that its rate capacity
566 * is not unknown. Reject unknown rates when calculating the total rate.
567 */
568 if ((BatteryData->Tag != BATTERY_TAG_INVALID) &&
569 (BatteryData->BatteryStatus.Rate != BATTERY_UNKNOWN_RATE))
570 {
571 /*
572 * Now the ultimate judgement for this battery is to determine
573 * if the battery behaves optimally based on its current power
574 * state it is and the rate flow of the battery.
575 *
576 * If the rate flow is positive the battery is receiving power
577 * which increases the chemical potential energy as electrons
578 * move around, THIS MEANS the battery is CHARGING. If the rate
579 * flow is negative the battery cells are producing way less
580 * electrical energy, thus the battery is DISCHARGING.
581 *
582 * A consistent battery is a battery of which power state matches
583 * the rate flow. If that were the case, then we have found a bad
584 * battery. The worst case is that a battery is physically damanged.
585 */
586 if ((BatteryData->BatteryStatus.PowerState & BATTERY_DISCHARGING) &&
587 (BatteryData->BatteryStatus.Rate >= 0))
588 {
590 DbgPrint("CompBatt: The battery is discharging but in reality it is charging... (Rate %d)\n",
591 BatteryData->BatteryStatus.Rate);
592
593 BadBattery = TRUE;
594 BadBatteriesCount++;
595 }
596
597 if ((BatteryData->BatteryStatus.PowerState & BATTERY_CHARGING) &&
598 (BatteryData->BatteryStatus.Rate <= 0))
599 {
601 DbgPrint("CompBatt: The battery is charging but in reality it is discharging... (Rate %d)\n",
602 BatteryData->BatteryStatus.Rate);
603
604 BadBattery = TRUE;
605 BadBatteriesCount++;
606 }
607
608 if (((BatteryData->BatteryStatus.PowerState & (BATTERY_CHARGING | BATTERY_DISCHARGING)) == 0) &&
609 (BatteryData->BatteryStatus.Rate != 0))
610 {
612 DbgPrint("CompBatt: The battery is neither charging or discharging but has a contradicting rate... (Rate %d)\n",
613 BatteryData->BatteryStatus.Rate);
614
615 BadBattery = TRUE;
616 BadBatteriesCount++;
617 }
618
619 /*
620 * Sum up the rate of this battery to make up the total, even if that means
621 * the battery may have incosistent rate. This is because it is still a linked
622 * battery to the composite battery and it is used to power up the system nonetheless.
623 */
624 ComputedRate += BatteryData->BatteryStatus.Rate;
625 }
626
627 /* We are done with this individual battery */
628 LinkedBatteries++;
629 IoReleaseRemoveLock(&BatteryData->RemoveLock, BatteryData->Irp);
630 }
631
632 /* Release the lock as we are no longer poking through the batteries list */
633 ExReleaseFastMutex(&DeviceExtension->Lock);
634
635 /* Print out the total count of bad batteries we have found */
636 if (BadBatteriesCount > 0)
637 {
639 DbgPrint("CompBatt: %lu bad batteries have been found!\n", BadBatteriesCount);
640 }
641
642 *TotalRate = ComputedRate;
643 *BatteriesCount = LinkedBatteries;
644 return BadBattery;
645}
646
675NTAPI
677 _In_ PCOMPBATT_DEVICE_EXTENSION DeviceExtension,
680{
682 BOOLEAN BadBattery;
683 ULONG TotalRate;
684 ULONG BatteriesCount;
685 ULONG HighestCapacity;
686 ULONG LowCapDifference, HighCapDifference, LowDelta, HighDelta;
688 PCOMPBATT_BATTERY_DATA BatteryData;
689 PLIST_ENTRY ListHead, NextEntry;
690
691 /*
692 * The caller wants to set new status notification settings but the composite
693 * battery does not have a valid tag assigned, or the tag does not actually match.
694 */
695 if (!(DeviceExtension->Flags & COMPBATT_TAG_ASSIGNED) ||
696 (DeviceExtension->Tag != BatteryTag))
697 {
699 DbgPrint("CompBatt: Composite battery tag not assigned or not matching (Tag -> %lu, Composite Tag -> %lu)\n",
700 BatteryTag, DeviceExtension->Tag);
701
703 }
704
705 /*
706 * Before we are setting up new status wait notification points we need to
707 * refresh the composite status so that we get to know what values should be
708 * set for the current notification wait status.
709 */
710 Status = CompBattQueryStatus(DeviceExtension,
713 if (!NT_SUCCESS(Status))
714 {
716 DbgPrint("CompBatt: Failed to refresh composite battery's status (Status 0x%08lx)\n", Status);
717
718 return Status;
719 }
720
721 /* Print out battery status data that has been polled */
723 DbgPrint("CompBatt: Latest composite battery status (when setting notify status)\n"
724 " PowerState -> 0x%lx\n"
725 " Capacity -> %u\n"
726 " Voltage -> %u\n"
727 " Rate -> %d\n",
732
733 /* Calculate the high and low capacity differences based on the real summed capacity of the composite */
734 LowCapDifference = DeviceExtension->BatteryStatus.Capacity - BatteryNotify->LowCapacity;
735 HighCapDifference = BatteryNotify->HighCapacity - DeviceExtension->BatteryStatus.Capacity;
736
737 /* Cache the notification parameters provided for later usage when polling for battery status */
738 DeviceExtension->WaitNotifyStatus.PowerState = BatteryNotify->PowerState;
739 DeviceExtension->WaitNotifyStatus.LowCapacity = BatteryNotify->LowCapacity;
740 DeviceExtension->WaitNotifyStatus.HighCapacity = BatteryNotify->HighCapacity;
741
742 /* Toggle the valid notify flag as these are the newer notification settings */
743 DeviceExtension->Flags |= COMPBATT_STATUS_NOTIFY_SET;
744
745 /*
746 * Get the number of currently linked batteries to composite and total rate,
747 * we will use these counters later to determine the wait values for each
748 * individual battery.
749 */
750 BadBattery = CompBattCalculateTotalRateAndLinkedBatteries(DeviceExtension,
751 &TotalRate,
752 &BatteriesCount);
753
754 /*
755 * Of course we have to be sure that we have at least one battery linked
756 * with the composite battery at this time of getting invoked to set new
757 * notification wait settings.
758 */
759 ASSERT(BatteriesCount != 0);
760
761 /* Walk over the linked batteries list and set up new wait configuration settings */
762 ExAcquireFastMutex(&DeviceExtension->Lock);
763 ListHead = &DeviceExtension->BatteryList;
764 for (NextEntry = ListHead->Flink;
765 NextEntry != ListHead;
766 NextEntry = NextEntry->Flink)
767 {
768 /* Acquire the remove lock so this battery does not disappear under us */
769 BatteryData = CONTAINING_RECORD(NextEntry, COMPBATT_BATTERY_DATA, BatteryLink);
770 if (!NT_SUCCESS(IoAcquireRemoveLock(&BatteryData->RemoveLock, BatteryData->Irp)))
771 continue;
772
773 /* Now release the device lock since the battery can't go away */
774 ExReleaseFastMutex(&DeviceExtension->Lock);
775
776 /* Make sure this battery has a tag before setting new wait values */
777 if (BatteryData->Tag != BATTERY_TAG_INVALID)
778 {
779 /*
780 * And also make sure this battery does not have an unknown
781 * capacity, we cannot set up new configuration wait settings
782 * based on that. Default the low and high wait capacities.
783 */
785 {
786 /*
787 * Calculate the low capacity wait setting. If at least one
788 * bad battery was found while we computed the total composite
789 * rate, then divide the difference between the total batteries.
790 * Otherwise compute the battery deltas of the composite based
791 * on total summed capacity rate. Otherwise if the total rate
792 * is 0, then the real wait low and high capacities will be on
793 * par with the real capacity.
794 */
795 if (BadBattery)
796 {
797 LowDelta = LowCapDifference / BatteriesCount;
798 HighDelta = HighCapDifference / BatteriesCount;
799 }
800 else
801 {
802 if (TotalRate)
803 {
804 LowDelta = COMPUTE_BATT_CAP_DELTA(LowCapDifference, BatteryData, TotalRate);
805 HighDelta = COMPUTE_BATT_CAP_DELTA(HighCapDifference, BatteryData, TotalRate);
806 }
807 else
808 {
809 LowDelta = 0;
810 HighDelta = 0;
811 }
812 }
813
814 /*
815 * Assign the wait low capacity setting ONLY if the battery delta
816 * is not high. Otherwise it has overflowed and we cannot use that
817 * for low capacity, of which we have to default it to 0.
818 */
819 if (BatteryData->BatteryStatus.Capacity > LowDelta)
820 {
821 BatteryData->WaitStatus.LowCapacity = BatteryData->BatteryStatus.Capacity - LowDelta;
822 }
823 else
824 {
826 }
827
828 /*
829 * Assign the wait high capacity setting ONLY if the real capacity
830 * is not above the maximum highest capacity constant.
831 */
832 HighestCapacity = COMPBATT_WAIT_MAX_HIGH_CAPACITY - HighDelta;
833 if (HighestCapacity < BatteryData->BatteryStatus.Capacity)
834 {
835 BatteryData->WaitStatus.HighCapacity = HighestCapacity;
836 }
837 else
838 {
839 BatteryData->WaitStatus.HighCapacity = BatteryData->BatteryStatus.Capacity + HighDelta;
840 }
841
842 /*
843 * We have set up the wait values but they are in conflict with the
844 * ones set up by the IRP complete worker. We have to cancel the IRP
845 * so the worker will copy our wait configuration values.
846 */
847 if ((BatteryData->Mode == COMPBATT_READ_STATUS) &&
848 (BatteryData->WaitStatus.PowerState != BatteryData->WorkerBuffer.WorkerWaitStatus.PowerState ||
849 BatteryData->WaitStatus.LowCapacity != BatteryData->WorkerBuffer.WorkerWaitStatus.LowCapacity ||
851 {
853 DbgPrint("CompBatt: Configuration wait values are in conflict\n"
854 " BatteryData->WaitStatus.PowerState -> 0x%lx\n"
855 " BatteryData->WorkerBuffer.WorkerWaitStatus.PowerState -> 0x%lx\n"
856 " BatteryData->WaitStatus.LowCapacity -> %u\n"
857 " BatteryData->WorkerBuffer.WorkerWaitStatus.LowCapacity -> %u\n"
858 " BatteryData->WaitStatus.HighCapacity -> %u\n"
859 " BatteryData->WorkerBuffer.WorkerWaitStatus.HighCapacity -> %u\n",
860 BatteryData->WaitStatus.PowerState,
862 BatteryData->WaitStatus.LowCapacity,
864 BatteryData->WaitStatus.HighCapacity,
866
867 IoCancelIrp(BatteryData->Irp);
868 }
869 }
870 else
871 {
874 }
875 }
876
877 /* We are done with this battery */
878 ExAcquireFastMutex(&DeviceExtension->Lock);
879 IoReleaseRemoveLock(&BatteryData->RemoveLock, BatteryData->Irp);
880 }
881
882 /* Release the lock as we are no longer poking through the batteries list */
883 ExReleaseFastMutex(&DeviceExtension->Lock);
884
885 /* Ensure the composite battery did not incur in drastic changes of tag */
886 if (!(DeviceExtension->Flags & COMPBATT_TAG_ASSIGNED) ||
887 (DeviceExtension->Tag != BatteryTag))
888 {
889 /*
890 * Either the last battery was removed (in this case the composite is no
891 * longer existing) or a battery was removed of which the whole battery
892 * information must be recomputed and such.
893 */
895 DbgPrint("CompBatt: Last battery or a battery was removed, the whole composite data must be recomputed\n");
896
898 }
899
900 return STATUS_SUCCESS;
901}
902
931NTAPI
933 _In_ PCOMPBATT_DEVICE_EXTENSION DeviceExtension,
934 _In_ ULONG Tag,
936{
937 PCOMPBATT_BATTERY_DATA BatteryData;
939 PLIST_ENTRY ListHead, NextEntry;
940 ULONGLONG LastReadTime, CurrentReadTime;
942
943 /*
944 * The caller wants to update the composite battery status but the composite
945 * itself does not have a valid tag assigned, or the tag does not actually match.
946 */
947 if (!(DeviceExtension->Flags & COMPBATT_TAG_ASSIGNED) ||
948 (DeviceExtension->Tag != Tag))
949 {
951 DbgPrint("CompBatt: Composite battery tag not assigned or not matching (Tag -> %lu, Composite Tag -> %lu)\n",
952 Tag, DeviceExtension->Tag);
953
955 }
956
957 /* Initialize the status and wait fields with zeros */
959 RtlZeroMemory(&Wait, sizeof(Wait));
960
961 /*
962 * The battery status was already updated when the caller queried for new
963 * status. We do not need to update the status again for no reason.
964 * Just give them the data outright.
965 */
966 CurrentReadTime = KeQueryInterruptTime();
967 LastReadTime = CurrentReadTime - DeviceExtension->InterruptTime;
968 if (LastReadTime < COMPBATT_FRESH_STATUS_TIME)
969 {
971 DbgPrint("CompBatt: Composite battery status data is fresh, no need to update it again\n");
972
973 RtlCopyMemory(BatteryStatus, &DeviceExtension->BatteryStatus, sizeof(BATTERY_STATUS));
974 return STATUS_SUCCESS;
975 }
976
977 /*
978 * Initialize the battery status context with unknown defaults, until we get
979 * to retrieve the real data from each battery and compute the exact status.
980 * Assume the system is powered by AC source for now until we find out it is
981 * not the case.
982 */
987
988 /* Iterate over all the present linked batteries and retrieve their status */
989 ExAcquireFastMutex(&DeviceExtension->Lock);
990 ListHead = &DeviceExtension->BatteryList;
991 for (NextEntry = ListHead->Flink;
992 NextEntry != ListHead;
993 NextEntry = NextEntry->Flink)
994 {
995 /* Acquire the remove lock so this battery does not disappear under us */
996 BatteryData = CONTAINING_RECORD(NextEntry, COMPBATT_BATTERY_DATA, BatteryLink);
997 if (!NT_SUCCESS(IoAcquireRemoveLock(&BatteryData->RemoveLock, BatteryData->Irp)))
998 continue;
999
1000 /* Now release the device lock since the battery can't go away */
1001 ExReleaseFastMutex(&DeviceExtension->Lock);
1002
1003 /* Setup the battery tag for the status wait which is needed to send off the IOCTL */
1004 Wait.BatteryTag = BatteryData->Tag;
1005
1006 /* Make sure this battery has a tag before we send off the IOCTL */
1007 if (BatteryData->Tag != BATTERY_TAG_INVALID)
1008 {
1009 /* Only query new battery status data if it is no longer fresh */
1010 LastReadTime = CurrentReadTime - BatteryData->InterruptTime;
1011 if (LastReadTime > COMPBATT_FRESH_STATUS_TIME)
1012 {
1013 RtlZeroMemory(&BatteryData->BatteryStatus,
1014 sizeof(BatteryData->BatteryStatus));
1016 BatteryData->DeviceObject,
1017 &Wait,
1018 sizeof(Wait),
1019 &BatteryData->BatteryStatus,
1020 sizeof(BatteryData->BatteryStatus),
1021 FALSE);
1022 if (!NT_SUCCESS(Status))
1023 {
1024 /*
1025 * If the device is being suddenly removed then we must invalidate
1026 * both this battery and composite tags.
1027 */
1029 {
1031 }
1032
1033 ExAcquireFastMutex(&DeviceExtension->Lock);
1034 IoReleaseRemoveLock(&BatteryData->RemoveLock, BatteryData->Irp);
1035 break;
1036 }
1037
1038 /* Update the timestamp of the current read of battery status */
1039 BatteryData->InterruptTime = CurrentReadTime;
1040 }
1041
1042 /*
1043 * Now it is time to combine the data into the composite status.
1044 * The battery is either charging or discharging. AC is present
1045 * only if the charger supplies current to all batteries. And
1046 * the composite is deemed as critical if at least one battery
1047 * is discharging and it is in crtitical state.
1048 */
1050 BatteryStatus->PowerState &= (BatteryData->BatteryStatus.PowerState | ~BATTERY_POWER_ON_LINE);
1051 if ((BatteryData->BatteryStatus.PowerState & BATTERY_CRITICAL) &&
1053 {
1055 }
1056
1057 /* Add up the battery capacity if it is not unknown */
1059 {
1061 {
1063 }
1064 else
1065 {
1067 }
1068 }
1069
1070 /* Always pick up the greatest voltage for the composite battery */
1071 if (BatteryData->BatteryStatus.Voltage != BATTERY_UNKNOWN_VOLTAGE)
1072 {
1074 {
1076 BatteryData->BatteryStatus.Voltage);
1077 }
1078 else
1079 {
1081 }
1082 }
1083
1084 /* Add up the battery discharge rate if it is not unknown */
1085 if (BatteryData->BatteryStatus.Rate != BATTERY_UNKNOWN_RATE)
1086 {
1088 {
1089 BatteryStatus->Rate += BatteryData->BatteryStatus.Rate;
1090 }
1091 else
1092 {
1093 BatteryStatus->Rate = BatteryData->BatteryStatus.Rate;
1094 }
1095 }
1096 }
1097
1098 /* We are done combining data from this battery */
1099 ExAcquireFastMutex(&DeviceExtension->Lock);
1100 IoReleaseRemoveLock(&BatteryData->RemoveLock, BatteryData->Irp);
1101 }
1102
1103 /* Release the lock as we are no longer poking through the batteries list */
1104 ExReleaseFastMutex(&DeviceExtension->Lock);
1105
1106 /* Ensure the composite battery did not incur in drastic changes of tag */
1107 if (!(DeviceExtension->Flags & COMPBATT_TAG_ASSIGNED) ||
1108 (DeviceExtension->Tag != Tag))
1109 {
1110 /*
1111 * Either the last battery was removed (in this case the composite is no
1112 * longer existing) or a battery was removed of which the whole battery
1113 * information must be recomputed and such.
1114 */
1116 DbgPrint("CompBatt: Last battery or a battery was removed, the whole composite data must be recomputed\n");
1117
1118 return STATUS_NO_SUCH_DEVICE;
1119 }
1120
1121 /*
1122 * If there is a battery that is charging while another one discharging,
1123 * then tell the caller the composite battery is actually discharging.
1124 * This is less likely to happen on a multi-battery system like laptops
1125 * as the charger would provide electricity to all the batteries.
1126 * Perhaps the most likely case scenario would be if the system were
1127 * to be powered by a UPS.
1128 */
1131 {
1132 BatteryStatus->PowerState &= ~BATTERY_CHARGING;
1133 }
1134
1135 /* Copy the combined status information to the composite battery */
1136 if (NT_SUCCESS(Status))
1137 {
1138 RtlCopyMemory(&DeviceExtension->BatteryStatus,
1140 sizeof(DeviceExtension->BatteryStatus));
1141
1142 /* Update the last read battery status timestamp as well */
1143 DeviceExtension->InterruptTime = CurrentReadTime;
1144 }
1145
1146 return Status;
1147}
1148
1150NTAPI
1152 _Out_ PBATTERY_INFORMATION BatteryInfo,
1153 _In_ PCOMPBATT_DEVICE_EXTENSION DeviceExtension)
1154{
1157 PCOMPBATT_BATTERY_DATA BatteryData;
1158 PLIST_ENTRY ListHead, NextEntry;
1159 if (CompBattDebug & COMPBATT_DEBUG_TRACE) DbgPrint("CompBatt: ENTERING GetBatteryInformation\n");
1160
1161 /* Set defaults */
1162 BatteryInfo->DefaultAlert1 = 0;
1163 BatteryInfo->DefaultAlert2 = 0;
1164 BatteryInfo->CriticalBias = 0;
1165
1166 /* Loop the battery list */
1167 ExAcquireFastMutex(&DeviceExtension->Lock);
1168 ListHead = &DeviceExtension->BatteryList;
1169 NextEntry = ListHead->Flink;
1170 while (NextEntry != ListHead)
1171 {
1172 /* Try to acquire the remove lock */
1173 BatteryData = CONTAINING_RECORD(NextEntry, COMPBATT_BATTERY_DATA, BatteryLink);
1174 if (NT_SUCCESS(IoAcquireRemoveLock(&BatteryData->RemoveLock, BatteryData->Irp)))
1175 {
1176 /* Now release the device lock since the battery can't go away */
1177 ExReleaseFastMutex(&DeviceExtension->Lock);
1178
1179 /* Build the query */
1180 InputBuffer.BatteryTag = BatteryData->Tag;
1181 InputBuffer.InformationLevel = BatteryInformation;
1182 InputBuffer.AtRate = 0;
1183
1184 /* Make sure the battery has a tag */
1185 if (BatteryData->Tag != BATTERY_TAG_INVALID)
1186 {
1187 /* Do we already have the data? */
1188 if (!(BatteryData->Flags & COMPBATT_BATTERY_INFORMATION_PRESENT))
1189 {
1190 /* Send the IOCTL to query the information */
1191 RtlZeroMemory(&BatteryData->BatteryInformation,
1192 sizeof(BatteryData->BatteryInformation));
1194 BatteryData->DeviceObject,
1195 &InputBuffer,
1196 sizeof(InputBuffer),
1197 &BatteryData->BatteryInformation,
1198 sizeof(BatteryData->BatteryInformation),
1199 FALSE);
1200 if (!NT_SUCCESS(Status))
1201 {
1202 /* Fail if the query had a problem */
1204 ExAcquireFastMutex(&DeviceExtension->Lock);
1205 IoReleaseRemoveLock(&BatteryData->RemoveLock, BatteryData->Irp);
1206 break;
1207 }
1208
1209 /* Next time we can use the static copy */
1212 DbgPrint("CompBattGetBatteryInformation: Read individual BATTERY_INFORMATION\n"
1213 "-------- Capabilities = %x\n-------- Technology = %x\n"
1214 "-------- Chemistry[4] = %x\n-------- DesignedCapacity = %x\n"
1215 "-------- FullChargedCapacity = %x\n-------- DefaultAlert1 = %x\n"
1216 "-------- DefaultAlert2 = %x\n-------- CriticalBias = %x\n"
1217 "-------- CycleCount = %x\n",
1218 BatteryData->BatteryInformation.Capabilities,
1219 BatteryData->BatteryInformation.Technology,
1220 BatteryData->BatteryInformation.Chemistry,
1223 BatteryData->BatteryInformation.DefaultAlert1,
1224 BatteryData->BatteryInformation.DefaultAlert2,
1225 BatteryData->BatteryInformation.CriticalBias,
1226 BatteryData->BatteryInformation.CycleCount);
1227 }
1228
1229 /* Combine capabilities */
1230 BatteryInfo->Capabilities |= BatteryData->BatteryInformation.Capabilities;
1231
1232 /* Add-on capacity */
1234 {
1235 BatteryInfo->DesignedCapacity += BatteryData->BatteryInformation.DesignedCapacity;
1236 }
1237
1238 /* Add on fully charged capacity */
1240 {
1241 BatteryInfo->FullChargedCapacity += BatteryData->BatteryInformation.FullChargedCapacity;
1242 }
1243
1244 /* Choose the highest alert */
1245 BatteryInfo->DefaultAlert1 = max(BatteryInfo->DefaultAlert1,
1246 BatteryData->BatteryInformation.DefaultAlert1);
1247
1248 /* Choose the highest alert */
1249 BatteryInfo->DefaultAlert2 = max(BatteryInfo->DefaultAlert2,
1250 BatteryData->BatteryInformation.DefaultAlert2);
1251
1252 /* Choose the highest critical bias */
1253 BatteryInfo->CriticalBias = max(BatteryInfo->CriticalBias,
1254 BatteryData->BatteryInformation.CriticalBias);
1255 }
1256
1257 /* Re-acquire the device extension lock and release the remove lock */
1258 ExAcquireFastMutex(&DeviceExtension->Lock);
1259 IoReleaseRemoveLock(&BatteryData->RemoveLock, BatteryData->Irp);
1260 }
1261
1262 /* Next entry */
1263 NextEntry = NextEntry->Flink;
1264 }
1265
1266 /* We are done with the list, check if the information was queried okay */
1267 ExReleaseFastMutex(&DeviceExtension->Lock);
1268 if (NT_SUCCESS(Status))
1269 {
1270 /* If there's no fully charged capacity, use the design capacity */
1271 if (!BatteryInfo->FullChargedCapacity)
1272 {
1273 BatteryInfo->FullChargedCapacity = BatteryInfo->DesignedCapacity;
1274 }
1275
1276 /* Print out final combined data */
1278 DbgPrint("CompBattGetBatteryInformation: Returning BATTERY_INFORMATION\n"
1279 "-------- Capabilities = %x\n-------- Technology = %x\n"
1280 "-------- Chemistry[4] = %x\n-------- DesignedCapacity = %x\n"
1281 "-------- FullChargedCapacity = %x\n-------- DefaultAlert1 = %x\n"
1282 "-------- DefaultAlert2 = %x\n-------- CriticalBias = %x\n"
1283 "-------- CycleCount = %x\n",
1284 BatteryInfo->Capabilities,
1285 BatteryInfo->Technology,
1286 BatteryInfo->Chemistry,
1287 BatteryInfo->DesignedCapacity,
1288 BatteryInfo->FullChargedCapacity,
1289 BatteryInfo->DefaultAlert1,
1290 BatteryInfo->DefaultAlert2,
1291 BatteryInfo->CriticalBias,
1292 BatteryInfo->CycleCount);
1293
1294 /* Copy the data into the device extension */
1295 RtlCopyMemory(&DeviceExtension->BatteryInformation,
1296 BatteryInfo,
1297 sizeof(DeviceExtension->BatteryInformation));
1298 DeviceExtension->Flags |= COMPBATT_BATTERY_INFORMATION_PRESENT;
1299 }
1300
1301 /* We are done */
1302 if (CompBattDebug & COMPBATT_DEBUG_TRACE) DbgPrint("CompBatt: EXITING GetBatteryInformation\n");
1303 return Status;
1304}
1305
1307NTAPI
1309 _Out_ PBATTERY_REPORTING_SCALE ReportingScale,
1310 _In_ PCOMPBATT_DEVICE_EXTENSION DeviceExtension)
1311{
1314 PCOMPBATT_BATTERY_DATA BatteryData;
1315 BATTERY_REPORTING_SCALE BatteryScale[4];
1316 PLIST_ENTRY ListHead, NextEntry;
1317 ULONG i;
1318 if (CompBattDebug & COMPBATT_DEBUG_TRACE) DbgPrint("CompBatt: ENTERING GetBatteryGranularity\n");
1319
1320 /* Set defaults */
1321 ReportingScale[0].Granularity = -1;
1322 ReportingScale[1].Granularity = -1;
1323 ReportingScale[2].Granularity = -1;
1324 ReportingScale[3].Granularity = -1;
1325
1326 /* Loop the battery list */
1327 ExAcquireFastMutex(&DeviceExtension->Lock);
1328 ListHead = &DeviceExtension->BatteryList;
1329 NextEntry = ListHead->Flink;
1330 while (NextEntry != ListHead)
1331 {
1332 /* Try to acquire the remove lock */
1333 BatteryData = CONTAINING_RECORD(NextEntry, COMPBATT_BATTERY_DATA, BatteryLink);
1334 if (NT_SUCCESS(IoAcquireRemoveLock(&BatteryData->RemoveLock, BatteryData->Irp)))
1335 {
1336 /* Now release the device lock since the battery can't go away */
1337 ExReleaseFastMutex(&DeviceExtension->Lock);
1338
1339 /* Build the query */
1340 InputBuffer.BatteryTag = BatteryData->Tag;
1341 InputBuffer.InformationLevel = BatteryGranularityInformation;
1342
1343 /* Make sure the battery has a tag */
1344 if (BatteryData->Tag != BATTERY_TAG_INVALID)
1345 {
1346 /* Send the IOCTL to query the information */
1347 RtlZeroMemory(&BatteryData->BatteryInformation,
1348 sizeof(BatteryData->BatteryInformation));
1350 BatteryData->DeviceObject,
1351 &InputBuffer,
1352 sizeof(InputBuffer),
1353 &BatteryScale,
1354 sizeof(BatteryScale),
1355 FALSE);
1356 if (!NT_SUCCESS(Status))
1357 {
1358 /* Fail if the query had a problem */
1359 ExAcquireFastMutex(&DeviceExtension->Lock);
1360 IoReleaseRemoveLock(&BatteryData->RemoveLock, BatteryData->Irp);
1361 break;
1362 }
1363
1364 /* Loop all 4 scales */
1365 for (i = 0; i < 4; i++)
1366 {
1367 /* Check for valid granularity */
1368 if (BatteryScale[i].Granularity)
1369 {
1370 /* If it's smaller, use it instead */
1371 ReportingScale[i].Granularity = min(BatteryScale[i].Granularity,
1372 ReportingScale[i].Granularity);
1373 }
1374
1375 }
1376 }
1377
1378 /* Re-acquire the device extension lock and release the remove lock */
1379 ExAcquireFastMutex(&DeviceExtension->Lock);
1380 IoReleaseRemoveLock(&BatteryData->RemoveLock, BatteryData->Irp);
1381 }
1382
1383 /* Next entry */
1384 NextEntry = NextEntry->Flink;
1385 }
1386
1387 /* All done */
1388 ExReleaseFastMutex(&DeviceExtension->Lock);
1389 if (CompBattDebug & COMPBATT_DEBUG_TRACE) DbgPrint("CompBatt: EXITING GetBatteryGranularity\n");
1390 return STATUS_SUCCESS;
1391}
1392
1407static
1408LONG
1410 _In_ PCOMPBATT_DEVICE_EXTENSION DeviceExtension)
1411{
1413 PCOMPBATT_BATTERY_DATA BatteryData;
1414 BATTERY_QUERY_INFORMATION QueryInformation;
1415 PLIST_ENTRY ListHead, NextEntry;
1416 ULONG Time;
1417 LONG ComputedAtRate = 0;
1418
1419 /* Walk over the linked batteries list to poll for "At Rate" value of each battery */
1420 ExAcquireFastMutex(&DeviceExtension->Lock);
1421 ListHead = &DeviceExtension->BatteryList;
1422 for (NextEntry = ListHead->Flink;
1423 NextEntry != ListHead;
1424 NextEntry = NextEntry->Flink)
1425 {
1426 /* Acquire the remove lock so this battery does not disappear under us */
1427 BatteryData = CONTAINING_RECORD(NextEntry, COMPBATT_BATTERY_DATA, BatteryLink);
1428 if (!NT_SUCCESS(IoAcquireRemoveLock(&BatteryData->RemoveLock, BatteryData->Irp)))
1429 continue;
1430
1431 /* Now release the device lock since the battery can't go away */
1432 ExReleaseFastMutex(&DeviceExtension->Lock);
1433
1434 /* Build the necessary information in order to query the battery estimated time */
1435 QueryInformation.BatteryTag = BatteryData->Tag;
1436 QueryInformation.InformationLevel = BatteryEstimatedTime;
1437 QueryInformation.AtRate = 0;
1438
1439 /* Make sure this battery has a valid tag before issuing the IOCTL */
1440 if (BatteryData->Tag != BATTERY_TAG_INVALID)
1441 {
1442 /*
1443 * Now it is time to issue the IOCTL to the battery device.
1444 * We are calculating the "At Rate" counter based on each linked
1445 * battery that is discharging, one at a time. This ensures
1446 * that when we will actually retrieve the estimation time of each
1447 * individual battery and sum it all up as one time for the composite
1448 * battery, that the estimated time is accurate enough.
1449 */
1451 BatteryData->DeviceObject,
1452 &QueryInformation,
1453 sizeof(QueryInformation),
1454 &Time,
1455 sizeof(Time),
1456 FALSE);
1457 if (NT_SUCCESS(Status))
1458 {
1459 if ((Time != 0) && (Time != BATTERY_UNKNOWN_TIME))
1460 {
1461 ComputedAtRate -= COMPUTE_ATRATE_DRAIN(BatteryData, Time);
1462 }
1463 }
1464 }
1465
1466 /* We are done with this battery */
1467 ExAcquireFastMutex(&DeviceExtension->Lock);
1468 IoReleaseRemoveLock(&BatteryData->RemoveLock, BatteryData->Irp);
1469 }
1470
1471 /* Release the lock as we are no longer poking through the batteries list */
1472 ExReleaseFastMutex(&DeviceExtension->Lock);
1473 return ComputedAtRate;
1474}
1475
1499NTAPI
1502 _In_ PCOMPBATT_DEVICE_EXTENSION DeviceExtension)
1503{
1505 PCOMPBATT_BATTERY_DATA BatteryData;
1507 BATTERY_QUERY_INFORMATION QueryInformation;
1508 PLIST_ENTRY ListHead, NextEntry;
1509 ULONG ReturnedTime;
1510 LONG ComputedAtRate;
1511
1512 /* Assume the battery time is not estimated yet */
1514
1515 /*
1516 * Before we are querying the composite estimated battery time we must
1517 * refresh the battery status cache if we have not done it so.
1518 */
1519 Status = CompBattQueryStatus(DeviceExtension,
1520 DeviceExtension->Tag,
1521 &BatteryStatus);
1522 if (!NT_SUCCESS(Status))
1523 {
1525 DbgPrint("CompBatt: Failed to refresh composite battery's status (Status 0x%08lx)\n", Status);
1526
1527 return Status;
1528 }
1529
1530 /* Print out battery status data that has been polled */
1532 DbgPrint("CompBatt: Latest composite battery status (when querying for estimated time)\n"
1533 " PowerState -> 0x%lx\n"
1534 " Capacity -> %u\n"
1535 " Voltage -> %u\n"
1536 " Rate -> %d\n",
1541
1542 /*
1543 * If the batteries are not being discharged and the system is directly
1544 * being powered by external AC source then it makes no sense to
1545 * compute the battery estimated time because that construct is for
1546 * WHEN the system is powered directly from batteries and it drains power.
1547 */
1548 if (DeviceExtension->BatteryStatus.PowerState & BATTERY_POWER_ON_LINE)
1549 {
1551 {
1552 DbgPrint("CompBatt: The system is powered by AC source, estimated time is not available\n");
1553 }
1554
1555 return STATUS_SUCCESS;
1556 }
1557
1558 /* Determine the draining "At Rate" counter for all batteries */
1559 ComputedAtRate = CompBattCalculateAtRateTime(DeviceExtension);
1560
1561 /*
1562 * A rate of 0 indicates none of the batteries that are linked with
1563 * the composite are being drained therefore we cannot estimate the
1564 * run time of the composite as it is not discharging.
1565 */
1566 if (ComputedAtRate == 0)
1567 {
1569 DbgPrint("CompBatt: No battery is discharging and no power is being drained, cannot estimate the run time\n");
1570
1571 return STATUS_SUCCESS;
1572 }
1573
1574 /* Walk over the linked batteries list and determine the exact estimated time */
1575 ExAcquireFastMutex(&DeviceExtension->Lock);
1576 ListHead = &DeviceExtension->BatteryList;
1577 for (NextEntry = ListHead->Flink;
1578 NextEntry != ListHead;
1579 NextEntry = NextEntry->Flink)
1580 {
1581 /* Acquire the remove lock so this battery does not disappear under us */
1582 BatteryData = CONTAINING_RECORD(NextEntry, COMPBATT_BATTERY_DATA, BatteryLink);
1583 if (!NT_SUCCESS(IoAcquireRemoveLock(&BatteryData->RemoveLock, BatteryData->Irp)))
1584 continue;
1585
1586 /* Now release the device lock since the battery can't go away */
1587 ExReleaseFastMutex(&DeviceExtension->Lock);
1588
1589 /* Build the necessary information in order to query the battery estimated time */
1590 QueryInformation.BatteryTag = BatteryData->Tag;
1591 QueryInformation.InformationLevel = BatteryEstimatedTime;
1592 QueryInformation.AtRate = ComputedAtRate;
1593
1594 /* Make sure this battery has a valid tag before issuing the IOCTL */
1595 if (BatteryData->Tag != BATTERY_TAG_INVALID)
1596 {
1598 BatteryData->DeviceObject,
1599 &QueryInformation,
1600 sizeof(QueryInformation),
1601 &ReturnedTime,
1602 sizeof(ReturnedTime),
1603 FALSE);
1604 if (!NT_SUCCESS(Status))
1605 {
1606 /*
1607 * If the device is being suddenly removed then we must invalidate
1608 * both this battery and composite tags.
1609 */
1611 {
1613 }
1614
1615 ExAcquireFastMutex(&DeviceExtension->Lock);
1616 IoReleaseRemoveLock(&BatteryData->RemoveLock, BatteryData->Irp);
1617
1618 /*
1619 * In other places we are ceasing the execution of the loop but
1620 * here we want to continue looking for other linked batteries.
1621 * This is because we are querying for the estimated battery time
1622 * at the time the last battery status was valid. Also bear in
1623 * mind IOCTL_BATTERY_QUERY_INFORMATION with InformationLevel as
1624 * BatteryEstimatedTime might not be a valid request supported
1625 * by this battery.
1626 */
1627 continue;
1628 }
1629
1630 /* Now sum up the estimated battery time */
1631 if (ReturnedTime != BATTERY_UNKNOWN_TIME)
1632 {
1633 if (*Time != BATTERY_UNKNOWN_TIME)
1634 {
1635 *Time += ReturnedTime;
1636 }
1637 else
1638 {
1639 *Time = ReturnedTime;
1640 }
1641 }
1642 }
1643
1644 /* We are done with this battery */
1645 ExAcquireFastMutex(&DeviceExtension->Lock);
1646 IoReleaseRemoveLock(&BatteryData->RemoveLock, BatteryData->Irp);
1647 }
1648
1649 /* Release the lock as we are no longer poking through the batteries list */
1650 ExReleaseFastMutex(&DeviceExtension->Lock);
1651 return Status;
1652}
1653
1655NTAPI
1657 _In_ PCOMPBATT_DEVICE_EXTENSION DeviceExtension,
1658 _In_ ULONG Tag,
1664{
1665 BATTERY_INFORMATION BatteryInfo;
1666 BATTERY_REPORTING_SCALE BatteryGranularity[4];
1667 PWCHAR BatteryName = L"Composite Battery";
1668 //BATTERY_MANUFACTURE_DATE Date;
1669 ULONG Dummy, Time;
1670 PVOID QueryData = NULL;
1671 ULONG QueryLength = 0;
1673 PAGED_CODE();
1674 if (CompBattDebug & COMPBATT_DEBUG_TRACE) DbgPrint("CompBatt: ENTERING QueryInformation\n");
1675
1676 /* Check for valid/correct tag */
1677 if ((Tag != DeviceExtension->Tag) ||
1678 (!(DeviceExtension->Flags & COMPBATT_TAG_ASSIGNED)))
1679 {
1680 /* Not right, so fail */
1681 return STATUS_NO_SUCH_DEVICE;
1682 }
1683
1684 /* Check what caller wants */
1685 switch (InfoLevel)
1686 {
1687 case BatteryInformation:
1688
1689 /* Query combined battery information */
1690 RtlZeroMemory(&BatteryInfo, sizeof(BatteryInfo));
1691 Status = CompBattGetBatteryInformation(&BatteryInfo, DeviceExtension);
1692 if (NT_SUCCESS(Status))
1693 {
1694 /* Return the data if successful */
1695 QueryData = &BatteryInfo;
1696 QueryLength = sizeof(BatteryInfo);
1697 }
1698 break;
1699
1701
1702 /* Query combined granularity information */
1703 RtlZeroMemory(&BatteryGranularity, sizeof(BatteryGranularity));
1704 Status = CompBattGetBatteryGranularity(BatteryGranularity, DeviceExtension);
1705 if (NT_SUCCESS(Status))
1706 {
1707 /* Return the data if successful */
1708 QueryLength = sizeof(BatteryGranularity);
1709 QueryData = &BatteryGranularity;
1710 }
1711 break;
1712
1714
1715 /* Query combined time estimate information */
1716 RtlZeroMemory(&Time, sizeof(Time));
1717 Status = CompBattGetEstimatedTime(&Time, DeviceExtension);
1718 if (NT_SUCCESS(Status))
1719 {
1720 /* Return the data if successful */
1721 QueryLength = sizeof(Time);
1722 QueryData = &Time;
1723 }
1724 break;
1725
1727 case BatteryDeviceName:
1728
1729 /* Return the static buffer */
1730 QueryData = BatteryName;
1731 QueryLength = sizeof(L"Composite Battery");
1732 break;
1733
1735
1736 /* Static data */
1737 //Date.Day = 26;
1738 //Date.Month = 06;
1739 //Date.Year = 1997;
1740 break;
1741
1742 case BatteryTemperature:
1743 case BatteryUniqueID:
1744
1745 /* Return zero */
1746 Dummy = 0;
1747 QueryData = &Dummy;
1748 QueryLength = sizeof(Dummy);
1749 break;
1750
1751 default:
1752 /* Everything else is unknown */
1754 break;
1755 }
1756
1757 /* Return the required length and check if the caller supplied enough */
1758 *ReturnedLength = QueryLength;
1759 if (BufferLength < QueryLength) Status = STATUS_BUFFER_TOO_SMALL;
1760
1761 /* Copy the data if there's enough space and it exists */
1762 if ((NT_SUCCESS(Status)) && (QueryData)) RtlCopyMemory(Buffer, QueryData, QueryLength);
1763
1764 /* Return function result */
1765 if (CompBattDebug & COMPBATT_DEBUG_TRACE) DbgPrint("CompBatt: EXITING QueryInformation\n");
1766 return Status;
1767}
1768
1770NTAPI
1774{
1775 /* Register add device routine */
1776 DriverObject->DriverExtension->AddDevice = CompBattAddDevice;
1777
1778 /* Register other handlers */
1785 return STATUS_SUCCESS;
1786}
1787
1788/* EOF */
static PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(PIRP Irp)
#define PAGED_CODE()
unsigned char BOOLEAN
LONG NTSTATUS
Definition: precomp.h:26
_In_ ULONG _In_ BATTERY_QUERY_INFORMATION_LEVEL _In_ LONG _In_ ULONG _Out_ PULONG ReturnedLength
Definition: batclass.h:188
#define IOCTL_BATTERY_QUERY_TAG
Definition: batclass.h:84
#define BATTERY_CRITICAL
Definition: batclass.h:76
_In_ ULONG _In_ PBATTERY_NOTIFY BatteryNotify
Definition: batclass.h:216
#define BATTERY_UNKNOWN_CAPACITY
Definition: batclass.h:65
_Out_ PULONG BatteryTag
Definition: batclass.h:173
_In_ ULONG _Out_ PBATTERY_STATUS BatteryStatus
Definition: batclass.h:199
#define BATTERY_UNKNOWN_VOLTAGE
Definition: batclass.h:79
_In_ ULONG _In_ BATTERY_QUERY_INFORMATION_LEVEL _In_ LONG AtRate
Definition: batclass.h:185
#define BATTERY_POWER_ON_LINE
Definition: batclass.h:73
#define BATTERY_DISCHARGING
Definition: batclass.h:74
@ BatteryInformation
Definition: batclass.h:97
@ BatteryManufactureName
Definition: batclass.h:103
@ BatteryGranularityInformation
Definition: batclass.h:98
@ BatteryUniqueID
Definition: batclass.h:104
@ BatteryEstimatedTime
Definition: batclass.h:100
@ BatteryDeviceName
Definition: batclass.h:101
@ BatteryTemperature
Definition: batclass.h:99
@ BatteryManufactureDate
Definition: batclass.h:102
#define IOCTL_BATTERY_QUERY_INFORMATION
Definition: batclass.h:86
#define BATTERY_CHARGING
Definition: batclass.h:75
#define BATTERY_UNKNOWN_RATE
Definition: batclass.h:82
enum _BATTERY_QUERY_INFORMATION_LEVEL BATTERY_QUERY_INFORMATION_LEVEL
#define BATTERY_TAG_INVALID
Definition: batclass.h:94
#define IOCTL_BATTERY_QUERY_STATUS
Definition: batclass.h:90
#define BATTERY_UNKNOWN_TIME
Definition: batclass.h:68
BCLASSAPI NTSTATUS NTAPI BatteryClassStatusNotify(_In_ PVOID ClassData)
Definition: battc.c:79
BCLASSAPI NTSTATUS NTAPI BatteryClassIoctl(PVOID ClassData, PIRP Irp)
Definition: battc.c:198
#define IRP_MJ_PNP
Definition: cdrw_usr.h:52
Definition: bufpool.h:45
NTSTATUS NTAPI CompBattQueryInformation(_In_ PCOMPBATT_DEVICE_EXTENSION DeviceExtension, _In_ ULONG Tag, _In_ BATTERY_QUERY_INFORMATION_LEVEL InfoLevel, _In_opt_ LONG AtRate, _In_ PVOID Buffer, _In_ ULONG BufferLength, _Out_ PULONG ReturnedLength)
Definition: compbatt.c:1656
NTSTATUS NTAPI CompBattMonitorIrpComplete(_In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp, _In_ PVOID Context)
Queues a work item thread worker which is bound to the individual CM (Control Method) ACPI battery to...
Definition: compbatt.c:92
NTSTATUS NTAPI CompBattQueryStatus(_In_ PCOMPBATT_DEVICE_EXTENSION DeviceExtension, _In_ ULONG Tag, _Out_ PBATTERY_STATUS BatteryStatus)
Queries the battery status of each individiual connected battery with the composite battery and combi...
Definition: compbatt.c:932
ULONG CompBattDebug
Definition: compbatt.c:17
NTSTATUS NTAPI CompBattQueryTag(_In_ PCOMPBATT_DEVICE_EXTENSION DeviceExtension, _Out_ PULONG Tag)
Definition: compbatt.c:453
NTSTATUS NTAPI CompBattSetStatusNotify(_In_ PCOMPBATT_DEVICE_EXTENSION DeviceExtension, _In_ ULONG BatteryTag, _In_ PBATTERY_NOTIFY BatteryNotify)
Sets a new configuration battery wait status settings of each battery. The purpose of this is so that...
Definition: compbatt.c:676
NTSTATUS NTAPI CompBattGetBatteryGranularity(_Out_ PBATTERY_REPORTING_SCALE ReportingScale, _In_ PCOMPBATT_DEVICE_EXTENSION DeviceExtension)
Definition: compbatt.c:1308
VOID NTAPI CompBattMonitorIrpCompleteWorker(_In_ PCOMPBATT_BATTERY_DATA BatteryData)
The brains of the battery IRP worker. It monitors the state of the IRP as well as sends the IRP down ...
Definition: compbatt.c:125
NTSTATUS NTAPI CompBattDisableStatusNotify(_In_ PCOMPBATT_DEVICE_EXTENSION DeviceExtension)
Definition: compbatt.c:489
static BOOLEAN CompBattCalculateTotalRateAndLinkedBatteries(_In_ PCOMPBATT_DEVICE_EXTENSION DeviceExtension, _Out_ PULONG TotalRate, _Out_ PULONG BatteriesCount)
Calculates the total discharging/charging rate flow of each individual battery linked with the compos...
Definition: compbatt.c:540
NTSTATUS NTAPI CompBattSystemControl(_In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp)
Definition: compbatt.c:42
VOID NTAPI CompBattRecalculateTag(_In_ PCOMPBATT_DEVICE_EXTENSION DeviceExtension)
Definition: compbatt.c:390
NTSTATUS NTAPI CompBattIoctl(_In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp)
Definition: compbatt.c:428
NTSTATUS NTAPI CompBattOpenClose(_In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp)
Definition: compbatt.c:23
NTSTATUS NTAPI CompBattGetEstimatedTime(_Out_ PULONG Time, _In_ PCOMPBATT_DEVICE_EXTENSION DeviceExtension)
Retrieves the estimated time of the composite battery based on the power drain rate of all the batter...
Definition: compbatt.c:1500
static LONG CompBattCalculateAtRateTime(_In_ PCOMPBATT_DEVICE_EXTENSION DeviceExtension)
Calculates the "At Rate" flow of the composite battery based on the sum of all connected batteries,...
Definition: compbatt.c:1409
NTSTATUS NTAPI CompBattGetBatteryInformation(_Out_ PBATTERY_INFORMATION BatteryInfo, _In_ PCOMPBATT_DEVICE_EXTENSION DeviceExtension)
Definition: compbatt.c:1151
NTSTATUS NTAPI CompBattPnpDispatch(_In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp)
Definition: comppnp.c:412
NTSTATUS NTAPI CompBattRemoveBattery(_In_ PUNICODE_STRING BatteryName, _In_ PCOMPBATT_DEVICE_EXTENSION DeviceExtension)
Definition: comppnp.c:226
#define COMPBATT_DEBUG_WARN
Definition: compbatt.h:70
#define COMPUTE_ATRATE_DRAIN(Batt, Time)
Definition: compbatt.h:62
#define COMPUTE_BATT_CAP_DELTA(LowDiff, Batt, TotalRate)
Definition: compbatt.h:56
#define COMPBATT_QUERY_TAG
Definition: compbatt.h:34
#define COMPBATT_WAIT_MAX_HIGH_CAPACITY
Definition: compbatt.h:41
#define COMPBATT_TAG_ASSIGNED
Definition: compbatt.h:29
#define COMPBATT_FRESH_STATUS_TIME
Definition: compbatt.h:51
NTSTATUS NTAPI BatteryIoctl(_In_ ULONG IoControlCode, _In_ PDEVICE_OBJECT DeviceObject, _In_ PVOID InputBuffer, _In_ ULONG InputBufferLength, _Out_ PVOID OutputBuffer, _Inout_ ULONG OutputBufferLength, _In_ BOOLEAN InternalDeviceIoControl)
Definition: compmisc.c:16
#define COMPBATT_BATTERY_INFORMATION_PRESENT
Definition: compbatt.h:27
#define COMPBATT_DEBUG_ERR
Definition: compbatt.h:71
#define COMPBATT_STATUS_NOTIFY_SET
Definition: compbatt.h:28
#define COMPBATT_DEBUG_INFO
Definition: compbatt.h:68
NTSTATUS NTAPI CompBattPowerDispatch(_In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp)
Definition: comppnp.c:18
NTSTATUS NTAPI CompBattAddDevice(_In_ PDRIVER_OBJECT DriverObject, _In_ PDEVICE_OBJECT PdoDeviceObject)
Definition: comppnp.c:328
#define COMPBATT_WAIT_MIN_LOW_CAPACITY
Definition: compbatt.h:40
#define COMPBATT_READ_STATUS
Definition: compbatt.h:35
#define COMPBATT_DEBUG_TRACE
Definition: compbatt.h:69
_In_ PIRP Irp
Definition: csq.h:116
#define STATUS_NOT_SUPPORTED
Definition: d3dkmdt.h:48
#define STATUS_DEVICE_REMOVED
Definition: d3dkmdt.h:39
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
DRIVER_INITIALIZE DriverEntry
Definition: condrv.c:21
Status
Definition: gdiplustypes.h:25
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
VOID FASTCALL ExAcquireFastMutex(IN PFAST_MUTEX FastMutex)
Definition: fmutex.c:23
VOID FASTCALL ExReleaseFastMutex(IN PFAST_MUTEX FastMutex)
Definition: fmutex.c:31
#define DbgPrint
Definition: hal.h:12
_In_ ULONG Mode
Definition: hubbusif.h:303
#define IoSetCompletionRoutine(_Irp, _CompletionRoutine, _Context, _InvokeOnSuccess, _InvokeOnError, _InvokeOnCancel)
Definition: irp.cpp:490
#define ASSERT(a)
Definition: mode.c:44
static PLARGE_INTEGER Time
Definition: time.c:105
#define min(a, b)
Definition: monoChain.cc:55
#define _Out_
Definition: no_sal2.h:160
#define _In_
Definition: no_sal2.h:158
#define _In_opt_
Definition: no_sal2.h:212
#define ASSERTMSG(msg, exp)
Definition: nt_native.h:431
#define UNREACHABLE
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:325
#define IoSkipCurrentIrpStackLocation(Irp)
Definition: ntifs_ex.h:421
#define IoCompleteRequest
Definition: irp.c:1240
BOOLEAN NTAPI IoCancelIrp(IN PIRP Irp)
Definition: irp.c:1101
#define IoCallDriver
Definition: irp.c:1225
VOID NTAPI IoFreeIrp(IN PIRP Irp)
Definition: irp.c:1666
#define L(x)
Definition: ntvdm.h:50
long LONG
Definition: pedump.c:60
#define IRP_MJ_CLOSE
Definition: rdpdr.c:45
#define IRP_MJ_DEVICE_CONTROL
Definition: rdpdr.c:52
#define IRP_MJ_CREATE
Definition: rdpdr.c:44
#define KeQueryInterruptTime()
Definition: ke.h:37
#define STATUS_MORE_PROCESSING_REQUIRED
Definition: shellext.h:68
#define STATUS_SUCCESS
Definition: shellext.h:65
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:69
UCHAR Chemistry[4]
Definition: batclass.h:118
ULONG FullChargedCapacity
Definition: batclass.h:120
ULONG LowCapacity
Definition: batclass.h:204
ULONG HighCapacity
Definition: batclass.h:205
ULONG PowerState
Definition: batclass.h:203
BATTERY_QUERY_INFORMATION_LEVEL InformationLevel
Definition: batclass.h:110
ULONG PowerState
Definition: batclass.h:154
ULONG Capacity
Definition: batclass.h:155
PDEVICE_OBJECT DeviceObject
Definition: compbatt.h:91
BATTERY_WAIT_STATUS WorkerWaitStatus
Definition: compbatt.h:120
BATTERY_INFORMATION BatteryInformation
Definition: compbatt.h:141
BATTERY_WAIT_STATUS WaitStatus
Definition: compbatt.h:112
BATTERY_STATUS BatteryStatus
Definition: compbatt.h:142
WORK_QUEUE_ITEM WorkItem
Definition: compbatt.h:98
IO_REMOVE_LOCK RemoveLock
Definition: compbatt.h:85
ULONGLONG InterruptTime
Definition: compbatt.h:145
union _COMPBATT_BATTERY_DATA::@629 WorkerBuffer
BATTERY_WAIT_STATUS WaitNotifyStatus
Definition: compbatt.h:198
PDEVICE_OBJECT DeviceObject
Definition: compbatt.h:208
PDEVICE_OBJECT AttachedDevice
Definition: compbatt.h:207
BATTERY_STATUS BatteryStatus
Definition: compbatt.h:197
struct _IO_STACK_LOCATION::@1583::@1584 DeviceIoControl
union _IO_STACK_LOCATION::@1583 Parameters
struct _IO_STACK_LOCATION::@4015::@4054 Others
Definition: typedefs.h:120
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
#define max(a, b)
Definition: svc.c:63
uint32_t * PULONG
Definition: typedefs.h:59
#define NTAPI
Definition: typedefs.h:36
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
uint16_t * PWCHAR
Definition: typedefs.h:56
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
uint32_t ULONG
Definition: typedefs.h:59
uint64_t ULONGLONG
Definition: typedefs.h:67
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define STATUS_NO_SUCH_DEVICE
Definition: udferr_usr.h:136
#define STATUS_CANCELLED
Definition: udferr_usr.h:170
_In_ PDEVICE_OBJECT DeviceObject
Definition: wdfdevice.h:2055
_Must_inspect_result_ _In_ WDFDEVICE _In_ BOOLEAN _In_opt_ PVOID Tag
Definition: wdfdevice.h:4065
_Must_inspect_result_ _In_ WDFDEVICE _In_ DEVICE_REGISTRY_PROPERTY _In_ ULONG BufferLength
Definition: wdfdevice.h:3771
_In_ WDFDPC _In_ BOOLEAN Wait
Definition: wdfdpc.h:170
_Must_inspect_result_ _In_ PDRIVER_OBJECT _In_ PCUNICODE_STRING RegistryPath
Definition: wdfdriver.h:215
_Must_inspect_result_ _In_ PDRIVER_OBJECT DriverObject
Definition: wdfdriver.h:213
_Must_inspect_result_ _In_ WDFIOTARGET _In_opt_ WDFREQUEST _In_opt_ PWDF_MEMORY_DESCRIPTOR InputBuffer
Definition: wdfiotarget.h:953
VOID NTAPI ExQueueWorkItem(IN PWORK_QUEUE_ITEM WorkItem, IN WORK_QUEUE_TYPE QueueType)
Definition: work.c:723
@ DelayedWorkQueue
Definition: extypes.h:190
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetNextIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2695
#define IoAcquireRemoveLock(RemoveLock, Tag)
#define IoReleaseRemoveLock(_RemoveLock, _Tag)
Definition: iofuncs.h:2764
#define IO_NO_INCREMENT
Definition: iotypes.h:598
#define IRP_MJ_SYSTEM_CONTROL
#define IRP_MJ_POWER
unsigned char UCHAR
Definition: xmlstorage.h:181