Wasn’t it Ravisankar Pudipeddi who posted these (trying to make sure credit
goes where credit is due)?
-----Original Message-----
From: Peter Viscarola [mailto:xxxxx@osr.com]
Sent: Friday, September 27, 2002 12:27 PM
To: NT Developers Interest List
Subject: [ntdev] 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).
You are currently subscribed to ntdev as: xxxxx@ntpsoftware.com
To unsubscribe send a blank email to %%email.unsub%%