📄 pddpower.cpp
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//
#include <pmimpl.h>
// pointers to battery APIs
typedef DWORD (WINAPI * PFN_GetSystemPowerStatusEx2)(PSYSTEM_POWER_STATUS_EX2, DWORD, BOOL);
typedef LONG (WINAPI * PFN_BatteryDrvrGetLevels)(void);
static PFN_GetSystemPowerStatusEx2 gpfnGetSystemPowerStatusEx2;
static PFN_BatteryDrvrGetLevels gpfnBatteryDrvrGetLevels;
// accesses to this variable should be protected by a critical section
extern "C" extern POWER_BROADCAST_POWER_INFO gSystemPowerStatus;
// This routine initializes variables used to update the platform's power status.
// It is called during PM initialization, so it doesn't take the PM lock before
// accessing gSystemPowerStatus. It returns TRUE if battery APIs are supported
// on the platform, FALSE otherwise.
BOOL
PmInitPowerStatus(HMODULE hmCoreDll)
{
BOOL fGotBatteryAPIs;
DEBUGCHK(hmCoreDll != NULL);
// initialize battery monitoring variables to "unknown status"
memset(&gSystemPowerStatus, 0xFF, sizeof(gSystemPowerStatus));
// get pointers to power information routines
gpfnGetSystemPowerStatusEx2 = (PFN_GetSystemPowerStatusEx2) GetProcAddress(hmCoreDll,
_T("GetSystemPowerStatusEx2"));
gpfnBatteryDrvrGetLevels = (PFN_BatteryDrvrGetLevels) GetProcAddress(hmCoreDll,
_T("BatteryDrvrGetLevels"));
DEBUGCHK((gpfnGetSystemPowerStatusEx2 == NULL && gpfnBatteryDrvrGetLevels == NULL)
|| (gpfnGetSystemPowerStatusEx2 != NULL && gpfnBatteryDrvrGetLevels != NULL));
// did we find the battery APIs?
if(gpfnGetSystemPowerStatusEx2 != NULL && gpfnBatteryDrvrGetLevels != NULL) {
fGotBatteryAPIs = TRUE;
} else {
fGotBatteryAPIs = FALSE;
}
return fGotBatteryAPIs;
}
// This routine refreshes the PM's power level and source variables. If the
// data that would be sent with a PBT_POWERINFOCHANGE notification has been
// modified, it generates the appropriate notifications. If the power source
// has changed, the routine returns TRUE. Otherwise it returns FALSE.
//
// Note that this routine does not set the FORCE flag in GetSystemPowerStatusEx2().
// It assumes that the battery driver has updated its internal cache information
// before sending a message to the PM. Also, it assumes that battery APIs are ready
// before it receives a notification.
BOOL
PmUpdatePowerStatus(void)
{
static POWER_BROADCAST_POWER_INFO pi;
BOOL fACLineStatusChange = FALSE;
SETFNAME(_T("PmUpdatePowerStatus"));
PREFAST_DEBUGCHK(gpfnGetSystemPowerStatusEx2 != NULL);
PREFAST_DEBUGCHK(gpfnBatteryDrvrGetLevels != NULL);
// do we have battery level information?
if(pi.dwNumLevels == 0) {
pi.dwNumLevels = gpfnBatteryDrvrGetLevels();
DEBUGCHK(pi.dwNumLevels != 0);
}
// construct a new power broadcast data structure
if(pi.dwNumLevels != 0) {
SYSTEM_POWER_STATUS_EX2 spsCurrent;
BOOL fPowerInfoChange = FALSE;
DWORD dwLen = gpfnGetSystemPowerStatusEx2(&spsCurrent, sizeof(spsCurrent), FALSE);
if(dwLen == 0) {
PMLOGMSG(ZONE_WARN, (_T("%s: GetSystemPowerStatusEx2() failed\r\n"),
pszFname));
} else {
// fill in our new data structure
pi.dwBatteryLifeTime = spsCurrent.BatteryLifeTime;
pi.dwBatteryFullLifeTime = spsCurrent.BatteryFullLifeTime;
pi.dwBackupBatteryLifeTime = spsCurrent.BackupBatteryLifeTime;
pi.dwBackupBatteryFullLifeTime = spsCurrent.BackupBatteryFullLifeTime;
pi.bACLineStatus = spsCurrent.ACLineStatus;
pi.bBatteryFlag = spsCurrent.BatteryFlag;
pi.bBatteryLifePercent = spsCurrent.BatteryLifePercent;
pi.bBackupBatteryFlag = spsCurrent.BackupBatteryFlag;
pi.bBackupBatteryLifePercent = spsCurrent.BackupBatteryLifePercent;
}
// determine whether we need to send out any notifications
PMLOCK();
if(memcmp(&gSystemPowerStatus, &pi, sizeof(gSystemPowerStatus)) != 0) {
fPowerInfoChange = TRUE;
if(gSystemPowerStatus.bACLineStatus != pi.bACLineStatus) {
fACLineStatusChange = TRUE;
}
gSystemPowerStatus = pi;
}
PMUNLOCK();
// send AC power notifications
if(fACLineStatusChange) {
POWER_BROADCAST pb;
// yes, generate a notification
PMLOGMSG(ZONE_PLATFORM, (_T("%s: AC line status changed to %s\r\n"),
pszFname,
pi.bACLineStatus == AC_LINE_OFFLINE ? _T("offline") :
pi.bACLineStatus == AC_LINE_ONLINE ? _T("online") :
pi.bACLineStatus == AC_LINE_UNKNOWN ? _T("unknown") : _T("<INVALID VALUE>")));
pb.Message = PBT_POWERSTATUSCHANGE;
pb.Flags = 0;
pb.Length = 0;
pb.SystemPowerState[0] = 0;
GenerateNotifications(&pb);
}
// send power info change notifications
if(fPowerInfoChange) {
POWER_BROADCAST_BUFFER pbb;
PPOWER_BROADCAST_POWER_INFO ppbpi = (PPOWER_BROADCAST_POWER_INFO) pbb.SystemPowerState;
// update the notification buffer
pbb.Message = PBT_POWERINFOCHANGE;
pbb.Flags = 0;
pbb.Length = sizeof(*ppbpi);
*ppbpi = pi;
GenerateNotifications((PPOWER_BROADCAST) &pbb);
}
}
return fACLineStatusChange;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -