Hi,
I have a question about filter driver and IRP_MJ_WRITE handling.
As I read before, I should not directly modify the MDL buffer. I should
create my own
buffer, asociate it with the Irp, and on the completion, return all
changed back.
The problem is, that I don’t know exactly how to create the MDL buffer (or
I’m not sure if I know it or not).
So, here is a code fragment:
— on IRP_MJ_WRITE, paging IO —
size = MmGetMdlByteCount(Irp->MdlAddress);
SaveMdl = Irp->MdlAddress;
Irp->MdlAddress = 0;
SavedUserBuffer = Irp->UserBuffer;
Irp->UserBuffer = 0;
NewBuffer = FsRtlAllocatePoolWithTag(NonPagedPoolMustSucceed, size, 1);
NewMdl = IoAllocateMdl(NewBuffer, size, FALSE, FALSE, 0);
MmProbeAndLockPagesNewMdl, KernelMode, IoWriteAccess);
Irp->MdlAddress = NewMdl;
Irp->UserBuffer = (PUCHAR)MmGetMdlVirtualAddress(Irp->MdlAddress);
— on IRP_MJ_WRITE completion —
Irp->MdlAddress = SavedMdl;
Irp->UserBuffer = SavedUserBuffer;
Thanks.
> NewBuffer = FsRtlAllocatePoolWithTag(NonPagedPoolMustSucceed, size,
1);
Never use this pool type. It is eliminated in XP.
Use paged or nonpaged pool.
Also invent some value like ‘1gaT’ for Tag parameter, the reversed
4character string. 1 is unsuitable.
NewMdl = IoAllocateMdl(NewBuffer, size, FALSE, FALSE, 0);
MmProbeAndLockPagesNewMdl, KernelMode, IoWriteAccess);
The above code used nonpaged pool. Though MmProbeAndLockPages is fine
for nonpaged pool, it is much better to replace it with
MmBuildMdlForNonPagedPool.
For pageable memory, you must use MmProbeAndLockPages.
Note that MmProbeAndLockPages requires the undo function of
MmUnlockPages, and IoFreeMdl will not do this automatically.
MmBuildMdlForNonPagedPool does not require undo functions, though
again - calling MmUnlockPages on it can do no harm (NT does not pay
attention to reference counts on pages in nonpaged pool).
Also note that, if you will return STATUS_SUCCESS from the completion
(or will have no completion), then Irp->MdlAddress will be
automatically unlocked and destroyed by the IO manager.
Irp->UserBuffer = (PUCHAR)MmGetMdlVirtualAddress(Irp->MdlAddress);
Yes. This one is a must for FSDs, though other drivers which use
Irp->MdlAddress usually use no Irp->UserBuffer.
Max