个人总结NDIS中NDIS_PACKET,NDIS_BUFFER的关系

来源:互联网 发布:如何修复缺少网络协议 编辑:程序博客网 时间:2024/06/05 01:03
//   // NDIS_PACKET结构的定义  //   typedef struct _NDIS_PACKET  {  NDIS_PACKET_PRIVATE Private;  //这个其实是一个链表结构,Private.Head指向第一个链表,Private.Tail指向最后一个  //以下有关于这个结构的解释  union  {  struct // For Connection-less miniports   {  UCHAR MiniportReserved[2*sizeof(PVOID)];  UCHAR WrapperReserved[2*sizeof(PVOID)];  };  struct  {  //   // For de-serialized miniports. And by implication conn-oriented miniports.   // This is for the send-path only. Packets indicated will use WrapperReserved   // instead of WrapperReservedEx   //   UCHAR MiniportReservedEx[3*sizeof(PVOID)];  UCHAR WrapperReservedEx[sizeof(PVOID)];  };  struct  {  UCHAR MacReserved[4*sizeof(PVOID)];  };  };  ULONG_PTR Reserved[2]; // For compatibility with Win  UCHAR ProtocolReserved[1];  } NDIS_PACKET, *PNDIS_PACKET, **PPNDIS_PACKET;  // NDIS_PACKET_PRIVATE 的定义  typedef struct _NDIS_PACKET_PRIVATE  {  UINT PhysicalCount; // number of physical pages in packet.   UINT TotalLength; // Total amount of data in the packet.   PNDIS_BUFFER Head; // 链表指针,指向第一个PNDIS_BUFFER Tail; // 链表指针,指向最后一个  // if Head is NULL the chain is empty; Tail doesn\'t have to be NULL also   PNDIS_PACKET_POOL Pool; // so we know where to free it back to   UINT Count;  ULONG Flags;  BOOLEAN ValidCounts;  UCHAR NdisPacketFlags; // See fPACKET_xxx bits below   USHORT NdisPacketOobOffset;  } NDIS_PACKET_PRIVATE, * PNDIS_PACKET_PRIVATE;  //NDIS_BUFFER定义 其实就是一个内存描述符typedef struct _NDIS_BUFFER {  struct _NDIS_BUFFER *Next; //指向下一个节点的指针PVOID VirtualAddress;      //指向报文首地址PNDIS_BUFFER_POOL Pool;  UINT Length;               //报文数据长度UINT Signature;  } NDIS_BUFFER, * PNDIS_BUFFER;  



注释写的很清楚了  那么他们的关系还是不清楚的话看看附图

 好了  这样一来我们的思路大概清楚了  NDIS_PACKET只不过是一个关于NDIS_BUFFER链表的结构  在NDIS_PACKET中的成员Private中有指向第一个NDIS_BUFFER的指针和指向最后一个NDIS_BUFFER的指针  分别是Private.Head和Private.Tail     而NDIS_BUFFER中就记录了我们数据包的地址和下一个NDIS_BUFFER的地址  操作有很多种方法   由于这些结构体本来对我们是不透明的   所以最安全的方法是用MS提供的一系列函数来操作NDIS_PACKET和NDIS_BUFFER  

    还是拿个例子好说话吧

NDIS_STATUS status ;    PNDIS_BUFFER NdisBuffer ;    UINT TotalPacketLength =, copysize =, DataOffset =, PhysicalBufferCount  ,  BufferCount   ;    PUCHAR mybuffer = NULL ,tembuffer = NULL ;  //假设这个是在PtReceive等函数中得到的PACKETNdisQueryPacket(packet                     //我们先得到第一个NDISBUFFER 的指针           , &PhysicalBufferCount                      , &BufferCount                                   ,&NdisBuffer                               //NdisBuffer就是指向链表头        , &TotalPacketLength        );/*其实也可以不用那么麻烦 直接  NdisBuffer = packet->Private.Head ;就可以取得第一个BUFFER了*/    status = NdisAllocateMemory( &mybuffer, 2048, 0, HighestAcceptableMax );  //分配我们自己的内存块    if( status != NDIS_STATUS_SUCCESS )        return NDIS_STATUS_FAILURE ;    NdisZeroMemory( mybuffer,) ;    NdisQueryBufferSafe(  //取得NDIS_BUFFER描述符中数据的首地址和大小                                NdisBuffer,                                &tembuffer,                                ©size,                                NormalPagePriority    );               //将数据复制到我们的内存中    NdisMoveMemory(mybuffer, tembuffer, copysize) ;    DataOffset = copysize ;    while(1)    {        /*                也可以这样操作而不用NdisGetNextBuffer        if(NdisBuffer->Next == packet->Private.Tail )            break ;        NdisBuffer = NdisBuffer->Next ;        if(pmdl == NULL )           break ;           */        //获得下一个NDIS_BUFFER的的指针    NdisGetNextBuffer(NdisBuffer , &NdisBuffer ) ;        如果指针是NULL  那么表示到链表尾了    if( NdisBuffer == NULL )        break ;    NdisQueryBufferSafe(                                NdisBuffer,                                &tembuffer,                                ©size,                                NormalPagePriority                                ) ;    NdisMoveMemory( mybuffer + DataOffset , tembuffer, copysize) ;    DataOffset += copysize  ;    }//OK  我们要的数据就全部都在我们申请的内存mybuffer 数据大小为DataOffset

转自:http://www.cppblog.com/ay19880703/archive/2008/09/18/62233.aspx

原创粉丝点击