Abort StandBy

StandBy Event

Resume Event

Introduction
This article shows how to capture and handle the OS events like Sleep, Stand-by, Hibernate, Power Status Changed, Low Battery, Critical Suspend, AC Power, Battery Power, Battery Life etc. in Windows XP and Vista. The article also details how the OS calls Sleep, Stand-by, Hibernate, Application Shutdown & Power Management in Windows Vista differs from Windows XP. It also deals with denying the suspension request: i.e., how an application can deny/abort the Sleep, Stand-by and Hibernate call made by the system in Windows XP and earlier.
Background
One of our client side applications was hanging whenever the system went to Suspended state. While debugging, I found that the developer missed handling events like Sleep, Stand-by & Hibernate, and hence the resultant was a system hang. I couldn't find a related article at CodeProject, hence I am posting it.
OS Events in Windows XP and Earlier
In Windows XP and earlier, The system broadcasts a PBT_APMQUERYSUSPEND
event to request permission for suspending system operation to all applications. The system broadcasts these events through the Win32 message call WM_POWERBROADCAST
setting the wParam
parameter to the appropriate power management event. The system broadcasts a PBT_APMSUSPEND
event immediately before suspending operation. This gives applications one last chance to prepare for the event. The WM_POWERBROADCAST
comes with two parameters: wParam
& lParam
. lParam
is function specific and is not generally used & wParam
can be any of the following:
Event |
Meaning |
PBT_APMQUERYSUSPEND |
Request for permission to suspend |
PBT_APMQUERYSUSPENDFAILED |
Suspension request denied |
PBT_APMSUSPEND |
System is suspending operation |
PBT_APMRESUMESUSPEND |
Operation resuming after suspension |
PBT_APMRESUMEAUTOMATIC |
Operation resuming automatically after event |
PBT_APMRESUMECRITICAL |
Operation resuming after critical suspension possibly due to failing battery |
PBT_APMBATTERYLOW |
Battery power is low |
PBT_APMPOWERSTATUSCHANGE |
Power status has changed |
PBT_APMOEMEVENT |
OEM-defined event occurred |
The system broadcasts the PBT_APMRESUMESUSPEND
or PBT_APMRESUMECRITICAL
event when system operation has been restored. If an application received a PBT_APMSUSPEND
event before the computer was suspended, it will receive the PBT_APMRESUMESUSPEND
event. Otherwise, it will receive the PBT_APMRESUMECRITICAL
(in case of failing battery) event. The PBT_APMRESUMEAUTOMATIC
and PBT_APMRESUMESUSPEND
events notify applications that the system has resumed and applications handling/processing these events automatically starts processing. E.g. Reconnect to network resources in the background without interrupting the user.
In Windows XP and earlier, the PBT_APMQUERYSUSPEND
event allowed applications to deny/abort the suspend operation from completing by returning BROADCAST_QUERY_DENY
.
case WM_POWERBROADCAST:
if (wParam==PBT_APMQUERYSUSPEND)
{
return (BROADCAST_QUERY_DENY);
}
The above code snippet will deny/abort the the Sleep, Stand-by and Hibernate call made by the system. If an application denies the suspend request, the system broadcasts a PBT_APMQUERYSUSPENDFAILED
event. This event notifies applications to continue operation as usual.
Suspension Process in Windows XP
The system suspension process is used primarily to save power or turn off a hard disk drive prior to moving a device. The order of Events in Windows XP is:
Case 1
PBT_APMQUERYSUSPEND
is sent to all applications.
- All applications return
TRUE
.
PBT_APMSUSPEND
is sent.
- All applications return
TRUE
and system goes to Suspended State.
Case 2
PBT_APMQUERYSUSPEND
is sent to all applications.
- An applications return
BROADCAST_QUERY_DENY
.
PBT_APMQUERYSUSPENDFAILED
is sent.
- All applications work normally and system doesn't go to Suspended State.
Resuming Process in Windows XP
The resume operations are as critical as suspension, and application developers should handle the messages appropriately that are received during this process.
In the similar vein to suspension, WM_POWERBROADCAST
message is used to notify the application that a resume is under process or has completed. The first event received is PBT_APMRESUMEAUTOMATIC
which informs the applications that an automatic resume is under process or has completed. The next event that is sent is PBT_APMRESUMESUSPEND
. This indicates that the system has safely resumed operations and that the application can start processing their job.
Application Shutdown in Windows XP
In Windows XP, each running application is sent the WM_QUERYENDSESSION
message at shutdown. Applications can return TRUE
to indicate that they can be closed, or FALSE
to indicate that they should not be closed. If an application returns FALSE
, in most cases, shutdown will be cancelled. Applications can also delay responding to WM_QUERYENDSESSION
in order to display UI asking what the user would like to do.
For example, when Notepad has unsaved data and displays a "Would you like to save your data?" dialog during shutdown. By default, applications can delay responding to WM_QUERYENDSESSION
for up to 5 seconds. After 5 seconds, Windows XP will display a dialog that indicates that the application is not responding and allows the user to terminate it. Until the user responds to this dialog, applications can block WM_QUERYENDSESSION
and, consequently, shutdown. If the user clicks the "End Now" button on the dialog, the application is immediately terminated and shutdown will continue. If the user clicks the "Cancel" button, shutdown is canceled and the application will continue running.
Applications that return TRUE
to WM_QUERYENDSESSION
are sent WM_ENDSESSION
with wParam == TRUE
. Applications have 5 seconds to respond to WM_ENDSESSION
before Windows displays a system dialog allowing the user to terminate the application. Unlike with WM_QUERYENDSESSION
, applications cannot cancel shutdown by responding FALSE
to WM_ENDSESSION
.
OS Events in Windows Vista
Microsoft Windows Vista ecosystem significant changes to power management infrastructure & functionality as compared to Windows XP and earlier. Application developers must be aware of the changes to power management in Windows Vista, and design their applications accordingly.
From the developer's perspective, the points which needs to be taken care of are changes to Sleep and Resume Events. In Windows Vista, applications can no longer block in-progress sleep transitions. The PBT_APMQUERYSUSPEND
event is not delivered to applications in Vista and hence applications cannot deny/abort the suspend operation. This is as per Microsoft's recommendation that applications should not block in-progress sleep transitions on any version of Windows.
In Vista, suspend transitions are pretty fast to increase the performance and hence applications handling the PBT_APMSUSPEND
event must process it within 2 seconds. Applications have 2 seconds to finish processing the PBT_APMSUSPEND
event before Windows continues with the sleep transition. If an application has not returned from the PBT_APMSUSPEND
event after 2 seconds, the system will go ahead to sleep state and any remaining processing completes after the system resumes from the sleep state.
The system transits to a sleep state as follows:
- User or the system (sleep idle timeout) initiates the sleep transition.
- Windows power manager notifies applications, services with the appropriate suspend events.
- Windows places the system hardware in a sleep state and saves system context in memory, on disk, or both in memory and on disk.
- System resumes from the sleep state later due to the user intervention by powering on the system or a wake-on-LAN.
- Services, and applications are notified that the system has resumed with the appropriate events.
The PBT_APMRESUMEAUTOMATIC
and PBT_APMRESUMESUSPEND
events notify applications that the system has resumed. The PBT_APMRESUMEAUTOMATIC
event is delivered to applications on every resume, but the PBT_APMRESUMESUSPEND
event is delivered on resume only when a user is present at the system. Windows uses notifications from the platform hardware and user input such as from keyboard or mouse to determine that a user is present at the system.
Vista as compared to its predecessors is bit aggressive in terms of both, Display Idle Timeout and System Sleep Idle Timeout. Windows tracks user input through keyboards and mouse. If the elapsed time since the last user input is larger than the display idle timeout specified in power policy, the display is turned off. If a system is idle longer than the sleep idle timeout specified in the power policy, Windows places the system in the Sleep state. It is the responsibility of the application to prevent the system from entering Sleep state or Display from being turned off, if application is performing some task which requires a larger time frame (E.g. Defragmentation).
Windows applications can prevent the Display Idle Timeout and the Sleep Idle Timeout by using the API Call SetThreadExecutionState
function. SetThreadExecutionState
takes a single parameter that indicates the resources to remain available. The Syntax of SetThreadExecutionState
is as follows:
EXECUTION_STATE WINAPI SetThreadExecutionState( __in EXECUTION_STATE esFlags)
The value of esFlags
can be any one or combination of the following:
ES_AWAYMODE_REQUIRED
- Forces away Mode. Away mode should be used only by media-recording and media-distribution applications that must perform critical background processing on desktop computers while the computer appears to be sleeping.
ES_CONTINUOUS
- Tells System that the state being set should remain in effect until the next call to SetThreadExecutionState
that uses ES_CONTINUOUS
and one of the other state flags is cleared.
ES_DISPLAY_REQUIRED
- Forces the display to be on (display idle timeout is prevented).
ES_SYSTEM_REQUIRED
- Forces the system to be in the working state (sleep idle timeout is prevented).
E.g.
SetThreadExecutionState(ES_CONTINUOUS | ES_SYSTEM_REQUIRED | ES_DISPLAY_REQUIRED);
SetThreadExecutionState(ES_CONTINUOUS);
Application developers should keep few things in mind while dealing with SetThreadExecutionState
.
SetThreadExecutionState
function does not always prevent a screen saver from executing.
- Application cannot block the suspend/sleep operation by using
SetThreadExecutionState
with the ES_SYSTEM_REQUIRED
flag.
- Calling
SetThreadExecutionState
without the ES_CONTINUOUS
flag resets the idle timers. For e.g.: If the Display Idle Timeout is set to 30 minutes in your power policy and 20 minutes have already elapsed since the last user input, now a call to SetThreadExecutionState
with only the ES_DISPLAY_REQUIRED
flag resets the idle countdown and the display will turn off 30 minutes later, assuming no additional user input.
Refer to MSDN for more details on SetThreadExecutionState
.
Suspension Process in Windows Vista
The system suspension process in Vista differs from Win-XP. Here PBT_APMQUERYSUSPEND
is no more sent to applications. The order of Events in Windows Vista is:
PBT_APMSUSPEND
is sent.
- System goes to Suspended State.
Resuming Process in Windows Vista
The resume operation is quite similar to Windows XP. WM_POWERBROADCAST
message is used to notify the application that a resume is under process or has completed. The first event received is PBT_APMRESUMEAUTOMATIC
which informs the applications that an automatic resume is under process or has completed. The next event that is sent is PBT_APMRESUMESUSPEND
. This indicates that the system has safely resumed operations and that the application can start processing their job.
Application Shutdown in Windows Vista
Application shutdown in Windows Vista has changed relative to Windows XP in various aspects.
In Windows XP, the UI displayed when applications block shutdown is a system dialog. Windows Vista will display visually distinctive UI. The UI more clearly communicates information about applications blocking shutdown.
In Windows XP, the UI for blocking applications allows users to either cancel shutdown or terminate the blocking application. If subsequent applications also block shutdown, the system displays identical UI for each blocking application. Windows Vista UI is capable of identifying multiple applications blocking shutdown and allowing users to terminate the blocking application and make shutdown "forceful."
In a forceful shutdown, Windows Vista will send applications WM_QUERYENDSESSION
with the ENDSESSION_FORCEFULSHUTDOWN
flag. If an application responds FALSE
, Windows will continue shutdown instead of canceling it, and will send the application WM_ENDSESSION
. If an application times out responding to WM_QUERYENDSESSION
or WM_ENDSESSION
, Windows will terminate it.
In Windows XP and earlier, the PBT_APMQUERYSUSPEND
event allowed applications to deny/abort the suspend operation from completing by returning BROADCAST_QUERY_DENY
but in Vista the PBT_APMQUERYSUSPEND
event is not delivered to applications and hence applications cannot deny/abort the suspend operation.
Knowing Your Power Source
Applications can determine that currently system is plugged into an AC power supply or running on DC/Battery power. Once it is known, you can adjust the behavior of your application accordingly. Win32
provides SYSTEM_POWER_STATUS
structure to deal with mostly all sort of Power related stuff. Your application can determine that currently system plugged in state as follows:
SYSTEM_POWER_STATUS SysPwrStat;
if (GetSystemPowerStatus(&SysPwrStat) == 0)
MessageBox(hWnd, "GetSystemPowerStatus Failed!", "OS-Event--Error", MB_ICONWARNING);
if(SysPwrStat.ACLineStatus)
{
}
else
{
}
Your application can determine the remaining BatteryPercent
and Batterytime
as follows:
int battlife = SysPwrStat.BatteryLifePercent;
int battsecs = SysPwrStat.BatteryLifeTime;
System broadcasts a PBT_APMPOWERSTATUSCHANGE
event whenever there is a change in the power status.
Examples:
- If your system is on Battery Power and say your Battery is at 57%. Now whenever your Battery Life Percent gets drained out to 56%, 55% and so on, System will broadcast a
PBT_APMPOWERSTATUSCHANGE
event every time.
- If your system is on AC Power and say your Battery is at 57% and charging. Now whenever your Battery Life Percent gets up to 58%, 59% and so on, System will broadcast a
PBT_APMPOWERSTATUSCHANGE
event every time.
case WM_POWERBROADCAST:
switch (wParam)
{
case PBT_APMPOWERSTATUSCHANGE:
sprintf(strBattlife,"%d",SysPwrStat.BatteryLifePercent);
MessageBox(hWnd, strBattlife,"OS-Event-BatteryLifePercent", MB_ICONINFORMATION);
}
Your application can also determine the Battery Status as follows:
if (SysPwrStat.BatteryFlag == 1)
{
}
if (SysPwrStat.BatteryFlag == 2)
{
}
if (SysPwrStat.BatteryFlag == 128)
{
}
if (SysPwrStat.BatteryFlag == 256)
{
}
Using the Application
The application OS_Events.exe is capable of Capturing / Handling Operating System Events like Stand by, Sleep, Hibernate, Power Status Changed, Low Battery, Critial Suspend, AC Power, Battery Power etc.
By default OS_Events.exe will block / deny Standby, Sleep, Hibernate Operations in Win-XP and earlier. To allow the Standby, Sleep, Hibernate Operations in Win-XP and earlier, return TRUE
from WM_POWERBROADCAST
in WndProc
. Whenever any of the OS event (mentioned at the top of the article) occurs, the application will capture it and notify you with a message box and also update the "Event Status" field in the Dialog box with the event occured.
If you close the DialogBox
, then you will not receive any message box about the events occurring but the application will still keep on denying block / deny Standby, Sleep, Hibernate Operations in Win-XP and earlier. For testing purposes, simply run the application OS_Events.exe and then try putting your System to stand-by from Start Menu ? ShutDown ? Stand-by. You can try closing the Lid of your Laptop too.
References
Additional Readings
- Application Shutdown Changes in Windows Vista (MSDN)
- Application Power Management Best Practices for Windows Vista (MSDN)
History