Storage filter reading problem

Hello,

I am writing a volume filter driver. This driver redirects writes to a different location on disk and then returns that data when parts that it has redirected are requested in a read. It can be turned on or off, so when it’s off it just passes all requests down the stack, but when it’s on it does the redirection. The location that it redirects to is a file on the same volume that it’s filtering. I know the locations of all the clusters of this file.

I was doing a test with the filter to make sure it was doing the reads properly. Basically I do a read using WdfIoTargetSendReadSynchronously() and then compare the buffer to what I get from WdfRequestFormatRequestUsingCurrentType() and WdfRequestSend(). For the test it’s supposed to be reading from the same disk location and the same number of bytes in both cases. All of these calls are successful and return the right number of bytes. The code is below. The problem is that when I compare the two buffers they don’t have the same data. Any ideas why this would be? Is my test bad or is the way I’m reading bad? Any insights would be appreciated.

VOID VFLT_EvtIoRead(IN WDFQUEUE Queue, IN WDFREQUEST Request, IN size_t Length)
{
NTSTATUS status;
WDFDEVICE device;
WDFIOTARGET target;

WDF_REQUEST_PARAMETERS params;
PVOID outBuffer;
PVOID testBuffer;
size_t bufferSize;

WDF_REQUEST_SEND_OPTIONS options;
BOOLEAN sent;
DWORD written;

WDF_REQUEST_PARAMETERS_INIT(&params);
WdfRequestGetParameters(Request, &params);

testBuffer = ExAllocatePoolWithTag(NonPagedPool, params.Parameters.Read.Length, ‘pmet’);

if(filterOn)
{
device = WdfIoQueueGetDevice(Queue);
target = WdfDeviceGetIoTarget(device);

written = 0;
status = readRequest(params.Parameters.Read.DeviceOffset,
params.Parameters.Read.Length,
testBuffer,
target,
device,
&written);
}

WdfRequestFormatRequestUsingCurrentType(Request);
WDF_REQUEST_SEND_OPTIONS_INIT(&options, WDF_REQUEST_SEND_OPTION_SYNCHRONOUS);

sent = WdfRequestSend(Request, WdfDeviceGetIoTarget(WdfIoQueueGetDevice(Queue)), &options);

if(filterOn)
{
status = WdfRequestRetrieveOutputBuffer(Request, 0, &outBuffer, &bufferSize);

written = RtlCompareMemory(testBuffer, outBuffer, params.Parameters.Read.Length);
if(written != params.Parameters.Read.Length)
{
DbgPrint(“Buffers don’t match!!!\n”);
}
}

ExFreePoolWithTag(testBuffer, ‘pmet’);

WdfRequestCompleteWithInformation(Request, STATUS_SUCCESS, params.Parameters.Read.Length);
return;
}

NTSTATUS readRequest(LONGLONG startPos, DWORD length, PVOID buffer, WDFIOTARGET IoTarget, WDFDEVICE device, DWORD* totalBytes)
{
NTSTATUS status;
DWORD written;
WDFMEMORY hMemory;
WDF_MEMORY_DESCRIPTOR memDesc;

status = WdfMemoryCreatePreallocated(WDF_NO_OBJECT_ATTRIBUTES, buffer, length, &hMemory);
WDF_MEMORY_DESCRIPTOR_INIT_HANDLE(&memDesc, hMemory, NULL);

status = WdfIoTargetSendReadSynchronously(WdfDeviceGetIoTarget(device), NULL, &memDesc, &startPos, NULL, &written);

*totalBytes += written;

return status;
}

I forgot to mention that most of the time this works fine. The buffers are different only once in a while.