I have a chunk of memory allocated from non paged pool using
ExAllocatePoolWithTag.
I want to map this to use space. So I write this function:
NTSTATUS
MapMemoryToUser(
IN PVOID pVAD,
IN ULONG uLength,
OUT PMDL *pMemMDL,
OUT PVOID *pUserVA)
{
PMDL pMDL;
PVOID pUserVAToReturn;
if((!pVAD)||(0 == uLength)) {
return STATUS_INVALID_PARAMETER;
}
// Allocate a buffer to share with the application
pMDL = IoAllocateMdl( pVAD,
uLength,
FALSE, // Secondary buffer
FALSE, // ChargeQuota
NULL); // IRP
if(!pMDL) {
return STATUS_INSUFFICIENT_RESOURCES;
}
MmBuildMdlForNonPagedPool(pMDL);
//
// The preferred V5 way to map the buffer into user space
//
pUserVAToReturn = MmMapLockedPagesSpecifyCache( pMDL, // MDL
UserMode, // Mode
MmCached, // Caching
NULL, // Address
FALSE, // Bugcheck?
NormalPagePriority); // Priority
// If we get NULL back, the request didn’t work.
if(!pUserVAToReturn) {
IoFreeMdl(pMDL);
return STATUS_INSUFFICIENT_RESOURCES;
}
// Return the allocated pointers.
*pUserVA = pUserVAToReturn;
*pMemMDL = pMDL;
return STATUS_SUCCESS;
}
this funciton is called in the context of a user thread and we tag the MDL
to the IRP there.
When I want to free the MDL I want to preserve the pVAD as it is. I just
want to unmap the MDL and the pUserVA. Will that work? this code from osr’s
article is below:
void UnMapMemory(
IN PMDL PMdl,
PVOID UserVa)
{
//
// Make sure we have an MDL to free.
//
if(!PMdl) {
return;
}
//
// Unmap the pages.
//
MmUnmapLockedPages(UserVa,PMdl);
//
// Free the pages from the MDL.
//
MmFreePagesFromMdl(PMdl); // I have doubts if I need to do this?
//
// Release the MDL.
//
IoFreeMdl(PMdl);
}