How to use MmMapLockedPagesSpecifyCache

Hi, all

Documentation about this function says that the caller must
call MmProbeAndLockPages before calling this function.
And it is true - when I remove the call of MmProbeAndLockPages,
I’ll get occasional (although very rare) bugcheck within
CcCopyRead, in the point when cache manager copies
the page to the buffer supplied by the caller. This means
that the page with the buffer is currently not resident.

But I am not able to make MmProbeAndLockPages
work, it always throws an exception. The docs say that I must
enclose the call into __try and __except block.
But IMHO when the function throws the exception,
then is something wrong (the page has not the access
which I specify in the call), am I right ?

I looked into the source of Fastfat, it seems that it does not
call MmProbeAndLockPages. I’m starting to be totally
clueless, could anyone give me an advice how to do it right ?

L.

MmProbeAndLockPages only raises an exception on an error. The docs are
correct to say that you should enclose the call in a try/except so that
you can handle an error if it is returned.

What exception is being raised when you call MmProbeAndLockPages? That
will give us a better clue as to what the problem is.

Regards,
Molly Brown
Microsoft Corporation

This posting is provided “AS IS” with no warranties and confers no
rights.

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Ladislav Zezula
Sent: Thursday, December 02, 2004 5:51 AM
To: Windows File Systems Devs Interest List
Subject: [ntfsd] How to use MmMapLockedPagesSpecifyCache

Hi, all

Documentation about this function says that the caller must call
MmProbeAndLockPages before calling this function.
And it is true - when I remove the call of MmProbeAndLockPages, I’ll get
occasional (although very rare) bugcheck within CcCopyRead, in the point
when cache manager copies the page to the buffer supplied by the caller.
This means that the page with the buffer is currently not resident.

But I am not able to make MmProbeAndLockPages work, it always throws an
exception. The docs say that I must enclose the call into __try and
__except block.
But IMHO when the function throws the exception, then is something wrong
(the page has not the access which I specify in the call), am I right ?

I looked into the source of Fastfat, it seems that it does not call
MmProbeAndLockPages. I’m starting to be totally clueless, could anyone
give me an advice how to do it right ?

L.


Questions? First check the IFS FAQ at
https://www.osronline.com/article.cfm?id=17

You are currently subscribed to ntfsd as: xxxxx@windows.microsoft.com
To unsubscribe send a blank email to xxxxx@lists.osr.com

Thank you, Molly, for the response.

Here are more details:

My filter calls CcCopyRead on behalf of cached IRP_MJ_READ
request. Before the call of CcCopyRead, the filter needs to “map”
the user buffer (See the snipet of the code at the end of this mail).

The “Operation”, passed to MmProbeAndLockPages for this case
is IoWriteAccess (I expect that on IRP_MJ_READ, I must have
write access to the page, on IRP_MJ_WRITE, I must have read
access to the page).

Maybe you will recognize that the code around call of
MmMapLockedPagesSpecifyCache is actually the macro
"MmGetSystemAddressForMdlSafe, changed so it uses
pointer “pMmGetSystemAddressForMdlSafe”, which is
dynamically retrieved address from the kernel (the driver
must run on Windows NT 4.0 too)

MmProbeAndLockPages throws the access violation
exception (0xC0000005).

if (Irp->MdlAddress == NULL)
{
return Irp->UserBuffer;
}
else
{

// Windows 2000+

if(pMmMapLockedPagesSpecifyCache != NULL)
{
MmProbeAndLockPages(Irp->MdlAddress,
KernelMode,
Operation);
IrpContext->LockedCount++;

if(Irp->MdlAddress->MdlFlags & (MDL_MAPPED_TO_SYSTEM_VA |
MDL_SOURCE_IS_NONPAGED_POOL))
{
IrpContext->LockedBuffer = Irp->MdlAddress->MappedSystemVa;
}
else
{
IrpContext->LockedBufferMdl = Irp->MdlAddress;
IrpContext->LockedBuffer = pMmMapLockedPagesSpecifyCache(
Irp->MdlAddress,
KernelMode,
MmCached,
NULL,
FALSE,
NormalPagePriority);
}
}
else
{
IrpContext->LockedBuffer =
MmGetSystemAddressForMdl(Irp->MdlAddress);
}
}

L.

Is there a reason why you think the Mdl you’ve received here has not
already been probed and locked?

I think you are seeing the AV here because the VirtualAddress used to
initialize this Mdl was a user mode address that is no longer valid in
your current process context. The Mdl must be probed and locked in the
context where it is allocated because in any other context the virtual
address is probably not valid.

In reading the MmMapLockedPagesSpecifyCache documentation, I can see how
you could arrive at your conclusion that you must call
MmProbeAndLockPages. It says that the caller must have already probed
and locked the Mdl, but what it really means is that the Mdl must have
already been probed and locked - who did it isn’t important. If a
higher filter created the Mdl and set it in the IRP (it should have
probed and locked it as part of this process), that is sufficient
preparation to call MmMapLockedPagesSpecifyCache.

Take a look at the routines FatLockUserBuffer() and FatMapUserBuffer()
in the fastfat sources of the IFS Kit for a pretty clean example of how
this works. FatLockUserBuffer() to setup the Mdl when an IRP is going
to be posted to a worker thread. FatMapUserBuffer() is called in the
operation itself once the real work of the operation has begun to get
the appropriate buffer to use. It either gets the buffer from the
Irp->UserBuffer or from the Irp->MdlAddress by calling
MmGetSystemAddressForMdlSafe. For NT 4.0 support, you just need to do
your macro expansion for MmGetSystemAddressForMdlSafe like you do below.

Regards,

Molly Brown
Microsoft Corporation

This posting is provided “AS IS” with no warranties and confers no
rights.

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Ladislav Zezula
Sent: Thursday, December 02, 2004 11:36 PM
To: Windows File Systems Devs Interest List
Subject: Re: [ntfsd] How to use MmMapLockedPagesSpecifyCache

Thank you, Molly, for the response.

Here are more details:

My filter calls CcCopyRead on behalf of cached IRP_MJ_READ request.
Before the call of CcCopyRead, the filter needs to “map”
the user buffer (See the snipet of the code at the end of this mail).

The “Operation”, passed to MmProbeAndLockPages for this case is
IoWriteAccess (I expect that on IRP_MJ_READ, I must have write access to
the page, on IRP_MJ_WRITE, I must have read access to the page).

Maybe you will recognize that the code around call of
MmMapLockedPagesSpecifyCache is actually the macro
"MmGetSystemAddressForMdlSafe, changed so it uses pointer
“pMmGetSystemAddressForMdlSafe”, which is dynamically retrieved address
from the kernel (the driver must run on Windows NT 4.0 too)

MmProbeAndLockPages throws the access violation exception (0xC0000005).

if (Irp->MdlAddress == NULL)
{
return Irp->UserBuffer;
}
else
{

// Windows 2000+

if(pMmMapLockedPagesSpecifyCache != NULL)
{
MmProbeAndLockPages(Irp->MdlAddress,
KernelMode,
Operation);
IrpContext->LockedCount++;

if(Irp->MdlAddress->MdlFlags & (MDL_MAPPED_TO_SYSTEM_VA |
MDL_SOURCE_IS_NONPAGED_POOL))
{
IrpContext->LockedBuffer =
Irp->MdlAddress->MappedSystemVa;
}
else
{
IrpContext->LockedBufferMdl = Irp->MdlAddress;
IrpContext->LockedBuffer =
pMmMapLockedPagesSpecifyCache(
Irp->MdlAddress,
KernelMode,
MmCached,
NULL,
FALSE,
NormalPagePriority);
}
}
else
{
IrpContext->LockedBuffer =
MmGetSystemAddressForMdl(Irp->MdlAddress);
}
}

L.


Questions? First check the IFS FAQ at
https://www.osronline.com/article.cfm?id=17

You are currently subscribed to ntfsd as: xxxxx@windows.microsoft.com
To unsubscribe send a blank email to xxxxx@lists.osr.com

> Is there a reason why you think the Mdl you’ve received here has not

already been probed and locked?

Maybe - In fact, I don’t know. I only rely to documentation
that says that, and it also says that I can call
MmProbeAndLockPages more times
(If I call the appropriate unlock function).

I think you are seeing the AV here because the VirtualAddress used to
initialize this Mdl was a user mode address that is no longer valid in
your current process context.

Seems that this is it. I didn’t write it in my original posting,
but the “sorry-but-the-pages-are-not-resident” bugcheck
always occurs in the worker thread (in the system process
context), so it actually means
“sorry-but-the-pages-are-not-valid-in-this-process”.

The only thing that seems strange to me is that the crash operation
is mapping “software” registry hive (the call stack of the original
thread stored in the IRP leads through

KeWaitForSingleObject (waits for the read operation)
CmpFileRead
HvpGetHiveHeader
HvMapHive

The question is if there is some user-mode address
in this scenario, I believe that the registry are mapped
in kernel mode, aren’t they ?

But anyway, this is what I’m doing wrong.
Thank you, Molly, now I see direction which I must go.

L.

MDLs which cross the module boundary are always probed and locked.

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

----- Original Message -----
From: “Ladislav Zezula”
To: “Windows File Systems Devs Interest List”
Sent: Monday, December 06, 2004 10:14 AM
Subject: Re: [ntfsd] How to use MmMapLockedPagesSpecifyCache

> > Is there a reason why you think the Mdl you’ve received here has not
> > already been probed and locked?
>
> Maybe - In fact, I don’t know. I only rely to documentation
> that says that, and it also says that I can call
> MmProbeAndLockPages more times
> (If I call the appropriate unlock function).
>
> > I think you are seeing the AV here because the VirtualAddress used to
> > initialize this Mdl was a user mode address that is no longer valid in
> > your current process context.
>
> Seems that this is it. I didn’t write it in my original posting,
> but the “sorry-but-the-pages-are-not-resident” bugcheck
> always occurs in the worker thread (in the system process
> context), so it actually means
> “sorry-but-the-pages-are-not-valid-in-this-process”.
>
> The only thing that seems strange to me is that the crash operation
> is mapping “software” registry hive (the call stack of the original
> thread stored in the IRP leads through
>
> KeWaitForSingleObject (waits for the read operation)
> CmpFileRead
> HvpGetHiveHeader
> HvMapHive
>
> The question is if there is some user-mode address
> in this scenario, I believe that the registry are mapped
> in kernel mode, aren’t they ?
>
> But anyway, this is what I’m doing wrong.
> Thank you, Molly, now I see direction which I must go.
>
> L.
>
>
>
> —
> Questions? First check the IFS FAQ at
https://www.osronline.com/article.cfm?id=17
>
> You are currently subscribed to ntfsd as: xxxxx@storagecraft.com
> To unsubscribe send a blank email to xxxxx@lists.osr.com
>

> MDLs which cross the module boundary are always probed and locked.

Well, thank you, but what does it mean in this case ?

L.

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

----- Original Message -----
From: “Ladislav Zezula”
> To: “Windows File Systems Devs Interest List”
> Sent: Monday, December 06, 2004 10:14 AM
> Subject: Re: [ntfsd] How to use MmMapLockedPagesSpecifyCache
>
>
>> > Is there a reason why you think the Mdl you’ve received here has not
>> > already been probed and locked?
>>
>> Maybe - In fact, I don’t know. I only rely to documentation
>> that says that, and it also says that I can call
>> MmProbeAndLockPages more times
>> (If I call the appropriate unlock function).
>>
>> > I think you are seeing the AV here because the VirtualAddress used to
>> > initialize this Mdl was a user mode address that is no longer valid in
>> > your current process context.
>>
>> Seems that this is it. I didn’t write it in my original posting,
>> but the “sorry-but-the-pages-are-not-resident” bugcheck
>> always occurs in the worker thread (in the system process
>> context), so it actually means
>> “sorry-but-the-pages-are-not-valid-in-this-process”.
>>
>> The only thing that seems strange to me is that the crash operation
>> is mapping “software” registry hive (the call stack of the original
>> thread stored in the IRP leads through
>>
>> KeWaitForSingleObject (waits for the read operation)
>> CmpFileRead
>> HvpGetHiveHeader
>> HvMapHive
>>
>> The question is if there is some user-mode address
>> in this scenario, I believe that the registry are mapped
>> in kernel mode, aren’t they ?
>>
>> But anyway, this is what I’m doing wrong.
>> Thank you, Molly, now I see direction which I must go.
>>
>> L.
>>
>>
>>
>> —
>> Questions? First check the IFS FAQ at
> https://www.osronline.com/article.cfm?id=17
>>
>> You are currently subscribed to ntfsd as: xxxxx@storagecraft.com
>> To unsubscribe send a blank email to xxxxx@lists.osr.com
>>
>
>
> —
> Questions? First check the IFS FAQ at
> https://www.osronline.com/article.cfm?id=17
>
> You are currently subscribed to ntfsd as: xxxxx@volny.cz
> To unsubscribe send a blank email to xxxxx@lists.osr.com
>
>

  1. If you receive the MDL from another module - as Irp->MdlAddress or
    similar means - it is already fully formed, and there is no need in calling
    MmProbeAndLockPages on it.

  2. If you send your own MDL to another module - as Irp->MdlAddress or
    similar means - then you must fully form the MDL. To do this, one of the below
    (mutually exclusive) means must be used:

IoBuildPartialMdl - if you are creating a subrange MDL and have the parent
MDL which describes the whole range.
MmBuildMdlForNonPagedPool - if you are sure that the memory described by
the MDL is nonpaged.
MmProbeAndLockPages under __try/__catch - in all other cases.

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

----- Original Message -----
From: “Ladislav Zezula”
To: “Windows File Systems Devs Interest List”
Sent: Monday, December 06, 2004 4:51 PM
Subject: Re: [ntfsd] How to use MmMapLockedPagesSpecifyCache

> > MDLs which cross the module boundary are always probed and locked.
>
> Well, thank you, but what does it mean in this case ?
>
> L.
>
>
> >
> > Maxim Shatskih, Windows DDK MVP
> > StorageCraft Corporation
> > xxxxx@storagecraft.com
> > http://www.storagecraft.com
> >
> > ----- Original Message -----
> > From: “Ladislav Zezula”
> > To: “Windows File Systems Devs Interest List”
> > Sent: Monday, December 06, 2004 10:14 AM
> > Subject: Re: [ntfsd] How to use MmMapLockedPagesSpecifyCache
> >
> >
> >> > Is there a reason why you think the Mdl you’ve received here has not
> >> > already been probed and locked?
> >>
> >> Maybe - In fact, I don’t know. I only rely to documentation
> >> that says that, and it also says that I can call
> >> MmProbeAndLockPages more times
> >> (If I call the appropriate unlock function).
> >>
> >> > I think you are seeing the AV here because the VirtualAddress used to
> >> > initialize this Mdl was a user mode address that is no longer valid in
> >> > your current process context.
> >>
> >> Seems that this is it. I didn’t write it in my original posting,
> >> but the “sorry-but-the-pages-are-not-resident” bugcheck
> >> always occurs in the worker thread (in the system process
> >> context), so it actually means
> >> “sorry-but-the-pages-are-not-valid-in-this-process”.
> >>
> >> The only thing that seems strange to me is that the crash operation
> >> is mapping “software” registry hive (the call stack of the original
> >> thread stored in the IRP leads through
> >>
> >> KeWaitForSingleObject (waits for the read operation)
> >> CmpFileRead
> >> HvpGetHiveHeader
> >> HvMapHive
> >>
> >> The question is if there is some user-mode address
> >> in this scenario, I believe that the registry are mapped
> >> in kernel mode, aren’t they ?
> >>
> >> But anyway, this is what I’m doing wrong.
> >> Thank you, Molly, now I see direction which I must go.
> >>
> >> L.
> >>
> >>
> >>
> >> —
> >> Questions? First check the IFS FAQ at
> > https://www.osronline.com/article.cfm?id=17
> >>
> >> You are currently subscribed to ntfsd as: xxxxx@storagecraft.com
> >> To unsubscribe send a blank email to xxxxx@lists.osr.com
> >>
> >
> >
> > —
> > Questions? First check the IFS FAQ at
> > https://www.osronline.com/article.cfm?id=17
> >
> > You are currently subscribed to ntfsd as: xxxxx@volny.cz
> > To unsubscribe send a blank email to xxxxx@lists.osr.com
> >
> >
>
>
> —
> Questions? First check the IFS FAQ at
https://www.osronline.com/article.cfm?id=17
>
> You are currently subscribed to ntfsd as: xxxxx@storagecraft.com
> To unsubscribe send a blank email to xxxxx@lists.osr.com
>

Max,

what you are saying it true. Shortly after the first reply to Molly’s
suggestions, I’ve sent another question with more info, where I am
explaining what exactly happened. Below is the copy
of the mail with more info.

You can see there that I create and lock the MDL, if I post the request
to a worker thread. The problem is that the address obtained from locked
MDL using MmGetSystemAddressForMdlSafe is not accessible
(for writing).

L.

----- Original Message -----
From: “Ladislav Zezula”
To: “Windows File Systems Devs Interest List”
Sent: Monday, December 06, 2004 10:22 AM
Subject: Re: [ntfsd] How to use MmMapLockedPagesSpecifyCache - more info

> Hi again, Molly,
>
> Here is more info about this problem. I found that
>
> 1) The original thread that issued the IRP_MJ_READ request.
> Irp->UserBuffer was E1A2E000,
> Irp->MdlAddress was NULL
> (so not an user mode address)
>
> 2) My filter has “decided” that the operation will
> be queued to worker thread.
> Before queuing, it performed the LockBuffer operation,
> (like FatLockUserBuffer), calling IoAllocateMdl
> and MmProbeAndLockPages.
> The pointer to created MDL has been set into Irp->MdlAddress.
> The MDL itself was this:
>
> kd> dt nt!_MDL FF4EF008
> +0x000 Next : (null)
> +0x004 Size : 32 (0x20 hexa)
> +0x006 MdlFlags : 138 (0x8A hexa)
> +0x008 Process : (null)
> +0x00c MappedSystemVa : 0xf9e2e000
> +0x010 StartVa : 0xe1a2e000
> +0x014 ByteCount : 0x200
> +0x018 ByteOffset : 0
>
> The MDL flags are
> MDL_PAGES_LOCKED
> MDL_ALLOCATED_FIXED_SIZE
> MDL_WRITE_OPERATION
>
> 3) The worker thread called the MapUserBuffer (like FatMapUserBuffer)
> operation, which uses my expanded version
> of MmGetSystemAddressForMdlSafe.
>
> Because of
>
> if(Irp->MdlAddress->MdlFlags & (MDL_MAPPED_TO_SYSTEM_VA |
> MDL_SOURCE_IS_NONPAGED_POOL))
>
> the MmMapLockedPagesSpecifyCache has actually not
> been called, instead the Irp->MdlAddress->MappedSystemVa
> has been used.
>
> But this address (f9e2e000) is not accessible, debugger
> shows error (this is why the system crashed with
> IRQL_NOT_LESS_OR_EQUAL).
> The another address in the MDL, e1a2e000,
> could be read without problem.
>
> Could you please look at these facts and guess what is wrong ?
> Maybe in the case of kernel mode buffers the buffer should
> not be locked … ?
>
> L.

Probably the original MDL was built using MmProbeAndLockPages with
IoReadAccess. In this case, you cannot update its contents - this will break
the user app.

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

----- Original Message -----
From: “Ladislav Zezula”
To: “Windows File Systems Devs Interest List”
Sent: Monday, December 06, 2004 5:25 PM
Subject: Re: [ntfsd] How to use MmMapLockedPagesSpecifyCache

> Max,
>
> what you are saying it true. Shortly after the first reply to Molly’s
> suggestions, I’ve sent another question with more info, where I am
> explaining what exactly happened. Below is the copy
> of the mail with more info.
>
> You can see there that I create and lock the MDL, if I post the request
> to a worker thread. The problem is that the address obtained from locked
> MDL using MmGetSystemAddressForMdlSafe is not accessible
> (for writing).
>
> L.
>
> ----- Original Message -----
> From: “Ladislav Zezula”
> To: “Windows File Systems Devs Interest List”
> Sent: Monday, December 06, 2004 10:22 AM
> Subject: Re: [ntfsd] How to use MmMapLockedPagesSpecifyCache - more info
>
>
> > Hi again, Molly,
> >
> > Here is more info about this problem. I found that
> >
> > 1) The original thread that issued the IRP_MJ_READ request.
> > Irp->UserBuffer was E1A2E000,
> > Irp->MdlAddress was NULL
> > (so not an user mode address)
> >
> > 2) My filter has “decided” that the operation will
> > be queued to worker thread.
> > Before queuing, it performed the LockBuffer operation,
> > (like FatLockUserBuffer), calling IoAllocateMdl
> > and MmProbeAndLockPages.
> > The pointer to created MDL has been set into Irp->MdlAddress.
> > The MDL itself was this:
> >
> > kd> dt nt!_MDL FF4EF008
> > +0x000 Next : (null)
> > +0x004 Size : 32 (0x20 hexa)
> > +0x006 MdlFlags : 138 (0x8A hexa)
> > +0x008 Process : (null)
> > +0x00c MappedSystemVa : 0xf9e2e000
> > +0x010 StartVa : 0xe1a2e000
> > +0x014 ByteCount : 0x200
> > +0x018 ByteOffset : 0
> >
> > The MDL flags are
> > MDL_PAGES_LOCKED
> > MDL_ALLOCATED_FIXED_SIZE
> > MDL_WRITE_OPERATION
> >
> > 3) The worker thread called the MapUserBuffer (like FatMapUserBuffer)
> > operation, which uses my expanded version
> > of MmGetSystemAddressForMdlSafe.
> >
> > Because of
> >
> > if(Irp->MdlAddress->MdlFlags & (MDL_MAPPED_TO_SYSTEM_VA |
> > MDL_SOURCE_IS_NONPAGED_POOL))
> >
> > the MmMapLockedPagesSpecifyCache has actually not
> > been called, instead the Irp->MdlAddress->MappedSystemVa
> > has been used.
> >
> > But this address (f9e2e000) is not accessible, debugger
> > shows error (this is why the system crashed with
> > IRQL_NOT_LESS_OR_EQUAL).
> > The another address in the MDL, e1a2e000,
> > could be read without problem.
> >
> > Could you please look at these facts and guess what is wrong ?
> > Maybe in the case of kernel mode buffers the buffer should
> > not be locked … ?
> >
> > L.
>
>
> —
> Questions? First check the IFS FAQ at
https://www.osronline.com/article.cfm?id=17
>
> You are currently subscribed to ntfsd as: xxxxx@storagecraft.com
> To unsubscribe send a blank email to xxxxx@lists.osr.com
>

> Probably the original MDL was built using MmProbeAndLockPages with

IoReadAccess. In this case, you cannot update its contents - this will
break
the user app.

No, this is not the problem. The source address has been given
by directly as a kernel mode pointer.
It was no user app, it was thread that maps registry hives
into memory.

Maybe in this case, I should not create the MDL, but Fastfat
does it exactly the same way as our filter.

L.

Can you resend the MDL lock/mapping code and where it is executed? I’ve had
SIMILAR problems with MDL locking and have resorted to doing all the work in the
dispatch routine (which was possible in my case).

Maybe in this case, I should not create the MDL, but Fastfat
does it exactly the same way as our filter.


Kind regards, Dejan M. MVP for DDK
http://www.alfasp.com E-mail: xxxxx@alfasp.com
Alfa Transparent File Encryptor - Transparent file encryption services.
Alfa File Protector - File protection and hiding library for Win32 developers.
Alfa File Monitor - File monitoring library for Win32 developers.

> Can you resend the MDL lock/mapping code and where it is executed? I’ve

had
SIMILAR problems with MDL locking and have resorted to doing all the work
in the
dispatch routine (which was possible in my case).

Well, here:

  1. In the IRP_MJ_READ handler, before posting to the
    worker thread (and only if the filter posts the IPR into worker thread),
    I use this:

PMDL Mdl = NULL;

PAGED_CODE();

if (Irp->MdlAddress == NULL)
{
//
// Allocate the Mdl, and Raise if we fail.
//

Mdl = IoAllocateMdl(Irp->UserBuffer, BufferLength, FALSE, FALSE,
Irp);

if (Mdl == NULL)
{
ExRaiseStatus(IrpContext, STATUS_INSUFFICIENT_RESOURCES);
}

//
// Now probe the buffer described by the Irp. If we get an
exception,
// deallocate the Mdl and return the appropriate “expected” status.
//

try
{
MmProbeAndLockPages(Mdl, Irp->RequestorMode, Operation);
}

except(EXCEPTION_EXECUTE_HANDLER)
{
IoFreeMdl(Mdl);
Irp->MdlAddress = NULL;

ExRaiseStatus(IrpContext, STATUS_INVALID_USER_BUFFER);
}
}
}

2). Before accessing the user buffer (regardles if in worker thread or
in “normal” dispatch routine), the filter uses this:

//
// If there is no Mdl, then we must be in the Fsd, and we can simply
// return the UserBuffer field from the Irp.
//

if (Irp->MdlAddress == NULL)
{
return Irp->UserBuffer;
}
else
{
if(pMmMapLockedPagesSpecifyCache != NULL)
{
if(Irp->MdlAddress->MdlFlags & (MDL_MAPPED_TO_SYSTEM_VA |
MDL_SOURCE_IS_NONPAGED_POOL))
{
IrpContext->LockedBuffer = Irp->MdlAddress->MappedSystemVa;
}
else
{
IrpContext->LockedBufferMdl = Irp->MdlAddress;
IrpContext->LockedBuffer = pMmMapLockedPagesSpecifyCache(
Irp->MdlAddress,
KernelMode,
MmCached,
NULL,
FALSE,
NormalPagePriority);
}
}
else
{
IrpContext->LockedBuffer =
MmGetSystemAddressForMdl(Irp->MdlAddress);
}
}

ASSERT(IrpContext->LockedBuffer != NULL);
return IrpContext->LockedBuffer;
}

You may notice that the first code snipet is very similar to FatLockBuffer
from FastFat source code, the second one is something like
FatMapUserBuffer.

L.

I also noticed FastFat used these for DASD access ONLY (in XP IFS Kit at least).
One thing though:
"Because of
if(Irp->MdlAddress->MdlFlags &
(MDL_MAPPED_TO_SYSTEM_VA |
MDL_SOURCE_IS_NONPAGED_POOL))

the MmMapLockedPagesSpecifyCache has actually not been called, instead the
Irp->MdlAddress->MappedSystemVa has been used. "

How come when these flags are NOT set in your case? (the e-mail with “more info”
where you posted the MDL flags and specifics)

You may notice that the first code snipet is very similar to FatLockBuffer
from FastFat source code, the second one is something like
FatMapUserBuffer.


Kind regards, Dejan M. MVP for DDK
http://www.alfasp.com E-mail: xxxxx@alfasp.com
Alfa Transparent File Encryptor - Transparent file encryption services.
Alfa File Protector - File protection and hiding library for Win32 developers.
Alfa File Monitor - File monitoring library for Win32 developers.

I found the problem. Oh, God, such a stupid bug I’ve made.
The problem is between chair and keyboard (as usually).

At the end of filter’s “read” dispatch
handler, I’m umapping the buffer mapped
by MmMapLockedPagesSpecifyCache.
I forgot to add that the filter may NOT
do it if the IRP is being posted to worker thread.

One more question to all:

I noticed that if I call MmMapLockedPagesSpecifyCache
without corresponding call of MmUnmapLockedPages,
I create a memory leak that will exhaust the available
memory after some time of copying files to the network.
But as I’m looking at FastFat example, it never calls
this API. Why ?

To Dejan Maximovic:

How come when these flags are NOT set in your case? (the e-mail with “more
info”
where you posted the MDL flags and specifics)

Ewww, you’re right. The MmMapLockedPagesSpecifyCache
HAS BEEN called here (I don’t know why I wrote this,
maybe a momentary lapse of reason).

I also looked ad description of ASSERTs in checked build
(MSDN “Checked Build ASSERTs”), the theMapSpecCache
expects

  • Mdl->ByteCount != 0 (true)
  • MDL_MAPPED_TO_SYSTEM_VA not set (true)
  • MDL_SOURCE_IS_NONPAGED_POOL not set (true)
  • MDL_PARTIAL_HAS_BEEN_MAPPED not set (true)
  • MDL_PAGES_LOCKED or MDL_PARTIAL set (true)

L.

> And why my filter does create a memory leak if the

last parameter
is “NormalPagePriority”, and doesn’t if
“HighPagePriority” ?

I thought you said:

I noticed that if I call MmMapLockedPagesSpecifyCache without corresponding call of
MmUnmapLockedPages, I create a memory leak that will exhaust the available memory
after some time of copying files to the network. But as I’m looking at FastFat
example, it never calls this API. Why ?

The I/O manager does it. Fat maps it for DASD only (and it’s user buffer in this
case, not paging I/O) so the I/O manager will always tear down the Fat’s Mdl.


Kind regards, Dejan M. MVP for DDK
http://www.alfasp.com E-mail: xxxxx@alfasp.com
Alfa Transparent File Encryptor - Transparent file encryption services.
Alfa File Protector - File protection and hiding library for Win32 developers.
Alfa File Monitor - File monitoring library for Win32 developers.

> I thought you said:

> I noticed that if I call MmMapLockedPagesSpecifyCache without
> corresponding call of
> MmUnmapLockedPages, I create a memory leak that will exhaust the
> available memory
> after some time of copying files to the network. But as I’m looking at
> FastFat
> example, it never calls this API. Why ?

Yes, this was because I didn’t know that the macros
GetSystemAddressForMdl (which I used in older
version of my filter) and GetSystemAddressForMdlSafe
(which I want to use when the filter runs on Win2000+),
are actually the same, except that you have to add the “PagePriority”
parameter. Now I know that the difference is in the parameter,
but I don’t know why.

Well, anyway, I can live without it, and the filter will work
without I know it. But as usually - the more you know,
the better your software will be.

L.