Hi
I am having a problem that appears to hang in ExReleaseResourceForThread
when I create my own IRP’s. I am trying to improve my encryption engine by
stopping the IRP that is passed into my write routine, create a new one
with the encrypted buffer and passing the new IRP on. In the completion
routine I then complete the org IRP and free mine. But on the third or forth
call the box hangs for about 5 mins in ExReleaseResourceForThread. Any ideas
?
NTSTATUS SFilterWriteMDLCompletion(IN PDEVICE_OBJECT DeviceObject, IN PIRP
Irp, IN PVOID Context)
{
ENCWRITEDATA *EncStore = (ENCWRITEDATA *)Context;
/* get the org IRP */
PIRP OrgIrp = EncStore->IRPOrg;
/* Set its status */
OrgIrp->IoStatus = Irp->IoStatus;
/* Propogate the IRP pending flag. */
if (OrgIrp->PendingReturned)
{
IoMarkIrpPending(OrgIrp);
}
IoCompleteRequest(OrgIrp, IO_NO_INCREMENT);
/* Free the MDL I allocated */
MmUnlockPages(Irp->MdlAddress);
IoFreeMdl(Irp->MdlAddress);
Irp->MdlAddress = NULL;
/* Free the irp */
IoFreeIrp(Irp);
/* Free the memory allocated */
ExFreePool(EncStore->EncBuffer);
/* Destroy the Key Info */
BWFreeMemory((LPBYTE)EncStore);
return (STATUS_MORE_PROCESSING_REQUIRED);
}
//
// Microsoft Sample
//
NTSTATUS SFilterWrite(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
NTSTATUS Status = STATUS_SUCCESS;
/* Get a pointer to this driver’s device extension for the specified
device. */
PtrSFilterDeviceExtension PtrDeviceExtension =
(PtrSFilterDeviceExtension)(DeviceObject->DeviceExtension);
/* Is it our Device */
if (ValidDeviceExtension(PtrDeviceExtension))
{
/* Do the default */
BOOLEAN DefaultCall = TRUE;
/* Get a pointer to the current stack location in the IRP */
PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation( Irp );
/* Workout the size of the buffer */
DWORD BufferSize = irpSp->Parameters.Write.Length;
/* Is traces lookup required */
BOOLEAN TraceLookup = (Irp->Flags & IRP_NOCACHE);
/* if there is something to handle */
if ((BufferSize) && (TraceLookup))
{
/* Check if File is Enciphered */
ENCWRITEDATA *EncStore = (ENCWRITEDATA
*)BWGetMemory(sizeof(ENCWRITEDATA));
BOOLEAN Tracing = EncryptionTraceCheck(irpSp->FileObject, TRUE,
&EncStore->KeyInfo);
if (Tracing)
{
/* Default to no error */
BOOL Error = FALSE;
/* According to NTFSD we must NEVER change the Buffer */
/* so we must allocate our own Irp with our own memory and pass it on */
if (Irp->MdlAddress)
{
/* Create an Encrypted Buffer store */
EncStore->EncBuffer = (LPBYTE)ExAllocatePool(NonPagedPool, BufferSize);
if (EncStore->EncBuffer)
{
EncStore->PlainBuffer =
(LPBYTE)MmGetSystemAddressForMdl(Irp->MdlAddress);
/* Record the org IRP */
EncStore->IRPOrg = Irp;
/* Allocate My IRP */
PIRP MyIRP =
IoAllocateIrp(PtrDeviceExtension->TargetDeviceObject->StackSize, FALSE);
if (MyIRP)
{
/* Fill in the required fields */
MyIRP->Flags = Irp->Flags;
MyIRP->Tail.Overlay.Thread = PsGetCurrentThread();
MyIRP->Tail.Overlay.OriginalFileObject = irpSp->FileObject;
/* Copy the Data from the org buffer */
RtlCopyMemory(EncStore->EncBuffer, EncStore->PlainBuffer,
BufferSize);
/* Get the SeekPos */
DWORD SeekPos = (DWORD)irpSp->Parameters.Write.ByteOffset.QuadPart;
/* Encipher the Org Buffer */
EncipherBuffer(EncStore->EncBuffer, BufferSize, SeekPos,
&EncStore->KeyInfo);
/* Allocate My MDL */
PMDL MyMDL = IoAllocateMdl(EncStore->EncBuffer, BufferSize, FALSE,
FALSE, MyIRP);
if (MyMDL)
{
/* Lock the pages (must be kernel as buffer is in kernel) */
MmProbeAndLockPages(MyMDL, KernelMode, IoReadAccess);
/* Get a pointer to the Next stack location in the IRP */
PIO_STACK_LOCATION NextIRPSp = IoGetNextIrpStackLocation(MyIRP);
NextIRPSp->MajorFunction = irpSp->MajorFunction;
NextIRPSp->MinorFunction = irpSp->MinorFunction;
NextIRPSp->Flags = 0;
NextIRPSp->DeviceObject = PtrDeviceExtension->TargetDeviceObject;
NextIRPSp->FileObject = irpSp->FileObject;
NextIRPSp->Parameters = irpSp->Parameters;
/* Setup Default completion Routine */
IoSetCompletionRoutine(MyIRP, SFilterWriteMDLCompletion, EncStore,
TRUE, TRUE, TRUE);
Status = IoCallDriver(PtrDeviceExtension->TargetDeviceObject,
MyIRP);
/* Stop other processing */
DefaultCall = FALSE;
}
else
{
Error = TRUE;
/* Destroy the Key Info */
BWFreeMemory((LPBYTE)EncStore);
/* Free the defunct IRP */
IoFreeIrp(MyIRP);
}
}
else
{
Error = TRUE;
/* Destroy the Key Info */
BWFreeMemory((LPBYTE)EncStore);
}
}
else
{
Error = TRUE;
}
/* handle the error */
if (Error)
{
DefaultCall = FALSE;
/* Say we could not do it */
Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
}
}
/* Clean up if no set Completion */
if (DefaultCall)
{
BWFreeMemory((LPBYTE)EncStore);
}
}
if (DefaultCall)
{
/* Setup Next Driver */
IoCopyCurrentIrpStackLocationToNext(Irp);
/* Setup Default completion Routine */
IoSetCompletionRoutine(Irp, SFilterDefaultCompletion, NULL, FALSE,
FALSE, FALSE);
/* No processing required pass on to appropriate file system driver. */
Status = IoCallDriver(PtrDeviceExtension->TargetDeviceObject, Irp);
}
}
}
return (Status);
}
Thanks
Paul