using STATUS_MORE_PROCESSING_REQUIRED: am I using it correctly??

Hello,
I’ve just want to be sure I am using STATUS_MORE_PROCESSING_REQUIRED
correctly. My code seems to work fine (code sample is pased below), but I’m
nervous because of a footnote in ‘File System Internals’ (page 165). The
footnote contains these sentences:
“The problem, through, is that there is a lot of post processing
required on that IRP that will have been abrubtly interrupted due to you
returning such a status code from your completion routine. You driver will
then have to device a method whereby such postprocessing can be resumed
later; this is not a trivial task.”
Well, just calling IoCompleteRequest on the irp certainly seems
trivial, so I am wondering if I am handling this correctly or are there more
steps I should be doing (note that everything seems to work just fine).
Aside from Nagar’s book, there isn’t much documentation on how to handle
STATUS_MORE_PROCESSING_REQUIRED. Here is some code, with all of the
irrelevant domain specific stuff stripped out. Am I doing this right?

Thanks,
Joel

NTSTATUS Create(PDEVICE_OBJECT pDev, PIRP pIrp)
{
NTSTATUS ntRet;
PDEVICE_OBJECT pNextDevice;
KEVENT event;

//event used to make call synchronous even if the fsd pends the
operation
KeInitializeEvent(&event, NotificationEvent, FALSE);

//get the deviced we are attached to from the device extension
pNextDevice =
((PDEVICE_EXTENSION)(pDev->DeviceExtension))->NextDriverDeviceObject;

IoCopyCurrentIrpStackLocationToNext(pIrp);

//set a completion routine
IoSetCompletionRoutine(pIrp,
CreateComplete,
&event,
TRUE,
TRUE,
TRUE);

//pass the irp down
ntRet = IoCallDriver(pNextDevice, pIrp);

if (ntRet == STATUS_PENDING)
{
//wait for the event that is signalled in our completion
KeWaitForSingleObject(&event,
Executive,
KernelMode,
FALSE,
NULL);

//get the real success code
ntRet = pIrp->IoStatus.Status;
}

//if the file was opened
if (NT_SUCCESS(ntRet))
{
//do some stuff that I didn’t want to do in the completion
routine
}

//we are done with the irp and ready to complete the request.
IoCompleteRequest(pIrp, IO_DISK_INCREMENT);

//done - should I always mark pending and return pending to prevent
the inherently synchronous io
//problem Nagar talks about?
return pIrp->PendingReturned ? STATUS_PENDING : ntRet;
}

NTSTATUS CreateComplete(PDEVICE_OBJECT pDev, PIRP pIrp, PKEVENT pContext)
{
//propogate the pending returned flag
if (pIrp->PendingReturned)
{
IoMarkIrpPending(pIrp);
}

//alert the mainline thread that the io was completed
KeSetEvent((PKEVENT)pContext, IO_NO_INCREMENT, FALSE);

//we need to hold onto this irp for whatever reason
return (STATUS_MORE_PROCESSING_REQUIRED);
}

using STATUS_MORE_PROCESSING_REQUIRED: am I using it
correctly??>STATUS_MORE_PROCESSING_REQUIRED. Here is some code, with all

of the irrelevant domain specific stuff stripped out. Am I doing this
right?

I would say - wrong a bit.

  1. Wait always, regardless of the return code from IoCallDriver.
  2. Call IoMarkIrpPending before IoCallDriver, and always return
    STATUS_PENDING from your dispatch routine. See Nagar’s book for details -
    “About STATUS_MORE_PROCESSING_REQUIRED stuff”.

Max