A bit on MDLs

Hi all,

I am creating my own IRP_MJ_WRITE with my iwn buffer. I make a buffer,
and an MDL(IoAllocateMdl) out of it. I build the MDL to the Non paged pool.
In my IRP completion routine, I need to...

  1. Ffree this MDL?
  2. Free the buffer in that MDL?
  3. Free the IRP?

Do I need all three of these, or do I just free the MDL and teh IRP.
Somewhere in the OSR threads I read that for MDLs allocated from nonpaged
pool, unmapping the buffer is not required. Why so?

  • amitr0

You should call MmBuildMdlForNonPagedPool to prepare the Mdl after
IoAllocateMdl.

You must free the IRP when you no longer need to use the IRP. It is quite
common for example to do this in the completion routine

You must free the MDL when you no longer need to use the MDL. You do not
“unmap” the MDL becuase the system address of the MDL was not “mapped” in
the first place since the buffer was non paged pool.

You must free the non paged pool buffer when you no longer need to use the
buffer.

“amitr0” wrote in message news:xxxxx@ntdev…
Hi all,

I am creating my own IRP_MJ_WRITE with my iwn buffer. I make a buffer, and
an MDL(IoAllocateMdl) out of it. I build the MDL to the Non paged pool. In
my IRP completion routine, I need to…

1. Ffree this MDL?
2. Free the buffer in that MDL?
3. Free the IRP?

Do I need all three of these, or do I just free the MDL and teh IRP.
Somewhere in the OSR threads I read that for MDLs allocated from nonpaged
pool, unmapping the buffer is not required. Why so?


- amitr0

thanks Lynodn, was just confirming whether I was on the right track or not,
here is my code, I think I am doing all corectly, just (someone) verify.

mdl = IoAllocateMdl(pBuff, len, FALSE, TRUE, 0);

MmBuildMdlForNonPagedPool(mdl);

irp = IoAllocateIrp(fsdDevice->StackSize, FALSE);

if (!irp) {

// Allocation failed, presumably due to memory allocation failure.

IoStatusBlock->Status = STATUS_INSUFFICIENT_RESOURCES;

IoStatusBlock->Information = 0;

}

irp->MdlAddress = Mdl;

irp->UserEvent = &event;

irp->UserIosb = IoStatusBlock;

irp->Tail.Overlay.Thread = PsGetCurrentThread();

irp->Tail.Overlay.OriginalFileObject= FileObject;

irp->RequestorMode = KernelMode;

***************************

// Free the IRP now that we are done with it. But first free the MDL (PBuff
is a VOID POINTER)

PBuff=MmGetSystemAddressForMdlSafe(Irp->MdlAddress,HighPagePriority);

IoFreeMdl(Irp->MdlAddress);

ExFreePool(PBuff);

IoFreeIrp(Irp);

// Allocation failed, presumably due to memory allocation failure.

Yes, free the MDL and the buffer here.

PBuff=MmGetSystemAddressForMdlSafe(Irp->MdlAddress,HighPagePriority);

Why HighPagePriority and not Normal?

IoFreeMdl(Irp->MdlAddress);
ExFreePool(PBuff);
IoFreeIrp(Irp);

Correct.

Maxim Shatskih, Windows DDK MVP
StorageCraft Corporation
xxxxx@storagecraft.com
http://www.storagecraft.com

Yes max, I am freeing the MDL when there is an alloc failure too, just gave
u the skel code.

Also I used HighpagePriority to take sure the macro never fails, is that
worng? would Normal be good enough always?

You should not be filling in anything in Tail.*. htat is private to the io manager. If you are building a threaded irp, use the IoBuild* routines instead.

d

– I can spell, I just can’t type.


From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of amitr0
Sent: Thursday, April 20, 2006 4:28 AM
To: Windows System Software Devs Interest List
Subject: Re: [ntdev] A bit on MDLs

thanks Lynodn, was just confirming whether I was on the right track or not, here is my code, I think I am doing all corectly, just (someone) verify.
?
mdl = IoAllocateMdl(pBuff, len, FALSE, TRUE, 0);
MmBuildMdlForNonPagedPool(mdl);
irp = IoAllocateIrp(fsdDevice->StackSize, FALSE);
if (!irp) {
// Allocation failed, presumably due to memory allocation failure.
?
IoStatusBlock->Status = STATUS_INSUFFICIENT_RESOURCES;
IoStatusBlock->Information = 0;
}
irp->MdlAddress = Mdl;
irp->UserEvent = &
event;
irp->UserIosb = IoStatusBlock;
irp->Tail.Overlay.Thread = PsGetCurrentThread();
irp->Tail.Overlay.OriginalFileObject= FileObject;
irp->RequestorMode = KernelMode;
?
***************************
?
// Free the IRP now that we are done with it. But first free the MDL (PBuff is a VOID POINTER)
PBuff=MmGetSystemAddressForMdlSafe(Irp->MdlAddress,HighPagePriority);
IoFreeMdl(Irp->MdlAddress);
ExFreePool(PBuff);
IoFreeIrp(Irp);
— Questions? First check the Kernel Driver FAQ at http://www.osronline.com/article.cfm?id=256 To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer

>Also I used HighpagePriority to take sure the macro never fails, is that

worng? would Normal be good enough always?

Normal is recommended. IIRC the page mapping can fail in any case, you must
handle this.

Maxim Shatskih, Windows DDK MVP
StorageCraft Corporation
xxxxx@storagecraft.com
http://www.storagecraft.com

“You should not be filling in anything in Tail.*. htat is private to the io
manager. If you are building a threaded irp, use the IoBuild* routines
instead.”

But then how do I make an IRP to write data to a FO? I copies part of the
code from OSR samples.

Set the file object in the next irp stack location along with the
parameters.

-p


From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of amitr0
Sent: Thursday, April 20, 2006 11:05 PM
To: Windows System Software Devs Interest List
Subject: Re: [ntdev] A bit on MDLs

“You should not be filling in anything in Tail.*. htat is private to
the io manager. If you are building a threaded irp, use the IoBuild*
routines instead.”

But then how do I make an IRP to write data to a FO? I copies part of
the code from OSR samples.
— Questions? First check the Kernel Driver FAQ at
http://www.osronline.com/article.cfm?id=256 To unsubscribe, visit the
List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer

This is the entire code, in case memory alloc suceeds for the IRP.

irp->MdlAddress = Mdl;

irp->UserEvent = &event;

irp->UserIosb = IoStatusBlock;

irp->Tail.Overlay.Thread = PsGetCurrentThread();

irp->Tail.Overlay.OriginalFileObject= FileObject;

irp->RequestorMode = KernelMode;

// Indicate that this is a WRITE operation.

irp->Flags = IRP_WRITE_OPERATION;

// Set up the next I/O stack location. These are the parameters

// that will be passed to the underlying driver.

ioStackLocation = IoGetNextIrpStackLocation(irp);

ioStackLocation->MajorFunction = IRP_MJ_WRITE;

ioStackLocation->MinorFunction = 0;

ioStackLocation->FileObject = FileObject;

// We use a completion routine to keep the I/O Manager from doing

// “cleanup” on our IRP - like freeing our MDL.

IoSetCompletionRoutine(irp, CAIrpIoCompletion, 0, TRUE, TRUE, TRUE);

ioStackLocation->Parameters.Write.Length = Length;

ioStackLocation->Parameters.Write.ByteOffset = *Offset;
// Send it on. Ignore the return code.

So I delete all the Irp tail initializations?

I don’t see why you can’t just use IoBuildAsynchronousFsdRequest() or IoBuildSynchronousFsdRequest() to build the PIRP for you. Irp->Tail.* fields have nothing to do with the processing of the pirp itself by the underlying stack, they have to do with the I/O manager and how it cleans up the irp and queues an APC into the correct process. Since this is your own irp and you are freeing it instead of letting it complete back to the i/o manager in the final completion routine (yours), none of the Irp->Tail.* fields matter anyways.

d

– I can spell, I just can’t type.


From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of amitr0
Sent: Thursday, April 20, 2006 11:56 PM
To: Windows System Software Devs Interest List
Subject: Re: [ntdev] A bit on MDLs

This is the entire code, in case memory alloc suceeds for the IRP.
?
?
irp->MdlAddress = Mdl;
irp->UserEvent = &
event;
irp->UserIosb = IoStatusBlock;
irp->Tail.Overlay.Thread = PsGetCurrentThread();
irp->Tail.Overlay.OriginalFileObject= FileObject;
irp->RequestorMode = KernelMode;
// Indicate that this is a WRITE operation.
irp->Flags = IRP_WRITE_OPERATION;
// Set up the next I/O stack location. These are the parameters
// that will be passed to the underlying driver.
ioStackLocation = IoGetNextIrpStackLocation(irp);
ioStackLocation->MajorFunction = IRP_MJ_WRITE;
ioStackLocation->MinorFunction = 0;
ioStackLocation->FileObject = FileObject;
// We use a completion routine to keep the I/O Manager from doing
// “cleanup” on our IRP - like freeing our MDL.
IoSetCompletionRoutine(irp, CAIrpIoCompletion, 0, TRUE, TRUE, TRUE);
ioStackLocation->Parameters.Write.Length = Length;
ioStackLocation->Parameters.Write.ByteOffset = *Offset;
// Send it on. Ignore the return code.
?
?
So I delete all the Irp tail initializations?
— Questions? First check the Kernel Driver FAQ at http://www.osronline.com/article.cfm?id=256 To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer

Yes, that is exactly what I had thought of when I read the code from OSR.
Thanks Doran.

>So I delete all the Irp tail initializations?

Yes. They are intended for IO manager’s routines like NtDeviceIoControlFile
only.

Maxim Shatskih, Windows DDK MVP
StorageCraft Corporation
xxxxx@storagecraft.com
http://www.storagecraft.com