CAUSE
This behavior may occur because the macro definition of
NdisQueryBufferSafe in the Windows 2000 DDK NDIS.H header file is incorrect. This macro is defined as follows:
#define NdisQueryBufferSafe(_Buffer, _VirtualAddress, _Length,
_Priority) \
{ \
PVOID _VA; \
\
_VA = MmGetSystemAddressForMdlSafe(_Buffer, _Priority); \
if (ARGUMENT_PRESENT(_VirtualAddress)) \
{ \
*(PVOID *)(_VirtualAddress) = _VA; \
} \
*(_Length) = (_VA != NULL) ? MmGetMdlByteCount(_Buffer) : 0; \
}
This macro is properly used only when you want to build non-binary-compatible (!BINARY_COMPATIBLE) NDIS drivers. The problem in the preceding definition of the macro is that
MmGetSystemAddressForMdlSafe is called
unconditionally, regardless of whether the _VirtualAddress argument is
present or not. The driver passes a _VirtualAddress argument
only when it has to copy user data (for example, to coalesce the whole packet or just the first 54 bytes for the MAC, IP, or TCP header). Therefore, by unconditionally calling
MmGetSystemAddressForMdlSafe, performance degradation may result.
RESOLUTION
To resolve this issue, define the macro as follows:
#define NdisQueryBufferSafe(_Buffer, _VirtualAddress, _Length, _Priority)\
{\
if (ARGUMENT_PRESENT(_VirtualAddress))\
{\
*(PVOID *)(_VirtualAddress) = MmGetSystemAddressForMdlSafe(_Buffer,_Priority); \
}\
*(_Length) = MmGetMdlByteCount(_Buffer);\
}
You can either update the %DDKROOT%\INC\DDK\NDIS.H header file of the Windows 2000 DDK or redefine the macro in your project header file.