1.6.3.2     NPF_GetDeviceMTU函数

函数获得最大传输单元(MTU),主要调用NdisRequest函数实现。对于各种错误情况,假设为以太网,假设为MTU1514个字节长度。

函数代码如下:

NTSTATUS

NPF_GetDeviceMTU(

               IN POPEN_INSTANCE pOpen,

               IN PIRP pIrp,

               OUT PUINT  pMtu)

{

    PLIST_ENTRY        RequestListEntry;

     PINTERNAL_REQUEST  MaxSizeReq;

     NDIS_STATUS        ReqStatus;

 

     ASSERT(pOpen != NULL);

     ASSERT(pIrp != NULL);

     ASSERT(pMtu != NULL);

 

/* 从双向链表中移出第一个元素*/

     RequestListEntry = ExInterlockedRemoveHeadList(

&pOpen->RequestList, &pOpen->RequestSpinLock);

 

     if (RequestListEntry == NULL)

     {

         // 错误,假设为以太网,设为1514个字节长度,函数返回

         *pMtu = 1514;

         return STATUS_SUCCESS;

     }

 

     MaxSizeReq = CONTAINING_RECORD(RequestListEntry, INTERNAL_REQUEST, ListElement);

     /* 设置Request成员的各参数*/

     MaxSizeReq->Request.RequestType = NdisRequestQueryInformation;

     MaxSizeReq->Request.DATA.QUERY_INFORMATION.Oid = OID_GEN_MAXIMUM_TOTAL_SIZE;

 

     MaxSizeReq->Request.DATA.QUERY_INFORMATION.InformationBuffer = pMtu;

     MaxSizeReq->Request.DATA.QUERY_INFORMATION.InformationBufferLength =

sizeof (*pMtu);

 

     NdisResetEvent(&MaxSizeReq->InternalRequestCompletedEvent);

 

     /* 提交请求*/

     NdisRequest(

         &ReqStatus,

         pOpen->AdapterHandle,

         &MaxSizeReq->Request);

 

     if (ReqStatus == NDIS_STATUS_PENDING)

     {// 挂起,等待请求完成

         NdisWaitEvent(&MaxSizeReq->InternalRequestCompletedEvent, 0);

         ReqStatus = MaxSizeReq->RequestStatus;

     }

 

/* 在双向链表尾部原子插入一个元素,因为前面移出了该请求*/

     ExInterlockedInsertTailList(&pOpen->RequestList, &MaxSizeReq->ListElement, &pOpen->RequestSpinLock);

 

     if (ReqStatus == NDIS_STATUS_SUCCESS)

     {// 成功,返回

         return STATUS_SUCCESS;

     }

     else

     {

         // 错误,假设为以太网,设为1514个字节长度,函数返回

         *pMtu = 1514;

         return STATUS_SUCCESS;

     }

}

CONTAINING_RECORD返回一个结构体实例的基地址,参数给定了该结构体类型、包含在该结构体中一个成员的地址与一个实例。宏原型如下:
PCHAR CONTAINING_RECORD(
IN PCHAR  Address,
IN TYPE  Type,
       IN PCHAR  Field
);
参数Address是指向Type类型结构体一个实例的一个成员指针。参数Type 是需要返回结构体基地址的类型名。参数Field是被Address指向的成员名称,该成员被包含在Type类型中。
返回包含Field成员的结构体的基地址。
参看下面代码来理解该宏定义
PLIST_ENTRY         RequestListEntry;

PINTERNAL_REQUEST   MaxSizeReq;

 

/* 从双向链表中移出第一个元素*/

RequestListEntry = ExInterlockedRemoveHeadList(

&pOpen->RequestList, &pOpen->RequestSpinLock);

 

MaxSizeReq=CONTAINING_RECORD(

RequestListEntry, INTERNAL_REQUEST, ListElement);

 

typedef struct _INTERNAL_REQUEST {

LIST_ENTRY     ListElement;

NDIS_EVENT       InternalRequestCompletedEvent;

NDIS_REQUEST     Request;

NDIS_STATUS      RequestStatus;

} INTERNAL_REQUEST, *PINTERNAL_REQUEST;

也就是我们知道结构体INTERNAL_REQUEST一个实例中的一个成员ListElement地址 RequestListEntry 需要获得包含该成员实例的INTERNAL_REQUEST结构体的实例的地址MaxSizeReq

 

本文出自 “千江月” 博客,请务必保留此出处http://eslxf.blog.51cto.com/918801/210889