2 * PROJECT: ReactOS ACPI-Compliant Control Method Battery
3 * LICENSE: BSD - See COPYING.ARM in the top level directory
4 * FILE: boot/drivers/bus/acpi/cmbatt/cmbatt.c
5 * PURPOSE: Main Initialization Code and IRP Handling
6 * PROGRAMMERS: ReactOS Portable Systems Group
9 /* INCLUDES *******************************************************************/
13 /* GLOBALS ********************************************************************/
16 PCALLBACK_OBJECT CmBattPowerCallBackObject
;
17 PVOID CmBattPowerCallBackRegistration
;
18 UNICODE_STRING GlobalRegistryPath
;
19 KTIMER CmBattWakeDpcTimerObject
;
20 KDPC CmBattWakeDpcObject
;
21 PDEVICE_OBJECT AcAdapterPdo
;
23 /* FUNCTIONS ******************************************************************/
27 CmBattPowerCallBack(PCMBATT_DEVICE_EXTENSION DeviceExtension
,
36 CmBattWakeDpc(PKDPC Dpc
,
37 PCMBATT_DEVICE_EXTENSION FdoExtension
,
38 PVOID SystemArgument1
,
39 PVOID SystemArgument2
)
46 CmBattNotifyHandler(PCMBATT_DEVICE_EXTENSION DeviceExtension
,
54 CmBattUnload(IN PDRIVER_OBJECT DriverObject
)
56 if (CmBattDebug
& CMBATT_GENERIC_INFO
) DPRINT("CmBattUnload: \n");
58 /* Check if we have a registered power callback */
59 if (CmBattPowerCallBackObject
)
62 ExUnregisterCallback(CmBattPowerCallBackRegistration
);
63 ObfDereferenceObject(CmBattPowerCallBackObject
);
66 /* Free the registry buffer if it exists */
67 if (GlobalRegistryPath
.Buffer
) ExFreePool(GlobalRegistryPath
.Buffer
);
69 /* Make sure we don't still have references to the DO */
70 if ((DriverObject
->DeviceObject
) && (CmBattDebug
& CMBATT_GENERIC_WARNING
))
72 DbgPrint("Unload called before all devices removed.\n");
78 CmBattVerifyStaticInfo(PCMBATT_DEVICE_EXTENSION DeviceExtension
,
82 return STATUS_NOT_IMPLEMENTED
;
87 CmBattOpenClose(IN PDEVICE_OBJECT DeviceObject
,
90 NTSTATUS Status
= STATUS_SUCCESS
;
91 PIO_STACK_LOCATION IoStackLocation
;
94 PCMBATT_DEVICE_EXTENSION DeviceExtension
;
96 if (CmBattDebug
& CMBATT_GENERIC_INFO
) DPRINT("CmBattOpenClose\n");
98 /* Grab the device extension and lock it */
99 DeviceExtension
= DeviceObject
->DeviceExtension
;
100 ExAcquireFastMutex(&DeviceExtension
->FastMutex
);
102 /* Check if someone is trying to open a device that doesn't exist yet */
103 Count
= DeviceExtension
->HandleCount
;
104 if (Count
== 0xFFFFFFFF)
106 /* Fail the request */
107 Status
= STATUS_NO_SUCH_DEVICE
;
108 if (CmBattDebug
& CMBATT_PNP_INFO
)
110 DbgPrint("CmBattOpenClose: Failed (UID = %x)(device being removed).\n",
111 DeviceExtension
->Tag
);
116 /* Check if this is an open or close */
117 IoStackLocation
= IoGetCurrentIrpStackLocation(Irp
);
118 Major
= IoStackLocation
->MajorFunction
;
119 if (Major
== IRP_MJ_CREATE
)
121 /* Increment the open count */
122 DeviceExtension
->HandleCount
= Count
+ 1;
123 if (CmBattDebug
& CMBATT_PNP_INFO
)
125 DbgPrint("CmBattOpenClose: Open (DeviceNumber = %x)(count = %x).\n",
126 DeviceExtension
->DeviceId
, Count
+ 1);
129 else if (Major
== IRP_MJ_CLOSE
)
131 /* Decrement the open count */
132 DeviceExtension
->HandleCount
= Count
- 1;
133 if (CmBattDebug
& CMBATT_PNP_INFO
)
135 DbgPrint("CmBattOpenClose: Close (DeviceNumber = %x)(count = %x).\n",
136 DeviceExtension
->DeviceId
, Count
+ 1);
141 /* Release lock and complete request */
142 ExReleaseFastMutex(&DeviceExtension
->FastMutex
);
143 Irp
->IoStatus
.Status
= Status
;
144 IofCompleteRequest(Irp
, IO_NO_INCREMENT
);
150 CmBattIoctl(PDEVICE_OBJECT DeviceObject
,
154 return STATUS_NOT_IMPLEMENTED
;
159 CmBattQueryTag(PCMBATT_DEVICE_EXTENSION DeviceExtension
,
163 return STATUS_NOT_IMPLEMENTED
;
168 CmBattDisableStatusNotify(PCMBATT_DEVICE_EXTENSION DeviceExtension
)
171 return STATUS_NOT_IMPLEMENTED
;
176 CmBattSetStatusNotify(PCMBATT_DEVICE_EXTENSION DeviceExtension
,
178 PBATTERY_NOTIFY BatteryNotify
)
181 return STATUS_NOT_IMPLEMENTED
;
186 CmBattGetBatteryStatus(IN PCMBATT_DEVICE_EXTENSION DeviceExtension
,
192 ULONG DesignVoltage
, PresentRate
, RemainingCapacity
;
194 if (CmBattDebug
& CMBATT_GENERIC_INFO
)
195 DbgPrint("CmBattGetBatteryStatus - CmBatt (%08x) Tag (%d)\n", DeviceExtension
, Tag
);
197 /* Validate ACPI data */
198 Status
= CmBattVerifyStaticInfo(DeviceExtension
, Tag
);
199 if (!NT_SUCCESS(Status
)) return Status
;
201 /* Check for delayed status notifications */
202 if (DeviceExtension
->DelayNotification
)
204 /* Process them now and don't do any other work */
205 CmBattNotifyHandler(DeviceExtension
, ACPI_BATT_NOTIFY_STATUS
);
209 /* Get _BST from ACPI */
210 Status
= CmBattGetBstData(DeviceExtension
, &DeviceExtension
->BstData
);
211 if (!NT_SUCCESS(Status
))
214 InterlockedExchange(&DeviceExtension
->ArLockValue
, 0);
218 /* Clear current BST information */
219 DeviceExtension
->State
= 0;
220 DeviceExtension
->RemainingCapacity
= 0;
221 DeviceExtension
->PresentVoltage
= 0;
222 DeviceExtension
->Rate
= 0;
224 /* Get battery state */
225 BstState
= DeviceExtension
->BstData
.State
;
227 /* Is the battery both charging and discharging? */
228 if ((BstState
& ACPI_BATT_STAT_DISCHARG
) && (BstState
& ACPI_BATT_STAT_CHARGING
) &&
229 (CmBattDebug
& (CMBATT_ACPI_WARNING
| CMBATT_GENERIC_WARNING
)))
230 DbgPrint("************************ ACPI BIOS BUG ********************\n* "
231 "CmBattGetBatteryStatus: Invalid state: _BST method returned 0x%08x for Battery State.\n"
232 "* One battery cannot be charging and discharging at the same time.\n",
235 /* Is the battery discharging? */
236 if (BstState
& ACPI_BATT_STAT_DISCHARG
)
238 /* Set power state and check if it just started discharging now */
239 DeviceExtension
->State
|= BATTERY_DISCHARGING
;
240 if (!(DeviceExtension
->State
& ACPI_BATT_STAT_DISCHARG
))
242 /* Remember the time when the state changed */
243 DeviceExtension
->InterruptTime
= KeQueryInterruptTime();
246 else if (BstState
& ACPI_BATT_STAT_CHARGING
)
248 /* Battery is charging, update power state */
249 DeviceExtension
->State
|= (BATTERY_CHARGING
| BATTERY_POWER_ON_LINE
);
252 /* Is the battery in a critical state? */
253 if (BstState
& ACPI_BATT_STAT_CRITICAL
) DeviceExtension
->State
|= BATTERY_CRITICAL
;
255 /* Read the voltage data */
256 DeviceExtension
->PresentVoltage
= DeviceExtension
->BstData
.PresentVoltage
;
258 /* Check if we have an A/C adapter */
261 /* Query information on it */
262 CmBattGetPsrData(AcAdapterPdo
, &PsrData
);
266 /* Otherwise, check if the battery is charging */
267 if (BstState
& ACPI_BATT_STAT_CHARGING
)
269 /* Then we'll assume there's a charger */
274 /* Assume no charger */
279 /* Is there a charger? */
282 /* Set the power state flag to reflect this */
283 DeviceExtension
->State
|= BATTERY_POWER_ON_LINE
;
284 if (CmBattDebug
& (CMBATT_GENERIC_INFO
| CMBATT_GENERIC_STATUS
))
285 DbgPrint("CmBattGetBatteryStatus: AC adapter is connected\n");
287 else if (CmBattDebug
& (CMBATT_GENERIC_INFO
| CMBATT_GENERIC_STATUS
))
289 DbgPrint("CmBattGetBatteryStatus: AC adapter is NOT connected\n");
292 /* Get some data we'll need */
293 DesignVoltage
= DeviceExtension
->BifData
.DesignVoltage
;
294 PresentRate
= DeviceExtension
->BstData
.PresentRate
;
295 RemainingCapacity
= DeviceExtension
->BstData
.RemainingCapacity
;
297 /* Check if we have battery data in Watts instead of Amps */
298 if (DeviceExtension
->BifData
.PowerUnit
== ACPI_BATT_POWER_UNIT_WATTS
)
300 /* Get the data from the BST */
301 DeviceExtension
->RemainingCapacity
= RemainingCapacity
;
302 DeviceExtension
->Rate
= PresentRate
;
304 /* Check if the rate is invalid */
305 if (PresentRate
> CM_MAX_VALUE
)
307 /* Set an unknown rate and don't touch the old value */
308 DeviceExtension
->Rate
= BATTERY_UNKNOWN_RATE
;
309 if ((PresentRate
!= CM_UNKNOWN_VALUE
) && (CmBattDebug
& CMBATT_ACPI_WARNING
))
311 DbgPrint("CmBattGetBatteryStatus - Rate is greater than CM_MAX_VALUE\n");
312 DbgPrint("---------------------- PresentRate = 0x%08x\n", PresentRate
);
316 else if ((DesignVoltage
!= CM_UNKNOWN_VALUE
) && (DesignVoltage
))
318 /* We have voltage data, what about capacity? */
319 if (RemainingCapacity
== CM_UNKNOWN_VALUE
)
321 /* Unable to calculate it */
322 DeviceExtension
->RemainingCapacity
= BATTERY_UNKNOWN_CAPACITY
;
323 if (CmBattDebug
& CMBATT_ACPI_WARNING
)
325 DbgPrint("CmBattGetBatteryStatus - Can't calculate RemainingCapacity \n");
326 DbgPrint("---------------------- RemainingCapacity = CM_UNKNOWN_VALUE\n");
331 /* Compute the capacity with the information we have */
332 DeviceExtension
->RemainingCapacity
= (DesignVoltage
* RemainingCapacity
+ 500) / 1000;
335 /* Check if we have a rate */
336 if (PresentRate
!= CM_UNKNOWN_VALUE
)
338 /* Make sure the rate isn't too large */
339 if (PresentRate
> (-500 / DesignVoltage
))
341 /* It is, so set unknown state */
342 DeviceExtension
->Rate
= BATTERY_UNKNOWN_RATE
;
343 if (CmBattDebug
& CMBATT_ACPI_WARNING
)
345 DbgPrint("CmBattGetBatteryStatus - Can't calculate Rate \n");
346 DbgPrint("---------------------- Overflow: PresentRate = 0x%08x\n", PresentRate
);
350 /* Compute the rate */
351 DeviceExtension
->Rate
= (PresentRate
* DesignVoltage
+ 500) / 1000;
355 /* We don't have a rate, so set unknown value */
356 DeviceExtension
->Rate
= BATTERY_UNKNOWN_RATE
;
357 if (CmBattDebug
& CMBATT_ACPI_WARNING
)
359 DbgPrint("CmBattGetBatteryStatus - Can't calculate Rate \n");
360 DbgPrint("---------------------- Present Rate = CM_UNKNOWN_VALUE\n");
366 /* We have no rate, and no capacity, set unknown values */
367 DeviceExtension
->Rate
= BATTERY_UNKNOWN_RATE
;
368 DeviceExtension
->RemainingCapacity
= BATTERY_UNKNOWN_CAPACITY
;
369 if (CmBattDebug
& CMBATT_ACPI_WARNING
)
371 DbgPrint("CmBattGetBatteryStatus - Can't calculate RemainingCapacity and Rate \n");
372 DbgPrint("---------------------- DesignVoltage = 0x%08x\n", DesignVoltage
);
376 /* Check if we have an unknown rate */
377 if (DeviceExtension
->Rate
== BATTERY_UNKNOWN_RATE
)
379 /* The battery is discharging but we don't know by how much... this is bad! */
380 if ((BstState
& ACPI_BATT_STAT_DISCHARG
) &&
381 (CmBattDebug
& (CMBATT_ACPI_WARNING
| CMBATT_GENERIC_WARNING
)))
382 DbgPrint("CmBattGetBatteryStatus: battery rate is unkown when battery is not charging!\n");
384 else if (DeviceExtension
->State
& BATTERY_DISCHARGING
)
386 /* The battery is discharging, so treat the rate as a negative rate */
387 DeviceExtension
->Rate
= -DeviceExtension
->Rate
;
389 else if (!(DeviceExtension
->State
& BATTERY_CHARGING
) && (DeviceExtension
->Rate
))
391 /* We are not charging, not discharging, but have a rate? Ignore it! */
392 if (CmBattDebug
& CMBATT_GENERIC_WARNING
)
393 DbgPrint("CmBattGetBatteryStatus: battery is not charging or discharging, but rate = %x\n",
394 DeviceExtension
->Rate
);
395 DeviceExtension
->Rate
= 0;
399 return STATUS_SUCCESS
;
404 CmBattQueryInformation(IN PCMBATT_DEVICE_EXTENSION FdoExtension
,
406 IN BATTERY_QUERY_INFORMATION_LEVEL InfoLevel
,
407 IN OPTIONAL LONG AtRate
,
409 IN ULONG BufferLength
,
410 OUT PULONG ReturnedLength
)
413 PVOID QueryData
= NULL
;
414 ULONG QueryLength
= 0;
415 ULONG RemainingTime
= 0;
416 ANSI_STRING TempString
;
417 UNICODE_STRING TempString2
;
418 WCHAR InfoBuffer
[256];
419 WCHAR TempBuffer
[256];
420 UNICODE_STRING InfoString
;
421 ULONG RemainingCapacity
;
422 BATTERY_REPORTING_SCALE BatteryReportingScale
[2];
425 if (CmBattDebug
& (CMBATT_ACPI_WARNING
| CMBATT_GENERIC_INFO
))
426 DbgPrint("CmBattQueryInformation - Tag (%d) Device %d, Informationlevel %d\n",
428 FdoExtension
->DeviceId
,
431 /* Check ACPI Data */
432 Status
= CmBattVerifyStaticInfo(FdoExtension
, Tag
);
433 if (!NT_SUCCESS(Status
)) return Status
;
435 /* Check what caller wants */
438 case BatteryInformation
:
439 /* Just return our static information */
440 QueryData
= &FdoExtension
->BatteryInformation
;
441 QueryLength
= sizeof(BATTERY_INFORMATION
);
444 case BatteryGranularityInformation
:
446 /* Return our static information, we have two scales */
447 BatteryReportingScale
[0].Granularity
= FdoExtension
->BatteryCapacityGranularity1
;
448 BatteryReportingScale
[0].Capacity
= FdoExtension
->BatteryInformation
.DefaultAlert1
;
449 BatteryReportingScale
[1].Granularity
= FdoExtension
->BatteryCapacityGranularity2
;
450 BatteryReportingScale
[1].Capacity
= FdoExtension
->BatteryInformation
.DesignedCapacity
;
451 QueryData
= BatteryReportingScale
;
452 QueryLength
= sizeof(BATTERY_REPORTING_SCALE
) * 2;
455 case BatteryEstimatedTime
:
457 /* Check if it's been more than 2 1/2 minutes since the last change */
458 if ((KeQueryInterruptTime() - 150000000) > (FdoExtension
->InterruptTime
))
460 /* Get new battery status */
461 CmBattGetBatteryStatus(FdoExtension
, FdoExtension
->Tag
);
463 /* If the caller didn't specify a rate, use our static one */
465 if (!Rate
) Rate
= FdoExtension
->Rate
;
467 /* If we don't have a valid negative rate, use unknown value */
468 if (Rate
>= 0) Rate
= BATTERY_UNKNOWN_RATE
;
470 /* Grab the remaining capacity */
471 RemainingCapacity
= FdoExtension
->RemainingCapacity
;
473 /* See if we don't know one or the other */
474 if ((Rate
== BATTERY_UNKNOWN_RATE
) ||
475 (RemainingCapacity
== BATTERY_UNKNOWN_CAPACITY
))
477 /* If the battery is discharging, we can't give out a time */
478 if ((FdoExtension
->BstData
.State
& ACPI_BATT_STAT_DISCHARG
) &&
479 (CmBattDebug
& CMBATT_GENERIC_WARNING
))
480 DbgPrint("CmBattQueryInformation: Can't calculate EstimatedTime.\n");
482 /* Check if we don't have a rate and capacity is going down */
483 if ((FdoExtension
->Rate
== BATTERY_UNKNOWN_RATE
) &&
484 (FdoExtension
->BstData
.State
& ACPI_BATT_STAT_DISCHARG
))
486 /* We have to fail, since we lack data */
487 Status
= STATUS_INVALID_DEVICE_REQUEST
;
488 if (CmBattDebug
& CMBATT_GENERIC_WARNING
)
489 DbgPrint("---------------------- PresentRate = BATTERY_UNKNOWN_RATE\n");
492 /* If we don't have capacity, the rate is useless */
493 if (RemainingCapacity
== BATTERY_UNKNOWN_CAPACITY
)
495 /* We have to fail the request */
496 Status
= STATUS_INVALID_DEVICE_REQUEST
;
497 if (CmBattDebug
& CMBATT_GENERIC_WARNING
)
498 DbgPrint("---------------------- RemainingCapacity = BATTERY_UNKNOWN_CAPACITY\n");
503 /* We have data, but is it valid? */
504 if (RemainingCapacity
> 0x123456)
506 /* The capacity seems bogus, so don't use it */
507 if (CmBattDebug
& CMBATT_ACPI_WARNING
)
508 DbgPrint("CmBattQueryInformation: Data Overflow in calculating Remaining Capacity.\n");
512 /* Compute the remaining time in seconds, based on rate */
513 RemainingTime
= (RemainingCapacity
* 3600) / -Rate
;
518 /* Return the remaining time */
519 QueryData
= &RemainingTime
;
520 QueryLength
= sizeof(ULONG
);
523 case BatteryDeviceName
:
525 /* Build the model number string */
526 RtlInitAnsiString(&TempString
, FdoExtension
->ModelNumber
);
528 /* Convert it to Unicode */
529 InfoString
.Buffer
= InfoBuffer
;
530 InfoString
.MaximumLength
= sizeof(InfoBuffer
);
531 Status
= RtlAnsiStringToUnicodeString(&InfoString
, &TempString
, 0);
533 /* Return the unicode buffer */
534 QueryData
= InfoString
.Buffer
;
535 QueryLength
= InfoString
.Length
;
538 case BatteryTemperature
:
539 case BatteryManufactureDate
:
541 /* We don't support these */
542 Status
= STATUS_INVALID_DEVICE_REQUEST
;
545 case BatteryManufactureName
:
547 /* Build the OEM info string */
548 RtlInitAnsiString(&TempString
, FdoExtension
->OemInfo
);
550 /* Convert it to Unicode */
551 InfoString
.Buffer
= InfoBuffer
;
552 InfoString
.MaximumLength
= sizeof(InfoBuffer
);
553 Status
= RtlAnsiStringToUnicodeString(&InfoString
, &TempString
, 0);
555 /* Return the unicode buffer */
556 QueryData
= InfoString
.Buffer
;
557 QueryLength
= InfoString
.Length
;
560 case BatteryUniqueID
:
562 /* Build the serial number string */
563 RtlInitAnsiString(&TempString
, FdoExtension
->SerialNumber
);
565 /* Convert it to Unicode */
566 InfoString
.Buffer
= InfoBuffer
;
567 InfoString
.MaximumLength
= sizeof(InfoBuffer
);
568 RtlAnsiStringToUnicodeString(&InfoString
, &TempString
, 0);
570 /* Setup a temporary string for concatenation */
571 TempString2
.Buffer
= TempBuffer
;
572 TempString2
.MaximumLength
= sizeof(TempBuffer
);
574 /* Check if there's an OEM string */
575 if (FdoExtension
->OemInfo
[0])
577 /* Build the OEM info string */
578 RtlInitAnsiString(&TempString
, FdoExtension
->OemInfo
);
580 /* Convert it to Unicode and append it */
581 RtlAnsiStringToUnicodeString(&TempString2
, &TempString
, 0);
582 RtlAppendUnicodeStringToString(&InfoString
, &TempString2
);
585 /* Build the model number string */
586 RtlInitAnsiString(&TempString
, FdoExtension
->ModelNumber
);
588 /* Convert it to Unicode and append it */
589 RtlAnsiStringToUnicodeString(&TempString2
, &TempString
, 0);
590 RtlAppendUnicodeStringToString(&InfoString
, &TempString2
);
592 /* Return the final appended string */
593 QueryData
= InfoString
.Buffer
;
594 QueryLength
= InfoString
.Length
;
599 /* Everything else is unknown */
600 Status
= STATUS_INVALID_PARAMETER
;
604 /* Return the required length and check if the caller supplied enough */
605 *ReturnedLength
= QueryLength
;
606 if (BufferLength
< QueryLength
) Status
= STATUS_BUFFER_TOO_SMALL
;
608 /* Copy the data if there's enough space and it exists */
609 if ((NT_SUCCESS(Status
)) && (QueryData
)) RtlCopyMemory(Buffer
, QueryData
, QueryLength
);
611 /* Return function result */
617 CmBattQueryStatus(IN PCMBATT_DEVICE_EXTENSION DeviceExtension
,
619 IN PBATTERY_STATUS BatteryStatus
)
623 if (CmBattDebug
& (CMBATT_ACPI_WARNING
| CMBATT_GENERIC_INFO
))
624 DbgPrint("CmBattQueryStatus - Tag (%d) Device %x\n", Tag
, DeviceExtension
->DeviceId
);
626 /* Query ACPI information */
627 Status
= CmBattGetBatteryStatus(DeviceExtension
, Tag
);
628 if (NT_SUCCESS(Status
))
630 BatteryStatus
->PowerState
= DeviceExtension
->State
;
631 BatteryStatus
->Capacity
= DeviceExtension
->RemainingCapacity
;
632 BatteryStatus
->Voltage
= DeviceExtension
->PresentVoltage
;
633 BatteryStatus
->Rate
= DeviceExtension
->Rate
;
637 if (CmBattDebug
& (CMBATT_GENERIC_INFO
))
638 DbgPrint("CmBattQueryStatus: Returning [%#08lx][%#08lx][%#08lx][%#08lx]\n",
639 BatteryStatus
->PowerState
,
640 BatteryStatus
->Capacity
,
641 BatteryStatus
->Voltage
,
642 BatteryStatus
->Rate
);
648 DriverEntry(IN PDRIVER_OBJECT DriverObject
,
649 IN PUNICODE_STRING RegistryPath
)
652 PDRIVER_EXTENSION DriverExtension
;
653 OBJECT_ATTRIBUTES ObjectAttributes
;
654 UNICODE_STRING CallbackName
;
656 /* Allocate registry path */
657 GlobalRegistryPath
.MaximumLength
= RegistryPath
->Length
+ sizeof(UNICODE_NULL
);
658 GlobalRegistryPath
.Length
= RegistryPath
->Length
;
659 GlobalRegistryPath
.Buffer
= ExAllocatePoolWithTag(PagedPool
,
660 GlobalRegistryPath
.MaximumLength
,
662 if (!GlobalRegistryPath
.Buffer
)
664 /* Fail if we're out of memory this early */
665 if (CmBattDebug
& CMBATT_GENERIC_WARNING
)
666 DbgPrint("CmBatt: Couldn't allocate pool for registry path.");
667 return STATUS_INSUFFICIENT_RESOURCES
;
670 /* Buffer allocated, copy the string */
671 RtlCopyUnicodeString(&GlobalRegistryPath
, RegistryPath
);
672 if (CmBattDebug
& CMBATT_GENERIC_INFO
)
673 DbgPrint("CmBatt DriverEntry - Obj (%08x) Path \"%ws\"\n",
675 RegistryPath
->Buffer
);
677 /* Setup the major dispatchers */
678 DriverObject
->MajorFunction
[0] = CmBattOpenClose
;
679 DriverObject
->MajorFunction
[2] = CmBattOpenClose
;
680 DriverObject
->MajorFunction
[14] = CmBattIoctl
;
681 DriverObject
->MajorFunction
[22] = CmBattPowerDispatch
;
682 DriverObject
->MajorFunction
[27] = CmBattPnpDispatch
;
683 DriverObject
->MajorFunction
[23] = CmBattSystemControl
;
685 /* And the unload routine */
686 DriverObject
->DriverUnload
= CmBattUnload
;
688 /* And the add device routine */
689 DriverExtension
= DriverObject
->DriverExtension
;
690 DriverExtension
->AddDevice
= CmBattAddDevice
;
692 /* Create a power callback */
693 RtlInitUnicodeString(&CallbackName
, L
"\\Callback\\PowerState");
694 InitializeObjectAttributes(&ObjectAttributes
,
699 Status
= ExCreateCallback(&CmBattPowerCallBackObject
, &ObjectAttributes
, 0, TRUE
);
700 if (!NT_SUCCESS(Status
))
702 /* No callback, fail */
703 CmBattPowerCallBackObject
= 0;
704 if (CmBattDebug
& CMBATT_GENERIC_WARNING
)
705 DbgPrint("CmBattRegisterPowerCallBack: failed status=0x%08x\n", Status
);
709 /* Register the power callback now */
710 CmBattPowerCallBackRegistration
= ExRegisterCallback(CmBattPowerCallBackObject
,
711 (PVOID
)CmBattPowerCallBack
,
713 if (CmBattPowerCallBackRegistration
)
715 /* Last thing: setup our DPC and timer for battery wake */
716 KeInitializeDpc(&CmBattWakeDpcObject
, (PVOID
)CmBattWakeDpc
, DriverObject
);
717 KeInitializeTimer(&CmBattWakeDpcTimerObject
);
721 ObfDereferenceObject(CmBattPowerCallBackObject
);
722 if (CmBattDebug
& CMBATT_GENERIC_WARNING
)
723 DbgPrint("CmBattRegisterPowerCallBack: ExRegisterCallback failed.\n");
727 Status
= STATUS_SUCCESS
;
730 /* Return failure or success */