📄 platform.cpp
字号:
if(dwElapsedTime >= gdwStateTimeLeft) {
// suspend timeout has expired
asNew = Suspend;
}
break;
case RestartTimeouts:
case PowerSourceChange:
// reset suspend timers to the value appropriate to the new power source
if(gActivityState == Resuming) {
gdwStateTimeLeft = dwResumingSuspendTimeout;
} else if(gActivityState == Suspend) {
gdwStateTimeLeft = INFINITE;
} else {
gdwStateTimeLeft = dwSuspendTimeout;
}
dwElapsedTime = 0;
break;
case UserActivity:
// if we're in normal operation, reset the suspend timeout
fUserActive = TRUE;
break;
case UserInactivity:
fUserActive = FALSE;
if(gActivityState == On) {
gdwStateTimeLeft = dwSuspendTimeout;
dwElapsedTime = 0;
}
break;
case SystemIdleTimerWasReset:
// reset the suspend timeout as long as we're not resuming
if(gActivityState != Resuming) {
gdwStateTimeLeft = dwSuspendTimeout;
dwElapsedTime = 0;
}
break;
case EnterUnattendedModeRequest:
// Update the number of unattended mode requests. These can be
// made while we're in any system power state unless
// gfSuspendToUnattendedMode is false, in which case we must be
// in Resuming or Unattended.
if(gfSuspendToUnattendedMode
|| gActivityState == Resuming
|| gActivityState == Unattended) {
gdwUnattendedModeRequests++;
}
// actually transition into unattended mode if we're currently
// resuming
if(gActivityState == Resuming) {
asNew = Unattended;
}
break;
case LeaveUnattendedModeRequest:
// Reduce the number of unattended mode requests. These can be
// made while we're in any system power state unless
// gfSuspendToUnattendedMode is FALSE, in which case we must
// be in Unattended mode.
if(gfSuspendToUnattendedMode || gActivityState == Unattended) {
PMLOGMSG(ZONE_WARN && (gdwUnattendedModeRequests == 0),
(_T("%s: LeaveUnattendedModeRequest received with request count %d\r\n"),
pszFname, gdwUnattendedModeRequests));
if(gdwUnattendedModeRequests > 0) {
gdwUnattendedModeRequests--;
}
if(gdwUnattendedModeRequests == 0 && gActivityState == Unattended) {
// suspend if we're currently in unattended mode
asNew = Suspend;
}
}
break;
case NoActivity:
// ignore inactivity
break;
case SystemPowerStateChange:
// someone is changing the system power state -- see if we need to update
// our state machine.
DEBUGCHK(gpSystemPowerState != NULL);
{
PLATFORM_ACTIVITY_STATE eActivityState;
BOOL fOk = SystemStateToActivityState(gpSystemPowerState, &eActivityState);
if(fOk) {
// is this a state change initiated by someone outside the PM?
if(eActivityState != asNew) {
// yes, we need to sync up with the transition
PMLOGMSG(ZONE_PLATFORM, (_T("%s: forcing state machine update to state %d\r\n"),
pszFname, eActivityState));
asNew = eActivityState;
}
}
dwElapsedTime = 0;
}
break;
default:
PMLOGMSG(ZONE_WARN, (_T("%s: unknown activity event state %d\r\n"), pszFname, eActivityEvent));
break;
}
// are we changing activity states?
if(asNew != gActivityState) {
fChangingActivityStates = TRUE;
gActivityState = asNew;
// reload the suspend timeout
switch(gActivityState) {
case Resuming:
gdwStateTimeLeft = dwResumingSuspendTimeout;
break;
case Suspend:
gdwStateTimeLeft = INFINITE;
break;
default:
gdwStateTimeLeft = dwSuspendTimeout;
break;
}
}
// don't suspend timeout while we're "on" and the user is actively using the system
if(gActivityState == On && fUserActive) {
gdwStateTimeLeft = INFINITE;
}
// calculate new timeouts and system power state names
pszNewState = ActivityStateToSystemState(gActivityState);
PREFAST_DEBUGCHK(pszNewState != NULL);
// update elapsed time
if(!fChangingActivityStates && gdwStateTimeLeft != INFINITE) {
if(gdwStateTimeLeft > dwElapsedTime) {
gdwStateTimeLeft -= dwElapsedTime;
} else {
gdwStateTimeLeft = 0;
}
}
// are we changing states or forcing an update?
PMLOGMSG(ZONE_PLATFORM,
(_T("%s: %s activity state '%s', state time left %d\r\n"), pszFname,
fChangingActivityStates ? _T("changing to") : _T("staying in"),
gActivityState == On ? _T("on") :
gActivityState == ScreenOff ? _T("ScreenOff") :
gActivityState == Unattended ? _T("Unattended") :
gActivityState == Resuming ? _T("Resuming") :
gActivityState == Suspend ? _T("Suspend") : _T("<UNKNOWN>"), gdwStateTimeLeft));
if(dwElapsedTime == INFINITE
|| gpSystemPowerState == NULL
|| _tcscmp(pszNewState, gpSystemPowerState->pszName) != 0) {
PMLOGMSG(ZONE_PLATFORM, (_T("%s: update from activity state %d to activity state %d\r\n"),
pszFname, gActivityState, asNew));
} else {
// no update necessary
pszNewState = NULL;
}
PMUNLOCK();
// SystemPowerStateChange notifications are informational only, so suppress
// the call to PmSetSystemPowerState().
if(eActivityEvent == SystemPowerStateChange) {
pszNewState = NULL;
}
// update the system power state if necessary
if(pszNewState != NULL) {
PmSetSystemPowerState_I(pszNewState, 0, 0, TRUE);
}
return gdwStateTimeLeft;
}
// This routine reads and verifies system power state information from
// the registry, then updates all devices appropriately. The caller of this
// routine should hold the system power state critical section. The fInternal
// flag indicates whether the call originated within the PM or outside it.
EXTERN_C DWORD WINAPI
PlatformSetSystemPowerState(LPCTSTR pszName, BOOL fForce, BOOL fInternal)
{
DWORD dwStatus = ERROR_SUCCESS;
PSYSTEM_POWER_STATE pNewSystemPowerState = NULL;
PDEVICE_POWER_RESTRICTION pNewCeilingDx = NULL;
BOOL fDoTransition = FALSE;
INT iPreSuspendPriority = 0;
static BOOL fFirstCall = TRUE;
SETFNAME(_T("PlatformSetSystemPowerState"));
// read system power state variables and construct new lists
if (gfFileSystemsAvailable)
PmUpdateSystemPowerStatesIfChanged();
dwStatus = RegReadSystemPowerState(pszName, &pNewSystemPowerState, &pNewCeilingDx);
// did we get registry information about the new power state?
if(dwStatus == ERROR_SUCCESS) {
BOOL fSuspendSystem = FALSE;
BOOL fWantStartupScreen = FALSE;
DWORD dwNewStateFlags = pNewSystemPowerState->dwFlags;
BOOL fPasswordOn = ((dwNewStateFlags & POWER_STATE_PASSWORD)!=0) ;
// assume we will update the system power state
fDoTransition = TRUE;
// Are we going to suspend the system as a whole?
if((dwNewStateFlags & (POWER_STATE_SUSPEND | POWER_STATE_OFF | POWER_STATE_CRITICAL | POWER_STATE_RESET)) != 0) {
fSuspendSystem = TRUE;
}
// A "critical" suspend might mean we have totally lost battery power and need
// to suspend really quickly. Depending on the platform, OEMs may be able
// to bypass driver notification entirely and rely on xxx_PowerDown() notifications
// to suspend gracefully. Or they may be able to implement a critical suspend
// kernel ioctl. This sample implementation is very generic and simply sets the
// POWER_FORCE flag, which is not used.
if(dwNewStateFlags & (POWER_STATE_CRITICAL | POWER_STATE_OFF | POWER_STATE_RESET)) {
fForce = TRUE;
}
// Determine whether to allow the system power state transition to take place.
// We will allow applications to initiate transitions to the "on" state, the
// "screenoff" state, or the "suspend" state. Since we may be translating an
// external request to enter POWER_STATE_SUSPEND into entering unattended mode,
// we'll allow external entities to go into unattended mode.
if(!fInternal) {
// allow aliases for these state names by using the flags field
BOOL fAllow = FALSE;
if(dwNewStateFlags & (POWER_STATE_SUSPEND | POWER_STATE_CRITICAL)) fAllow = TRUE; // suspend state
if(dwNewStateFlags & POWER_STATE_RESET) fAllow = TRUE; // reboot
if(dwNewStateFlags & POWER_STATE_OFF) fAllow = TRUE; // cold suspend
if(dwNewStateFlags & (POWER_STATE_IDLE | POWER_STATE_ON)) fAllow = TRUE; // normal operation
if(gfSuspendToUnattendedMode && _tcscmp(pszName, _T("unattended")) == 0) {
fAllow = TRUE; // unattended mode
}
if(!fAllow) {
PMLOCK();
// we should also permit changes to the current system state to succeed
if(gpSystemPowerState != NULL
&& _tcscmp(gpSystemPowerState->pszName, pNewSystemPowerState->pszName) != 0) {
fDoTransition = FALSE;
dwStatus = ERROR_ACCESS_DENIED;
}
PMUNLOCK();
}
}
// if everything seems ok, do the set operation
if(fDoTransition) {
POWER_BROADCAST_BUFFER pbb;
PDEVICE_LIST pdl;
BOOL fResumeSystem = FALSE;
// send out system power state change notifications
pbb.Message = PBT_TRANSITION;
pbb.Flags = pNewSystemPowerState->dwFlags;
pbb.Length = _tcslen(pNewSystemPowerState->pszName) + 1; // char count not byte count for now
if(pbb.Length > MAX_PATH) {
// truncate the system power state name -- note, we actually have MAX_PATH + 1
// characters available.
pbb.Length = MAX_PATH;
}
_tcsncpy(pbb.SystemPowerState, pNewSystemPowerState->pszName, pbb.Length);
pbb.Length *= sizeof(pbb.SystemPowerState[0]); // convert to byte count
GenerateNotifications((PPOWER_BROADCAST) &pbb);
// are we suspending?
if(fSuspendSystem && gpfnGwesPowerDown != NULL) {
// is GWES ready?
if(!gfGwesReady) {
DEBUGCHK(ghevGwesReady != NULL);
if(WaitForSingleObject(ghevGwesReady, 0) == WAIT_OBJECT_0) {
gfGwesReady = TRUE;
CloseHandle(ghevGwesReady);
ghevGwesReady = NULL;
}
}
// Start the process of suspending GWES
if(gfGwesReady) {
fWantStartupScreen = gpfnGwesPowerDown();
}
}
// update global system state variables
PMLOCK();
PSYSTEM_POWER_STATE pOldSystemPowerState = gpSystemPowerState;
PDEVICE_POWER_RESTRICTION pOldCeilingDx = gpCeilingDx;
if(gpSystemPowerState != NULL
&& (gpSystemPowerState->dwFlags & (POWER_STATE_SUSPEND | POWER_STATE_OFF | POWER_STATE_CRITICAL)) != 0) {
// we are exiting a suspended state
fResumeSystem = TRUE;
}
gpSystemPowerState = pNewSystemPowerState;
gpCeilingDx = pNewCeilingDx;
PMUNLOCK();
// are we suspending, resuming, or neither?
if(fSuspendSystem) {
INT iCurrentPriority;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -