SFilter with bad data returned

Hi, my name is Igal and I am trying to implement the following:

Access file on an NTFS drive (d:) are transferred via IRPs to a sFilter, then this IRP is retransferred to a filter which incorporates a thread which fills the required buffer.

User -> IO MANAGER -> Sfilter -> Filter -> Disk -> Filter - >Sfilter -> IO Manager -> User

The access to these files is read only!

I am attaching part of the of SFRead function which is implemented in the Sfilter driver

Get the buffer from an upper driver (cache manager/page manager/User) and lock the buffer in a new MDL

if( DeviceObject->Flags & DO_BUFFERED_IO )
{
ULONG numBytes;
PVOID buffer;

DbgPrint(“Buffered I/O \r\n”);
buffer = (PVOID)Irp->AssociatedIrp.SystemBuffer;
numBytes = pIoStackIrp->Parameters.Read.Length;
pNewMDL = IoAllocateMdl( buffer,
numBytes,
FALSE,
FALSE,
newIrp );

}
else
if ( Irp->MdlAddress )
{
ULONG numBytes;
PVOID buffer;

buffer = MmGetSystemAddressForMdlSafe(Irp->MdlAddress,NormalPagePriority);
numBytes = MmGetMdlByteCount(Irp->MdlAddress);

pNewMDL = IoAllocateMdl( buffer,
numBytes,
FALSE,
FALSE,
newIrp );
}
else
{
pNewMDL = IoAllocateMdl( Irp->UserBuffer,
irpSp->Parameters.Read.Length,
FALSE,
FALSE,
newIrp );

}
if ( !pNewMDL )
{
KdPrint((“IOALLOCATEMDL FAILED\n”));
IoFreeIrp(newIrp);

Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_INSUFFICIENT_RESOURCES;
}

__try
{
MmProbeAndLockPages(pNewMDL,Irp->RequestorMode,IoWriteAccess);
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
status = GetExceptionCode();
KdPrint((“EXCEPTION MMPROBEANDLOCKPAGES STATUS\n”));
IoFreeMdl(pNewMDL);
IoFreeIrp(newIrp);

Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_INSUFFICIENT_RESOURCES;
}
/* store pointer to MDL - release it in SendCompletionRoutine */
newIrp->Tail.Overlay.DriverContext[2] = pNewMDL;
#endif
IoMarkIrpPending(Irp);
IoSetCompletionRoutine(newIrp, (PIO_COMPLETION_ROUTINE) SendCompletionRoutine,
NULL, TRUE, TRUE, TRUE);

newIrp->Tail.Overlay.Thread = Irp->Tail.Overlay.Thread;
newIrpStack = IoGetNextIrpStackLocation(newIrp);
newIrpStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
newIrpStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_MAKE_IRP;
/*
* send file number to filter.sys - avoid additional seek procedure
*/
newIrp->Tail.Overlay.DriverContext[1] = (PVOID)i;
newIrpStack->Parameters.DeviceIoControl.InputBufferLength = irpSp->Parameters.Read.ByteOffset.HighPart;
newIrpStack->Parameters.DeviceIoControl.OutputBufferLength = irpSp->Parameters.Read.ByteOffset.LowPart;
/*
* store pointer to original IRP - complete it in SendCompletionRoutine
*/
newIrp->Tail.Overlay.DriverContext[3] = Irp;
IoCallDriver(dvr[index].dvr,newIrp);
return STATUS_PENDING;
}

IoSkipCurrentIrpStackLocation( Irp );
return IoCallDriver( ((PSFILTER_DEVICE_EXTENSION) DeviceObject->DeviceExtension)->AttachedToDeviceObject, Irp );
/*
* when filter is done filling the buffer the completion routing is called and the used MDL is release
*/
#pragma LOCKEDCODE
NTSTATUS SendCompletionRoutine(PDEVICE_OBJECT fido, PIRP Irp, PVOID pdx)
{ // SendCompletionRoutine
ULONG info;
LONGLONG _64info;
PIRP origIrp;
PIO_STACK_LOCATION irpSp;
NTSTATUS st = Irp->IoStatus.Status;
BOOLEAN SynchronousIo,
PagingIo;

UNREFERENCED_PARAMETER(pdx);
UNREFERENCED_PARAMETER(fido);
origIrp = (PIRP)Irp->Tail.Overlay.DriverContext[3];
irpSp = IoGetCurrentIrpStackLocation(origIrp);
info = Irp->IoStatus.Information;
_64info = (LONGLONG)info;

SynchronousIo = (irpSp->FileObject->Flags & FO_SYNCHRONOUS_IO ? TRUE : FALSE);
PagingIo = (origIrp->Flags & IRP_PAGING_IO ? TRUE : FALSE);

if ( SynchronousIo && !PagingIo )
irpSp->FileObject->CurrentByteOffset.QuadPart += _64info;
if (!PagingIo)
irpSp->FileObject->Flags &= ~FO_FILE_FAST_IO_READ;

if ( Irp->Tail.Overlay.DriverContext[2] == Irp->MdlAddress )
{
MmUnlockPages(Irp->MdlAddress);
IoFreeMdl(Irp->MdlAddress);
Irp->MdlAddress = NULL;
}
IoFreeIrp(Irp);
CompleteRequest(origIrp,st,info);
return STATUS_MORE_PROCESSING_REQUIRED;
}

NOW to the problem…

In the beginning I get UserBuffer “requests” but after a while of accessing a file (as a result of low band width?) windows starts to requests large buffers(4K, 64K) from the file (paging? Chaching?) using MDLAddress. And then I start experience BAD data, I am an embedded engineer, so these type of errors I have experienced in the past as a result of a cached memory which was not invalidated (so user actually get access to a wrong data, but yet I might be wrong).

By the way I have experienced a bad file position but I hope that I have solved it. It was as a result of updating CurrentByteOffset field although I got to fill Asynchronous buffers.

Respectfully yours,

Igal