I have a completion routine that needs to be run at Irql Passive. To
handle those cases where the Irql is higher I pass off the processing to a
worker thread. Having read in OSR’s Win2K/XP IFS FAQ that you shouldn’t
wait in completion for worker to finish (couldn’t figure out how anyway
since at least one call to set up and wait required an “Irql must be
passive” function in every scenario I could come up with.) I rewrote my
Dispatch routine to wait instead.
Problem is sometimes I’m getting a KMODE_EXCEPTION -
STATUS_ACCESS_VIOLATION when touching Irp stuff which leads me to believe
that sometimes the Irp has been torn down before my worker thread gets to
it. Not good.
Am thinking the status I return in the completion routine might be problem
but don’t think STATUS_MORE_PROCESSING_REQUIRED is appropriate here since,
among other things, I didn’t create the Irp and therefore wouldn’t feel
comfortable Completing it.
Here’s a rough sketch of what I’m doing. Any insights would be much
appreciated:
DISPATCH:
IoCopyCurrentIrpStackLocationToNext(Irp);
pEvent = ExAllocatePool( NonPagedPool, sizeof(KEVENT));
if (pEvent)
{
KeInitializeEvent(pEvent, SynchronizationEvent, FALSE);
IoSetCompletionRoutine(
Irp,
CreateCompletion,
pEvent, //context
TRUE,
TRUE,
TRUE);
(void) IoCallDriver(pDeviceExtension->NextDeviceObject, Irp);
KeWaitForSingleObject(pEvent, Executive, KernelMode, TRUE, 0);
ExFreePool(pEvent);
return Irp->IoStatus.Status;
}
COMPLETION:
pWData = ExAllocatePool( NonPagedPool, sizeof(WORK_DATA));
if (pWData)
{
pIOWorkItem = IoAllocateWorkItem( DeviceObject );
pWData->DeviceObject = DeviceObject;
pWData->Irp = Irp;
pWData->pIOWorkItem = pIOWorkItem;
pWData->pIrpStack = pIrpStack;
pWData->pEvent = Context;
IoQueueWorkItem( pIOWorkItem, &WorkerCreateFilter, CriticalWorkQueue,
(PVOID) pWData);
}
}
if (Irp->PendingReturned)
{
IoMarkIrpPending( Irp );
}
return STATUS_SUCCESS;
WORKER:
//Do processing, then… (problem (sometimes): KMODE_EXCEPTION -
STATUS_ACCESS_VIOLATION Irp already torn down?)
KeSetEvent(pWData->pEvent, 0 , FALSE);
IoFreeWorkItem(pWData->pIOWorkItem);
ExFreePool(pWData);