|
|
/*******************************************************************************
* * (C) COPYRIGHT MICROSOFT CORP., 1996 * * TITLE: BATSTATE.C * * VERSION: 2.0 * * AUTHOR: ReedB * * DATE: 17 Oct, 1996 * * DESCRIPTION: * BATSTATE.C contains helper function which maintain the global battery * state list. * *******************************************************************************/
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <windows.h>
#include <commctrl.h>
#include <dbt.h>
#include <devioctl.h>
#include <ntpoapi.h>
#include <poclass.h>
#include "powrprofp.h"
#include "batmeter.h"
// Simulated battery only for debug build.
#ifndef DEBUG
#undef SIM_BATTERY
#endif
/*******************************************************************************
* * G L O B A L D A T A * *******************************************************************************/
// Global battery state list. This list has the composite system battery state
// as it's always present head. individual battery devices are linked to this
// head. Use WalkBatteryState(ALL, ... to walk the entire list, including the
// head. Use WalkBatteryState(DEVICES, ... to walk just the device list. If a
// battery is in this list, it's displayable. g_ulBatCount is the count of
// battery devices in this list. The composite battery is not counted.
extern BATTERY_STATE g_bs; extern ULONG g_ulBatCount; extern HWND g_hwndBatMeter;
#ifdef WINNT
/*******************************************************************************
* * RegisterForDeviceNotification * * DESCRIPTION: * Do registration for WM_DEVICECHANGED. * * PARAMETERS: * *******************************************************************************/
BOOL RegisterForDeviceNotification(PBATTERY_STATE pbs) { DEV_BROADCAST_HANDLE dbh;
memset(&dbh, 0, sizeof(DEV_BROADCAST_HANDLE));
dbh.dbch_size = sizeof(DEV_BROADCAST_HANDLE); dbh.dbch_devicetype = DBT_DEVTYP_HANDLE; dbh.dbch_handle = pbs->hDevice; if (!g_hwndBatMeter) { BATTRACE(( "RegisterForDeviceNotification, NULL g_hwndBatMeter")); return FALSE; }
pbs->hDevNotify = RegisterDeviceNotification(g_hwndBatMeter, &dbh, DEVICE_NOTIFY_WINDOW_HANDLE); if (!pbs->hDevNotify) { BATTRACE(( "RegisterDeviceNotification failed")); return FALSE; } return TRUE; }
/*******************************************************************************
* * UnregisterForDeviceNotification * * DESCRIPTION: * * * PARAMETERS: * *******************************************************************************/
void UnregisterForDeviceNotification(PBATTERY_STATE pbs) { if (pbs->hDevNotify) { UnregisterDeviceNotification(pbs->hDevNotify); pbs->hDevNotify = NULL; } } #endif
/*******************************************************************************
* * SystemPowerStatusToBatteryState * * DESCRIPTION: * Fill in BATTERY_STATE fields based on passed SYSTEM_POWER_STATUS. * * PARAMETERS: * *******************************************************************************/
void SystemPowerStatusToBatteryState( LPSYSTEM_POWER_STATUS lpsps, PBATTERY_STATE pbs ) { pbs->ulPowerState = 0; if (lpsps->ACLineStatus == AC_LINE_ONLINE) { pbs->ulPowerState |= BATTERY_POWER_ON_LINE; } if (lpsps->BatteryFlag & BATTERY_FLAG_CHARGING) { pbs->ulPowerState |= BATTERY_CHARGING; } if (lpsps->BatteryFlag & BATTERY_FLAG_CRITICAL) { pbs->ulPowerState |= BATTERY_CRITICAL; } pbs->ulBatLifePercent = lpsps->BatteryLifePercent; pbs->ulBatLifeTime = lpsps->BatteryLifeTime; }
/*******************************************************************************
* * WalkBatteryState * * DESCRIPTION: * * PARAMETERS: * *******************************************************************************/
BOOL WalkBatteryState( PBATTERY_STATE pbsStart, WALKENUMPROC pfnWalkEnumProc, HWND hWnd, LPARAM lParam1, LPARAM lParam2 ) { PBATTERY_STATE pbsTmp;
while (pbsStart) { // Save the next entry in case the current one is deleted.
pbsTmp = pbsStart->bsNext; if (!pfnWalkEnumProc(pbsStart, hWnd, lParam1, lParam2)) { return FALSE; } pbsStart = pbsTmp; }
return TRUE; }
/*******************************************************************************
* * UpdateBatInfoProc * * DESCRIPTION: * Updates battery information for an individual battery device. * * PARAMETERS: * *******************************************************************************/
BOOL UpdateBatInfoProc( PBATTERY_STATE pbs, HWND hWnd, LPARAM lParam1, LPARAM lParam2 ) { DWORD dwByteCount, dwIOCTL, dwWait; BATTERY_STATUS bs; BATTERY_WAIT_STATUS bws; BATTERY_INFORMATION bi; BATTERY_QUERY_INFORMATION bqi;
if (pbs->hDevice == INVALID_HANDLE_VALUE) { BATTRACE(( "UpdateBatInfoProc, Bad battery driver handle, LastError: 0x%X", GetLastError())); return FALSE; }
// If no tag, then don't update the battery info.
dwIOCTL = IOCTL_BATTERY_QUERY_TAG; dwWait = 0; if (DeviceIoControl(pbs->hDevice, dwIOCTL, &dwWait, sizeof(dwWait), &(pbs->ulTag), sizeof(ULONG), &dwByteCount, NULL)) {
bqi.BatteryTag = pbs->ulTag; bqi.InformationLevel = BatteryInformation; bqi.AtRate = 0; dwIOCTL = IOCTL_BATTERY_QUERY_INFORMATION; if (DeviceIoControl(pbs->hDevice, dwIOCTL, &bqi, sizeof(bqi), &bi, sizeof(bi), &dwByteCount, NULL)) {
if (bi.FullChargedCapacity != UNKNOWN_CAPACITY) { pbs->ulFullChargedCapacity = bi.FullChargedCapacity; } else { pbs->ulFullChargedCapacity = bi.DesignedCapacity; }
memset(&bws, 0, sizeof(BATTERY_WAIT_STATUS)); bws.BatteryTag = pbs->ulTag; dwIOCTL = IOCTL_BATTERY_QUERY_STATUS; if (DeviceIoControl(pbs->hDevice, dwIOCTL, &bws, sizeof(BATTERY_WAIT_STATUS), &bs, sizeof(BATTERY_STATUS), &dwByteCount, NULL)) {
pbs->ulPowerState = bs.PowerState; if (pbs->ulFullChargedCapacity < bs.Capacity) { pbs->ulFullChargedCapacity = bs.Capacity; BATTRACE(( "UpdateBatInfoProc, unable to calculate ulFullChargedCapacity")); } if (pbs->ulFullChargedCapacity == 0) { pbs->ulBatLifePercent = 0; } else { pbs->ulBatLifePercent = (100 * bs.Capacity) / pbs->ulFullChargedCapacity; } return TRUE; } } } else { pbs->ulTag = BATTERY_TAG_INVALID;
// No battery tag, that's ok, the user may have removed the battery.
if (GetLastError() == ERROR_FILE_NOT_FOUND) { return TRUE; } } BATTRACE(( "UpdateBatInfoProc, IOCTL: %X Failure, BatNum: %d, LastError: %d\n", dwIOCTL, pbs->ulBatNum, GetLastError())); return FALSE; }
/*******************************************************************************
* * SimUpdateBatInfoProc * * DESCRIPTION: * Simulate the update of battery information for an individual batter device. * * PARAMETERS: * *******************************************************************************/
BOOL SimUpdateBatInfoProc( PBATTERY_STATE pbs, HWND hWnd, LPARAM lParam1, LPARAM lParam2 ) { pbs->ulTag = pbs->ulBatNum; if (pbs->ulBatNum == 1) { pbs->ulFullChargedCapacity = 2000; pbs->ulFullChargedCapacity = 1991; pbs->ulPowerState = BATTERY_CHARGING | BATTERY_POWER_ON_LINE; pbs->ulBatLifePercent = 75; } else { pbs->ulFullChargedCapacity = 3000; pbs->ulFullChargedCapacity = 2991; pbs->ulPowerState = BATTERY_DISCHARGING | BATTERY_CRITICAL; pbs->ulBatLifePercent = 3; } return TRUE; }
/*******************************************************************************
* * AddBatteryStateDevice * * DESCRIPTION: * Add only displayable batteries to the battery list. New entry is appended * to battery state list. * * PARAMETERS: * *******************************************************************************/
PBATTERY_STATE AddBatteryStateDevice(LPTSTR lpszName, ULONG ulBatNum) { PBATTERY_STATE pbs, pbsTemp = &g_bs; LPTSTR lpsz = NULL; DWORD strsize;
if (!lpszName) { return NULL; }
// Append to end of list
while (pbsTemp->bsNext) { pbsTemp = pbsTemp->bsNext; }
// Allocate storage for new battery device state.
if (pbs = LocalAlloc(LPTR, sizeof(BATTERY_STATE))) { strsize = STRSIZE(lpszName); if (lpsz = LocalAlloc(0, strsize)) { lstrcpyn(lpsz, lpszName,strsize); pbs->lpszDeviceName = lpsz; pbs->ulSize = sizeof(BATTERY_STATE); pbs->ulBatNum = ulBatNum;
// Open a handle to the battery driver.
pbs->hDevice = CreateFile(lpszName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); #ifdef WINNT
// Setup for notification by PNP when battery goes away.
RegisterForDeviceNotification(pbs); #endif
// Get the current battery info from the battery driver.
if (UpdateBatInfoProc(pbs, NULL, 0, 0)) {
// Link the new battery device state into the list.
pbsTemp->bsNext = pbs; pbs->bsPrev = pbsTemp; return pbs; } LocalFree(lpsz); } LocalFree(pbs); } return NULL; }
/*******************************************************************************
* * SimAddBatteryStateDevice * * DESCRIPTION: * Simulate the addition of displayable batteries to the battery list. * New entry is appended to battery state list. * * PARAMETERS: * *******************************************************************************/
PBATTERY_STATE SimAddBatteryStateDevice(LPTSTR lpszName, ULONG ulBatNum) { PBATTERY_STATE pbs, pbsTemp = &g_bs; LPTSTR lpsz = NULL; DWORD strsize;
if (!lpszName) { return NULL; }
// Append to end of list
while (pbsTemp->bsNext) { pbsTemp = pbsTemp->bsNext; }
// Allocate storage for new battery device state.
if (pbs = LocalAlloc(LPTR, sizeof(BATTERY_STATE))) { strsize = STRSIZE(lpszName); if (lpsz = LocalAlloc(0, strsize)) { lstrcpyn(lpsz, lpszName,strsize); pbs->lpszDeviceName = lpsz; pbs->ulSize = sizeof(BATTERY_STATE); pbs->ulBatNum = ulBatNum;
// Open a handle to the battery driver.
pbs->hDevice = (HANDLE) -1;
// Get the current battery info from the battery driver.
if (SimUpdateBatInfoProc(pbs, NULL, 0, 0)) {
// Link the new battery device state into the list.
pbsTemp->bsNext = pbs; pbs->bsPrev = pbsTemp; return pbs; } LocalFree(lpsz); } LocalFree(pbs); } return NULL; }
/*******************************************************************************
* * RemoveBatteryStateDevice * * DESCRIPTION: * * PARAMETERS: * *******************************************************************************/
BOOL RemoveBatteryStateDevice(PBATTERY_STATE pbs) { // Unlink
if (pbs->bsNext) { pbs->bsNext->bsPrev = pbs->bsPrev; } if (pbs->bsPrev) { pbs->bsPrev->bsNext = pbs->bsNext; }
#ifdef winnt
UnregisterForDeviceNotification(pbs); #endif
// Free the battery driver handle if one was opened.
if (pbs->hDevice != INVALID_HANDLE_VALUE) { CloseHandle(pbs->hDevice); }
// Free the device name.
LocalFree(pbs->lpszDeviceName);
// Destroy any icons.
if (pbs->hIconCache) { DestroyIcon(pbs->hIconCache); } if (pbs->hIconCache16) { DestroyIcon(pbs->hIconCache16); }
// Free the associated storage.
LocalFree(pbs);
return TRUE; }
/*******************************************************************************
* * RemoveMissingProc * * DESCRIPTION: * Remove a battery from the global battery state list. * * PARAMETERS: * lParam2 - REMOVE_MISSING or REMOVE_ALL * *******************************************************************************/
BOOL RemoveMissingProc( PBATTERY_STATE pbs, HWND hWnd, LPARAM lParam1, LPARAM lParam2) { UINT i; LPTSTR *pszDeviceNames;
if (lParam2 == REMOVE_MISSING) { if ((pszDeviceNames = (LPTSTR *)lParam1) != NULL) { for (i = 0; i < NUM_BAT; i++) { if (pszDeviceNames[i]) { if (!lstrcmp(pbs->lpszDeviceName, pszDeviceNames[i])) { // Device found in device list, leave it alone.
return TRUE; } } else { continue; } } } }
// Device not in the device names list, remove it.
RemoveBatteryStateDevice(pbs); return TRUE; }
/*******************************************************************************
* * FindNameProc * * DESCRIPTION: * Returns FALSE (stop searching) if we find the name, else TRUE. * * PARAMETERS: * *******************************************************************************/
BOOL FindNameProc(PBATTERY_STATE pbs, HWND hWnd, LPARAM lParam1, LPARAM lParam2) { if (lParam1) { if (!lstrcmp(pbs->lpszDeviceName, (LPTSTR)lParam1)) { // Device found in device list.
return FALSE; } } return TRUE; }
|