What does MmProbeAndLockPages actually lock?Updated: May 25, 2007 Drivers sometimes need to lock pages so they stay in memory during certain operations, such as copying data from a device to the data buffer in a DPC routine or performing DMA to the buffer. The MmProbeAndLockPages routine makes a specified memory range resident (if it isn't already), confirms that the pages permit the specified operation at the specified access mode, and locks the pages in memory so that they cannot be paged out. MmProbeAndLockPages does this by incrementing the reference count on the page frame number (PFN) entries in the page frame number database, which describes the state of each page in physical memory. As long as the PFN reference count is non-zero, the physical page will not be reused. However, it's important not to confuse the physical pages with their virtual addresses. MmProbeAndLockPages locks physical pages in memory, but their virtual addresses can become invalid if the relevant working set is trimmed (or if the process frees or unmaps the address range). Even though the backing physical pages are guaranteed to remain resident, the virtual address mappings are not. One symptom of this in your driver is that MmIsAddressValid will indicate a page fault for the virtual address, suggesting that the memory has been paged out. If the driver attempts to touch the virtual address (assuming the address range hasn't been deleted) it encounters the same issues as when it attempts to touch pageable memory: If the driver is running below DISPATCH_LEVEL, the system can service a page fault; if the driver is running at or above DISPATCH_LEVEL, the system will bugcheck. (For an in-depth discussion of how Windows manages virtual and physical memory, see Chapter Seven of Inside Windows 2000, Third Edition.) If a virtual address is needed at or above DISPATCH_LEVEL, or in another process context, the driver must map the MDL using MmGetSystemAddressForMdlSafe to obtain a non-trimmable system virtual address for the MDL. This virtual address is never inserted in the working set and so it cannot be removed—it is guaranteed to work regardless of the process context of the thread or the IRQL at which the address is referenced. What should you do?
The following code fragment from the system IOCTL sample in the Windows DDK (%winddk%\src\general\ioctl\sys\sioctl.c) shows how to do this: For more information: Solomon, David A. and Russinovich, Mark E. Inside Microsoft Windows 2000, Third Edition, Microsoft Press, 2000, ISBN 0-7356-1021-5 Windows DDK System IOCTL sample - %winddk%\src\general\ioctl\sys\sioctl.c |