Help on IoAllocateMdl()

When I call IoAllocateMdl() to create MDL for the user memory, sometimes I
got a negative value for pMdl->Size but IoAllocateMdl() did not fail. Can
anyone explain it to me? The data type for Size in MDL is CSHORT (#define
short CSHORT), so the negative value is allowed for the Size. However, when
a size is negative, how can I use it to determine the size of MDL allocated?

Thanks,

zhong

Size cannot be negative, so your question doesn’t make any sense. Size
is a positive value from 28 to 65535 (28 being the smallest possible
MDL). To go “negative” (that is above 32767 so when you cast from an
unsigned number to a signed number you get sign extension) you would be
describing a memory region that is 8185 pages long ((32768-28)/4) or
just shy of 32MB. The largest possible MDL that can be described then
is thus 16377 pages (67080192 bytes).

Thus, the answer to your question is that it means the memory region you
are attempting to describe is between 3334145 and 67080192 bytes long.
I have not confirmed this, but I wouldn’t be surprised to find out that
the size is truncated if the memory region is LARGER than the 67080192
number.

Regards,

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

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of
xxxxx@exgate.tek.com
Sent: Monday, April 26, 2004 7:44 PM
To: ntdev redirect
Subject: [ntdev] Help on IoAllocateMdl()

When I call IoAllocateMdl() to create MDL for the user memory, sometimes
I
got a negative value for pMdl->Size but IoAllocateMdl() did not fail.
Can
anyone explain it to me? The data type for Size in MDL is CSHORT
(#define
short CSHORT), so the negative value is allowed for the Size. However,
when
a size is negative, how can I use it to determine the size of MDL
allocated?

Thanks,

zhong


Questions? First check the Kernel Driver FAQ at
http://www.osronline.com/article.cfm?id=256

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

Tony:

I absolutely agree with you. It does not make sense to have a negative value
for size. But that is why I am asking for help.

Here is the output from WinDbg after I call IoAllocateMdl() in the following
code snippet:

Name Value Type
pMdl 0xfec3e000 struct _MDL * struct _MDL
*
Next 0x00000000 struct _MDL * struct _MDL *
Size -32736 short
MdlFlags 0
short
Process 0x006c0065 struct _EPROCESS * struct
_EPROCESS *
MappedSystemVa 0x00fe0000 void *
StartVa 0x04490000 void
*
ByteCount 0x2000000
unsigned long
ByteOffset 0x40 unsigned
long
pUserVa 0x0449040 unsigned
long *

The following is the code I am executing. The function PciMemLock() is
directly called from the DispatchControl() routine.

NTSTATUS DispatchControl(PDEVICE_OBJECT fdo, PIRP Irp)
{

case PLX_IOCTL_MEMORY_LOCK:
DrvTraceNoInfo((“PLX_IOCTL_MEMORY_LOCK\n”));

if (pdx->devpower > MIN_WORKING_POWER_STATE)
{
pIoBuffer->ReturnCode = ApiPowerDown;
}
else
{
pIoBuffer->ReturnCode = ApiSuccess;
PciMem.UserAddr = (ULONG)pIoBuffer->u.MemLock.pUserVa;
PciMem.Size = pIoBuffer->u.MemLock.Size;
status = PciMemLock(pdx, &PciMem,
pIoBuffer->u.MemLock.Option, stack->FileObject);
}

break;

}

NTSTATUS
PciMemLock(PDEVICE_EXTENSION pdx, PCI_MEMORY * pPciMem, UCHAR Option, PVOID
pOwner)
{
ULONG * pUserVa = (ULONG*)pPciMem->UserAddr;
ULONG nSize = pPciMem->Size;
MDL_ENTRY *pMdlEntry = NULL;
BOOLEAN bFlag;

DrvTrace(DRV_IOCTL, (“Lock the user memory %p, size %d\n”,pUserVa,
nSize));

pMdlEntry = (MDL_ENTRY*)ExAllocatePoolWithTag(NonPagedPool,
sizeof(MDL_ENTRY), 0x4C4D454D);
if (pMdlEntry == NULL)
{
DrvTrace(DRV_IOCTL, (“ERROR - Unable to build MDL Entry for the user
buffer.\n”));
return STATUS_INSUFFICIENT_RESOURCES;
}

switch (Option)
{
case USER_BUFFER_ALLOC:
// The buffer must be already allocated by the user application
if ((pUserVa == NULL) || (nSize == 0)) {
DrvTrace(DRV_IOCTL, (“ERROR - The buffer is uninitialized\n”));
ExFreePool(pMdlEntry);
return STATUS_INVALID_PARAMETER;
}

// Try to allocate MDL for the user buffer
pMdlEntry->pMdl = IoAllocateMdl(
(PVOID)pUserVa,
nSize,
FALSE,
FALSE,
NULL
);

if (pMdlEntry->pMdl == NULL) // WinDbg output
caught here.
{
DrvTrace(DRV_IOCTL, (“ERROR - Unable to build MDL for the user
buffer.\n”));
ExFreePool(pMdlEntry);
return STATUS_INSUFFICIENT_RESOURCES;
}

// Attempt to lock the user buffer into memory. May raise memory
access violation
// if the memory is not available or can’t access.
bFlag = FALSE;

__try
{
MmProbeAndLockPages(
pMdlEntry->pMdl,
UserMode,
IoModifyAccess
);
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
// Flag the exception
bFlag = TRUE;
}

// Verify that the pages were locked
if (bFlag)
{
DrvTrace(DRV_DMAOPEN, (“ERROR - Unable to lock pages\n”));
IoFreeMdl(
pMdlEntry->pMdl
);
ExFreePool(pMdlEntry);
return STATUS_ACCESS_VIOLATION;
}

break;

case KERNEL_BUFFER_ALLOC_PAGED:

return STATUS_NOT_SUPPORTED;

break;

case KERNEL_BUFFER_ALLOC_NONPAGED:
return STATUS_NOT_SUPPORTED;

break;

default:
return STATUS_INVALID_PARAMETER;
break;
}

pMdlEntry->pOwner = pOwner;
ExInterlockedInsertTailList(
&(pdx->List_Mdl),
&(pMdlEntry->ListEntry),
&(pdx->Lock_MdlList)
);

return STATUS_SUCCESS;
}

Can you see any wrong doing in my code?

Thanks,

zhong

-----Original Message-----
From: Tony Mason [mailto:xxxxx@osr.com]
Sent: Monday, April 26, 2004 5:11 PM
To: Windows System Software Devs Interest List
Subject: RE: [ntdev] Help on IoAllocateMdl()

Size cannot be negative, so your question doesn’t make any sense. Size
is a positive value from 28 to 65535 (28 being the smallest possible
MDL). To go “negative” (that is above 32767 so when you cast from an
unsigned number to a signed number you get sign extension) you would be
describing a memory region that is 8185 pages long ((32768-28)/4) or
just shy of 32MB. The largest possible MDL that can be described then
is thus 16377 pages (67080192 bytes).

Thus, the answer to your question is that it means the memory region you
are attempting to describe is between 3334145 and 67080192 bytes long.
I have not confirmed this, but I wouldn’t be surprised to find out that
the size is truncated if the memory region is LARGER than the 67080192
number.

Regards,

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

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of
xxxxx@exgate.tek.com
Sent: Monday, April 26, 2004 7:44 PM
To: ntdev redirect
Subject: [ntdev] Help on IoAllocateMdl()

When I call IoAllocateMdl() to create MDL for the user memory, sometimes
I
got a negative value for pMdl->Size but IoAllocateMdl() did not fail.
Can
anyone explain it to me? The data type for Size in MDL is CSHORT
(#define
short CSHORT), so the negative value is allowed for the Size. However,
when
a size is negative, how can I use it to determine the size of MDL
allocated?

Thanks,

zhong


Questions? First check the Kernel Driver FAQ at
http://www.osronline.com/article.cfm?id=256

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


Questions? First check the Kernel Driver FAQ at
http://www.osronline.com/article.cfm?id=256

You are currently subscribed to ntdev as: xxxxx@exgate.tek.com
To unsubscribe send a blank email to xxxxx@lists.osr.com

This is just windbg displaying the MDL size as a signed decimal value rather
than an unsigned hex value. The maximum size (in pages) for an MDL allocated
through IoAllocateMdl is 0xffff. You are within those bounds, and
IoAllocateMdl would return NULL if you weren’t.

Try using the windbg command “.force_radix_output 1” and you will be less
easily confused by this sort of disinformational noise.

=====================
Mark Roddy

-----Original Message-----
From: xxxxx@exgate.tek.com
[mailto:xxxxx@exgate.tek.com]
Sent: Tuesday, April 27, 2004 12:23 PM
To: Windows System Software Devs Interest List
Subject: RE: [ntdev] Help on IoAllocateMdl()

Tony:

I absolutely agree with you. It does not make sense to have a
negative value for size. But that is why I am asking for help.

Here is the output from WinDbg after I call IoAllocateMdl()
in the following code snippet:

Name Value
Type
pMdl 0xfec3e000 struct _MDL *
struct _MDL
*
Next 0x00000000 struct _MDL *
struct _MDL *
Size -32736 short
MdlFlags 0
short
Process 0x006c0065 struct _EPROCESS * struct
_EPROCESS *
MappedSystemVa 0x00fe0000
void *
StartVa 0x04490000
void
*
ByteCount 0x2000000
unsigned long
ByteOffset 0x40 unsigned
long
pUserVa 0x0449040
unsigned
long *

The following is the code I am executing. The function
PciMemLock() is directly called from the DispatchControl() routine.

NTSTATUS DispatchControl(PDEVICE_OBJECT fdo, PIRP Irp) { …
case PLX_IOCTL_MEMORY_LOCK:
DrvTraceNoInfo((“PLX_IOCTL_MEMORY_LOCK\n”));

if (pdx->devpower > MIN_WORKING_POWER_STATE)
{
pIoBuffer->ReturnCode = ApiPowerDown;
}
else
{
pIoBuffer->ReturnCode = ApiSuccess;
PciMem.UserAddr = (ULONG)pIoBuffer->u.MemLock.pUserVa;
PciMem.Size = pIoBuffer->u.MemLock.Size;
status = PciMemLock(pdx, &PciMem,
pIoBuffer->u.MemLock.Option, stack->FileObject);
}

break;

}

NTSTATUS
PciMemLock(PDEVICE_EXTENSION pdx, PCI_MEMORY * pPciMem, UCHAR
Option, PVOID
pOwner)
{
ULONG * pUserVa = (ULONG*)pPciMem->UserAddr;
ULONG nSize = pPciMem->Size;
MDL_ENTRY *pMdlEntry = NULL;
BOOLEAN bFlag;

DrvTrace(DRV_IOCTL, (“Lock the user memory %p, size
%d\n”,pUserVa, nSize));

pMdlEntry = (MDL_ENTRY*)ExAllocatePoolWithTag(NonPagedPool,
sizeof(MDL_ENTRY), 0x4C4D454D);
if (pMdlEntry == NULL)
{
DrvTrace(DRV_IOCTL, (“ERROR - Unable to build MDL
Entry for the user buffer.\n”));
return STATUS_INSUFFICIENT_RESOURCES;
}

switch (Option)
{
case USER_BUFFER_ALLOC:
// The buffer must be already allocated by the user
application
if ((pUserVa == NULL) || (nSize == 0)) {
DrvTrace(DRV_IOCTL, (“ERROR - The buffer is
uninitialized\n”));
ExFreePool(pMdlEntry);
return STATUS_INVALID_PARAMETER;
}

// Try to allocate MDL for the user buffer
pMdlEntry->pMdl = IoAllocateMdl(
(PVOID)pUserVa,
nSize,
FALSE,
FALSE,
NULL
);

if (pMdlEntry->pMdl == NULL) // WinDbg output
caught here.
{
DrvTrace(DRV_IOCTL, (“ERROR - Unable to build MDL
for the user buffer.\n”));
ExFreePool(pMdlEntry);
return STATUS_INSUFFICIENT_RESOURCES;
}

// Attempt to lock the user buffer into memory. May
raise memory access violation
// if the memory is not available or can’t access.
bFlag = FALSE;

__try
{
MmProbeAndLockPages(
pMdlEntry->pMdl,
UserMode,
IoModifyAccess
);
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
// Flag the exception
bFlag = TRUE;
}

// Verify that the pages were locked
if (bFlag)
{
DrvTrace(DRV_DMAOPEN, (“ERROR - Unable to lock pages\n”));
IoFreeMdl(
pMdlEntry->pMdl
);
ExFreePool(pMdlEntry);
return STATUS_ACCESS_VIOLATION;
}

break;

case KERNEL_BUFFER_ALLOC_PAGED:

return STATUS_NOT_SUPPORTED;

break;

case KERNEL_BUFFER_ALLOC_NONPAGED:
return STATUS_NOT_SUPPORTED;

break;

default:
return STATUS_INVALID_PARAMETER;
break;
}

pMdlEntry->pOwner = pOwner;
ExInterlockedInsertTailList(
&(pdx->List_Mdl),
&(pMdlEntry->ListEntry),
&(pdx->Lock_MdlList)
);

return STATUS_SUCCESS;
}

Can you see any wrong doing in my code?

Thanks,

zhong

-----Original Message-----
From: Tony Mason [mailto:xxxxx@osr.com]
Sent: Monday, April 26, 2004 5:11 PM
To: Windows System Software Devs Interest List
Subject: RE: [ntdev] Help on IoAllocateMdl()

Size cannot be negative, so your question doesn’t make any
sense. Size
is a positive value from 28 to 65535 (28 being the smallest possible
MDL). To go “negative” (that is above 32767 so when you cast from an
unsigned number to a signed number you get sign extension)
you would be
describing a memory region that is 8185 pages long ((32768-28)/4) or
just shy of 32MB. The largest possible MDL that can be described then
is thus 16377 pages (67080192 bytes).

Thus, the answer to your question is that it means the memory
region you
are attempting to describe is between 3334145 and 67080192 bytes long.
I have not confirmed this, but I wouldn’t be surprised to
find out that
the size is truncated if the memory region is LARGER than the 67080192
number.

Regards,

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

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of
xxxxx@exgate.tek.com
Sent: Monday, April 26, 2004 7:44 PM
To: ntdev redirect
Subject: [ntdev] Help on IoAllocateMdl()

When I call IoAllocateMdl() to create MDL for the user
memory, sometimes
I
got a negative value for pMdl->Size but IoAllocateMdl() did not fail.
Can
anyone explain it to me? The data type for Size in MDL is CSHORT
(#define
short CSHORT), so the negative value is allowed for the Size. However,
when
a size is negative, how can I use it to determine the size of MDL
allocated?

Thanks,

zhong


Questions? First check the Kernel Driver FAQ at
http://www.osronline.com/article.cfm?id=256

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


Questions? First check the Kernel Driver FAQ at
http://www.osronline.com/article.cfm?id=256

You are currently subscribed to ntdev as:
xxxxx@exgate.tek.com
To unsubscribe send a blank email to xxxxx@lists.osr.com


Questions? First check the Kernel Driver FAQ at
http://www.osronline.com/article.cfm?id=256

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

The MDL in question describes a memory region that is 33,554,432 bytes
long (see the “ByteCount” field.) This requires exactly 8193 page
entries (32768 bytes, not starting on a page boundary) plus the fixed
size (28 byte) MDL structure itself. Thus, the size of the MDL is
32,794 bytes. When you sign extend this, you get -32736.

Regards,

Tony

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of
xxxxx@exgate.tek.com
Sent: Tuesday, April 27, 2004 12:23 PM
To: ntdev redirect
Subject: RE: [ntdev] Help on IoAllocateMdl()

Tony:

I absolutely agree with you. It does not make sense to have a negative
value
for size. But that is why I am asking for help.

Here is the output from WinDbg after I call IoAllocateMdl() in the
following
code snippet:

Name Value
Type
pMdl 0xfec3e000 struct _MDL * struct
_MDL
*
Next 0x00000000 struct _MDL * struct _MDL *
Size -32736 short
MdlFlags 0
short
Process 0x006c0065 struct _EPROCESS * struct
_EPROCESS *
MappedSystemVa 0x00fe0000 void *
StartVa 0x04490000
void
*
ByteCount 0x2000000
unsigned long
ByteOffset 0x40 unsigned
long
pUserVa 0x0449040 unsigned
long *

The following is the code I am executing. The function PciMemLock() is
directly called from the DispatchControl() routine.

NTSTATUS DispatchControl(PDEVICE_OBJECT fdo, PIRP Irp)
{

case PLX_IOCTL_MEMORY_LOCK:
DrvTraceNoInfo((“PLX_IOCTL_MEMORY_LOCK\n”));

if (pdx->devpower > MIN_WORKING_POWER_STATE)
{
pIoBuffer->ReturnCode = ApiPowerDown;
}
else
{
pIoBuffer->ReturnCode = ApiSuccess;
PciMem.UserAddr = (ULONG)pIoBuffer->u.MemLock.pUserVa;
PciMem.Size = pIoBuffer->u.MemLock.Size;
status = PciMemLock(pdx, &PciMem,
pIoBuffer->u.MemLock.Option, stack->FileObject);
}

break;

}

NTSTATUS
PciMemLock(PDEVICE_EXTENSION pdx, PCI_MEMORY * pPciMem, UCHAR Option,
PVOID
pOwner)
{
ULONG * pUserVa = (ULONG*)pPciMem->UserAddr;
ULONG nSize = pPciMem->Size;
MDL_ENTRY *pMdlEntry = NULL;
BOOLEAN bFlag;

DrvTrace(DRV_IOCTL, (“Lock the user memory %p, size %d\n”,pUserVa,
nSize));

pMdlEntry = (MDL_ENTRY*)ExAllocatePoolWithTag(NonPagedPool,
sizeof(MDL_ENTRY), 0x4C4D454D);
if (pMdlEntry == NULL)
{
DrvTrace(DRV_IOCTL, (“ERROR - Unable to build MDL Entry for the
user
buffer.\n”));
return STATUS_INSUFFICIENT_RESOURCES;
}

switch (Option)
{
case USER_BUFFER_ALLOC:
// The buffer must be already allocated by the user application
if ((pUserVa == NULL) || (nSize == 0)) {
DrvTrace(DRV_IOCTL, (“ERROR - The buffer is
uninitialized\n”));
ExFreePool(pMdlEntry);
return STATUS_INVALID_PARAMETER;
}

// Try to allocate MDL for the user buffer
pMdlEntry->pMdl = IoAllocateMdl(
(PVOID)pUserVa,
nSize,
FALSE,
FALSE,
NULL
);

if (pMdlEntry->pMdl == NULL) // WinDbg output
caught here.
{
DrvTrace(DRV_IOCTL, (“ERROR - Unable to build MDL for the
user
buffer.\n”));
ExFreePool(pMdlEntry);
return STATUS_INSUFFICIENT_RESOURCES;
}

// Attempt to lock the user buffer into memory. May raise memory
access violation
// if the memory is not available or can’t access.
bFlag = FALSE;

__try
{
MmProbeAndLockPages(
pMdlEntry->pMdl,
UserMode,
IoModifyAccess
);
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
// Flag the exception
bFlag = TRUE;
}

// Verify that the pages were locked
if (bFlag)
{
DrvTrace(DRV_DMAOPEN, (“ERROR - Unable to lock pages\n”));
IoFreeMdl(
pMdlEntry->pMdl
);
ExFreePool(pMdlEntry);
return STATUS_ACCESS_VIOLATION;
}

break;

case KERNEL_BUFFER_ALLOC_PAGED:

return STATUS_NOT_SUPPORTED;

break;

case KERNEL_BUFFER_ALLOC_NONPAGED:
return STATUS_NOT_SUPPORTED;

break;

default:
return STATUS_INVALID_PARAMETER;
break;
}

pMdlEntry->pOwner = pOwner;
ExInterlockedInsertTailList(
&(pdx->List_Mdl),
&(pMdlEntry->ListEntry),
&(pdx->Lock_MdlList)
);

return STATUS_SUCCESS;
}

Can you see any wrong doing in my code?

Thanks,

zhong

-----Original Message-----
From: Tony Mason [mailto:xxxxx@osr.com]
Sent: Monday, April 26, 2004 5:11 PM
To: Windows System Software Devs Interest List
Subject: RE: [ntdev] Help on IoAllocateMdl()

Size cannot be negative, so your question doesn’t make any sense. Size
is a positive value from 28 to 65535 (28 being the smallest possible
MDL). To go “negative” (that is above 32767 so when you cast from an
unsigned number to a signed number you get sign extension) you would be
describing a memory region that is 8185 pages long ((32768-28)/4) or
just shy of 32MB. The largest possible MDL that can be described then
is thus 16377 pages (67080192 bytes).

Thus, the answer to your question is that it means the memory region you
are attempting to describe is between 3334145 and 67080192 bytes long.
I have not confirmed this, but I wouldn’t be surprised to find out that
the size is truncated if the memory region is LARGER than the 67080192
number.

Regards,

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

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of
xxxxx@exgate.tek.com
Sent: Monday, April 26, 2004 7:44 PM
To: ntdev redirect
Subject: [ntdev] Help on IoAllocateMdl()

When I call IoAllocateMdl() to create MDL for the user memory, sometimes
I
got a negative value for pMdl->Size but IoAllocateMdl() did not fail.
Can
anyone explain it to me? The data type for Size in MDL is CSHORT
(#define
short CSHORT), so the negative value is allowed for the Size. However,
when
a size is negative, how can I use it to determine the size of MDL
allocated?

Thanks,

zhong


Questions? First check the Kernel Driver FAQ at
http://www.osronline.com/article.cfm?id=256

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


Questions? First check the Kernel Driver FAQ at
http://www.osronline.com/article.cfm?id=256

You are currently subscribed to ntdev as: xxxxx@exgate.tek.com
To unsubscribe send a blank email to xxxxx@lists.osr.com


Questions? First check the Kernel Driver FAQ at
http://www.osronline.com/article.cfm?id=256

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

Thanks,

So if I want to use pMdl->Size to figure out how many pages have been
described, should I cast it to USHORT? Like the following:

TotalPages = (((USHORT)(pMdl->Size) - sizeof(MDL)) / sizeof(ULONG));

By definition in WDM.h, the type of pMdl->Size is CSHORT, which is “short”.

zhong

-----Original Message-----
From: Tony Mason [mailto:xxxxx@osr.com]
Sent: Tuesday, April 27, 2004 9:45 AM
To: Windows System Software Devs Interest List
Subject: RE: [ntdev] Help on IoAllocateMdl()

The MDL in question describes a memory region that is 33,554,432 bytes
long (see the “ByteCount” field.) This requires exactly 8193 page
entries (32768 bytes, not starting on a page boundary) plus the fixed
size (28 byte) MDL structure itself. Thus, the size of the MDL is
32,794 bytes. When you sign extend this, you get -32736.

Regards,

Tony

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of
xxxxx@exgate.tek.com
Sent: Tuesday, April 27, 2004 12:23 PM
To: ntdev redirect
Subject: RE: [ntdev] Help on IoAllocateMdl()

Tony:

I absolutely agree with you. It does not make sense to have a negative
value
for size. But that is why I am asking for help.

Here is the output from WinDbg after I call IoAllocateMdl() in the
following
code snippet:

Name Value
Type
pMdl 0xfec3e000 struct _MDL * struct
_MDL
*
Next 0x00000000 struct _MDL * struct _MDL *
Size -32736 short
MdlFlags 0
short
Process 0x006c0065 struct _EPROCESS * struct
_EPROCESS *
MappedSystemVa 0x00fe0000 void *
StartVa 0x04490000
void
*
ByteCount 0x2000000
unsigned long
ByteOffset 0x40 unsigned
long
pUserVa 0x0449040 unsigned
long *

The following is the code I am executing. The function PciMemLock() is
directly called from the DispatchControl() routine.

NTSTATUS DispatchControl(PDEVICE_OBJECT fdo, PIRP Irp)
{

case PLX_IOCTL_MEMORY_LOCK:
DrvTraceNoInfo((“PLX_IOCTL_MEMORY_LOCK\n”));

if (pdx->devpower > MIN_WORKING_POWER_STATE)
{
pIoBuffer->ReturnCode = ApiPowerDown;
}
else
{
pIoBuffer->ReturnCode = ApiSuccess;
PciMem.UserAddr = (ULONG)pIoBuffer->u.MemLock.pUserVa;
PciMem.Size = pIoBuffer->u.MemLock.Size;
status = PciMemLock(pdx, &PciMem,
pIoBuffer->u.MemLock.Option, stack->FileObject);
}

break;

}

NTSTATUS
PciMemLock(PDEVICE_EXTENSION pdx, PCI_MEMORY * pPciMem, UCHAR Option,
PVOID
pOwner)
{
ULONG * pUserVa = (ULONG*)pPciMem->UserAddr;
ULONG nSize = pPciMem->Size;
MDL_ENTRY *pMdlEntry = NULL;
BOOLEAN bFlag;

DrvTrace(DRV_IOCTL, (“Lock the user memory %p, size %d\n”,pUserVa,
nSize));

pMdlEntry = (MDL_ENTRY*)ExAllocatePoolWithTag(NonPagedPool,
sizeof(MDL_ENTRY), 0x4C4D454D);
if (pMdlEntry == NULL)
{
DrvTrace(DRV_IOCTL, (“ERROR - Unable to build MDL Entry for the
user
buffer.\n”));
return STATUS_INSUFFICIENT_RESOURCES;
}

switch (Option)
{
case USER_BUFFER_ALLOC:
// The buffer must be already allocated by the user application
if ((pUserVa == NULL) || (nSize == 0)) {
DrvTrace(DRV_IOCTL, (“ERROR - The buffer is
uninitialized\n”));
ExFreePool(pMdlEntry);
return STATUS_INVALID_PARAMETER;
}

// Try to allocate MDL for the user buffer
pMdlEntry->pMdl = IoAllocateMdl(
(PVOID)pUserVa,
nSize,
FALSE,
FALSE,
NULL
);

if (pMdlEntry->pMdl == NULL) // WinDbg output
caught here.
{
DrvTrace(DRV_IOCTL, (“ERROR - Unable to build MDL for the
user
buffer.\n”));
ExFreePool(pMdlEntry);
return STATUS_INSUFFICIENT_RESOURCES;
}

// Attempt to lock the user buffer into memory. May raise memory
access violation
// if the memory is not available or can’t access.
bFlag = FALSE;

__try
{
MmProbeAndLockPages(
pMdlEntry->pMdl,
UserMode,
IoModifyAccess
);
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
// Flag the exception
bFlag = TRUE;
}

// Verify that the pages were locked
if (bFlag)
{
DrvTrace(DRV_DMAOPEN, (“ERROR - Unable to lock pages\n”));
IoFreeMdl(
pMdlEntry->pMdl
);
ExFreePool(pMdlEntry);
return STATUS_ACCESS_VIOLATION;
}

break;

case KERNEL_BUFFER_ALLOC_PAGED:

return STATUS_NOT_SUPPORTED;

break;

case KERNEL_BUFFER_ALLOC_NONPAGED:
return STATUS_NOT_SUPPORTED;

break;

default:
return STATUS_INVALID_PARAMETER;
break;
}

pMdlEntry->pOwner = pOwner;
ExInterlockedInsertTailList(
&(pdx->List_Mdl),
&(pMdlEntry->ListEntry),
&(pdx->Lock_MdlList)
);

return STATUS_SUCCESS;
}

Can you see any wrong doing in my code?

Thanks,

zhong

-----Original Message-----
From: Tony Mason [mailto:xxxxx@osr.com]
Sent: Monday, April 26, 2004 5:11 PM
To: Windows System Software Devs Interest List
Subject: RE: [ntdev] Help on IoAllocateMdl()

Size cannot be negative, so your question doesn’t make any sense. Size
is a positive value from 28 to 65535 (28 being the smallest possible
MDL). To go “negative” (that is above 32767 so when you cast from an
unsigned number to a signed number you get sign extension) you would be
describing a memory region that is 8185 pages long ((32768-28)/4) or
just shy of 32MB. The largest possible MDL that can be described then
is thus 16377 pages (67080192 bytes).

Thus, the answer to your question is that it means the memory region you
are attempting to describe is between 3334145 and 67080192 bytes long.
I have not confirmed this, but I wouldn’t be surprised to find out that
the size is truncated if the memory region is LARGER than the 67080192
number.

Regards,

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

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of
xxxxx@exgate.tek.com
Sent: Monday, April 26, 2004 7:44 PM
To: ntdev redirect
Subject: [ntdev] Help on IoAllocateMdl()

When I call IoAllocateMdl() to create MDL for the user memory, sometimes
I
got a negative value for pMdl->Size but IoAllocateMdl() did not fail.
Can
anyone explain it to me? The data type for Size in MDL is CSHORT
(#define
short CSHORT), so the negative value is allowed for the Size. However,
when
a size is negative, how can I use it to determine the size of MDL
allocated?

Thanks,

zhong


Questions? First check the Kernel Driver FAQ at
http://www.osronline.com/article.cfm?id=256

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


Questions? First check the Kernel Driver FAQ at
http://www.osronline.com/article.cfm?id=256

You are currently subscribed to ntdev as: xxxxx@exgate.tek.com
To unsubscribe send a blank email to xxxxx@lists.osr.com


Questions? First check the Kernel Driver FAQ at
http://www.osronline.com/article.cfm?id=256

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


Questions? First check the Kernel Driver FAQ at
http://www.osronline.com/article.cfm?id=256

You are currently subscribed to ntdev as: xxxxx@exgate.tek.com
To unsubscribe send a blank email to xxxxx@lists.osr.com

Or use the ADDRESS_AND_SIZE_TO_SPAN_PAGES macro on the virtual address
and length of the MDL.

-p

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of
xxxxx@exgate.tek.com
Sent: Tuesday, April 27, 2004 10:49 AM
To: Windows System Software Devs Interest List
Subject: RE: [ntdev] Help on IoAllocateMdl()

Thanks,

So if I want to use pMdl->Size to figure out how many pages have been
described, should I cast it to USHORT? Like the following:

TotalPages = (((USHORT)(pMdl->Size) - sizeof(MDL)) / sizeof(ULONG));

By definition in WDM.h, the type of pMdl->Size is CSHORT, which is
“short”.

zhong

-----Original Message-----
From: Tony Mason [mailto:xxxxx@osr.com]
Sent: Tuesday, April 27, 2004 9:45 AM
To: Windows System Software Devs Interest List
Subject: RE: [ntdev] Help on IoAllocateMdl()

The MDL in question describes a memory region that is 33,554,432 bytes
long (see the “ByteCount” field.) This requires exactly 8193 page
entries (32768 bytes, not starting on a page boundary) plus the fixed
size (28 byte) MDL structure itself. Thus, the size of the MDL is
32,794 bytes. When you sign extend this, you get -32736.

Regards,

Tony

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of
xxxxx@exgate.tek.com
Sent: Tuesday, April 27, 2004 12:23 PM
To: ntdev redirect
Subject: RE: [ntdev] Help on IoAllocateMdl()

Tony:

I absolutely agree with you. It does not make sense to have a negative
value
for size. But that is why I am asking for help.

Here is the output from WinDbg after I call IoAllocateMdl() in the
following
code snippet:

Name Value
Type
pMdl 0xfec3e000 struct _MDL * struct
_MDL
*
Next 0x00000000 struct _MDL * struct _MDL *
Size -32736 short
MdlFlags 0
short
Process 0x006c0065 struct _EPROCESS * struct
_EPROCESS *
MappedSystemVa 0x00fe0000 void *
StartVa 0x04490000
void
*
ByteCount 0x2000000
unsigned long
ByteOffset 0x40 unsigned
long
pUserVa 0x0449040 unsigned
long *

The following is the code I am executing. The function PciMemLock() is
directly called from the DispatchControl() routine.

NTSTATUS DispatchControl(PDEVICE_OBJECT fdo, PIRP Irp)
{

case PLX_IOCTL_MEMORY_LOCK:
DrvTraceNoInfo((“PLX_IOCTL_MEMORY_LOCK\n”));

if (pdx->devpower > MIN_WORKING_POWER_STATE)
{
pIoBuffer->ReturnCode = ApiPowerDown;
}
else
{
pIoBuffer->ReturnCode = ApiSuccess;
PciMem.UserAddr = (ULONG)pIoBuffer->u.MemLock.pUserVa;
PciMem.Size = pIoBuffer->u.MemLock.Size;
status = PciMemLock(pdx, &PciMem,
pIoBuffer->u.MemLock.Option, stack->FileObject);
}

break;

}

NTSTATUS
PciMemLock(PDEVICE_EXTENSION pdx, PCI_MEMORY * pPciMem, UCHAR Option,
PVOID
pOwner)
{
ULONG * pUserVa = (ULONG*)pPciMem->UserAddr;
ULONG nSize = pPciMem->Size;
MDL_ENTRY *pMdlEntry = NULL;
BOOLEAN bFlag;

DrvTrace(DRV_IOCTL, (“Lock the user memory %p, size %d\n”,pUserVa,
nSize));

pMdlEntry = (MDL_ENTRY*)ExAllocatePoolWithTag(NonPagedPool,
sizeof(MDL_ENTRY), 0x4C4D454D);
if (pMdlEntry == NULL)
{
DrvTrace(DRV_IOCTL, (“ERROR - Unable to build MDL Entry for the
user
buffer.\n”));
return STATUS_INSUFFICIENT_RESOURCES;
}

switch (Option)
{
case USER_BUFFER_ALLOC:
// The buffer must be already allocated by the user application
if ((pUserVa == NULL) || (nSize == 0)) {
DrvTrace(DRV_IOCTL, (“ERROR - The buffer is
uninitialized\n”));
ExFreePool(pMdlEntry);
return STATUS_INVALID_PARAMETER;
}

// Try to allocate MDL for the user buffer
pMdlEntry->pMdl = IoAllocateMdl(
(PVOID)pUserVa,
nSize,
FALSE,
FALSE,
NULL
);

if (pMdlEntry->pMdl == NULL) // WinDbg output
caught here.
{
DrvTrace(DRV_IOCTL, (“ERROR - Unable to build MDL for the
user
buffer.\n”));
ExFreePool(pMdlEntry);
return STATUS_INSUFFICIENT_RESOURCES;
}

// Attempt to lock the user buffer into memory. May raise memory
access violation
// if the memory is not available or can’t access.
bFlag = FALSE;

__try
{
MmProbeAndLockPages(
pMdlEntry->pMdl,
UserMode,
IoModifyAccess
);
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
// Flag the exception
bFlag = TRUE;
}

// Verify that the pages were locked
if (bFlag)
{
DrvTrace(DRV_DMAOPEN, (“ERROR - Unable to lock pages\n”));
IoFreeMdl(
pMdlEntry->pMdl
);
ExFreePool(pMdlEntry);
return STATUS_ACCESS_VIOLATION;
}

break;

case KERNEL_BUFFER_ALLOC_PAGED:

return STATUS_NOT_SUPPORTED;

break;

case KERNEL_BUFFER_ALLOC_NONPAGED:
return STATUS_NOT_SUPPORTED;

break;

default:
return STATUS_INVALID_PARAMETER;
break;
}

pMdlEntry->pOwner = pOwner;
ExInterlockedInsertTailList(
&(pdx->List_Mdl),
&(pMdlEntry->ListEntry),
&(pdx->Lock_MdlList)
);

return STATUS_SUCCESS;
}

Can you see any wrong doing in my code?

Thanks,

zhong

-----Original Message-----
From: Tony Mason [mailto:xxxxx@osr.com]
Sent: Monday, April 26, 2004 5:11 PM
To: Windows System Software Devs Interest List
Subject: RE: [ntdev] Help on IoAllocateMdl()

Size cannot be negative, so your question doesn’t make any sense. Size
is a positive value from 28 to 65535 (28 being the smallest possible
MDL). To go “negative” (that is above 32767 so when you cast from an
unsigned number to a signed number you get sign extension) you would be
describing a memory region that is 8185 pages long ((32768-28)/4) or
just shy of 32MB. The largest possible MDL that can be described then
is thus 16377 pages (67080192 bytes).

Thus, the answer to your question is that it means the memory region you
are attempting to describe is between 3334145 and 67080192 bytes long.
I have not confirmed this, but I wouldn’t be surprised to find out that
the size is truncated if the memory region is LARGER than the 67080192
number.

Regards,

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

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of
xxxxx@exgate.tek.com
Sent: Monday, April 26, 2004 7:44 PM
To: ntdev redirect
Subject: [ntdev] Help on IoAllocateMdl()

When I call IoAllocateMdl() to create MDL for the user memory, sometimes
I
got a negative value for pMdl->Size but IoAllocateMdl() did not fail.
Can
anyone explain it to me? The data type for Size in MDL is CSHORT
(#define
short CSHORT), so the negative value is allowed for the Size. However,
when
a size is negative, how can I use it to determine the size of MDL
allocated?

Thanks,

zhong


Questions? First check the Kernel Driver FAQ at
http://www.osronline.com/article.cfm?id=256

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


Questions? First check the Kernel Driver FAQ at
http://www.osronline.com/article.cfm?id=256

You are currently subscribed to ntdev as: xxxxx@exgate.tek.com
To unsubscribe send a blank email to xxxxx@lists.osr.com


Questions? First check the Kernel Driver FAQ at
http://www.osronline.com/article.cfm?id=256

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


Questions? First check the Kernel Driver FAQ at
http://www.osronline.com/article.cfm?id=256

You are currently subscribed to ntdev as: xxxxx@exgate.tek.com
To unsubscribe send a blank email to xxxxx@lists.osr.com


Questions? First check the Kernel Driver FAQ at
http://www.osronline.com/article.cfm?id=256

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