个人总结NDIS中NDIS_PACKET,NDIS_BUFFER的关系
1
//
2 // NDIS_PACKET结构的定义
3 //
4 typedef struct _NDIS_PACKET
5 {
6 NDIS_PACKET_PRIVATE Private;
7 // 这个其实是一个链表结构,Private.Head指向第一个链表,Private.Tail指向最后一个
8 // 以下有关于这个结构的解释
9
10 union
11 {
12 struct // For Connection-less miniports
13 {
14 UCHAR MiniportReserved[ 2 * sizeof (PVOID)];
15 UCHAR WrapperReserved[ 2 * sizeof (PVOID)];
16 };
17
18 struct
19 {
20 //
21 // For de-serialized miniports. And by implication conn-oriented miniports.
22 // This is for the send-path only. Packets indicated will use WrapperReserved
23 // instead of WrapperReservedEx
24 //
25 UCHAR MiniportReservedEx[ 3 * sizeof (PVOID)];
26 UCHAR WrapperReservedEx[ sizeof (PVOID)];
27 };
28
29 struct
30 {
31 UCHAR MacReserved[ 4 * sizeof (PVOID)];
32 };
33 };
34
35 ULONG_PTR Reserved[ 2 ]; // For compatibility with Win95
36 UCHAR ProtocolReserved[ 1 ];
37
38 } NDIS_PACKET, * PNDIS_PACKET, ** PPNDIS_PACKET;
39
40 // NDIS_PACKET_PRIVATE 的定义
41 typedef struct _NDIS_PACKET_PRIVATE
42 {
43 UINT PhysicalCount; // number of physical pages in packet.
44 UINT TotalLength; // Total amount of data in the packet.
45 PNDIS_BUFFER Head; // 链表指针,指向第一个
46 PNDIS_BUFFER Tail; // 链表指针, 指向最后一个
47
48 // if Head is NULL the chain is empty; Tail doesn\'t have to be NULL also
49
50 PNDIS_PACKET_POOL Pool; // so we know where to free it back to
51 UINT Count;
52 ULONG Flags;
53 BOOLEAN ValidCounts;
54 UCHAR NdisPacketFlags; // See fPACKET_xxx bits below
55 USHORT NdisPacketOobOffset;
56 } NDIS_PACKET_PRIVATE, * PNDIS_PACKET_PRIVATE;
57
58 // NDIS_BUFFER定义 其实就是一个内存描述符
59
60 typedef struct _NDIS_BUFFER {
61 struct _NDIS_BUFFER * Next; // 指向下一个节点的指针
62 PVOID VirtualAddress; // 指向报文首地址
63 PNDIS_BUFFER_POOL Pool;
64 UINT Length; // 报文数据长度
65 UINT Signature;
66 } NDIS_BUFFER, * PNDIS_BUFFER;
2 // NDIS_PACKET结构的定义
3 //
4 typedef struct _NDIS_PACKET
5 {
6 NDIS_PACKET_PRIVATE Private;
7 // 这个其实是一个链表结构,Private.Head指向第一个链表,Private.Tail指向最后一个
8 // 以下有关于这个结构的解释
9
10 union
11 {
12 struct // For Connection-less miniports
13 {
14 UCHAR MiniportReserved[ 2 * sizeof (PVOID)];
15 UCHAR WrapperReserved[ 2 * sizeof (PVOID)];
16 };
17
18 struct
19 {
20 //
21 // For de-serialized miniports. And by implication conn-oriented miniports.
22 // This is for the send-path only. Packets indicated will use WrapperReserved
23 // instead of WrapperReservedEx
24 //
25 UCHAR MiniportReservedEx[ 3 * sizeof (PVOID)];
26 UCHAR WrapperReservedEx[ sizeof (PVOID)];
27 };
28
29 struct
30 {
31 UCHAR MacReserved[ 4 * sizeof (PVOID)];
32 };
33 };
34
35 ULONG_PTR Reserved[ 2 ]; // For compatibility with Win95
36 UCHAR ProtocolReserved[ 1 ];
37
38 } NDIS_PACKET, * PNDIS_PACKET, ** PPNDIS_PACKET;
39
40 // NDIS_PACKET_PRIVATE 的定义
41 typedef struct _NDIS_PACKET_PRIVATE
42 {
43 UINT PhysicalCount; // number of physical pages in packet.
44 UINT TotalLength; // Total amount of data in the packet.
45 PNDIS_BUFFER Head; // 链表指针,指向第一个
46 PNDIS_BUFFER Tail; // 链表指针, 指向最后一个
47
48 // if Head is NULL the chain is empty; Tail doesn\'t have to be NULL also
49
50 PNDIS_PACKET_POOL Pool; // so we know where to free it back to
51 UINT Count;
52 ULONG Flags;
53 BOOLEAN ValidCounts;
54 UCHAR NdisPacketFlags; // See fPACKET_xxx bits below
55 USHORT NdisPacketOobOffset;
56 } NDIS_PACKET_PRIVATE, * PNDIS_PACKET_PRIVATE;
57
58 // NDIS_BUFFER定义 其实就是一个内存描述符
59
60 typedef struct _NDIS_BUFFER {
61 struct _NDIS_BUFFER * Next; // 指向下一个节点的指针
62 PVOID VirtualAddress; // 指向报文首地址
63 PNDIS_BUFFER_POOL Pool;
64 UINT Length; // 报文数据长度
65 UINT Signature;
66 } 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
还是拿个例子好说话吧
1
NDIS_STATUS status ;
2 PNDIS_BUFFER NdisBuffer ;
3 UINT TotalPacketLength = 0 , copysize = 0 , DataOffset = 0 , PhysicalBufferCount , BufferCount ;
4 PUCHAR mybuffer = NULL ,tembuffer = NULL ;
5
6 // 假设这个是在PtReceive等函数中得到的PACKET
7 NdisQueryPacket(packet // 我们先得到第一个NDISBUFFER 的指针
8 , & PhysicalBufferCount
9 , & BufferCount
10 , & NdisBuffer // NdisBuffer就是指向链表头
11 , & TotalPacketLength
12 );
13 /*
14 其实也可以不用那么麻烦 直接 NdisBuffer = packet->Private.Head ;就可以取得第一个BUFFER了
15 */
16
17 status = NdisAllocateMemory( & mybuffer, 2048 , 0 , HighestAcceptableMax ); // 分配我们自己的内存块
18
19 if ( status != NDIS_STATUS_SUCCESS )
20 return NDIS_STATUS_FAILURE ;
21
22 NdisZeroMemory( mybuffer, 2048 ) ;
23
24 NdisQueryBufferSafe( // 取得NDIS_BUFFER描述符中数据的首地址和大小
25 NdisBuffer,
26 & tembuffer,
27 & copysize,
28 NormalPagePriority
29 );
30
31 // 将数据复制到我们的内存中
32 NdisMoveMemory(mybuffer, tembuffer, copysize) ;
33
34 DataOffset = copysize ;
35
36 while ( 1 )
37 {
38 /*
39 也可以这样操作而不用NdisGetNextBuffer
40 if(NdisBuffer->Next == packet->Private.Tail )
41 break ;
42
43 NdisBuffer = NdisBuffer->Next ;
44
45 if(pmdl == NULL )
46 break ;
47 */
48 // 获得下一个NDIS_BUFFER的的指针
49 NdisGetNextBuffer(NdisBuffer , & NdisBuffer ) ;
50 如果指针是NULL 那么表示到链表尾了
51 if ( NdisBuffer == NULL )
52 break ;
53
54 NdisQueryBufferSafe(
55 NdisBuffer,
56 & tembuffer,
57 & copysize,
58 NormalPagePriority
59 ) ;
60
61 NdisMoveMemory( mybuffer + DataOffset , tembuffer, copysize) ;
62
63 DataOffset += copysize ;
64
65 }
66
67 // OK 我们要的数据就全部都在我们申请的内存mybuffer 数据大小为DataOffset
2 PNDIS_BUFFER NdisBuffer ;
3 UINT TotalPacketLength = 0 , copysize = 0 , DataOffset = 0 , PhysicalBufferCount , BufferCount ;
4 PUCHAR mybuffer = NULL ,tembuffer = NULL ;
5
6 // 假设这个是在PtReceive等函数中得到的PACKET
7 NdisQueryPacket(packet // 我们先得到第一个NDISBUFFER 的指针
8 , & PhysicalBufferCount
9 , & BufferCount
10 , & NdisBuffer // NdisBuffer就是指向链表头
11 , & TotalPacketLength
12 );
13 /*
14 其实也可以不用那么麻烦 直接 NdisBuffer = packet->Private.Head ;就可以取得第一个BUFFER了
15 */
16
17 status = NdisAllocateMemory( & mybuffer, 2048 , 0 , HighestAcceptableMax ); // 分配我们自己的内存块
18
19 if ( status != NDIS_STATUS_SUCCESS )
20 return NDIS_STATUS_FAILURE ;
21
22 NdisZeroMemory( mybuffer, 2048 ) ;
23
24 NdisQueryBufferSafe( // 取得NDIS_BUFFER描述符中数据的首地址和大小
25 NdisBuffer,
26 & tembuffer,
27 & copysize,
28 NormalPagePriority
29 );
30
31 // 将数据复制到我们的内存中
32 NdisMoveMemory(mybuffer, tembuffer, copysize) ;
33
34 DataOffset = copysize ;
35
36 while ( 1 )
37 {
38 /*
39 也可以这样操作而不用NdisGetNextBuffer
40 if(NdisBuffer->Next == packet->Private.Tail )
41 break ;
42
43 NdisBuffer = NdisBuffer->Next ;
44
45 if(pmdl == NULL )
46 break ;
47 */
48 // 获得下一个NDIS_BUFFER的的指针
49 NdisGetNextBuffer(NdisBuffer , & NdisBuffer ) ;
50 如果指针是NULL 那么表示到链表尾了
51 if ( NdisBuffer == NULL )
52 break ;
53
54 NdisQueryBufferSafe(
55 NdisBuffer,
56 & tembuffer,
57 & copysize,
58 NormalPagePriority
59 ) ;
60
61 NdisMoveMemory( mybuffer + DataOffset , tembuffer, copysize) ;
62
63 DataOffset += copysize ;
64
65 }
66
67 // OK 我们要的数据就全部都在我们申请的内存mybuffer 数据大小为DataOffset