Usually, you may notice when using !irp in with a Stop 0x9F, that the completion status shows three different fields; sometimes with the addition of the pending flag being set. In this blog post, I’m going to explain what is actually happening and which completion status field is set.
As you can see, there is three different IO Completion Status fields present, so the question is, which one is WinDbg suggesting? These fields are defined depending upon what the driver was going to do with the completed IRP. They are used with the IoSetCompletionRoutine function, which is defined as follows:
These are all BOOL values, and thereby will be either true or false, depending upon the bit values. InvokeOnSuccess and InvokeOnError decided wherever the completion routine defined within the IO_STACK_LOCATION data structure will be called upon if the IRP is completed with a NTSTATUS Success value or NTSTATUS Error value.
The next important data structure is the IO_STACK_LOCATION data structure, which contains the completion routine and the control flags seen with the !irp extension. We need to use the 0xfffffa80116e07d0 address, since this is the address of the data structure for the current IRP stack location.
The flags field is used to check wherever the SL_PENDING_RETURNED flag has been set, and the IRP is pending.
The Control flags field is divided into two parts e and 0. Let’s start with the numeric value first. There are three possible values: 0, 1 and 2.
0 = Nothing
1 = Pending
2 = Error
The second part corresponds to our Success, Error and Cancel fields as seen before. We need to convert e into numerical form, which is always 14. You then need to convert this 14 or 0xe into a binary format which is 1110. I used a free online binary converter to do this.
The 0 corresponding to the Pending field, and the other three values correspond to the BOOL values seen with the IoSetCompletionRoutine.