You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
819 lines
23 KiB
819 lines
23 KiB
/*++
|
|
|
|
Copyright (c) 1990 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
Abstract:
|
|
|
|
Author:
|
|
|
|
Ken Reneris
|
|
|
|
Environment:
|
|
|
|
console
|
|
|
|
--*/
|
|
|
|
//
|
|
// set variable to define global variables
|
|
//
|
|
|
|
#include <tchar.h>
|
|
#include <wchar.h>
|
|
#include <nt.h>
|
|
#include <ntrtl.h>
|
|
#include <nturtl.h>
|
|
#include <windows.h>
|
|
#include <initguid.h>
|
|
#include <devguid.h>
|
|
|
|
#include <errno.h>
|
|
//#include <malloc.h>
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <batclass.h>
|
|
|
|
#include <setupapi.h>
|
|
|
|
//
|
|
// Misc constants
|
|
//
|
|
#define RANGE 1
|
|
#define MAX_NUMBER_OF_BATTERIES 8
|
|
#define MAX_DEVICE_NAME_LENGTH 100
|
|
|
|
//
|
|
// Battery Device Names
|
|
//
|
|
PVOID COMPOSITE_NAME = _T("\\Device\\CompositeBattery");
|
|
|
|
//
|
|
// Globals
|
|
//
|
|
BOOLEAN LongTerm = FALSE;
|
|
|
|
#pragma pack(1)
|
|
typedef struct _ID_MAP {
|
|
UCHAR LocalId;
|
|
UCHAR ActualId;
|
|
} ID_MAP, *PID_MAP;
|
|
#pragma pack()
|
|
|
|
|
|
#pragma pack(1)
|
|
typedef struct _MFG_DATE {
|
|
|
|
UCHAR Day; // 1-31
|
|
UCHAR Month; // 1-12
|
|
USHORT Year; // 1996 - ?
|
|
} MFG_DATE, *PMFG_DATE;
|
|
#pragma pack()
|
|
|
|
|
|
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* GetBatteryDriverNames
|
|
*
|
|
* DESCRIPTION: Finds all battery class devices
|
|
*
|
|
* PARAMETERS:
|
|
* DriverNames - pointer to an array of UNICODE_STRING structures to fill in
|
|
* MaxBatteries - number of elements in DriverNames array
|
|
*
|
|
* RETURN VALUE: The number of batteries found
|
|
* Will always find the Composite battery whether it exists or not
|
|
*
|
|
*******************************************************************************/
|
|
|
|
UCHAR GetBatteryDriverNames(UNICODE_STRING * DriverNames, UCHAR MaxBatteries)
|
|
{
|
|
UCHAR driverCount, index;
|
|
DWORD reqSize;
|
|
HDEVINFO devInfo;
|
|
SP_INTERFACE_DEVICE_DATA interfaceDevData;
|
|
PSP_INTERFACE_DEVICE_DETAIL_DATA funcClassDevData;
|
|
|
|
if ((MaxBatteries == 0) || (DriverNames == NULL)) {
|
|
return 0;
|
|
}
|
|
|
|
driverCount = 0;
|
|
|
|
// Hard code the first battery to be the composite battery.
|
|
|
|
RtlInitUnicodeString (&DriverNames[driverCount], COMPOSITE_NAME);
|
|
driverCount++;
|
|
|
|
// Use the SETUPAPI.DLL interface to get the
|
|
// possible battery driver names.
|
|
devInfo = SetupDiGetClassDevs((LPGUID)&GUID_DEVICE_BATTERY, NULL, NULL,
|
|
DIGCF_PRESENT | DIGCF_INTERFACEDEVICE);
|
|
|
|
if (devInfo != INVALID_HANDLE_VALUE) {
|
|
interfaceDevData.cbSize = sizeof(SP_DEVINFO_DATA);
|
|
|
|
index = 0;
|
|
while (driverCount < MaxBatteries) {
|
|
if (SetupDiEnumInterfaceDevice(devInfo,
|
|
0,
|
|
(LPGUID)&GUID_DEVICE_BATTERY,
|
|
index,
|
|
&interfaceDevData)) {
|
|
|
|
// Get the required size of the function class device data.
|
|
SetupDiGetInterfaceDeviceDetail(devInfo,
|
|
&interfaceDevData,
|
|
NULL,
|
|
0,
|
|
&reqSize,
|
|
NULL);
|
|
|
|
funcClassDevData = LocalAlloc(0, reqSize);
|
|
if (funcClassDevData != NULL) {
|
|
funcClassDevData->cbSize =
|
|
sizeof(SP_INTERFACE_DEVICE_DETAIL_DATA);
|
|
|
|
if (SetupDiGetInterfaceDeviceDetail(devInfo,
|
|
&interfaceDevData,
|
|
funcClassDevData,
|
|
reqSize,
|
|
&reqSize,
|
|
NULL)) {
|
|
|
|
reqSize = (lstrlen(funcClassDevData->DevicePath) + 1)
|
|
* sizeof(TCHAR);
|
|
|
|
RtlInitUnicodeString(
|
|
&DriverNames[driverCount],
|
|
funcClassDevData->DevicePath
|
|
);
|
|
driverCount++;
|
|
}
|
|
else {
|
|
printf("SetupDiGetInterfaceDeviceDetail, failed: %d", GetLastError());
|
|
}
|
|
|
|
LocalFree(funcClassDevData);
|
|
}
|
|
} else {
|
|
if (ERROR_NO_MORE_ITEMS == GetLastError()) {
|
|
break;
|
|
}
|
|
else {
|
|
printf ("SetupDiEnumInterfaceDevice, failed: %d", GetLastError());
|
|
}
|
|
}
|
|
index++;
|
|
}
|
|
SetupDiDestroyDeviceInfoList(devInfo);
|
|
}
|
|
else {
|
|
printf("SetupDiGetClassDevs on GUID_DEVICE_BATTERY, failed: %d", GetLastError());
|
|
}
|
|
return driverCount;
|
|
}
|
|
|
|
|
|
HANDLE
|
|
OpenBattery (PUNICODE_STRING BatteryName)
|
|
{
|
|
NTSTATUS status;
|
|
OBJECT_ATTRIBUTES ObjA;
|
|
IO_STATUS_BLOCK IOSB;
|
|
HANDLE driverHandle;
|
|
|
|
DWORD lastError;
|
|
|
|
|
|
// HACK: I can't seems to find the correct device
|
|
// names, so I can't open the composite battery using CreateFile()
|
|
// and I can't open the detected batteries using NtOpenFile(), so I
|
|
// have to use a different method of opening the battery depending on
|
|
// which battery it is.
|
|
if (BatteryName->Buffer == COMPOSITE_NAME) {
|
|
InitializeObjectAttributes(
|
|
&ObjA,
|
|
BatteryName,
|
|
OBJ_CASE_INSENSITIVE,
|
|
0,
|
|
0 );
|
|
|
|
status = NtOpenFile (
|
|
&driverHandle, // return handle
|
|
SYNCHRONIZE | FILE_READ_DATA | FILE_WRITE_DATA, // desired access
|
|
&ObjA, // Object
|
|
&IOSB, // io status block
|
|
FILE_SHARE_READ | FILE_SHARE_WRITE, // share access
|
|
FILE_SYNCHRONOUS_IO_ALERT // open options
|
|
);
|
|
|
|
if (!NT_SUCCESS(status)) {
|
|
printf ("Error opening %ws: NTSTATUS = 0x%08lx\n",
|
|
BatteryName->Buffer, status);
|
|
return NULL;
|
|
}
|
|
} else {
|
|
driverHandle = CreateFile (BatteryName->Buffer,
|
|
GENERIC_READ | GENERIC_WRITE,
|
|
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
|
NULL,
|
|
OPEN_EXISTING,
|
|
FILE_ATTRIBUTE_NORMAL,
|
|
NULL);
|
|
|
|
if (INVALID_HANDLE_VALUE == driverHandle) {
|
|
lastError = GetLastError ();
|
|
printf ("Error opening %ws: GetLastError = 0x%08lx \n",
|
|
BatteryName->Buffer, lastError);
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
printf("Opened %ws \n", BatteryName->Buffer);
|
|
|
|
return driverHandle;
|
|
}
|
|
|
|
|
|
ULONG
|
|
GetBatteryTag (HANDLE DriverHandle)
|
|
{
|
|
NTSTATUS Status;
|
|
IO_STATUS_BLOCK IOSB;
|
|
ULONG BatteryTag;
|
|
ULONG Timeout = 0;
|
|
|
|
if (LongTerm) {
|
|
Timeout = (ULONG)-1;
|
|
}
|
|
|
|
Status = NtDeviceIoControlFile(
|
|
DriverHandle,
|
|
(HANDLE) NULL, // event
|
|
(PIO_APC_ROUTINE) NULL,
|
|
(PVOID) NULL,
|
|
&IOSB,
|
|
IOCTL_BATTERY_QUERY_TAG,
|
|
&Timeout, // input buffer
|
|
sizeof (Timeout),
|
|
&BatteryTag, // output buffer
|
|
sizeof (BatteryTag)
|
|
);
|
|
|
|
|
|
if (!NT_SUCCESS(Status)) {
|
|
BatteryTag = BATTERY_TAG_INVALID;
|
|
if (Status == STATUS_NO_SUCH_DEVICE) {
|
|
printf ("(Battery is not physically present or is not connected)\n");
|
|
} else {
|
|
printf ("Query Battery tag failed: Status = %x\n", Status);
|
|
}
|
|
|
|
}
|
|
|
|
printf("Battery Tag = 0x%08lx.\n", BatteryTag);
|
|
return BatteryTag;
|
|
}
|
|
|
|
|
|
BOOLEAN
|
|
GetBatteryInfo (
|
|
HANDLE DriverHandle,
|
|
ULONG BatteryTag,
|
|
IN BATTERY_QUERY_INFORMATION_LEVEL Level,
|
|
OUT PVOID Buffer,
|
|
IN ULONG BufferLength
|
|
)
|
|
{
|
|
NTSTATUS Status;
|
|
IO_STATUS_BLOCK IOSB;
|
|
BATTERY_QUERY_INFORMATION BInfo;
|
|
|
|
memset (Buffer, 0, BufferLength);
|
|
BInfo.BatteryTag = BatteryTag;
|
|
BInfo.InformationLevel = Level;
|
|
BInfo.AtRate = 0; // This is needed for reading estimated time correctly.
|
|
|
|
Status = NtDeviceIoControlFile(
|
|
DriverHandle,
|
|
(HANDLE) NULL, // event
|
|
(PIO_APC_ROUTINE) NULL,
|
|
(PVOID) NULL,
|
|
&IOSB,
|
|
IOCTL_BATTERY_QUERY_INFORMATION,
|
|
&BInfo, // input buffer
|
|
sizeof (BInfo),
|
|
Buffer, // output buffer
|
|
BufferLength
|
|
);
|
|
|
|
|
|
if (!NT_SUCCESS(Status)) {
|
|
|
|
if ((Status == STATUS_INVALID_PARAMETER) ||
|
|
(Status == STATUS_INVALID_DEVICE_REQUEST) ||
|
|
(Status == STATUS_NOT_SUPPORTED)) {
|
|
|
|
printf ("Not Supported by Battery, Level %x, Status: %x\n", Level, Status);
|
|
} else {
|
|
printf ("Query failed: Level %x, Status = %x\n", Level, Status);
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
|
|
|
|
VOID
|
|
GetBatteryStatus (
|
|
HANDLE DriverHandle,
|
|
IN PBATTERY_WAIT_STATUS WaitStatus,
|
|
IN PBATTERY_INFORMATION BInfo,
|
|
OUT PBATTERY_STATUS BatteryStatus
|
|
)
|
|
{
|
|
NTSTATUS Status;
|
|
IO_STATUS_BLOCK IOSB;
|
|
ULONG Volts;
|
|
|
|
|
|
memset (BatteryStatus, 0xAB, sizeof(BatteryStatus));
|
|
|
|
Status = NtDeviceIoControlFile(
|
|
DriverHandle,
|
|
(HANDLE) NULL, // event
|
|
(PIO_APC_ROUTINE) NULL,
|
|
(PVOID) NULL,
|
|
&IOSB,
|
|
IOCTL_BATTERY_QUERY_STATUS,
|
|
WaitStatus, // input buffer
|
|
sizeof (BATTERY_WAIT_STATUS),
|
|
BatteryStatus, // output buffer
|
|
sizeof (BATTERY_STATUS)
|
|
);
|
|
|
|
//
|
|
// dump battery status
|
|
//
|
|
printf ("[Current Status Information]\n");
|
|
printf (" Power State...........: ");
|
|
|
|
if (!NT_SUCCESS(Status)) {
|
|
printf ("Query failed: Status = %x\n", Status);
|
|
return ;
|
|
}
|
|
|
|
|
|
//
|
|
// Print the PowerState
|
|
//
|
|
|
|
printf ("%08x ", BatteryStatus->PowerState);
|
|
|
|
if (BatteryStatus->PowerState & BATTERY_POWER_ON_LINE) {
|
|
printf ("Power_Online ");
|
|
}
|
|
|
|
if (BatteryStatus->PowerState & BATTERY_DISCHARGING) {
|
|
printf ("Discharging ");
|
|
}
|
|
|
|
if (BatteryStatus->PowerState & BATTERY_CHARGING) {
|
|
printf ("Charging ");
|
|
}
|
|
|
|
if (BatteryStatus->PowerState & BATTERY_CRITICAL) {
|
|
printf ("Critical! ");
|
|
}
|
|
|
|
if (BatteryStatus->PowerState == 0) {
|
|
printf ("No flags set.");
|
|
}
|
|
|
|
printf ("\n");
|
|
|
|
|
|
//
|
|
// Print the Voltage
|
|
//
|
|
|
|
Volts = BatteryStatus->Voltage;
|
|
if (Volts == BATTERY_UNKNOWN_VOLTAGE) {
|
|
printf (" Voltage...............: %08x UNKNOWN\n", Volts);
|
|
} else {
|
|
printf (" Voltage...............: %08x %d.%03d V\n", Volts, (Volts/1000), Volts - ((Volts/1000)*1000));
|
|
}
|
|
|
|
|
|
//
|
|
// Print the Rate
|
|
//
|
|
|
|
if (BatteryStatus->Rate == BATTERY_UNKNOWN_RATE) {
|
|
printf (" Rate..................: %08x UNKNOWN\n", BatteryStatus->Rate);
|
|
} else {
|
|
if (BInfo->Capabilities & BATTERY_CAPACITY_RELATIVE) {
|
|
printf (" Rate..................: %08x %d % per hour ", BatteryStatus->Rate, BatteryStatus->Rate);
|
|
} else {
|
|
printf (" Rate..................: %08x %d mW ", BatteryStatus->Rate, BatteryStatus->Rate);
|
|
}
|
|
|
|
if (BatteryStatus->PowerState & BATTERY_CHARGING) {
|
|
printf ("(Charging)\n");
|
|
} else if (BatteryStatus->PowerState & BATTERY_DISCHARGING) {
|
|
printf ("(Discharging)\n");
|
|
} else {
|
|
printf ("(Quiescent)\n");
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// Print the Current Capacity
|
|
//
|
|
|
|
if (BatteryStatus->Capacity == BATTERY_UNKNOWN_CAPACITY) {
|
|
printf (" Current Battery Charge: %08x UNKNOWN\n");
|
|
} else {
|
|
printf (" Current Battery Charge: %08x ", BatteryStatus->Capacity);
|
|
|
|
if (BatteryStatus->Capacity == 0xFFFF) {
|
|
printf ("Invalid");
|
|
} else {
|
|
printf ("%d mWh ", BatteryStatus->Capacity);
|
|
}
|
|
if ((BInfo->FullChargedCapacity != 0) &
|
|
(BInfo->FullChargedCapacity != BATTERY_UNKNOWN_CAPACITY)){
|
|
printf ("(%d%%)",
|
|
BatteryStatus->Capacity * 100 / BInfo->FullChargedCapacity);
|
|
}
|
|
printf ("\n");
|
|
}
|
|
|
|
printf ("\n");
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
QueryBattery (PUNICODE_STRING BatteryName)
|
|
{
|
|
HANDLE driverHandle;
|
|
ULONG batteryTag;
|
|
BATTERY_INFORMATION BInfo;
|
|
ULONG BETime;
|
|
WCHAR BDeviceName[MAX_BATTERY_STRING_SIZE];
|
|
MFG_DATE BManDate;
|
|
WCHAR BManName[MAX_BATTERY_STRING_SIZE];
|
|
ULONG BETemp;
|
|
WCHAR BEUID[MAX_BATTERY_STRING_SIZE];
|
|
BATTERY_REPORTING_SCALE BEGran[4];
|
|
BATTERY_WAIT_STATUS WStat;
|
|
BATTERY_STATUS BStat;
|
|
ULONG i;
|
|
ULONG Cent;
|
|
ULONG Far;
|
|
|
|
if ((driverHandle = OpenBattery (BatteryName)) == NULL) {
|
|
return;
|
|
}
|
|
|
|
printf ("Opened driver w/handle %d\n", driverHandle);
|
|
|
|
batteryTag = GetBatteryTag (driverHandle);
|
|
if (batteryTag == BATTERY_TAG_INVALID) {
|
|
NtClose(driverHandle);
|
|
return;
|
|
}
|
|
|
|
printf ("[Static Information]\n");
|
|
printf (" Battery Tag...........: %x\n", batteryTag);
|
|
|
|
//
|
|
// Get generic info
|
|
//
|
|
|
|
if (GetBatteryInfo (driverHandle, batteryTag, BatteryInformation, &BInfo, sizeof(BInfo))) {
|
|
|
|
//
|
|
// Print the Capabilities
|
|
//
|
|
|
|
printf (" Capabilities..........: ");
|
|
|
|
printf ("%08x ", BInfo.Capabilities);
|
|
|
|
if (BInfo.Capabilities & BATTERY_SYSTEM_BATTERY) {
|
|
printf ("System ");
|
|
}
|
|
|
|
if (BInfo.Capabilities & BATTERY_CAPACITY_RELATIVE) {
|
|
printf ("Capacity_Relative ");
|
|
}
|
|
|
|
if (BInfo.Capabilities & BATTERY_IS_SHORT_TERM) {
|
|
printf ("Short_Term ");
|
|
}
|
|
printf ("\n");
|
|
|
|
|
|
//
|
|
// Print the Technology
|
|
//
|
|
|
|
printf (" Technology............: %08x ", BInfo.Technology);
|
|
|
|
if (BInfo.Technology == 0) {
|
|
printf ("Primary Battery ");
|
|
} else if (BInfo.Technology == 1) {
|
|
printf ("Secondary Battery ");
|
|
} else {
|
|
printf ("Unknown ");
|
|
}
|
|
printf ("\n");
|
|
|
|
|
|
//
|
|
// Print the Chemistry
|
|
//
|
|
|
|
printf (" Chemistry.............: %4.4s\n", BInfo.Chemistry);
|
|
|
|
|
|
//
|
|
// Print the Designed Capacity
|
|
//
|
|
|
|
printf (" Designed Capacity.....: ");
|
|
|
|
if (BInfo.DesignedCapacity == BATTERY_UNKNOWN_CAPACITY) {
|
|
printf ("%08x UNKNOWN\n", BInfo.DesignedCapacity);
|
|
} else {
|
|
if (BInfo.Capabilities & BATTERY_CAPACITY_RELATIVE) {
|
|
printf ("%08x %d%%\n", BInfo.DesignedCapacity, BInfo.DesignedCapacity);
|
|
} else {
|
|
printf ("%08x %d mWh\n", BInfo.DesignedCapacity, BInfo.DesignedCapacity);
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// Print the Full Charged Capacity
|
|
//
|
|
|
|
printf (" Full Charged Capacity.: ");
|
|
|
|
if (BInfo.FullChargedCapacity == BATTERY_UNKNOWN_CAPACITY) {
|
|
printf ("%08x UNKNOWN\n", BInfo.FullChargedCapacity);
|
|
} else {
|
|
if (BInfo.Capabilities & BATTERY_CAPACITY_RELATIVE) {
|
|
printf ("%08x %d%%\n", BInfo.FullChargedCapacity, BInfo.FullChargedCapacity);
|
|
} else {
|
|
printf ("%08x %d mWh\n", BInfo.FullChargedCapacity, BInfo.FullChargedCapacity);
|
|
}
|
|
}
|
|
|
|
if ((BInfo.FullChargedCapacity == 0) ||
|
|
(BInfo.FullChargedCapacity == BATTERY_UNKNOWN_CAPACITY)){
|
|
//
|
|
// Print Alert 1
|
|
//
|
|
|
|
printf (" Default Alert1 (crit).: %08x %d mWh\n",
|
|
BInfo.DefaultAlert1, BInfo.DefaultAlert1);
|
|
|
|
|
|
//
|
|
// Print Alert 2
|
|
//
|
|
|
|
printf (" Default Alert2 (low)..: %08x %d mWh (%d%%)\n",
|
|
BInfo.DefaultAlert2, BInfo.DefaultAlert2);
|
|
|
|
} else {
|
|
|
|
//
|
|
// Print Alert 1
|
|
//
|
|
|
|
printf (" Default Alert1 (crit).: %08x %d mWh (%d%%)\n",
|
|
BInfo.DefaultAlert1, BInfo.DefaultAlert1,
|
|
(BInfo.DefaultAlert1*100)/BInfo.FullChargedCapacity);
|
|
|
|
|
|
//
|
|
// Print Alert 2
|
|
//
|
|
|
|
printf (" Default Alert2 (low)..: %08x %d mWh (%d%%)\n",
|
|
BInfo.DefaultAlert2, BInfo.DefaultAlert2,
|
|
(BInfo.DefaultAlert2*100)/BInfo.FullChargedCapacity);
|
|
}
|
|
|
|
//
|
|
// Print the Critical Bias
|
|
//
|
|
|
|
printf (" Critical Bias.........: %08x\n", BInfo.CriticalBias);
|
|
|
|
|
|
//
|
|
// Print the Cycle Count
|
|
//
|
|
|
|
printf (" Cycle Count...........: %08x %d\n", BInfo.CycleCount, BInfo.CycleCount);
|
|
}
|
|
|
|
|
|
//
|
|
// Print the battery granularity
|
|
//
|
|
|
|
printf (" Granularity...........: ");
|
|
if (GetBatteryInfo (driverHandle, batteryTag, BatteryGranularityInformation, BEGran, sizeof(BEGran))) {
|
|
|
|
printf ("%08x Capacity(1) %08x\n", BEGran[0].Granularity, BEGran[0].Capacity);
|
|
|
|
for (i = 1; i < 4; i++) {
|
|
if ((BEGran[i].Granularity != -1) && (BEGran[i].Granularity != 0)) {
|
|
printf (" %08x Capacity(%d) %08x\n",
|
|
BEGran[i].Granularity, (i+1), BEGran[i].Capacity);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// Print the temperature
|
|
//
|
|
|
|
printf (" Temperature...........: ");
|
|
if (GetBatteryInfo (driverHandle, batteryTag, BatteryTemperature, &BETemp, sizeof(BETemp))) {
|
|
printf ("%08x", BETemp);
|
|
|
|
//
|
|
// Print temp as something reasonable - Centigrade and Fahrenheit
|
|
//
|
|
if (BETemp > 0) {
|
|
Cent = (BETemp/10) - 273;
|
|
Far = ((Cent*2) - (Cent/5)) + 32;
|
|
printf (" %d C %d F", Cent, Far);
|
|
}
|
|
printf ("\n");
|
|
}
|
|
|
|
|
|
//
|
|
// Print the Unique ID
|
|
//
|
|
|
|
printf (" Unique ID.............: ");
|
|
if (GetBatteryInfo (driverHandle, batteryTag, BatteryUniqueID, BEUID, sizeof(BEUID))) {
|
|
printf ("%ws\n", BEUID);
|
|
}
|
|
|
|
|
|
//
|
|
// Print the estimated run time
|
|
//
|
|
|
|
printf (" Estimated Runtime.....: ");
|
|
if (GetBatteryInfo (driverHandle, batteryTag, BatteryEstimatedTime, &BETime, sizeof(BETime))) {
|
|
printf ("%08x ", BETime);
|
|
|
|
if (BETime != BATTERY_UNKNOWN_TIME) {
|
|
printf ("%d Seconds ", BETime);
|
|
printf ("(%d:%d:%d)", BETime / 3600, (BETime % 3600) / 60, (BETime % 3600) % 60);
|
|
} else {
|
|
printf ("Not Available");
|
|
}
|
|
printf ("\n");
|
|
}
|
|
|
|
|
|
//
|
|
// Print the device name
|
|
//
|
|
|
|
printf (" Device Name...........: ");
|
|
if (GetBatteryInfo (driverHandle, batteryTag, BatteryDeviceName, BDeviceName, sizeof(BDeviceName))) {
|
|
printf ("%ws\n", BDeviceName);
|
|
}
|
|
|
|
|
|
//
|
|
// Print the manufacture date
|
|
//
|
|
|
|
printf (" Manufacture Date......: ");
|
|
if (GetBatteryInfo (driverHandle, batteryTag, BatteryManufactureDate, &BManDate, sizeof(BManDate))) {
|
|
printf ("%02X%02X%04X %02d/%02d/%d\n", BManDate.Month, BManDate.Day, BManDate.Year,
|
|
BManDate.Month, BManDate.Day, BManDate.Year);
|
|
}
|
|
|
|
|
|
//
|
|
// Print the manufacturer name
|
|
//
|
|
|
|
printf (" Manufacturer Name.....: ");
|
|
if (GetBatteryInfo (driverHandle, batteryTag, BatteryManufactureName, BManName, sizeof(BManName))) {
|
|
printf ("%ws\n", BManName);
|
|
}
|
|
|
|
printf ("\n");
|
|
|
|
|
|
//
|
|
// Get the battery status and print it out
|
|
//
|
|
|
|
memset (&WStat, 0, sizeof(WStat));
|
|
WStat.BatteryTag = batteryTag;
|
|
|
|
GetBatteryStatus (driverHandle, &WStat, &BInfo, &BStat);
|
|
|
|
//
|
|
// If the user requested it perform a long term status change request
|
|
//
|
|
|
|
if (LongTerm) {
|
|
|
|
printf ("Starting long-term status change request (5 min.)\n");
|
|
|
|
WStat.PowerState = BStat.PowerState;
|
|
WStat.LowCapacity = BStat.Capacity - RANGE;
|
|
WStat.HighCapacity = BStat.Capacity + RANGE;
|
|
WStat.Timeout = 50000000; // 5 min
|
|
GetBatteryStatus (driverHandle, &WStat, &BInfo, &BStat);
|
|
}
|
|
|
|
NtClose(driverHandle);
|
|
}
|
|
|
|
|
|
int
|
|
__cdecl
|
|
main(USHORT argc, CHAR **argv)
|
|
{
|
|
ULONG battTag;
|
|
ULONG battNum;
|
|
ULONG RetVal;
|
|
UCHAR param;
|
|
UNICODE_STRING batteries [MAX_NUMBER_OF_BATTERIES];
|
|
UCHAR numBatts;
|
|
|
|
|
|
RtlZeroMemory (batteries, sizeof(UNICODE_STRING)*MAX_NUMBER_OF_BATTERIES);
|
|
|
|
_tprintf (_T("Parameters: [L] - Issue Long-term status change request\n"));
|
|
|
|
if (argc > 1) {
|
|
param = argv[1][0];
|
|
|
|
if ((param == 'l') || param == 'L') {
|
|
LongTerm = TRUE;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
while (1) {
|
|
|
|
numBatts = GetBatteryDriverNames (batteries, MAX_NUMBER_OF_BATTERIES);
|
|
|
|
printf ("\n");
|
|
for (battNum = 0; battNum < numBatts; battNum++) {
|
|
_tprintf(_T("Batt#%d: %s \n"), battNum, batteries[battNum].Buffer);
|
|
}
|
|
|
|
printf ("\nBattery Number: ");
|
|
if (scanf ("%d", &battNum) != 1) {
|
|
return 0; // Program exit
|
|
}
|
|
printf ("\n");
|
|
|
|
if (battNum < numBatts) {
|
|
|
|
QueryBattery (&batteries [battNum]);
|
|
|
|
} else {
|
|
printf ("Invalid Battery Number\n");
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
|