Sometimes I experience strange behavior when writing to the irp->MdlAddress
buffer of a disk filter driver I am writing.
In my IRP_MJ_READ routine I need to return the contents of an internal
buffer in stead of passing the request on to the disk driver.
If I enter the code below in the IRP_MJ_READ dispatch routine the assertion
occasionally fails, i.e., the RtlCopyMemory command did not copy correctly.
if (irp->MdlAddress) {
void* mdlBuffer = MmGetSystemAddressForMdlSafe(irp->MdlAddress,
NormalPagePriority);
ULONG length = IoGetCurrentIrpStackLocation(irp)->Parameters.Read.Length;
RtlCopyMemory(mdlBuffer, buffer, length);
ASSERT(RtlEqualMemory(mdlBuffer, buffer, length )); // <- This assertion
occasionally fails
}
Typically irp->MdlAddress->MdlFlags is (MDL_IO_PAGE_READ | MDL_PAGES_LOCKED)
before the MmGetSystemAddressForMdlSafe() call and (MDL_IO_PAGE_READ |
MDL_PAGES_LOCKED | MDL_MAPPED_TO_SYSTEM_VA) afterwards.
What really puzzles me is that after one ore more attempts the test code
below succeeds. It looks like the MDL is not fully ready yet on the first
attempt and that a separate thread is building it simultaneously.
do {
differs = FALSE;
RtlFillMemory(mdlBuffer, length, ‘X’);
for (i = 0; i < length; ++i) {
if (buffer[i] != ‘X’) {
differs = TRUE;
KdPrint( ("Byte %d of %d differs.\n", i, length) );
}
}
} while (differs);
Can anybody please tell me what is going on.
Thanks
