MmProbeAndLockPages

What causes MmProbeAndLockPages to raise the exception
0xC00000A1L. I call this function in my read dispatch
function to lock the pages in a user mode buffer to
return data. Before I complete the request I call
MmUnlockPages to unlock the pages. On the 2500th call
to MmProbeAndLockPages it raises this exception. Why
does this happen?

Ben


Do You Yahoo!?
Yahoo! - Official partner of 2002 FIFA World Cup
http://fifaworldcup.yahoo.com

Your process working set is not big enough to allow the locking operation to
be performed.

Regards Dan

----- Original Message -----
From: “Benjamin Hejl”
To: “NT Developers Interest List”
Sent: Friday, June 07, 2002 6:16 PM
Subject: [ntdev] MmProbeAndLockPages

> What causes MmProbeAndLockPages to raise the exception
> 0xC00000A1L. I call this function in my read dispatch
> function to lock the pages in a user mode buffer to
> return data. Before I complete the request I call
> MmUnlockPages to unlock the pages. On the 2500th call
> to MmProbeAndLockPages it raises this exception. Why
> does this happen?
>
> Ben
>
> __________________________________________________
> Do You Yahoo!?
> Yahoo! - Official partner of 2002 FIFA World Cup
> http://fifaworldcup.yahoo.com
>
> —
> You are currently subscribed to ntdev as: xxxxx@rdsor.ro
> To unsubscribe send a blank email to %%email.unsub%%
>

What causes this, how can I fix it, and how can it be avoided?

Ben

Your process working set is not big enough to allow the locking operation to
be performed.

Regards Dan

----- Original Message -----
From: “Benjamin Hejl”
> To: “NT Developers Interest List”
> Sent: Friday, June 07, 2002 6:16 PM
> Subject: [ntdev] MmProbeAndLockPages
>
>
> > What causes MmProbeAndLockPages to raise the exception
> > 0xC00000A1L. I call this function in my read dispatch
> > function to lock the pages in a user mode buffer to
> > return data. Before I complete the request I call
> > MmUnlockPages to unlock the pages. On the 2500th call
> > to MmProbeAndLockPages it raises this exception. Why
> > does this happen?
> >
> > Ben
> >
> > __________________________________________________
> > Do You Yahoo!?
> > Yahoo! - Official partner of 2002 FIFA World Cup
> > http://fifaworldcup.yahoo.com
> >
> > —
> > You are currently subscribed to ntdev as: xxxxx@rdsor.ro
> > To unsubscribe send a blank email to %%email.unsub%%
> >

//
// MessageId: STATUS_WORKING_SET_QUOTA
//
// MessageText:
//
// The working set is not big enough to allow the requested pages to be
locked.
//
#define STATUS_WORKING_SET_QUOTA ((NTSTATUS)0xC00000A1L

Hmmmm… that might be suggestive of the problem, no?

I think you have hit a limit on the number of times that a single page can
be locked, are you ever unlocking this page?

-----Original Message-----
From: Benjamin Hejl [mailto:xxxxx@yahoo.com] ,
Sent: Friday, June 07, 2002 11:16 AM
To: NT Developers Interest List
Subject: [ntdev] MmProbeAndLockPages

What causes MmProbeAndLockPages to raise the exception
0xC00000A1L. I call this function in my read dispatch
function to lock the pages in a user mode buffer to return
data. Before I complete the request I call MmUnlockPages to
unlock the pages. On the 2500th call to MmProbeAndLockPages
it raises this exception. Why does this happen?

Ben


Do You Yahoo!?
Yahoo! - Official partner of 2002 FIFA World Cup
http://fifaworldcup.yahoo.com


You are currently subscribed to ntdev as: xxxxx@stratus.com To
unsubscribe send a blank email to %%email.unsub%%

I do call MmUnlockPages before I complete the request. Shouldnt that
unlock the page?

//
// MessageId: STATUS_WORKING_SET_QUOTA
//
// MessageText:
//
// The working set is not big enough to allow the requested pages to be
locked.
//
#define STATUS_WORKING_SET_QUOTA ((NTSTATUS)0xC00000A1L

Hmmmm… that might be suggestive of the problem, no?

I think you have hit a limit on the number of times that a single page can
be locked, are you ever unlocking this page?

> -----Original Message-----
> From: Benjamin Hejl [mailto:xxxxx@yahoo.com] ,
> Sent: Friday, June 07, 2002 11:16 AM
> To: NT Developers Interest List
> Subject: [ntdev] MmProbeAndLockPages
>
>
> What causes MmProbeAndLockPages to raise the exception
> 0xC00000A1L. I call this function in my read dispatch
> function to lock the pages in a user mode buffer to return
> data. Before I complete the request I call MmUnlockPages to
> unlock the pages. On the 2500th call to MmProbeAndLockPages
> it raises this exception. Why does this happen?
>
> Ben
>
> __________________________________________________
> Do You Yahoo!?
> Yahoo! - Official partner of 2002 FIFA World Cup
http://fifaworldcup.yahoo.com


You are currently subscribed to ntdev as: xxxxx@stratus.com To
unsubscribe send a blank email to %%email.unsub%%

I think this exception is raised only if the process maximum working set
size is exceeded and if some memory manager variable which holds the number
of system global currently locked pages reach a treshold. For the second
case, the status throw is a bit misguiding.

As far as I know, locking a page too many times wont throw this kind of
error, since usually only the reference count of the page is incremented
after the first locking. But Im really not sure about it.

Anyway, most likely you loose resources somehow, and you dont unlock all
pages you lock. Check your execution paths to see if every locking operation
has a subsequent unlock, in all cases.

Regards, Dan

----- Original Message -----
From: “Roddy, Mark”
To: “NT Developers Interest List”
Sent: Friday, June 07, 2002 6:30 PM
Subject: [ntdev] RE: MmProbeAndLockPages

> //
> // MessageId: STATUS_WORKING_SET_QUOTA
> //
> // MessageText:
> //
> // The working set is not big enough to allow the requested pages to be
> locked.
> //
> #define STATUS_WORKING_SET_QUOTA ((NTSTATUS)0xC00000A1L
>
> Hmmmm… that might be suggestive of the problem, no?
>
> I think you have hit a limit on the number of times that a single page can
> be locked, are you ever unlocking this page?
>
> > -----Original Message-----
> > From: Benjamin Hejl [mailto:xxxxx@yahoo.com] ,
> > Sent: Friday, June 07, 2002 11:16 AM
> > To: NT Developers Interest List
> > Subject: [ntdev] MmProbeAndLockPages
> >
> >
> > What causes MmProbeAndLockPages to raise the exception
> > 0xC00000A1L. I call this function in my read dispatch
> > function to lock the pages in a user mode buffer to return
> > data. Before I complete the request I call MmUnlockPages to
> > unlock the pages. On the 2500th call to MmProbeAndLockPages
> > it raises this exception. Why does this happen?
> >
> > Ben
> >
> > __________________________________________________
> > Do You Yahoo!?
> > Yahoo! - Official partner of 2002 FIFA World Cup
> http://fifaworldcup.yahoo.com
>
> —
> You are currently subscribed to ntdev as: xxxxx@stratus.com To
> unsubscribe send a blank email to %%email.unsub%%
>
> —
> You are currently subscribed to ntdev as: xxxxx@rdsor.ro
> To unsubscribe send a blank email to %%email.unsub%%
>

C:\Documents and Settings\peterwie>winerror -s c00000a1
1453 ERROR_WORKING_SET_QUOTA <–> c00000a1 STATUS_WORKING_SET_QUOTA

sounds like perhaps you aren’t unlocking everything that you locked
down.

-p

-----Original Message-----
From: Benjamin Hejl [mailto:xxxxx@yahoo.com]
Sent: Friday, June 07, 2002 8:16 AM
To: NT Developers Interest List
Subject: [ntdev] MmProbeAndLockPages

What causes MmProbeAndLockPages to raise the exception 0xC00000A1L. I
call this function in my read dispatch function to lock the pages in a
user mode buffer to return data. Before I complete the request I call
MmUnlockPages to unlock the pages. On the 2500th call to
MmProbeAndLockPages it raises this exception. Why does this happen?

Ben


Do You Yahoo!?
Yahoo! - Official partner of 2002 FIFA World Cup
http://fifaworldcup.yahoo.com


You are currently subscribed to ntdev as: xxxxx@microsoft.com To
unsubscribe send a blank email to %%email.unsub%%

Is it possible that you are MAPPING this page and forgetting to unmap it?
Calling MmMapLockedPages will count against the working set quota; even if
you unlock the page later, the working set quota will not be adjusted.

Just a thought.

Regards,

Tony

Tony Mason
Consulting Partner
OSR Open Systems Resources, Inc.
http://www.osr.com

-----Original Message-----
From: Dan Partelly [mailto:xxxxx@rdsor.ro]
Sent: Friday, June 07, 2002 12:09 PM
To: NT Developers Interest List
Subject: [ntdev] RE: MmProbeAndLockPages

I think this exception is raised only if the process maximum working set
size is exceeded and if some memory manager variable which holds the number
of system global currently locked pages reach a treshold. For the second
case, the status throw is a bit misguiding.

As far as I know, locking a page too many times wont throw this kind of
error, since usually only the reference count of the page is incremented
after the first locking. But Im really not sure about it.

Anyway, most likely you loose resources somehow, and you dont unlock all
pages you lock. Check your execution paths to see if every locking operation
has a subsequent unlock, in all cases.

Regards, Dan

----- Original Message -----
From: “Roddy, Mark”
To: “NT Developers Interest List”
Sent: Friday, June 07, 2002 6:30 PM
Subject: [ntdev] RE: MmProbeAndLockPages

> //
> // MessageId: STATUS_WORKING_SET_QUOTA
> //
> // MessageText:
> //
> // The working set is not big enough to allow the requested pages to be
> locked.
> //
> #define STATUS_WORKING_SET_QUOTA ((NTSTATUS)0xC00000A1L
>
> Hmmmm… that might be suggestive of the problem, no?
>
> I think you have hit a limit on the number of times that a single page can
> be locked, are you ever unlocking this page?
>
> > -----Original Message-----
> > From: Benjamin Hejl [mailto:xxxxx@yahoo.com] ,
> > Sent: Friday, June 07, 2002 11:16 AM
> > To: NT Developers Interest List
> > Subject: [ntdev] MmProbeAndLockPages
> >
> >
> > What causes MmProbeAndLockPages to raise the exception
> > 0xC00000A1L. I call this function in my read dispatch
> > function to lock the pages in a user mode buffer to return
> > data. Before I complete the request I call MmUnlockPages to
> > unlock the pages. On the 2500th call to MmProbeAndLockPages
> > it raises this exception. Why does this happen?
> >
> > Ben
> >
> > __________________________________________________
> > Do You Yahoo!?
> > Yahoo! - Official partner of 2002 FIFA World Cup
> http://fifaworldcup.yahoo.com
>
> —
> You are currently subscribed to ntdev as: xxxxx@stratus.com To
> unsubscribe send a blank email to %%email.unsub%%
>
> —
> You are currently subscribed to ntdev as: xxxxx@rdsor.ro
> To unsubscribe send a blank email to %%email.unsub%%
>


You are currently subscribed to ntdev as: xxxxx@osr.com
To unsubscribe send a blank email to %%email.unsub%%

1: kd> x MmReferenceCountCheck
1: kd> dd MmReferenceCountCheck
80474a30 000009c4

hex 9c4 = dec 2500 coincidence? You be the judge :slight_smile:

-----Original Message-----
From: Dan Partelly [mailto:xxxxx@rdsor.ro]
Sent: Friday, June 07, 2002 12:09 PM
To: NT Developers Interest List
Subject: [ntdev] RE: MmProbeAndLockPages

I think this exception is raised only if the process maximum
working set size is exceeded and if some memory manager
variable which holds the number of system global currently
locked pages reach a treshold. For the second case, the
status throw is a bit misguiding.

As far as I know, locking a page too many times wont throw
this kind of error, since usually only the reference count of
the page is incremented after the first locking. But Im
really not sure about it.

Anyway, most likely you loose resources somehow, and you dont
unlock all pages you lock. Check your execution paths to see
if every locking operation has a subsequent unlock, in all cases.

Regards, Dan

----- Original Message -----
From: “Roddy, Mark”
> To: “NT Developers Interest List”
> Sent: Friday, June 07, 2002 6:30 PM
> Subject: [ntdev] RE: MmProbeAndLockPages
>
>
> > //
> > // MessageId: STATUS_WORKING_SET_QUOTA
> > //
> > // MessageText:
> > //
> > // The working set is not big enough to allow the
> requested pages to
> > be locked. //
> > #define STATUS_WORKING_SET_QUOTA ((NTSTATUS)0xC00000A1L
> >
> > Hmmmm… that might be suggestive of the problem, no?
> >
> > I think you have hit a limit on the number of times that a
> single page
> > can be locked, are you ever unlocking this page?
> >
> > > -----Original Message-----
> > > From: Benjamin Hejl [mailto:xxxxx@yahoo.com] ,
> > > Sent: Friday, June 07, 2002 11:16 AM
> > > To: NT Developers Interest List
> > > Subject: [ntdev] MmProbeAndLockPages
> > >
> > >
> > > What causes MmProbeAndLockPages to raise the exception
> 0xC00000A1L.
> > > I call this function in my read dispatch function to lock
> the pages
> > > in a user mode buffer to return data. Before I complete
> the request
> > > I call MmUnlockPages to unlock the pages. On the 2500th call to
> > > MmProbeAndLockPages it raises this exception. Why does
> this happen?
> > >
> > > Ben
> > >
> > > __________________________________________________
> > > Do You Yahoo!?
> > > Yahoo! - Official partner of 2002 FIFA World Cup
> > http://fifaworldcup.yahoo.com
> >
> > —
> > You are currently subscribed to ntdev as: xxxxx@stratus.com To
> > unsubscribe send a blank email to %%email.unsub%%
> >
> > —
> > You are currently subscribed to ntdev as: xxxxx@rdsor.ro To
> > unsubscribe send a blank email to %%email.unsub%%
> >
>
>
> —
> You are currently subscribed to ntdev as:
> xxxxx@stratus.com To unsubscribe send a blank email to
> %%email.unsub%%
>

Well, I have same problem. Here is the function where I lock/unlock pages
and I would highly appreciate if anybody can find my mistake (I just lost
last hope). The only thing is that I’m allocating MDLs and lock them for all
types of buffers that come to my routine (including not only those that
address UM buffer, but also KM buffers, including MDLs):

BOOL CCTLDevice::OnHandleAppMessage( PVOID pInput, ULONG InpLen, PVOID
pOutput, ULONG OutLen,

PIO_STATUS_BLOCK pIoStatus, BOOL /*bFastIo*/)
{
PMDL pAmInMdlBuffer = NULL;
PMDL pAmOutMdlBuffer = NULL;
PVOID pLockedInAmBuffer = NULL;
PVOID pLockedOutAmBuffer = NULL;

bool isInBufferLocked = false;
bool isOutBufferLocked = false;

NTSTATUS devCtrlStatus = STATUS_SUCCESS;

__try
{
//
// Handle memory issues. The assumption is that the IOCTL
used
// METHOD DIRECT_OUT
//

//
// 1) Allocate an MDL for the input AM buffers:
//

if( pInput && InpLen )
{
pAmInMdlBuffer = IoAllocateMdl( pInput, InpLen,
FALSE, FALSE, NULL);

if( NULL == pAmInMdlBuffer )
{
DBGREPORT(“\nAMInterface Device could not
allocate mdl for AM IN buffer”);

pIoStatus -> Information = 0;
pIoStatus -> Status = STATUS_NO_MEMORY;

return FALSE;
}
}

if( pOutput && OutLen )
{
pAmOutMdlBuffer = IoAllocateMdl( pOutput, OutLen,
FALSE, FALSE, NULL);

if( NULL == pAmOutMdlBuffer )
{
DBGREPORT(“\nAMInterface Device could not
allocate mdl for AM OUT buffer”);

if( pAmInMdlBuffer != NULL )
{
IoFreeMdl(pAmInMdlBuffer);
}

pIoStatus -> Information = 0;
pIoStatus -> Status = STATUS_NO_MEMORY;

return FALSE;
}
}

//
// 2) Probe and lock the pages:
//

if( pAmInMdlBuffer )
{
MmProbeAndLockPages( pAmInMdlBuffer, KernelMode,
IoReadAccess);
isInBufferLocked = true;
}

if( pAmOutMdlBuffer )
{
MmProbeAndLockPages( pAmOutMdlBuffer, KernelMode,
IoWriteAccess);
isOutBufferLocked = true;
}

// 3) Get an VA that we can use:

#if (WINVER>=0x500)

pLockedInAmBuffer = MmGetSystemAddressForMdlSafe(
pAmInMdlBuffer, NormalPagePriority);
pLockedOutAmBuffer = MmGetSystemAddressForMdlSafe(
pAmOutMdlBuffer, NormalPagePriority);

#else // (WINVER>=0x500)

pLockedInAmBuffer = MmGetSystemAddressForMdl( pAmInMdlBuffer
);
pLockedOutAmBuffer = MmGetSystemAddressForMdl(
pAmOutMdlBuffer );

#endif // (WINVER>=0x500)

//
// Now, we can call the "real handler:
//

devCtrlStatus = m_pMsgDispatcher -> DispatchMessage( 0,
pLockedInAmBuffer, InpLen,

pLockedOutAmBuffer, OutLen,

pIoStatus -> Information );
pIoStatus -> Status = devCtrlStatus;

//
// Not matter what the return status, let’s unlock the
// buffer, and free the mdl:
//

if( NULL != pAmOutMdlBuffer && isOutBufferLocked)
{
MmUnlockPages(pAmOutMdlBuffer);
isOutBufferLocked = false;
}

if( NULL != pAmOutMdlBuffer )
{
IoFreeMdl(pAmOutMdlBuffer);
pAmOutMdlBuffer = NULL;
}

if( NULL != pAmInMdlBuffer && isInBufferLocked)
{
MmUnlockPages(pAmInMdlBuffer);
isInBufferLocked = false;
}

if( NULL != pAmInMdlBuffer )
{
IoFreeMdl(pAmInMdlBuffer);
pAmInMdlBuffer = NULL;
}

return TRUE;
}
__except( EXCEPTION_EXECUTE_HANDLER )
{
DBGREPORTEXCEPTION();

if( NULL != pAmOutMdlBuffer && isOutBufferLocked)
{
MmUnlockPages(pAmOutMdlBuffer);
}

if(NULL != pAmOutMdlBuffer)
{
IoFreeMdl(pAmOutMdlBuffer);
}

if( NULL != pAmInMdlBuffer && isInBufferLocked)
{
MmUnlockPages(pAmInMdlBuffer);
}

if(NULL != pAmInMdlBuffer)
{
IoFreeMdl(pAmInMdlBuffer);
}

pIoStatus -> Status = GetExceptionCode();
pIoStatus -> Information = 0;

return FALSE;
}
}

-----Original Message-----
From: Peter Wieland [mailto:xxxxx@windows.microsoft.com]
Sent: Friday, June 07, 2002 9:56 AM
To: NT Developers Interest List
Subject: [ntdev] RE: MmProbeAndLockPages

C:\Documents and Settings\peterwie>winerror -s c00000a1
1453 ERROR_WORKING_SET_QUOTA <–> c00000a1 STATUS_WORKING_SET_QUOTA

sounds like perhaps you aren’t unlocking everything that you locked
down.

-p

-----Original Message-----
From: Benjamin Hejl [mailto:xxxxx@yahoo.com]
Sent: Friday, June 07, 2002 8:16 AM
To: NT Developers Interest List
Subject: [ntdev] MmProbeAndLockPages

What causes MmProbeAndLockPages to raise the exception 0xC00000A1L. I
call this function in my read dispatch function to lock the pages in a
user mode buffer to return data. Before I complete the request I call
MmUnlockPages to unlock the pages. On the 2500th call to
MmProbeAndLockPages it raises this exception. Why does this happen?

Ben


Do You Yahoo!?
Yahoo! - Official partner of 2002 FIFA World Cup
http://fifaworldcup.yahoo.com


You are currently subscribed to ntdev as: xxxxx@microsoft.com To
unsubscribe send a blank email to %%email.unsub%%


You are currently subscribed to ntdev as: xxxxx@Starbase.com
To unsubscribe send a blank email to %%email.unsub%%

MmGetSystemAddressForMdl* creates a range of system PTE entries if they
don’t already exist. Go look at the macro - see that call to
MmMapLockedPages?

To tear it down, you have to have a corresponding MmUnmapPages call if you
actually mapped the pages. Unlocking them is not sufficient.

This is the one area in which you are FAR better allowing the I/O subsystem
to do the work for you - attach these to an IRP and they’ll be torn down
properly. FYI - to tear them down “properly” requires violating the opacity
of MDLs, which is why it is better to let the I/O Manager do it. (This
becomes an issue because you don’t unlock non-paged addresses, you don’t
unmap if you didn’t map, etc. So you need to know what happened inside
these macros and functions).

Regards,

Tony

Tony Mason

Consulting Partner

OSR Open Systems Resources, Inc.

http://www.osr.com

-----Original Message-----
From: Vladimir Chtchetkine [mailto:xxxxx@starbase.com]
Sent: Friday, June 07, 2002 1:14 PM
To: NT Developers Interest List
Subject: [ntdev] RE: MmProbeAndLockPages

Well, I have same problem. Here is the function where I lock/unlock pages
and I would highly appreciate if anybody can find my mistake (I just lost
last hope). The only thing is that I’m allocating MDLs and lock them for all
types of buffers that come to my routine (including not only those that
address UM buffer, but also KM buffers, including MDLs):

BOOL CCTLDevice::OnHandleAppMessage( PVOID pInput, ULONG InpLen, PVOID
pOutput, ULONG OutLen,

PIO_STATUS_BLOCK pIoStatus, BOOL /*bFastIo*/)
{
PMDL pAmInMdlBuffer = NULL;
PMDL pAmOutMdlBuffer = NULL;
PVOID pLockedInAmBuffer = NULL;
PVOID pLockedOutAmBuffer = NULL;

bool isInBufferLocked = false;
bool isOutBufferLocked = false;

NTSTATUS devCtrlStatus = STATUS_SUCCESS;

__try
{
//
// Handle memory issues. The assumption is that the IOCTL
used
// METHOD DIRECT_OUT
//

//
// 1) Allocate an MDL for the input AM buffers:
//

if( pInput && InpLen )
{
pAmInMdlBuffer = IoAllocateMdl( pInput, InpLen,
FALSE, FALSE, NULL);

if( NULL == pAmInMdlBuffer )
{
DBGREPORT(“\nAMInterface Device could not
allocate mdl for AM IN buffer”);

pIoStatus -> Information = 0;
pIoStatus -> Status = STATUS_NO_MEMORY;

return FALSE;
}
}

if( pOutput && OutLen )
{
pAmOutMdlBuffer = IoAllocateMdl( pOutput, OutLen,
FALSE, FALSE, NULL);

if( NULL == pAmOutMdlBuffer )
{
DBGREPORT(“\nAMInterface Device could not
allocate mdl for AM OUT buffer”);

if( pAmInMdlBuffer != NULL )
{
IoFreeMdl(pAmInMdlBuffer);
}

pIoStatus -> Information = 0;
pIoStatus -> Status = STATUS_NO_MEMORY;

return FALSE;
}
}

//
// 2) Probe and lock the pages:
//

if( pAmInMdlBuffer )
{
MmProbeAndLockPages( pAmInMdlBuffer, KernelMode,
IoReadAccess);
isInBufferLocked = true;
}

if( pAmOutMdlBuffer )
{
MmProbeAndLockPages( pAmOutMdlBuffer, KernelMode,
IoWriteAccess);
isOutBufferLocked = true;
}

// 3) Get an VA that we can use:

#if (WINVER>=0x500)

pLockedInAmBuffer = MmGetSystemAddressForMdlSafe(
pAmInMdlBuffer, NormalPagePriority);
pLockedOutAmBuffer = MmGetSystemAddressForMdlSafe(
pAmOutMdlBuffer, NormalPagePriority);

#else // (WINVER>=0x500)

pLockedInAmBuffer = MmGetSystemAddressForMdl( pAmInMdlBuffer
);
pLockedOutAmBuffer = MmGetSystemAddressForMdl(
pAmOutMdlBuffer );

#endif // (WINVER>=0x500)

//
// Now, we can call the "real handler:
//

devCtrlStatus = m_pMsgDispatcher -> DispatchMessage( 0,
pLockedInAmBuffer, InpLen,

pLockedOutAmBuffer, OutLen,

pIoStatus -> Information );

pIoStatus -> Status = devCtrlStatus;

//
// Not matter what the return status, let’s unlock the
// buffer, and free the mdl:
//

if( NULL != pAmOutMdlBuffer && isOutBufferLocked)
{
MmUnlockPages(pAmOutMdlBuffer);
isOutBufferLocked = false;
}

if( NULL != pAmOutMdlBuffer )
{
IoFreeMdl(pAmOutMdlBuffer);
pAmOutMdlBuffer = NULL;
}

if( NULL != pAmInMdlBuffer && isInBufferLocked)
{
MmUnlockPages(pAmInMdlBuffer);
isInBufferLocked = false;
}

if( NULL != pAmInMdlBuffer )
{
IoFreeMdl(pAmInMdlBuffer);
pAmInMdlBuffer = NULL;
}

return TRUE;
}
__except( EXCEPTION_EXECUTE_HANDLER )
{
DBGREPORTEXCEPTION();

if( NULL != pAmOutMdlBuffer && isOutBufferLocked)
{
MmUnlockPages(pAmOutMdlBuffer);
}

if(NULL != pAmOutMdlBuffer)
{
IoFreeMdl(pAmOutMdlBuffer);
}

if( NULL != pAmInMdlBuffer && isInBufferLocked)
{
MmUnlockPages(pAmInMdlBuffer);
}

if(NULL != pAmInMdlBuffer)
{
IoFreeMdl(pAmInMdlBuffer);
}

pIoStatus -> Status = GetExceptionCode();
pIoStatus -> Information = 0;

return FALSE;
}
}

-----Original Message-----
From: Peter Wieland [mailto:xxxxx@windows.microsoft.com
mailto:xxxxx ]
Sent: Friday, June 07, 2002 9:56 AM
To: NT Developers Interest List
Subject: [ntdev] RE: MmProbeAndLockPages

C:\Documents and Settings\peterwie>winerror -s c00000a1
1453 ERROR_WORKING_SET_QUOTA <–> c00000a1 STATUS_WORKING_SET_QUOTA

sounds like perhaps you aren’t unlocking everything that you locked
down.

-p

-----Original Message-----
From: Benjamin Hejl [mailto:xxxxx@yahoo.com mailto:xxxxx]
Sent: Friday, June 07, 2002 8:16 AM
To: NT Developers Interest List
Subject: [ntdev] MmProbeAndLockPages

What causes MmProbeAndLockPages to raise the exception 0xC00000A1L. I
call this function in my read dispatch function to lock the pages in a
user mode buffer to return data. Before I complete the request I call
MmUnlockPages to unlock the pages. On the 2500th call to
MmProbeAndLockPages it raises this exception. Why does this happen?

Ben

__________________________________________________
Do You Yahoo!?
Yahoo! - Official partner of 2002 FIFA World Cup
http://fifaworldcup.yahoo.com http:


You are currently subscribed to ntdev as: xxxxx@microsoft.com To
unsubscribe send a blank email to %%email.unsub%%


You are currently subscribed to ntdev as: xxxxx@Starbase.com
To unsubscribe send a blank email to %%email.unsub%%


You are currently subscribed to ntdev as: xxxxx@osr.com
To unsubscribe send a blank email to %%email.unsub%%</http:></mailto:xxxxx></mailto:xxxxx>

So doing something like this would not work:
In a dispatch function call MmProbeAndLockPages
Later before the Irp has been completed call MmGetSystemAddressForMdlSafe
Calling MmUnlockPages to unlock the pages
Finally complete the request

Instead I would need to call MmUnmapPages in that sequence?

Ben

MmGetSystemAddressForMdl* creates a range of system PTE entries if they
don’t already exist. Go look at the macro - see that call to
MmMapLockedPages?

To tear it down, you have to have a corresponding MmUnmapPages call if you
actually mapped the pages. Unlocking them is not sufficient.

This is the one area in which you are FAR better allowing the I/O subsystem
to do the work for you - attach these to an IRP and they’ll be torn down
properly. FYI - to tear them down “properly” requires violating the opacity
of MDLs, which is why it is better to let the I/O Manager do it. (This
becomes an issue because you don’t unlock non-paged addresses, you don’t
unmap if you didn’t map, etc. So you need to know what happened inside
these macros and functions).

Regards,

Tony

Tony Mason

Consulting Partner

OSR Open Systems Resources, Inc.

http://www.osr.com

-----Original Message-----
From: Vladimir Chtchetkine [mailto:xxxxx@starbase.com]
Sent: Friday, June 07, 2002 1:14 PM
To: NT Developers Interest List
Subject: [ntdev] RE: MmProbeAndLockPages

Well, I have same problem. Here is the function where I lock/unlock pages
and I would highly appreciate if anybody can find my mistake (I just lost
last hope). The only thing is that I’m allocating MDLs and lock them for all
types of buffers that come to my routine (including not only those that
address UM buffer, but also KM buffers, including MDLs):

BOOL CCTLDevice::OnHandleAppMessage( PVOID pInput, ULONG InpLen, PVOID
pOutput, ULONG OutLen,

PIO_STATUS_BLOCK pIoStatus, BOOL /*bFastIo*/)
{
PMDL pAmInMdlBuffer = NULL;
PMDL pAmOutMdlBuffer = NULL;
PVOID pLockedInAmBuffer = NULL;
PVOID pLockedOutAmBuffer = NULL;

bool isInBufferLocked = false;
bool isOutBufferLocked = false;

NTSTATUS devCtrlStatus = STATUS_SUCCESS;

__try
{
//
// Handle memory issues. The assumption is that the IOCTL
used
// METHOD DIRECT_OUT
//

//
// 1) Allocate an MDL for the input AM buffers:
//

if( pInput && InpLen )
{
pAmInMdlBuffer = IoAllocateMdl( pInput, InpLen,
FALSE, FALSE, NULL);

if( NULL == pAmInMdlBuffer )
{
DBGREPORT(“\nAMInterface Device could not
allocate mdl for AM IN buffer”);

pIoStatus -> Information = 0;
pIoStatus -> Status = STATUS_NO_MEMORY;

return FALSE;
}
}

if( pOutput && OutLen )
{
pAmOutMdlBuffer = IoAllocateMdl( pOutput, OutLen,
FALSE, FALSE, NULL);

if( NULL == pAmOutMdlBuffer )
{
DBGREPORT(“\nAMInterface Device could not
allocate mdl for AM OUT buffer”);

if( pAmInMdlBuffer != NULL )
{
IoFreeMdl(pAmInMdlBuffer);
}

pIoStatus -> Information = 0;
pIoStatus -> Status = STATUS_NO_MEMORY;

return FALSE;
}
}

//
// 2) Probe and lock the pages:
//

if( pAmInMdlBuffer )
{
MmProbeAndLockPages( pAmInMdlBuffer, KernelMode,
IoReadAccess);
isInBufferLocked = true;
}

if( pAmOutMdlBuffer )
{
MmProbeAndLockPages( pAmOutMdlBuffer, KernelMode,
IoWriteAccess);
isOutBufferLocked = true;
}

// 3) Get an VA that we can use:

#if (WINVER>=0x500)

pLockedInAmBuffer = MmGetSystemAddressForMdlSafe(
pAmInMdlBuffer, NormalPagePriority);
pLockedOutAmBuffer = MmGetSystemAddressForMdlSafe(
pAmOutMdlBuffer, NormalPagePriority);

#else // (WINVER>=0x500)

pLockedInAmBuffer = MmGetSystemAddressForMdl( pAmInMdlBuffer
);
pLockedOutAmBuffer = MmGetSystemAddressForMdl(
pAmOutMdlBuffer );

#endif // (WINVER>=0x500)

//
// Now, we can call the "real handler:
//

devCtrlStatus = m_pMsgDispatcher -> DispatchMessage( 0,
pLockedInAmBuffer, InpLen,

pLockedOutAmBuffer, OutLen,

pIoStatus -> Information );

pIoStatus -> Status = devCtrlStatus;

//
// Not matter what the return status, let’s unlock the
// buffer, and free the mdl:
//

if( NULL != pAmOutMdlBuffer && isOutBufferLocked)
{
MmUnlockPages(pAmOutMdlBuffer);
isOutBufferLocked = false;
}

if( NULL != pAmOutMdlBuffer )
{
IoFreeMdl(pAmOutMdlBuffer);
pAmOutMdlBuffer = NULL;
}

if( NULL != pAmInMdlBuffer && isInBufferLocked)
{
MmUnlockPages(pAmInMdlBuffer);
isInBufferLocked = false;
}

if( NULL != pAmInMdlBuffer )
{
IoFreeMdl(pAmInMdlBuffer);
pAmInMdlBuffer = NULL;
}

return TRUE;
}
__except( EXCEPTION_EXECUTE_HANDLER )
{
DBGREPORTEXCEPTION();

if( NULL != pAmOutMdlBuffer && isOutBufferLocked)
{
MmUnlockPages(pAmOutMdlBuffer);
}

if(NULL != pAmOutMdlBuffer)
{
IoFreeMdl(pAmOutMdlBuffer);
}

if( NULL != pAmInMdlBuffer && isInBufferLocked)
{
MmUnlockPages(pAmInMdlBuffer);
}

if(NULL != pAmInMdlBuffer)
{
IoFreeMdl(pAmInMdlBuffer);
}

pIoStatus -> Status = GetExceptionCode();
pIoStatus -> Information = 0;

return FALSE;
}
}

-----Original Message-----
From: Peter Wieland [mailto:xxxxx@windows.microsoft.com
mailto:xxxxx ]
> Sent: Friday, June 07, 2002 9:56 AM
> To: NT Developers Interest List
> Subject: [ntdev] RE: MmProbeAndLockPages
>
>
>
> C:\Documents and Settings\peterwie>winerror -s c00000a1
> 1453 ERROR_WORKING_SET_QUOTA <–> c00000a1 STATUS_WORKING_SET_QUOTA
>
> sounds like perhaps you aren’t unlocking everything that you locked
> down.
>
> -p
>
> -----Original Message-----
> From: Benjamin Hejl [mailto:xxxxx@yahoo.com mailto:xxxxx]
> Sent: Friday, June 07, 2002 8:16 AM
> To: NT Developers Interest List
> Subject: [ntdev] MmProbeAndLockPages
>
>
>
> What causes MmProbeAndLockPages to raise the exception 0xC00000A1L. I
> call this function in my read dispatch function to lock the pages in a
> user mode buffer to return data. Before I complete the request I call
> MmUnlockPages to unlock the pages. On the 2500th call to
> MmProbeAndLockPages it raises this exception. Why does this happen?
>
> Ben
>
> __________________________________________________
> Do You Yahoo!?
> Yahoo! - Official partner of 2002 FIFA World Cup
> http://fifaworldcup.yahoo.com http:
>
> —
> You are currently subscribed to ntdev as: xxxxx@microsoft.com To
> unsubscribe send a blank email to %%email.unsub%%
>
> —
> You are currently subscribed to ntdev as: xxxxx@Starbase.com
> To unsubscribe send a blank email to %%email.unsub%%
>
> —
> You are currently subscribed to ntdev as: xxxxx@osr.com
> To unsubscribe send a blank email to %%email.unsub%%</http:></mailto:xxxxx></mailto:xxxxx>

Mark, your certainly right. Is not a coincidence.

Regards, Dan
----- Original Message -----
From: “Roddy, Mark”
To: “NT Developers Interest List”
Sent: Friday, June 07, 2002 8:05 PM
Subject: [ntdev] RE: MmProbeAndLockPages

> 1: kd> x MmReferenceCountCheck
> 1: kd> dd MmReferenceCountCheck
> 80474a30 000009c4
>
> hex 9c4 = dec 2500 coincidence? You be the judge :slight_smile:
>
> > -----Original Message-----
> > From: Dan Partelly [mailto:xxxxx@rdsor.ro]
> > Sent: Friday, June 07, 2002 12:09 PM
> > To: NT Developers Interest List
> > Subject: [ntdev] RE: MmProbeAndLockPages
> >
> >
> > I think this exception is raised only if the process maximum
> > working set size is exceeded and if some memory manager
> > variable which holds the number of system global currently
> > locked pages reach a treshold. For the second case, the
> > status throw is a bit misguiding.
> >
> > As far as I know, locking a page too many times wont throw
> > this kind of error, since usually only the reference count of
> > the page is incremented after the first locking. But Im
> > really not sure about it.
> >
> > Anyway, most likely you loose resources somehow, and you dont
> > unlock all pages you lock. Check your execution paths to see
> > if every locking operation has a subsequent unlock, in all cases.
> >
> > Regards, Dan
> >
> > ----- Original Message -----
> > From: “Roddy, Mark”
> > To: “NT Developers Interest List”
> > Sent: Friday, June 07, 2002 6:30 PM
> > Subject: [ntdev] RE: MmProbeAndLockPages
> >
> >
> > > //
> > > // MessageId: STATUS_WORKING_SET_QUOTA
> > > //
> > > // MessageText:
> > > //
> > > // The working set is not big enough to allow the
> > requested pages to
> > > be locked. //
> > > #define STATUS_WORKING_SET_QUOTA ((NTSTATUS)0xC00000A1L
> > >
> > > Hmmmm… that might be suggestive of the problem, no?
> > >
> > > I think you have hit a limit on the number of times that a
> > single page
> > > can be locked, are you ever unlocking this page?
> > >
> > > > -----Original Message-----
> > > > From: Benjamin Hejl [mailto:xxxxx@yahoo.com] ,
> > > > Sent: Friday, June 07, 2002 11:16 AM
> > > > To: NT Developers Interest List
> > > > Subject: [ntdev] MmProbeAndLockPages
> > > >
> > > >
> > > > What causes MmProbeAndLockPages to raise the exception
> > 0xC00000A1L.
> > > > I call this function in my read dispatch function to lock
> > the pages
> > > > in a user mode buffer to return data. Before I complete
> > the request
> > > > I call MmUnlockPages to unlock the pages. On the 2500th call to
> > > > MmProbeAndLockPages it raises this exception. Why does
> > this happen?
> > > >
> > > > Ben
> > > >
> > > > __________________________________________________
> > > > Do You Yahoo!?
> > > > Yahoo! - Official partner of 2002 FIFA World Cup
> > > http://fifaworldcup.yahoo.com
> > >
> > > —
> > > You are currently subscribed to ntdev as: xxxxx@stratus.com To
> > > unsubscribe send a blank email to %%email.unsub%%
> > >
> > > —
> > > You are currently subscribed to ntdev as: xxxxx@rdsor.ro To
> > > unsubscribe send a blank email to %%email.unsub%%
> > >
> >
> >
> > —
> > You are currently subscribed to ntdev as:
> > xxxxx@stratus.com To unsubscribe send a blank email to
> > %%email.unsub%%
> >
>
> —
> You are currently subscribed to ntdev as: xxxxx@rdsor.ro
> To unsubscribe send a blank email to %%email.unsub%%
>

> To tear it down, you have to have a corresponding MmUnmapPages call
if you

actually mapped the pages. Unlocking them is not sufficient.

MmUnlockPages will do the unmap for a MDL created by
MmProbeAndLockPages.
IO manager will automatically call MmUnlockPages in IoCompleteRequest,
if the IRP was unwound to the end without
STATUS_MORE_PROCESSING_REQUIRED.

MDLs created by MmBuildMdlForNonPagedPool are IIRC never mapped to
system PTEs - instead their virtual address is reused as mapped
address.

Max