The Basics

Rules for Irp Dispatching and Completion Routines
(By: By The Members of NTDEV and NTFSD | Published: 01-May-03| Modified: 01-May-03)

IRP Dispatching and Handling

  • 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)
    • 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
    • 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 before calling IoCompleteRequest. In some cases, you can use Irp->IoStatus as a temporary storage before this, assuming you do not pass the IRP to another driver. However, this does not apply to IRPs for IRP_MJ_PNP, because these IRPs arrive from the PnP Manager with a default status already filled into the IoStatus.Status field.
  • Because of special logic in the I/O Manager's completion handling code, drivers can also pass an IRP to another by "return IoCallDriver(...)" without setting a completion routine in the IRP. 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 CDFS in NT V4.0):

    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 you set a completion routine into an IRP that's passed into your driver, and if that completion routine returns STATUS_MORE_PROCESSING_REQUIRED, your dispatch routine for that IRP 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).

This article was printed from OSR Online http://www.osronline.com

Copyright 2017 OSR Open Systems Resources, Inc.