- //
- // 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等函数中得到的PACKET
- NdisQueryPacket(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