In my previous post, I talked about how state changing PnP IRPs (refered to from now own as just PnP IRPs) are serialized against each other and briefly mentioned which power IRPs they were synchronized against. This merits its own entry. In short, PnP IRPs are only synchronized against system power IRPs (e.g. IRP_MN_SET_POWER/SystemPowerState irps). PnP IRPs are not synchronized against any other power IRP, which are

  • IRP_MN_SET_POWER/DevicePowerState
  • IRP_MN_WAIT_WAKE
  • IRP_MN_QUERY_POWER/SystemPowerState
  • IRP_MN_QUERY_POWER/DevicePowerState
  • IRP_MN_POWER_SEQUENCE (unimplemented)

If you think about it, it makes sense that some of these power IRPs are not synchronized against PnP IRPs. Let's take wait wake as an example, your device has idled out and armed itself for wake, which means a wait wake IRP is pending in the stack at the PDO. While idled out, the device is surprise removed from the system. If the wait wake power irp was synchronized against PnP IRPs, the PnP IRP_MN_SURPRISE_REMOVAL IRP would never arrive in the until the wait wake IRP was completed by the PDO or canceled by the device stack's power policy owner. While you could argue that the bus driver should complete the wait wake IRP when it reports the device as missing and have the wait wake IRP be synchronized against PnP IRPs, there are two problems with this approach. First, it places an additional burden on the bus driver and writing a bus driver is complicated enough ;). Second, any driver in the stack can cause a IRP_MN_SURPRISE_REMOVAL IRP to be sent to the stack (by invalidating the device state with IoInvalidateDeviceState and then returning a failed state in IRP_MN_QUERY_PNP_DEVICE_STATE (not to mention the problem that IRP_MN_QUERY_PNP_DEVICE_STATE is also a state changing PnP IRP so there is no way you could query the state while a wait wake irp was pended) without the knowledge of the bus driver, so the bus driver or power policy owner would not be able to proactively cancel the wait irp to allow the surprise removal IRP to arrive.

On the other hand, you might wonder why the OS did not serialize IRP_MN_QUERY_POWER/DevicePowerState power IRPS against PnP IRPs. Unlike wait wake IRPs, device power IRPs are not pended in the stack, they flow through the stack and return back to the PnP manager rather quickly. I wondered the same thing. The only reason I could think of why they are not synchronized is that on Windows 2000 the power policy owner was supposed to pend the IRP_MN_SET_POWER/SystemPowerIrp until the requested IRP_MN_SET_POWER/DevicePowerIrp has completed. This means that you be able to have both types of power IRPs pended in the stack at the same time, which is not possible if both of these types of IRPs are synchronized against each other.

So, what does this mean for you as a driver writer? If your driver is WDM, you have manually synchronize the sending and waiting for power irps during PnP and IRP_MN_SET_POWER/SystemPowerState state transitions (for instance, waiting for a D0 irp to complete when returning from idle and receiving a IRP_MN_SET_POWER/SystemPowerIrp where you will have to send a Dx IRP). This will involve a lot of state management and is not a simple task. On the other hand, if your driver uses KMDF, there is nothing you need to do; KMDF will take care of all the state management for you.