When it comes to the changes expected in Windows Vista, the GUI has almost certainly received the most attention. However, there are other changes coming in Vista that will impact driver writers more than having to choose "run as admin" when launching a command prompt. Some of the most interesting and welcome changes come in the field of power management.

Tweaks and Updates
It's never been a lot of fun to write power code for a Windows driver. Due to the accumulation of subtle rules and special cases, it's been even less fun trying to get that power code to work correctly. But there's hope - Vista introduces some simplifications that will make your life easier.

Thanks to the excellent work done by the power management team, starting in Vista PoCallDriver is deprecated, which means you simply use IoCallDriver to send IRP_MJ_ POWER IRPs throughout the system. In fact, if you step into the Vista implementation of PoCallDriver in the debugger, you'll see it just calls IoCallDriver. Also, in terms of implementation (and recognizing that implementation details can change without notice), if you step into IoCallDriver you'll see this function now checks the IRP major function code and calls the Power Manager if the function is power-related.

An even more significant change is that drivers no longer need to call PoStartNextPowerIrp. In fact, in Vista this function does absolutely nothing. What's particularly nice about this change is that while the function call is now obsolete, the basic rules for power request serialization remain the same. For example, there can still only be one S-IRP and one D-IRP active on a device stack at a time.

Do you remember all the weird rules about when you're allowed to set DO_POWER_PAGABLE and DO_POWER_INRUSH in your device object depending on what other drivers in the stack have set? No? Well, don't bother learning them now. Starting with Vista drivers are free to set DO_POWER_PAGABLE and DO_POWER_INRUSH as required, and the Power Manager will "do the right thing." If any device in the stack is marked pagable, then the whole stack is considered pagable. If any device is marked inrush, then the whole stack is considered inrush. Nice, huh?

Check Your Code
Vista also includes a few Power Manager changes that could cause your driver's power code to run a bit differently than it ran before. For example, the Power Manager is now more likely to send power IRPs in parallel to different device stacks than it was in the past. This is due to the fact that the Power Manager now always uses its pool of worker threads to dispatch S- and D-IRPs. Presently, the Power Manager uses up to eight worker threads for this purpose (this number is subject to change at any time). Another thing that increases the likelihood that multiple power IRPs will be in progress simultaneously is the increasing prevalence of mutli-core and hyperthreaded machines. As we've often advised here in The NT Insider, it's critical these days to be sure your driver's code is multiprocessor safe.

Speaking of implementation details, another thing that's changed in Vista is a detail of the way PoRequestPowerIrp is implemented. When you call PoRequestPowerIrp in Vista, the resultant S-or D-IRP is always queued asynchronously. In other words, the IRP generated by PoRequestPowerIrp is never dispatched to the device stack on the same thread that called PoRequestPowerIrp, which often happened in previous versions of Windows. While it was never correct to assume PoRequestPowerIrp sent its IRP synchronously, there are drivers that make this implicit assumption. So, you might want to review your power code for any assumptions that your driver makes in this regard.

Sleep More - Sleep Different
Vista also introduces new issues regarding sleep states (S2-S4). For example, starting in Vista, the default "off" state is S3. As a result, drivers are likely to see many more sleep/resume transitions than they have in the past - even on desktop machines. If your sleep and hibernate code isn't particularly well tested or thought out, you should take a close look at it before trying to support Vista because this code will certainly get a workout running on Vista.

Related to the issue of more sleep/resume transitions is the time it takes your driver to perform those transitions. Because of the increased number of sleep/resume transitions in Vista, any delay your driver introduces during resume processing will become readily apparent. Who wants to use a system that has an annoyingly long resume time? If your driver doesn't follow best practices for fast resume processing, or if it introduces a significant delay during resume, you'll almost certainly want to revisit that code for Vista.

Probably the most interesting change in Vista regarding sleep states is the introduction of the new pseudo-state called hybrid sleep. In hybrid sleep the system not only suspends to S3, but also writes a copy of the system image to the hibernation file. When it is time to return to S0, the system will resume from S3 unless power has been lost while sleeping, in which case the system will resume from S4 using the image written to the hibernation file. Note that this implies that the S3 to S4 transition can occur without an intervening transition to S0. To make hybrid sleep work seamlessly with existing drivers, the Power Manager tells drivers the system is going to S4 (that is Parameters.Power.State in the S-IRP I/O stack location is set to PowerSystemHibernate). This allows drivers to prepare their devices for the worst-case transition.

In Vista it is possible for drivers to differentiate between ordinary transitions to/from S4 and transitions to/from hybrid sleep. Drivers can do this using the newly defined field Parameters.Power.SystemPowerStateContext in the power IRP's I/O stack location. This field contains a SYSTEM_POWER_STATE_CONTEXT structure that is defined in wdm.h in Figure 1.

As you can probably guess, CurrentSystemState contains the state from which the system is transitioning. This will be S0 for any transition to a sleep state, but during transitions to S3 it will be either S3 or S4 depending on the state from which the system is waking.

TargetSystemState contains the state to which the system will immediately transition. For transitions to hybrid sleep, TargetSystemState is set to S3. EffectiveSystemState is the state the system might enter at some point in the future. For transitions to hybrid sleep, EffectiveSystemState is set to S4.

Don't Fight the Power
Have the changes to Vista made it fun to write power management code for WDM drivers? Uh - no. But these changes have made writing that code easier and more rational. Be sure to use the guidelines in this article and get your driver ready for Vista.

The NT Insider thanks the devs and PMs in the Windows power management team for their generous assistance in helping us prepare this article.