Hi folks, I’ve read the following articles:
- IFS FAQ (https://www.osronline.com/article.cfm^article=17.htm#Q56)
- Master of the Obvious – MDLs are Lists that Describe Memory (https://www.osronline.com/article.cfm^id=423.htm)
and have the following questions on the sample (https://github.com/microsoft/Windows-driver-samples/blob/main/filesys/miniFilter/swapBuffers/swapBuffers.c):
Q1
In read pre-op (SwapPreReadBuffers
) we allocated our own MDL (newMdl
) and swapped it with the IRP’s MDL:
L953: iopb->Parameters.Read.MdlAddress = newMdl;
We did not save the original MdlAddress
before overwriting it. If it’s not null, then who frees it? The comments at the end of post-op (SwapPostReadBuffers
, L1200) states that “freeing of the MDL (if there is one) is handled by FltMgr”. There are 2 MDLs here, and I guess FltMgr handles one of them, so what about the other one?
Q2
The aforementioned comments state that the filter manager is the one that does the freeing. However, the IFS FAQ states that it’s the I/O Manager that cleans up the MDL:
A normal driver will associate an MDL it creates to describe the user buffer with the IRP. This
is useful because it ensures that when the IRP is completed the I/O Manager will clean up these
MDLs, which eliminates the need for the driver to provide special handling for such clean-up.
Is this a typo with the code comments, or is this really the case for minifilters?
Q3
In read post-op (SwapPostReadBuffers
), we did not call MmProbeAndLockPages
on MdlAddress
, but proceeded to call MmGetSystemAddressForMdlSafe
on it (L1089). How is this safe? The “Master of the Obvious” article states:
When a driver specifies METHOD_DIRECT, the I/O manager guarantees that the driver will receive
an MDL that describes the full virtual address range specified by the original requestor and
that the MDL has been probed and locked.
Is this the reason why?
Q4
In read post-op, handling of the case of user buffer is deferred via FltDoCompletionProcessingWhenSafe
. Instead of doing this, can we do the following?
- In pre-op, use
IoAllocateMdl
to create a MDL for the user buffer - Call
MmProbeAndLockPages
on it - Pass MDL to post-op via completion context
- In post-op call
MmGetSystemAddressForMdlSafe
on it
We would be doing all the work directly in pre and post callbacks, soFltDoCompletionProcessingWhenSafe
is not needed.
Q5
If the aforementioned approach is possible, then can we take it a step further by doing all the work of getting the system address of the original buffer (be it a user buffer, system buffer, or MdlAddress
) in read pre-op, and then pass the address to post-op via the completion context? This keeps all the related code in the same scope and thus facilitates comprehension and maintenance. Are there any ptifalls/gotchas with this approach?