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);
}