Click here to Skip to main content
Licence CPOL
First Posted 12 Oct 2008
Views 53,881
Downloads 1,943
Bookmarked 64 times

Handling OS Events in Windows XP and Vista

By | 12 Oct 2008 | Article
Details how to capture OS Events like Sleep, Stand-by, Hibernate, Application Shutdown & Power Management in Windows XP and Vista, and how these OS Events in Windows Vista differ from Windows XP. Also deals with denying or aborting suspension requests in an application.
Abort StandBy

StandBy-Deny.jpg

StandBy Event

StandyBy.JPG

Resume Event

OS_Events_Src

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

  1. PBT_APMQUERYSUSPEND is sent to all applications.
  2. All applications return TRUE.
  3. PBT_APMSUSPEND is sent.
  4. All applications return TRUE and system goes to Suspended State.

Case 2

  1. PBT_APMQUERYSUSPEND is sent to all applications.
  2. An applications return BROADCAST_QUERY_DENY.
  3. PBT_APMQUERYSUSPENDFAILED is sent.
  4. 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:

  1. User or the system (sleep idle timeout) initiates the sleep transition.
  2. Windows power manager notifies applications, services with the appropriate suspend events.
  3. Windows places the system hardware in a sleep state and saves system context in memory, on disk, or both in memory and on disk.
  4. System resumes from the sleep state later due to the user intervention by powering on the system or a wake-on-LAN.
  5. 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.

// will disable the Display and Sleep Idle Timeouts:
SetThreadExecutionState(ES_CONTINUOUS | ES_SYSTEM_REQUIRED | ES_DISPLAY_REQUIRED);

//...

SetThreadExecutionState(ES_CONTINUOUS);

Application developers should keep few things in mind while dealing with SetThreadExecutionState.

  1. SetThreadExecutionState function does not always prevent a screen saver from executing.
  2. Application cannot block the suspend/sleep operation by using SetThreadExecutionState with the ES_SYSTEM_REQUIRED flag.
  3. 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:

  1. PBT_APMSUSPEND is sent.
  2. 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)
{
    // You are on AC Power;
}
else
{  
    // You are on DC/Battery Power;
}

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:

  1. 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.
  2. 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:
        //Power Status Change Event Occured.
        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)
{
    // Battery Status is High.
}
if (SysPwrStat.BatteryFlag == 2)
{
    // Battery Status is Low.
}
if (SysPwrStat.BatteryFlag == 128)
{
    // No Battery in System.
}
if (SysPwrStat.BatteryFlag == 256)
{
    // Battery Status Unknown.
}  

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

  • Initial version:1.0

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Raghuwanshi.G.S



India India

Member



Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
  Refresh
GeneralMy vote of 5memberAndyOrproVision21:35 1 Mar '12  
GeneralVista and sleep statememberJ_Madden4:02 3 Sep '09  
Questiondetecting UPS activationmemberEric Strain7:05 16 Aug '09  
AnswerRe: detecting UPS activationmemberEric Strain9:08 5 Sep '09  
Generalparts of this are taken verbatim from msdn, including errorsmemberBrian Knittel13:25 30 Jul '09  
QuestionHow to know the suspend level (S1/S2/S3)?memberngonhan2k522:58 1 Jun '09  
Questionhow to remove the battery programmaticallymemberts_cortex2:26 14 Apr '09  
QuestionProblems in VistamemberMember 570394:37 14 Oct '08  
AnswerRe: Problems in VistamemberMathewsBob21:26 16 Nov '08  

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web01 | 2.5.120717.2 | Last Updated 13 Oct 2008
Article Copyright 2008 by Raghuwanshi.G.S
Everything else Copyright © CodeProject, 1999-2012
Terms of Use
Layout: fixed | fluid