Which PnP IRPs are state changing?

While not clear in the WDK documentation, there are two types of PnP IRPs: state changing and non-state changing. Does this distinction matter? Absolutely. State changing PnP IRPs have a contract associated with them while non-state changing IRPs have no contract whatsoever. Before I get into the gory details, I want to list the members of each type

State Changing Non-state Changing
IRP_MN_START_DEVICE (0x00) IRP_MN_QUERY_INTERFACE (0x08)
IRP_MN_QUERY_REMOVE_DEVICE (0x01) IRP_MN_QUERY_RESOURCES (0x0A)
IRP_MN_REMOVE_DEVICE (0x02) IRP_MN_QUERY_RESOURCE_REQUIREMENTS (0x0B)
IRP_MN_CANCEL_REMOVE_DEVICE (0x03) IRP_MN_QUERY_DEVICE_TEXT (0x0C)
IRP_MN_STOP_DEVICE (0x04) IRP_MN_FILTER_RESOURCE_REQUIREMENTS (0x0D)
IRP_MN_QUERY_STOP_DEVICE (0x05) IRP_MN_READ_CONFIG (0x0F)
IRP_MN_CANCEL_STOP_DEVICE (0x06) IRP_MN_WRITE_CONFIG (0x10)
IRP_MN_EJECT (0x11) IRP_MN_SET_LOCK (0x12)
IRP_MN_QUERY_PNP_DEVICE_STATE (0x14) IRP_MN_QUERY_ID (0x13)
IRP_MN_SURPRISE_REMOVAL (0x17) IRP_MN_QUERY_BUS_INFORMATION (0x15)
. IRP_MN_DEVICE_USAGE_NOTIFICATION (0x16)

IRP_MN_QUERY_DEVICE_RELATIONS (0x07), or QDR, is notably missing from my list. Why? Because the QDR IRP's contract depends on the DEVICE_RELATION_TYPE specifiedin the query. Note that PowerRelations is not currently implemented by any released OS and that SingleBusRelations is undocumented, so they are unqualified.

State Changing Non-state Changing
BusRelations TargetDeviceRelation
EjectionRelations
RemovalRelations

 So what does it mean to be a state changing PnP IRP?  It means that...

  1. These requests are serialized against each other.  You will never have two state changing IRPs in your stack at once.  For instance, you cannot be processing both an IRP_MN_START_DEVICE and IRP_MN_QUERY_REMOVE_DEVICE at the same time.  You can rely on this serialization when implementing implicit power up/down code in your WDM driver (KMDF already takes care of this for you) when processing each of these IRPs.  
  2. With the excpetion of QDR, it is very like that you will have to handle these requests explicitly in your driver instead of blindly passing them down the stack.
  3. There is a definitive order in which you will recieve the IRPs.  I will not go into all of the permuations, but as an example, you cannot receive an IRP_MN_QUERY_REMOVE_DEVICE IRP when you are in the query stopped case (e.g. the last PnP IRP you processed was a IRP_MN_QUERY_STOP_DEVICE)
  4. These PnP IRPs are serialized against System power irps.  NOTE:   they are not serialized against device, wait wake, or query system power irps.  Again, you can use this to your advantage when managing state changes when processing either of these IRP types.  For instance, once you have seen an Sx power irp, you know that you will not see a IRP_MN_QUERY_REMOVE or IRP_MN_SURPRISE_REMOVAL PnP IRP until you have completed the S0 power irp.

A very good hint as to if the PnP IRP is state changing or not is if a driver may send the IRP.  If a driver is allowed to send the IRP, then it is deifnitively not a state changing power IRP.  This is why IRP_MN_QUERY_CAPABILITIES is a non state changing IRP and IRP_MN_QUERY_DEVICE_STATE is.  The former can be sent by any driver at any time, the later is sent to the device stack by the manager (either by its own decision or someone called IoInvalidateDeviceState with the stack's PDO).