Why KMDF does not have a callback for IRP_MN_QUERY_POWER/SystemPowerState

I was going to blog about this after I had some KMDF entries under my belt, but Raymond Chen got things started today with his post about how Windows Vista is not letting applications veto a power transition to a low power state (Sx, see the Glossary).  KMDF has a very flexible power model, you can specify as a driver what device power state you want your device to go to while the machine is running or powering down, and if you want your device armed for wake when it powers down.  The one thing KMDF does not expose is the ability for a driver to IRP_MN_QUERY_POWER for a SystemPowerState. 

Let's say you had a system which was capable of S1 and S3 (which are varying degrees of how deeply asleep your machine is, see MSDN for more details) and you had 2 drivers which handled IRP_MN_QUERY_POWER.  Driver A fails the query for S3 and Driver B fails the query for S1.  You now have a machine which cannot go into standby at all.   Furthermore, the user get's a cryptic popup along the lines of "The device <insert device description> is failing the request to go into low power."  So now the user has 2 problems, neither of which are easily solvable

  1. The user can't go put the machine into standby at all
  2. The user has to disable the device, which assumes that
    • The user can find device manager in the first place
    • The device is disablable (yes, that is word ;) in driver speak)
    • The potential app that has opened the device has registered for pnp notifications so the disable will not be vetoed
    • The driver can actually handle a graceful remove and not cause a BSOD (you'll be amazed at how many drivers i have debugged which don't handle a remove properly).

Why would a driver fail a query Sx request anyways?  Let's say the driver is burning a CD and that if the machine went to sleep in the middle of the burn, the user is left with a useless coaster.  When we implemented the power support in KMDF we decided that it was up to the app to display a meaningful message as to why the suspend failed, the driver could not convey such a message (or even know where to display it in the case of FUS).  I guess the app doesn't get to display a message anymore and you get a useless coaster. That's still better then not being able to into standby at all.

(And for those of you who are saying KMDF is yet another restrictive driver model, you can still actually respond to the IRP_MN_QUERY_POWER irp, you just have to register a preprocessing routine for it.)