[ACPI] Move CMBATT and COMPBATT out of the acpi directory (#7599)

Move these out of ACPI in preparation for ACPI_NEW so they keep their juicy commit history.
Also both ACPIs can coexist for awhile as I don't see the old driver getting removed anytime soon.
This commit is contained in:
Justin Miller 2025-01-29 00:49:35 -08:00 committed by GitHub
parent b35becef2e
commit a8da29e888
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
19 changed files with 3 additions and 3 deletions

View file

@ -0,0 +1,18 @@
list(APPEND SOURCE
compbatt.c
compmisc.c
comppnp.c)
list(APPEND PCH_SKIP_SOURCE
guid.c)
add_library(compbatt MODULE
${SOURCE}
${PCH_SKIP_SOURCE}
compbatt.rc)
set_module_type(compbatt kernelmodedriver)
add_importlibs(compbatt ntoskrnl hal battc)
add_pch(compbatt compbatt.h "${PCH_SKIP_SOURCE}")
add_cd_file(TARGET compbatt DESTINATION reactos/system32/drivers FOR all)

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,329 @@
/*
* PROJECT: ReactOS Composite Battery Driver
* LICENSE: MIT (https://spdx.org/licenses/MIT)
* PURPOSE: Composite battery main header file
* COPYRIGHT: Copyright 2010 ReactOS Portable Systems Group <ros.arm@reactos.org>
* Copyright 2024 George Bișoc <george.bisoc@reactos.org>
*/
/* INCLUDES *******************************************************************/
#ifndef _COMPBATT_PCH_
#define _COMPBATT_PCH_
#include <wdm.h>
#include <batclass.h>
/* DEFINES ********************************************************************/
//
// I/O remove lock allocate tag
//
#define COMPBATT_TAG 'aBoC'
//
// Composite battery flags
//
#define COMPBATT_BATTERY_INFORMATION_PRESENT 0x04
#define COMPBATT_STATUS_NOTIFY_SET 0x10
#define COMPBATT_TAG_ASSIGNED 0x80
//
// IRP complete worker mode states
//
#define COMPBATT_QUERY_TAG 1
#define COMPBATT_READ_STATUS 2
//
// Low/High capacity wait constants
//
#define COMPBATT_WAIT_MIN_LOW_CAPACITY 0
#define COMPBATT_WAIT_MAX_HIGH_CAPACITY 0x7FFFFFFF
//
// One hour in seconds, used to calculate the total rate of each battery for time estimation
//
#define COMPBATT_ATRATE_HOUR_IN_SECS 3600
//
// Time constant of which the battery status data is considered fresh (50000000 * 100ns == 5s)
//
#define COMPBATT_FRESH_STATUS_TIME 50000000
//
// Macro that calculates the delta of a battery's capacity
//
#define COMPUTE_BATT_CAP_DELTA(LowDiff, Batt, TotalRate) \
((ULONG)(((LONGLONG)LowDiff * (Batt)->BatteryStatus.Rate) / TotalRate))
//
// Macro that calculates the "At Rate" time drain of the battery
//
#define COMPUTE_ATRATE_DRAIN(Batt, Time) \
((LONG)((Batt)->BatteryStatus.Capacity) * COMPBATT_ATRATE_HOUR_IN_SECS / Time)
//
// Composite battery debug levels
//
#define COMPBATT_DEBUG_INFO 0x1
#define COMPBATT_DEBUG_TRACE 0x2
#define COMPBATT_DEBUG_WARN 0x4
#define COMPBATT_DEBUG_ERR 0x10
#define COMPBATT_DEBUG_ALL_LEVELS (COMPBATT_DEBUG_INFO | COMPBATT_DEBUG_TRACE | COMPBATT_DEBUG_WARN | COMPBATT_DEBUG_ERR)
/* STRUCTURES *****************************************************************/
//
// Individual ACPI battery data
//
typedef struct _COMPBATT_BATTERY_DATA
{
/* The linked battery with the Composite Battery */
LIST_ENTRY BatteryLink;
/* I/O remove lock which protects the battery from being removed */
IO_REMOVE_LOCK RemoveLock;
/*
* The associated device object (usually CMBATT) and the I/O battery packet
* which is used to transport and gather battery data.
*/
PDEVICE_OBJECT DeviceObject;
PIRP Irp;
/*
* The Executive work item, which serves as a worker item for the
* IRP battery monitor worker.
*/
WORK_QUEUE_ITEM WorkItem;
/*
* Execution state mode of the individual battery. Only two modes are valid:
*
* COMPBATT_QUERY_TAG - The battery is currently waiting for a tag to get assigned;
* COMPBATT_READ_STATUS - The battery is querying battery status.
*/
UCHAR Mode;
/*
* The battery wait configuration settings, set up by the SetStatusNotify method.
* These values are used to instruct CMBATT when the battery status should be retrieved.
*/
BATTERY_WAIT_STATUS WaitStatus;
/*
* A union that serves as the buffer which holds battery monitor IRP data, specifically
* managed by CompBattMonitorIrpCompleteWorker, to avoid allocating separate memory pools.
*/
union
{
BATTERY_WAIT_STATUS WorkerWaitStatus;
BATTERY_STATUS WorkerStatus;
ULONG WorkerTag;
} WorkerBuffer;
/* The ID of the battery that associates the identification of this battery */
ULONG Tag;
/*
* The battery flags that govern the behavior of the battery. The valid flags are:
*
* COMPBATT_BATTERY_INFORMATION_PRESENT - The static battery information ha been
* queried. Re-querying such information is not needed.
*
* COMPBATT_STATUS_NOTIFY_SET - The current notification wait settings are valid.
*
* COMPBATT_TAG_ASSIGNED - The battery has a tag assigned and it can be read.
*/
ULONG Flags;
/* The static battery information and battery status */
BATTERY_INFORMATION BatteryInformation;
BATTERY_STATUS BatteryStatus;
/* The interrupt time of which the battery status was last read */
ULONGLONG InterruptTime;
/* A uniquely given name of the battery that associates it */
UNICODE_STRING BatteryName;
} COMPBATT_BATTERY_DATA, *PCOMPBATT_BATTERY_DATA;
//
// Composite battery device extension data
//
typedef struct _COMPBATT_DEVICE_EXTENSION
{
/*
* The class data initialized and used by Battery Class. It contains information
* such as miniport data used for registration and communication between the
* Composite Battery and Battery Class, wait and context events, etc.
*/
PVOID ClassData;
/*
* The successor computed tag. This field is used when there are more upcoming
* batteries to be connected with the Composite Battery, of which the tag is
* incremented by 1 by each new battery that is connected.
*/
ULONG NextTag;
/* A list of linked batteries connected with the Composite Battery */
LIST_ENTRY BatteryList;
/* A mutex lock which ensures proper synchronization of Composite Battery operations */
FAST_MUTEX Lock;
/* The ID of the Composite Battery */
ULONG Tag;
/*
* The battery flags that govern the behavior of the battery. The valid flags are:
*
* COMPBATT_BATTERY_INFORMATION_PRESENT - The static battery information has been
* queried. Re-querying such information is not needed.
*
* COMPBATT_STATUS_NOTIFY_SET - The current notification wait settings are valid.
*
* COMPBATT_TAG_ASSIGNED - The battery has a tag assigned and it can be read.
*/
ULONG Flags;
/*
* The Composite Battery static information, status and wait status settings.
* Note that both the battery information and status are combined, based upon
* the individual information and status of each linked battery.
*/
BATTERY_INFORMATION BatteryInformation;
BATTERY_STATUS BatteryStatus;
BATTERY_WAIT_STATUS WaitNotifyStatus;
/* The interrupt time of which the battery status was last read */
ULONGLONG InterruptTime;
/*
* The physical device object that associates the Composite Battery and
* the attached device, typically the ACPI driver.
*/
PDEVICE_OBJECT AttachedDevice;
PDEVICE_OBJECT DeviceObject;
/* The notification entry that identifies the registered I/O PnP notification */
PVOID NotificationEntry;
} COMPBATT_DEVICE_EXTENSION, *PCOMPBATT_DEVICE_EXTENSION;
/* PROTOTYPES *****************************************************************/
NTSTATUS
NTAPI
CompBattAddDevice(
_In_ PDRIVER_OBJECT DriverObject,
_In_ PDEVICE_OBJECT PdoDeviceObject
);
NTSTATUS
NTAPI
CompBattPowerDispatch(
_In_ PDEVICE_OBJECT DeviceObject,
_In_ PIRP Irp
);
NTSTATUS
NTAPI
CompBattPnpDispatch(
_In_ PDEVICE_OBJECT DeviceObject,
_In_ PIRP Irp
);
NTSTATUS
NTAPI
CompBattQueryInformation(
_In_ PCOMPBATT_DEVICE_EXTENSION FdoExtension,
_In_ ULONG Tag,
_In_ BATTERY_QUERY_INFORMATION_LEVEL InfoLevel,
_In_opt_ LONG AtRate,
_In_ PVOID Buffer,
_In_ ULONG BufferLength,
_Out_ PULONG ReturnedLength
);
NTSTATUS
NTAPI
CompBattQueryStatus(
_In_ PCOMPBATT_DEVICE_EXTENSION DeviceExtension,
_In_ ULONG Tag,
_Out_ PBATTERY_STATUS BatteryStatus
);
NTSTATUS
NTAPI
CompBattGetEstimatedTime(
_Out_ PULONG Time,
_In_ PCOMPBATT_DEVICE_EXTENSION DeviceExtension
);
NTSTATUS
NTAPI
CompBattSetStatusNotify(
_In_ PCOMPBATT_DEVICE_EXTENSION DeviceExtension,
_In_ ULONG BatteryTag,
_In_ PBATTERY_NOTIFY BatteryNotify
);
NTSTATUS
NTAPI
CompBattDisableStatusNotify(
_In_ PCOMPBATT_DEVICE_EXTENSION DeviceExtension
);
NTSTATUS
NTAPI
CompBattQueryTag(
_In_ PCOMPBATT_DEVICE_EXTENSION DeviceExtension,
_Out_ PULONG Tag
);
NTSTATUS
NTAPI
CompBattMonitorIrpComplete(
_In_ PDEVICE_OBJECT DeviceObject,
_In_ PIRP Irp,
_In_ PVOID Context
);
VOID
NTAPI
CompBattMonitorIrpCompleteWorker(
_In_ PCOMPBATT_BATTERY_DATA BatteryData
);
NTSTATUS
NTAPI
CompBattGetDeviceObjectPointer(
_In_ PUNICODE_STRING DeviceName,
_In_ ACCESS_MASK DesiredAccess,
_Out_ PFILE_OBJECT *FileObject,
_Out_ PDEVICE_OBJECT *DeviceObject
);
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
);
NTSTATUS
NTAPI
CompBattRemoveBattery(
_In_ PUNICODE_STRING BatteryName,
_In_ PCOMPBATT_DEVICE_EXTENSION DeviceExtension
);
extern ULONG CompBattDebug;
#endif /* _COMPBATT_PCH_ */

View file

@ -0,0 +1,5 @@
#define REACTOS_VERSION_DLL
#define REACTOS_STR_FILE_DESCRIPTION "Composite Battery Driver"
#define REACTOS_STR_INTERNAL_NAME "compbatt"
#define REACTOS_STR_ORIGINAL_FILENAME "compbatt.sys"
#include <reactos/version.rc>

View file

@ -0,0 +1,128 @@
/*
* PROJECT: ReactOS Composite Battery Driver
* LICENSE: MIT (https://spdx.org/licenses/MIT)
* PURPOSE: Miscellaneous Support Routines
* COPYRIGHT: Copyright 2010 ReactOS Portable Systems Group <ros.arm@reactos.org>
*/
/* INCLUDES *******************************************************************/
#include "compbatt.h"
/* FUNCTIONS ******************************************************************/
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)
{
IO_STATUS_BLOCK IoStatusBlock;
KEVENT Event;
NTSTATUS Status;
PIRP Irp;
PAGED_CODE();
if (CompBattDebug & COMPBATT_DEBUG_TRACE) DbgPrint("CompBatt: ENTERING BatteryIoctl\n");
/* Initialize the event and IRP */
KeInitializeEvent(&Event, SynchronizationEvent, 0);
Irp = IoBuildDeviceIoControlRequest(IoControlCode,
DeviceObject,
InputBuffer,
InputBufferLength,
OutputBuffer,
OutputBufferLength,
InternalDeviceIoControl,
&Event,
&IoStatusBlock);
if (Irp)
{
/* Call the class driver miniport */
Status = IoCallDriver(DeviceObject, Irp);
if (Status == STATUS_PENDING)
{
/* Wait for result */
KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
Status = IoStatusBlock.Status;
}
/* Print failure */
if (!(NT_SUCCESS(Status)) && (CompBattDebug & COMPBATT_DEBUG_ERR))
DbgPrint("BatteryIoctl: Irp failed - %x\n", Status);
/* Done */
if (CompBattDebug & COMPBATT_DEBUG_TRACE) DbgPrint("CompBatt: EXITING BatteryIoctl\n");
}
else
{
/* Out of memory */
if (CompBattDebug & COMPBATT_DEBUG_ERR) DbgPrint("BatteryIoctl: couldn't create Irp\n");
Status = STATUS_INSUFFICIENT_RESOURCES;
}
/* Return status */
return Status;
}
NTSTATUS
NTAPI
CompBattGetDeviceObjectPointer(
_In_ PUNICODE_STRING DeviceName,
_In_ ACCESS_MASK DesiredAccess,
_Out_ PFILE_OBJECT *FileObject,
_Out_ PDEVICE_OBJECT *DeviceObject)
{
NTSTATUS Status;
OBJECT_ATTRIBUTES ObjectAttributes;
IO_STATUS_BLOCK IoStatusBlock;
PFILE_OBJECT LocalFileObject;
HANDLE DeviceHandle;
PAGED_CODE();
/* Open a file object handle to the device */
InitializeObjectAttributes(&ObjectAttributes,
DeviceName,
OBJ_KERNEL_HANDLE,
NULL,
NULL);
Status = ZwCreateFile(&DeviceHandle,
DesiredAccess,
&ObjectAttributes,
&IoStatusBlock,
NULL,
0,
FILE_SHARE_READ | FILE_SHARE_WRITE,
FILE_OPEN,
0,
NULL,
0);
if (NT_SUCCESS(Status))
{
/* Reference the file object */
Status = ObReferenceObjectByHandle(DeviceHandle,
0,
*IoFileObjectType,
KernelMode,
(PVOID)&LocalFileObject,
NULL);
if (NT_SUCCESS(Status))
{
/* Return the FO and the associated DO */
*FileObject = LocalFileObject;
*DeviceObject = IoGetRelatedDeviceObject(LocalFileObject);
}
/* Close the handle */
ZwClose(DeviceHandle);
}
/* Return status */
return Status;
}
/* EOF */

View file

@ -0,0 +1,505 @@
/*
* PROJECT: ReactOS Composite Battery Driver
* LICENSE: MIT (https://spdx.org/licenses/MIT)
* PURPOSE: Plug-and-Play IOCTL/IRP Handling
* COPYRIGHT: Copyright 2010 ReactOS Portable Systems Group <ros.arm@reactos.org>
*/
/* INCLUDES *******************************************************************/
#include "compbatt.h"
#include <wdmguid.h>
/* FUNCTIONS ******************************************************************/
NTSTATUS
NTAPI
CompBattPowerDispatch(
_In_ PDEVICE_OBJECT DeviceObject,
_In_ PIRP Irp)
{
PCOMPBATT_DEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
if (CompBattDebug & COMPBATT_DEBUG_WARN) DbgPrint("CompBatt: PowerDispatch received power IRP.\n");
/* Start the next IRP */
PoStartNextPowerIrp(Irp);
/* Call the next driver in the stack */
IoSkipCurrentIrpStackLocation(Irp);
return PoCallDriver(DeviceExtension->AttachedDevice, Irp);
}
PCOMPBATT_BATTERY_DATA
NTAPI
RemoveBatteryFromList(
_In_ PCUNICODE_STRING BatteryName,
_In_ PCOMPBATT_DEVICE_EXTENSION DeviceExtension)
{
PLIST_ENTRY ListHead, NextEntry;
PCOMPBATT_BATTERY_DATA BatteryData;
if (CompBattDebug & COMPBATT_DEBUG_TRACE)
DbgPrint("CompBatt: ENTERING RemoveBatteryFromList\n");
/* Loop the battery list */
ExAcquireFastMutex(&DeviceExtension->Lock);
ListHead = &DeviceExtension->BatteryList;
NextEntry = ListHead->Flink;
while (NextEntry != ListHead)
{
/* Get the battery information and compare the name */
BatteryData = CONTAINING_RECORD(NextEntry, COMPBATT_BATTERY_DATA, BatteryLink);
if (!RtlCompareUnicodeString(BatteryName, &BatteryData->BatteryName, TRUE))
{
/* Flush pending deletes and any lock waiters */
IoAcquireRemoveLock(&BatteryData->RemoveLock, 0);
ExReleaseFastMutex(&DeviceExtension->Lock);
IoReleaseRemoveLockAndWait(&BatteryData->RemoveLock, 0);
/* Remove the entry from the list */
ExAcquireFastMutex(&DeviceExtension->Lock);
RemoveEntryList(&BatteryData->BatteryLink);
ExReleaseFastMutex(&DeviceExtension->Lock);
return BatteryData;
}
/* Next */
NextEntry = NextEntry->Flink;
}
/* Done */
ExReleaseFastMutex(&DeviceExtension->Lock);
if (CompBattDebug & COMPBATT_DEBUG_TRACE) DbgPrint("CompBatt: EXITING RemoveBatteryFromList\n");
return NULL;
}
BOOLEAN
NTAPI
IsBatteryAlreadyOnList(
_In_ PCUNICODE_STRING BatteryName,
_In_ PCOMPBATT_DEVICE_EXTENSION DeviceExtension)
{
PLIST_ENTRY ListHead, NextEntry;
PCOMPBATT_BATTERY_DATA BatteryData;
BOOLEAN Found = FALSE;
if (CompBattDebug & COMPBATT_DEBUG_TRACE)
DbgPrint("CompBatt: ENTERING IsBatteryAlreadyOnList\n");
/* Loop the battery list */
ExAcquireFastMutex(&DeviceExtension->Lock);
ListHead = &DeviceExtension->BatteryList;
NextEntry = ListHead->Flink;
while (NextEntry != ListHead)
{
/* Get the battery information and compare the name */
BatteryData = CONTAINING_RECORD(NextEntry, COMPBATT_BATTERY_DATA, BatteryLink);
if (!RtlCompareUnicodeString(BatteryName, &BatteryData->BatteryName, TRUE))
{
/* Got it */
Found = TRUE;
break;
}
/* Next */
NextEntry = NextEntry->Flink;
}
/* Release the lock and return search status */
ExReleaseFastMutex(&DeviceExtension->Lock);
if (CompBattDebug & COMPBATT_DEBUG_TRACE) DbgPrint("CompBatt: EXITING IsBatteryAlreadyOnList\n");
return Found;
}
NTSTATUS
NTAPI
CompBattAddNewBattery(
_In_ PUNICODE_STRING BatteryName,
_In_ PCOMPBATT_DEVICE_EXTENSION DeviceExtension)
{
NTSTATUS Status = STATUS_SUCCESS;
PCOMPBATT_BATTERY_DATA BatteryData;
PIRP Irp;
PIO_STACK_LOCATION IoStackLocation;
PFILE_OBJECT FileObject;
PAGED_CODE();
if (CompBattDebug & COMPBATT_DEBUG_WARN)
DbgPrint("CompBatt: ENTERING AddNewBattery \"%w\" \n", BatteryName->Buffer);
/* Is this a new battery? */
if (!IsBatteryAlreadyOnList(BatteryName, DeviceExtension))
{
/* Allocate battery data */
BatteryData = ExAllocatePoolWithTag(NonPagedPool,
sizeof(COMPBATT_BATTERY_DATA) +
BatteryName->Length,
'CtaB');
if (BatteryData)
{
/* Initialize the data and write the battery name */
RtlZeroMemory(BatteryData, sizeof(COMPBATT_BATTERY_DATA));
BatteryData->Tag = BATTERY_TAG_INVALID;
BatteryData->BatteryName.MaximumLength = BatteryName->Length;
BatteryData->BatteryName.Buffer = (PWCHAR)(BatteryData + 1);
RtlCopyUnicodeString(&BatteryData->BatteryName, BatteryName);
/* Get the device object */
Status = CompBattGetDeviceObjectPointer(BatteryName,
FILE_ALL_ACCESS,
&FileObject,
&BatteryData->DeviceObject);
if (NT_SUCCESS(Status))
{
/* Reference the DO and drop the FO */
ObReferenceObject(BatteryData->DeviceObject);
ObDereferenceObject(FileObject);
/* Allocate the battery IRP */
Irp = IoAllocateIrp(BatteryData->DeviceObject->StackSize + 1, 0);
if (Irp)
{
/* Save it */
BatteryData->Irp = Irp;
/* Setup the stack location */
IoStackLocation = IoGetNextIrpStackLocation(Irp);
IoStackLocation->Parameters.Others.Argument1 = DeviceExtension;
IoStackLocation->Parameters.Others.Argument2 = BatteryData;
/* Set IRP data */
IoSetNextIrpStackLocation(Irp);
Irp->IoStatus.Status = STATUS_DEVICE_NOT_CONNECTED;
/* Insert this battery in the list */
ExAcquireFastMutex(&DeviceExtension->Lock);
InsertTailList(&DeviceExtension->BatteryList,
&BatteryData->BatteryLink);
ExReleaseFastMutex(&DeviceExtension->Lock);
/* Initialize the work item and delete lock */
IoInitializeRemoveLock(&BatteryData->RemoveLock, COMPBATT_TAG, 0, 0);
ExInitializeWorkItem(&BatteryData->WorkItem,
(PVOID)CompBattMonitorIrpCompleteWorker,
BatteryData);
/* Setup the IRP work entry */
CompBattMonitorIrpComplete(BatteryData->DeviceObject, Irp, NULL);
Status = STATUS_SUCCESS;
}
else
{
/* Fail, no memory */
if (CompBattDebug & COMPBATT_DEBUG_ERR)
DbgPrint("CompBatt: Couldn't allocate new battery Irp\n");
Status = STATUS_INSUFFICIENT_RESOURCES;
ObDereferenceObject(BatteryData->DeviceObject);
}
}
else if (CompBattDebug & COMPBATT_DEBUG_ERR)
{
/* Fail */
DbgPrint("CompBattAddNewBattery: Failed to get device Object. status = %lx\n",
Status);
}
if (!NT_SUCCESS(Status))
{
/* Free the battery data */
ExFreePool(BatteryData);
}
}
else
{
/* Fail, no memory */
if (CompBattDebug & COMPBATT_DEBUG_ERR)
DbgPrint("CompBatt: Couldn't allocate new battery node\n");
Status = STATUS_INSUFFICIENT_RESOURCES;
}
}
/* We're done */
if (CompBattDebug & COMPBATT_DEBUG_TRACE) DbgPrint("CompBatt: EXITING AddNewBattery\n");
return Status;
}
NTSTATUS
NTAPI
CompBattRemoveBattery(
_In_ PUNICODE_STRING BatteryName,
_In_ PCOMPBATT_DEVICE_EXTENSION DeviceExtension)
{
PCOMPBATT_BATTERY_DATA BatteryData;
if (CompBattDebug & COMPBATT_DEBUG_TRACE) DbgPrint("CompBatt: RemoveBattery\n");
/* Remove the entry */
BatteryData = RemoveBatteryFromList(BatteryName, DeviceExtension);
if (BatteryData)
{
/* Dereference and free it */
ObDereferenceObject(BatteryData->DeviceObject);
ExFreePool(BatteryData);
/* Notify class driver */
DeviceExtension->Flags = 0;
BatteryClassStatusNotify(DeviceExtension->ClassData);
}
/* It's done */
return STATUS_SUCCESS;
}
NTSTATUS
NTAPI
CompBattGetBatteries(
_In_ PCOMPBATT_DEVICE_EXTENSION DeviceExtension)
{
PWCHAR p;
NTSTATUS Status;
PWCHAR LinkList;
UNICODE_STRING LinkString;
if (CompBattDebug & COMPBATT_DEBUG_TRACE) DbgPrint("CompBatt: ENTERING GetBatteries\n");
/* Get all battery links */
Status = IoGetDeviceInterfaces(&GUID_DEVICE_BATTERY, NULL, 0, &LinkList);
p = LinkList;
if (NT_SUCCESS(Status))
{
/* Loop all strings inside */
while (TRUE)
{
/* Create the string */
RtlInitUnicodeString(&LinkString, p);
if (!LinkString.Length) break;
/* Add this battery and move on */
Status = CompBattAddNewBattery(&LinkString, DeviceExtension);
p += (LinkString.Length / sizeof(WCHAR)) + sizeof(UNICODE_NULL);
}
/* Parsing complete, clean up buffer */
ExFreePool(LinkList);
}
else if (CompBattDebug & COMPBATT_DEBUG_ERR)
{
/* Fail */
DbgPrint("CompBatt: Couldn't get list of batteries\n");
}
/* Done */
if (CompBattDebug & COMPBATT_DEBUG_TRACE) DbgPrint("CompBatt: EXITING GetBatteries\n");
return Status;
}
NTSTATUS
NTAPI
CompBattPnpEventHandler(
_In_ PDEVICE_INTERFACE_CHANGE_NOTIFICATION Notification,
_In_ PCOMPBATT_DEVICE_EXTENSION DeviceExtension)
{
if (CompBattDebug & COMPBATT_DEBUG_TRACE) DbgPrint("CompBatt: ENTERING PnpEventHandler\n");
if (CompBattDebug & COMPBATT_DEBUG_WARN) DbgPrint("CompBatt: Received device interface change notification\n");
/* Check what happened */
if (IsEqualGUIDAligned(&Notification->Event, &GUID_DEVICE_INTERFACE_ARRIVAL))
{
/* Add the new battery */
if (CompBattDebug & COMPBATT_DEBUG_WARN)
DbgPrint("CompBatt: Received notification of battery arrival\n");
CompBattAddNewBattery(Notification->SymbolicLinkName, DeviceExtension);
}
else if (IsEqualGUIDAligned(&Notification->Event, &GUID_DEVICE_INTERFACE_REMOVAL))
{
/* Don't do anything */
if (CompBattDebug & COMPBATT_DEBUG_WARN)
DbgPrint("CompBatt: Received notification of battery removal\n");
}
else
{
/* Shouldn't happen */
if (CompBattDebug & COMPBATT_DEBUG_WARN) DbgPrint("CompBatt: Received unhandled PnP event\n");
}
/* Done, return success */
if (CompBattDebug & COMPBATT_DEBUG_TRACE) DbgPrint("CompBatt: EXITING PnpEventHandler\n");
return STATUS_SUCCESS;
}
NTSTATUS
NTAPI
CompBattAddDevice(
_In_ PDRIVER_OBJECT DriverObject,
_In_ PDEVICE_OBJECT PdoDeviceObject)
{
NTSTATUS Status;
UNICODE_STRING DeviceName;
PCOMPBATT_DEVICE_EXTENSION DeviceExtension;
PDEVICE_OBJECT DeviceObject;
UNICODE_STRING SymbolicLinkName;
BATTERY_MINIPORT_INFO MiniportInfo;
if (CompBattDebug & COMPBATT_DEBUG_WARN) DbgPrint("CompBatt: Got an AddDevice - %x\n", PdoDeviceObject);
/* Create the device */
RtlInitUnicodeString(&DeviceName, L"\\Device\\CompositeBattery");
Status = IoCreateDevice(DriverObject,
sizeof(COMPBATT_DEVICE_EXTENSION),
&DeviceName,
FILE_DEVICE_BATTERY,
FILE_DEVICE_SECURE_OPEN,
FALSE,
&DeviceObject);
if (!NT_SUCCESS(Status)) return Status;
/* Setup symbolic link for Win32 access */
RtlInitUnicodeString(&SymbolicLinkName, L"\\DosDevices\\CompositeBattery");
IoCreateSymbolicLink(&SymbolicLinkName, &DeviceName);
/* Initialize the device extension */
DeviceExtension = DeviceObject->DeviceExtension;
RtlZeroMemory(DeviceExtension, sizeof(COMPBATT_DEVICE_EXTENSION));
/* Attach to device stack and set DO pointers */
DeviceExtension->AttachedDevice = IoAttachDeviceToDeviceStack(DeviceObject,
PdoDeviceObject);
DeviceExtension->DeviceObject = DeviceObject;
if (!DeviceExtension->AttachedDevice)
{
/* Fail */
if (CompBattDebug & COMPBATT_DEBUG_ERR)
DbgPrint("CompBattAddDevice: Could not attach to LowerDevice.\n");
IoDeleteDevice(DeviceObject);
return STATUS_UNSUCCESSFUL;
}
/* Set device object flags */
DeviceObject->Flags |= (DO_POWER_PAGABLE | DO_BUFFERED_IO);
DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
/* Setup the device extension */
ExInitializeFastMutex(&DeviceExtension->Lock);
InitializeListHead(&DeviceExtension->BatteryList);
DeviceExtension->Flags = 0;
DeviceExtension->NextTag = 1;
/* Setup the miniport data */
RtlZeroMemory(&MiniportInfo, sizeof(MiniportInfo));
MiniportInfo.MajorVersion = BATTERY_CLASS_MAJOR_VERSION;
MiniportInfo.MinorVersion = BATTERY_CLASS_MINOR_VERSION;
MiniportInfo.Context = DeviceExtension;
MiniportInfo.DeviceName = &DeviceName;
MiniportInfo.QueryTag = (BCLASS_QUERY_TAG)CompBattQueryTag;
MiniportInfo.QueryInformation = (BCLASS_QUERY_INFORMATION)CompBattQueryInformation;
MiniportInfo.SetInformation = NULL;
MiniportInfo.QueryStatus = (BCLASS_QUERY_STATUS)CompBattQueryStatus;
MiniportInfo.SetStatusNotify = (BCLASS_SET_STATUS_NOTIFY)CompBattSetStatusNotify;
MiniportInfo.DisableStatusNotify = (BCLASS_DISABLE_STATUS_NOTIFY)CompBattDisableStatusNotify;
MiniportInfo.Pdo = NULL;
/* Register with the class driver */
Status = BatteryClassInitializeDevice(&MiniportInfo,
&DeviceExtension->ClassData);
if (!NT_SUCCESS(Status))
{
/* Undo everything */
IoDetachDevice(DeviceExtension->AttachedDevice);
IoDeleteDevice(DeviceObject);
}
/* Return status */
return Status;
}
NTSTATUS
NTAPI
CompBattPnpDispatch(
_In_ PDEVICE_OBJECT DeviceObject,
_In_ PIRP Irp)
{
PIO_STACK_LOCATION IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
NTSTATUS Status;
PCOMPBATT_DEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
if (CompBattDebug & COMPBATT_DEBUG_TRACE) DbgPrint("CompBatt: ENTERING PnpDispatch\n");
/* Set default error */
Status = STATUS_NOT_SUPPORTED;
/* Check what kind of PnP function this is */
switch (IoStackLocation->MinorFunction)
{
case IRP_MN_START_DEVICE:
/* Device is starting, register for new batteries and pick up current ones */
Status = IoRegisterPlugPlayNotification(EventCategoryDeviceInterfaceChange,
0,
(PVOID)&GUID_DEVICE_BATTERY,
DeviceObject->DriverObject,
(PDRIVER_NOTIFICATION_CALLBACK_ROUTINE)CompBattPnpEventHandler,
DeviceExtension,
&DeviceExtension->NotificationEntry);
if (NT_SUCCESS(Status))
{
/* Now go get the batteries */
if (CompBattDebug & COMPBATT_DEBUG_WARN)
DbgPrint("CompBatt: Successfully registered for PnP notification\n");
Status = CompBattGetBatteries(DeviceExtension);
}
else
{
/* We failed */
if (CompBattDebug & COMPBATT_DEBUG_ERR)
DbgPrint("CompBatt: Couldn't register for PnP notification - %x\n",
Status);
}
break;
case IRP_MN_CANCEL_STOP_DEVICE:
/* Explicitly say ok */
Status = STATUS_SUCCESS;
break;
case IRP_MN_CANCEL_REMOVE_DEVICE:
/* Explicitly say ok */
Status = STATUS_SUCCESS;
break;
case IRP_MN_SURPRISE_REMOVAL:
/* Explicitly say ok */
Status = STATUS_SUCCESS;
break;
case IRP_MN_QUERY_PNP_DEVICE_STATE:
/* Add this in */
Irp->IoStatus.Information |= PNP_DEVICE_NOT_DISABLEABLE;
Status = STATUS_SUCCESS;
break;
default:
/* Not supported */
break;
}
/* Set IRP status if we have one */
if (Status != STATUS_NOT_SUPPORTED) Irp->IoStatus.Status = Status;
/* Did someone pick it up? */
if ((NT_SUCCESS(Status)) || (Status == STATUS_NOT_SUPPORTED))
{
/* Still unsupported, try ACPI */
IoSkipCurrentIrpStackLocation(Irp);
Status = IoCallDriver(DeviceExtension->AttachedDevice, Irp);
}
else
{
/* Complete the request */
Status = Irp->IoStatus.Status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
}
/* Release the remove lock and return status */
if (CompBattDebug & COMPBATT_DEBUG_TRACE) DbgPrint("CompBatt: EXITING PnpDispatch\n");
return Status;
}
/* EOF */

View file

@ -0,0 +1,8 @@
/* DO NOT USE THE PRECOMPILED HEADER FOR THIS FILE! */
#include <wdm.h>
#include <initguid.h>
#include <wdmguid.h>
#include <batclass.h>
/* NO CODE HERE, THIS IS JUST REQUIRED FOR THE GUID DEFINITIONS */