#include #include #ifndef FAR #define FAR #endif // // Debug // #define DEBUG DBG #if DEBUG extern ULONG CompBattDebug; #define BattPrint(l,m) if(l & CompBattDebug) DbgPrint m #else #define BattPrint(l,m) #endif #define BATT_LOW 0x00000001 #define BATT_NOTE 0x00000002 #define BATT_WARN 0x00000004 #define BATT_ERROR 0x00000008 #define BATT_ERRORS (BATT_ERROR | BATT_WARN) #define BATT_MP 0x00000010 #define BATT_DEBUG 0x00000020 #define BATT_TRACE 0x00000100 #define BATT_DATA 0x00000200 // // Battery class info // #define NTMS 10000L // 1 millisecond is ten thousand 100ns #define NTSEC (NTMS * 1000L) #define NTMIN ((ULONGLONG) 60 * NTSEC) #define SEC 1000 #define MIN (60 * SEC) // // Poll rates for when a notification alarm cannot be set // #define MIN_STATUS_POLL_RATE (3L * NTMIN) #define MAX_STATUS_POLL_RATE (20 * NTSEC) #define STATUS_VALID_TIME (2 * NTSEC) #define MAX_HIGH_CAPACITY 0x7fffffff #define MIN_LOW_CAPACITY 0x0 // // Charge/Discharge policy values (in percent) // #define BATTERY_MIN_SAFE_CAPACITY 2 // Min we will attempt to run on #define BATTERY_MAX_CHARGE_CAPACITY 90 // Max we will attempt to charge // // Cache expiration timeouts -- when the cached battery status/info expires. // #define CACHE_STATUS_TIMEOUT (4 * NTSEC) #define CACHE_INFO_TIMEOUT (4 * NTSEC) // // Cached battery info // typedef struct { ULONG Tag; ULONG Valid; BATTERY_INFORMATION Info; ULONGLONG InfoTimeStamp; UCHAR ManufacturerNameLength; UCHAR ManufacturerName[MAX_BATTERY_STRING_SIZE]; UCHAR DeviceNameLength; UCHAR DeviceName[MAX_BATTERY_STRING_SIZE]; BATTERY_MANUFACTURE_DATE ManufacturerDate; ULONG SerialNumber; BATTERY_STATUS Status; ULONGLONG StatusTimeStamp; } STATIC_BAT_INFO, *PSTATIC_BAT_INFO; #define VALID_TAG_DATA 0x01 // manufacturer, device, serial # #define VALID_MODE 0x02 #define VALID_INFO 0x04 #define VALID_CYCLE_COUNT 0x08 #define VALID_SANITY_CHECK 0x10 #define VALID_TAG 0x80 #define VALID_NOTIFY 0x100 #define VALID_ALL 0x1F // (does not include tag) // // Locking mechanism for battery nodes so we don't delete out from under // ourselves. I would just use an IO_REMOVE_LOCK, but that's NT not WDM... // typedef struct _COMPBATT_DELETE_LOCK { BOOLEAN Deleted; BOOLEAN Reserved [3]; LONG RefCount; KEVENT DeleteEvent; } COMPBATT_DELETE_LOCK, *PCOMPBATT_DELETE_LOCK; VOID CompbattInitializeDeleteLock ( IN PCOMPBATT_DELETE_LOCK Lock ); NTSTATUS CompbattAcquireDeleteLock ( IN PCOMPBATT_DELETE_LOCK Lock ); VOID CompbattReleaseDeleteLock ( IN PCOMPBATT_DELETE_LOCK Lock ); VOID CompbattReleaseDeleteLockAndWait ( IN PCOMPBATT_DELETE_LOCK Lock ); // // Battery node in the composite's list of batteries // typedef struct { LIST_ENTRY Batteries; // All batteries in composite COMPBATT_DELETE_LOCK DeleteLock; PDEVICE_OBJECT DeviceObject; // device object for the battery PIRP StatusIrp; // current status irp at device WORK_QUEUE_ITEM WorkItem; // Used for restarting status Irp // if it is completed at DPC level BOOLEAN NewBatt; // Is this a new battery on the list UCHAR State; BATTERY_WAIT_STATUS Wait; union { BATTERY_STATUS Status; BATTERY_WAIT_STATUS Wait; ULONG Tag; } IrpBuffer; // // Keep some static information around so we don't have to go out to the // batteries all the time. // STATIC_BAT_INFO Info; // // Symbolic link name for the battery. Since we calculate the length of this // structure based on the structure size plus the length of this string, the // string must be the last thing declared in the structure. // UNICODE_STRING BattName; } COMPOSITE_ENTRY, *PCOMPOSITE_ENTRY; #define CB_ST_GET_TAG 0 #define CB_ST_GET_STATUS 1 // // Composite battery device extension // typedef struct { PVOID Class; // Class information // ULONG Tag; // Current tag of composite battery ULONG NextTag; // Next tag LIST_ENTRY Batteries; // All batteries FAST_MUTEX ListMutex; // List synchronization // // Keep some static information around so we don't have to go out to the // batteries all the time. // STATIC_BAT_INFO Info; BATTERY_WAIT_STATUS Wait; PDEVICE_OBJECT LowerDevice; // PDO PDEVICE_OBJECT DeviceObject; // Compbatt Device PVOID NotificationEntry; // PnP registration handle } COMPOSITE_BATTERY, *PCOMPOSITE_BATTERY; // // Prototypes // NTSTATUS DriverEntry ( IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath ); NTSTATUS CompBattIoctl( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ); NTSTATUS CompBattSystemControl( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ); NTSTATUS CompBattQueryTag ( IN PVOID Context, OUT PULONG BatteryTag ); NTSTATUS CompBattQueryInformation ( IN PVOID Context, IN ULONG BatteryTag, IN BATTERY_QUERY_INFORMATION_LEVEL Level, IN LONG AtRate, OUT PVOID Buffer, IN ULONG BufferLength, OUT PULONG ReturnedLength ); NTSTATUS CompBattQueryStatus ( IN PVOID Context, IN ULONG BatteryTag, OUT PBATTERY_STATUS BatteryStatus ); NTSTATUS CompBattSetStatusNotify ( IN PVOID Context, IN ULONG BatteryTag, IN PBATTERY_NOTIFY BatteryNotify ); NTSTATUS CompBattDisableStatusNotify ( IN PVOID Context ); NTSTATUS CompBattDriverEntry ( IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath ); NTSTATUS CompBattGetBatteryInformation ( IN PBATTERY_INFORMATION TotalBattInfo, IN PCOMPOSITE_BATTERY CompBatt ); NTSTATUS CompBattGetBatteryGranularity ( IN PBATTERY_REPORTING_SCALE GranularityBuffer, IN PCOMPOSITE_BATTERY CompBatt ); NTSTATUS CompBattPrivateIoctl( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ); NTSTATUS CompBattGetEstimatedTime ( IN PULONG TimeBuffer, IN PCOMPOSITE_BATTERY CompBatt ); NTSTATUS CompBattAddDevice ( IN PDRIVER_OBJECT DriverObject, IN PDEVICE_OBJECT PDO ); NTSTATUS CompBattPowerDispatch( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ); NTSTATUS CompBattPnpDispatch( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ); VOID CompBattUnload( IN PDRIVER_OBJECT DriverObject ); NTSTATUS CompBattOpenClose( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ); NTSTATUS BatteryIoctl( IN ULONG Ioctl, IN PDEVICE_OBJECT DeviceObject, IN PVOID InputBuffer, IN ULONG InputBufferLength, IN PVOID OutputBuffer, IN ULONG OutputBufferLength, IN BOOLEAN PrivateIoctl ); NTSTATUS CompBattPnpEventHandler( IN PVOID NotificationStructure, IN PVOID Context ); NTSTATUS CompBattAddNewBattery( IN PUNICODE_STRING SymbolicLinkName, IN PCOMPOSITE_BATTERY CompBatt ); NTSTATUS CompBattRemoveBattery( IN PUNICODE_STRING SymbolicLinkName, IN PCOMPOSITE_BATTERY CompBatt ); BOOLEAN IsBatteryAlreadyOnList( IN PUNICODE_STRING SymbolicLinkName, IN PCOMPOSITE_BATTERY CompBatt ); PCOMPOSITE_ENTRY RemoveBatteryFromList( IN PUNICODE_STRING SymbolicLinkName, IN PCOMPOSITE_BATTERY CompBatt ); NTSTATUS CompBattGetBatteries( IN PCOMPOSITE_BATTERY CompBatt ); BOOLEAN CompBattVerifyStaticInfo ( IN PCOMPOSITE_BATTERY CompBatt ); VOID CompBattMonitorIrpCompleteWorker ( IN PVOID Context ); NTSTATUS CompBattMonitorIrpComplete ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context ); VOID CompBattRecalculateTag ( IN PCOMPOSITE_BATTERY CompBatt ); VOID CompBattChargeDischarge ( IN PCOMPOSITE_BATTERY CompBatt ); NTSTATUS CompBattGetDeviceObjectPointer( IN PUNICODE_STRING ObjectName, IN ACCESS_MASK DesiredAccess, OUT PFILE_OBJECT *FileObject, OUT PDEVICE_OBJECT *DeviceObject );