RE: IRP Completion Rules -- Rules for I/O Completion Rout ines

RE: [ntdev] IRP Completion Rules – Rules for I/O Completion RoutinesHe posted another set of rules, though intersecting with my text a lot.

----- Original Message -----
From: Smith, Joel
To: NT Developers Interest List
Sent: Friday, September 27, 2002 9:26 PM
Subject: [ntdev] RE: IRP Completion Rules – Rules for I/O Completion Rout ines

Wasn’t it Ravisankar Pudipeddi who posted these (trying to make sure credit goes where credit is due)?

-----Original Message-----
From: Peter Viscarola []
Sent: Friday, September 27, 2002 12:27 PM
To: NT Developers Interest List
Subject: [ntdev] IRP Completion Rules – Rules for I/O Completion

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.


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:

(VOID)IoCallDriver(BottomDeviceObject, Irp);

I/O Completion Routines

  • There are only three valid return codes from an I/O Completion Routine:

  • 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 ) {

  • 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).

You are currently subscribed to ntdev as:
To unsubscribe send a blank email to %%email.unsub%%

You are currently subscribed to ntdev as:
To unsubscribe send a blank email to %%email.unsub%%