IRP Completion Rules -- Rules for I/O Completion Routines

Max Shatskih posted some iron-clad rules for IRP handling on the NTFSD
forum, and asked if somebody would post them on the web. I’ve done some
editing on Max’ original rules, limited their scope somewhat, and added a
couple more.

If we can get broad concensus on these rules (thanks Max), I’ll be MORE than
happy to post them on the web site in a prominent place.

Corrections/suggestions/recommendations appreciated.

Peter
OSR


IRP Completion Rules

  • If a dispatch routine returns STATUS_PENDING, the IRP passed into the
    dispatch routine must be marked pending with IoMarkIrpPending().
  • If an IRP is marked pending with IoMarkIrpPending() in a dispatch routine,
    that dispatch routine must return STATUS_PENDING.
  • If an IRP is to be marked pending, IoMarkIrpPending must be called before
    the IRP is accessible from any context in which it might be completed.
  • If you complete the IRP in the dispatch routine, you must fill
    Irp->IoStatus.Status with the IRP’s completion status (this may NOT be
    STATUS_PENDING), you must fill Irp->IoStatus.Information with the number of
    bytes read or written by the request if the request is being completed with
    a success status (for data transfer operations and IOCTLs), and then you
    must call IoCompleteRequest(). On return from the dispatch routine, you must
    return the same status that you filled into Irp->IoStatus.Status. Note that
    in some cases Irp->IoStatus.Information can hold a pointer.
  • Once you call IoCompleteRequest(), you no longer “own” the IRP, and must
    not refer to any of its contents.
  • Irp->IoStatus.Status must be filled only just before IoCompleteRequest.
    You can use Irp->IoStatus as a temporary storage before this, assuming you
    do not pass the IRP to another driver.
  • Because of special logic in the I/O Manager’s completion handling code,
    drivers can also pass an IRP to another by “return IoCallDriver(.)”. In this
    case, IoMarkIrpPending must not be called.
  • The following sequence is also valid, though slower. It is necessary as a
    workaround for filtering some buggy drivers like NT4’s CDFS:

IoMarkIrpPending(Irp);
(VOID)IoCallDriver(BottomDeviceObject, Irp);
return STATUS_PENDING;

I/O Completion Routines

  • There are only three valid return codes from an I/O Completion Routine:
    STATUS_MORE_PROCESSING_REQUIRED, STATUS_SUCCESS, and
    STATUS_CONTINUE_COMPLETION (which is identical to STATUS_SUCCESS, see
    NTDDK.H)

  • STATUS_MORE_PROCESSING_REQUIRED means that IoCompleteRequest returns to
    its caller
    immediately. No further completion routines are called, and IRP is not
    returned to the I/O Manager.

  • If and only if the completion routine returns STATUS_SUCCESS (or
    STATUS_CONTINUE_COMPLETION) , then it must do the following:

if( Irp->PendingReturned ) {
IoMarkIrpPending(Irp);
}

  • If your completion routine returns STATUS_MORE_PROCESSING_REQUIRED, your
    dispatch routine for that IRP (if you have one, that is, if you did not
    create the IRP in your driver) must either return STATUS_PENDING or it must
    block until the completion routine has run (for example, waiting on an event
    that is set from within the completion routine).

Peter Viscarola wrote:

I think posting this information will be a good idea, especially since
I’m sure you guys will add appropriate caveats about how there are many
other factors to consider in handling IRPs. I’d recommend that the page
you create make it clear that all you’re talking about is return codes
from dispatch and completion routines and about when and how to call
IoMarkIrpPending. It would also be well to reference the KB article
(Q320275?) that Eliyas spent so much time on earlier this summer. FWIW,
I spend 90 pages on IRP handling in the 2d edition of my WDM book and 2
days in an advanced seminar.

  • Irp->IoStatus.Status must be filled only just before IoCompleteRequest.
    You can use Irp->IoStatus as a temporary storage before this, assuming you
    do not pass the IRP to another driver.

Seems like a good rule, but Microsoft violates it with PNP and POWER
requests. In fact, when completing one of these IRPs that you don’t
specifically understand in a bus driver, you mustn’t touch *either*
Status or Information.

  • Because of special logic in the I/O Manager’s completion handling code,
    drivers can also pass an IRP to another by “return IoCallDriver(.)”. In this
    case, IoMarkIrpPending must not be called.

… in the dispatch routine. But if you install a completion routine…

  • There are only three valid return codes from an I/O Completion Routine:
    STATUS_MORE_PROCESSING_REQUIRED, STATUS_SUCCESS, and
    STATUS_CONTINUE_COMPLETION (which is identical to STATUS_SUCCESS, see
    NTDDK.H)

Which means just two values. I’d document STATUS_SUCCESS and
STATUS_MORE_PROCESSING_REQUIRED and then mention that the .net DDK will
define some additional synonyms whose names are more evocative. The last
information I had was that there would be STATUS_CONTINUE_COMPLETION
plus an enumeration with two additional synonyms.

  • If your completion routine returns STATUS_MORE_PROCESSING_REQUIRED, your
    dispatch routine for that IRP (if you have one, that is, if you did not
    create the IRP in your driver) must either return STATUS_PENDING or it must
    block until the completion routine has run (for example, waiting on an event
    that is set from within the completion routine).

Maybe word this as, “if you install a completion routine for an IRP that
someone else hands you, and if it returns S_M_P_R . . .”. I missed the
“if you have one” qualification the first time, and I immediately
started thinking about the mandatory completion routine for an
asynchronous IRP that I create.


Walter Oney, Consulting and Training
Check out new US seminar schedule at http://www.oneysoft.com

“Walter Oney” wrote in message news:xxxxx@ntdev…
>
> Peter Viscarola wrote:
>
> I think posting this information will be a good idea, especially since…

EXCELLENT points, Walter, thanks. I’ll do the appropriate updates as you
suggest. I would have completely missed the issue around status and PnP and
Power IRPs… nice catch.

Hey, when DO we get to see the 2nd edition of your book?

Peter
OSR

Peter Viscarola wrote:

Hey, when DO we get to see the 2nd edition of your book?

Well, if you sign up for one my seminars, I can get you an early copy


But seriously folks, January is the ETA for bookstores according to my
editors.


Walter Oney, Consulting and Training
Check out new US seminar schedule at http://www.oneysoft.com

> Bi Chen wrote:

I am registered on your web (my home email address). Will I get an
eamil notice when your WDM book (2nd edition) is publically available?

I hadn’t planned to do that, but you’re now the second reader who’s
asked. I’ll keep your e-mail address on file for a private notification
in any case.


Walter Oney, Consulting and Training
Check out new US seminar schedule at http://www.oneysoft.com