This case is the “dispatch side post processing case”. The IRP is not being
re-used, instead your driver’s completion handler is interrupting the
completion process, preventing the OS from completing the IO request. The
completion handler signals a waiting thread (represented by your dispatch
routine) and that waiting thread process the results of the IO request and
then restarts the completion process that was interrupted by the completion
handler. The IRP in question is not being reused for another IO request as
the original IO request has not been fully processed. Having interrupted the
original IRP completion, the dispatch side processing must complete this IRP
a second time. Note that this sort of processing can be repeated by every
driver in a device stack.
See the following:
http://support.microsoft.com/default.aspx?scid=kb;EN-US;320275 and
http://www.microsoft.com/whdc/driver/kernel/IRPs.mspx
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Alan Kung
Sent: Sunday, July 04, 2004 10:18 AM
To: Windows System Software Devs Interest List
Subject: Re: [ntdev] stupid completion question
Dear Mark Roddy
Thank you for the help.
in the following code example,
May I ask
does it re-use the irp ? Why the completion routine
can only return STATUS_MORE_PROCESSING_REQUIRED ?
Does the CompletionRoutine_2 be finished before it call
IoCompleteRequest ?
NTSTATUS
DispatchRoutine_2(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
{
KEVENT event;
NTSTATUS status;
KeInitializeEvent(&event, NotificationEvent, FALSE);
//
// You are setting completion routine, so you must copy
// current stack location to the next. You cannot skip a
location
// here.
//
IoCopyCurrentIrpStackLocationToNext(Irp);
IoSetCompletionRoutine(Irp,
CompletionRoutine_2,
&event,
TRUE,
TRUE,
TRUE
);
status = IoCallDriver(TopOfDeviceStack, Irp);
if (status == STATUS_PENDING) {
KeWaitForSingleObject(&event,
Executive, // WaitReason
KernelMode, // must be Kernelmode to
prevent the stack getting paged out
FALSE,
NULL // indefinite wait
);
status = Irp->IoStatus.Status;
}
// <---- Do your own work here.
//
// Because you stopped the completion of the IRP in the
CompletionRoutine
// by returing STATUS_MORE_PROCESSING_REQUIRED, you must call
// IoCompleteRequest here.
//
IoCompleteRequest (Irp, IO_NO_INCREMENT);
return status;
}
NTSTATUS
CompletionRoutine_2(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context
)
{
if (Irp->PendingReturned == TRUE) {
//
// You will set the event only if the lower driver has returned
// STATUS_PENDING earlier. This optimization removes the need to
// call KeSetEvent unnecessarily and improves performance
because the
// system does not have to acquire an internal lock.
//
KeSetEvent ((PKEVENT) Context, IO_NO_INCREMENT, FALSE);
}
// This is the only status you can return.
return STATUS_MORE_PROCESSING_REQUIRED;
}
Best Regards,
Questions? First check the Kernel Driver FAQ at
http://www.osronline.com/article.cfm?id=256
You are currently subscribed to ntdev as: xxxxx@hollistech.com
To unsubscribe send a blank email to xxxxx@lists.osr.com