Listing 10.7 shows the SetPowerState routine in DeviceIo.cpp that actually changes the device power state. SetPowerState simply stores the new device state in the Wdm2 device extension and then calls PoSetPowerState to inform the Power Manager. A SetPowerState routine for a real device will need to interact with the device to change the power state. This will need to synchronize itself with any other hardware activities. A Critical Section routine called via KeSynchronizeExecution might be used for this purpose. If powering a device down, you may need to store some context information that the device normally holds. For example, you could store "the current volume settings" for a set of speakers. When power is restored, pass the stored volume settings to the device. As stated before, you may want to queue up I/O request IRPs while a device is powered down. Listing 10.7 SetPowerState routineSetPowerState
void SetPowerState(IN PWDM2_DEVICE_EXTENSION dx, IN DEVICE_POWER_STATE NewDevicePowerState) {
DebugPrint("SetPowerState %d", NewDevicePowerState);
// Use KeSynchronizeExecution if necessary
// to actually change power in device
// Remember new state
dx->PowerState = NewDevicePowerState;
POWER_STATE NewState;
NewState.DeviceState = NewDevicePowerState;
PoSetPowerState(dx->fdo, DevicePowerState, NewState);
}