2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS TCP/IP protocol driver
5 * PURPOSE: Miscellaneous operations on NDIS_BUFFERs and packets.
6 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
8 * CSH 01/08-2000 Created
13 VOID
XNdisGetFirstBufferFromPacket(PNDIS_PACKET Packet
,
14 PNDIS_BUFFER
*FirstBuffer
,
16 PUINT FirstBufferLength
,
17 PUINT TotalBufferLength
)
21 _Buffer
= (Packet
)->Private
.Head
;
22 *(FirstBuffer
) = _Buffer
;
23 *(FirstBufferVA
) = MmGetMdlVirtualAddress(_Buffer
);
24 if (_Buffer
!= NULL
) {
25 *(FirstBufferLength
) = MmGetMdlByteCount(_Buffer
);
26 _Buffer
= _Buffer
->Next
;
28 *(FirstBufferLength
) = 0;
29 *(TotalBufferLength
) = *(FirstBufferLength
);
30 while (_Buffer
!= NULL
) {
31 *(TotalBufferLength
) += MmGetMdlByteCount(_Buffer
);
32 _Buffer
= _Buffer
->Next
;
41 PVOID
*VirtualAddress
,
45 * Queries an NDIS buffer for information
47 * Buffer = Pointer to NDIS buffer to query
48 * VirtualAddress = Address of buffer to place virtual address
49 * Length = Address of buffer to place length of buffer
52 if (VirtualAddress
!= NULL
)
53 *(PVOID
*)VirtualAddress
= Buffer
->MappedSystemVa
;
55 *Length
= ((PMDL
)Buffer
)->ByteCount
;
58 __inline INT
SkipToOffset(
64 * FUNCTION: Skip Offset bytes into a buffer chain
66 * Buffer = Pointer to NDIS buffer
67 * Offset = Number of bytes to skip
68 * Data = Address of a pointer that on return will contain the
69 * address of the offset in the buffer
70 * Size = Address of a pointer that on return will contain the
71 * size of the destination buffer
73 * Offset into buffer, -1 if buffer chain was smaller than Offset bytes
83 XNdisQueryBuffer(Buffer
, (PVOID
)Data
, Size
);
86 *Data
= (PCHAR
)((ULONG_PTR
) *Data
+ Offset
);
93 NdisGetNextBuffer(Buffer
, &Buffer
);
100 UINT
CopyBufferToBufferChain(
101 PNDIS_BUFFER DstBuffer
,
106 * FUNCTION: Copies data from a buffer to an NDIS buffer chain
108 * DstBuffer = Pointer to destination NDIS buffer
109 * DstOffset = Destination start offset
110 * SrcData = Pointer to source buffer
111 * Length = Number of bytes to copy
113 * Number of bytes copied to destination buffer
115 * The number of bytes copied may be limited by the destination
119 UINT BytesCopied
, BytesToCopy
, DstSize
;
122 TI_DbgPrint(DEBUG_PBUFFER
, ("DstBuffer (0x%X) DstOffset (0x%X) SrcData (0x%X) Length (%d)\n", DstBuffer
, DstOffset
, SrcData
, Length
));
124 /* Skip DstOffset bytes in the destination buffer chain */
125 if (SkipToOffset(DstBuffer
, DstOffset
, &DstData
, &DstSize
) == -1)
128 /* Start copying the data */
131 BytesToCopy
= MIN(DstSize
, Length
);
133 RtlCopyMemory((PVOID
)DstData
, (PVOID
)SrcData
, BytesToCopy
);
134 BytesCopied
+= BytesToCopy
;
135 SrcData
= (PCHAR
)((ULONG_PTR
)SrcData
+ BytesToCopy
);
137 Length
-= BytesToCopy
;
141 DstSize
-= BytesToCopy
;
143 /* No more bytes in desination buffer. Proceed to
144 the next buffer in the destination buffer chain */
145 NdisGetNextBuffer(DstBuffer
, &DstBuffer
);
149 XNdisQueryBuffer(DstBuffer
, (PVOID
)&DstData
, &DstSize
);
157 UINT
CopyBufferChainToBuffer(
159 PNDIS_BUFFER SrcBuffer
,
163 * FUNCTION: Copies data from an NDIS buffer chain to a buffer
165 * DstData = Pointer to destination buffer
166 * SrcBuffer = Pointer to source NDIS buffer
167 * SrcOffset = Source start offset
168 * Length = Number of bytes to copy
170 * Number of bytes copied to destination buffer
172 * The number of bytes copied may be limited by the source
176 UINT BytesCopied
, BytesToCopy
, SrcSize
;
179 TI_DbgPrint(DEBUG_PBUFFER
, ("DstData 0x%X SrcBuffer 0x%X SrcOffset 0x%X Length %d\n",DstData
,SrcBuffer
, SrcOffset
, Length
));
181 /* Skip SrcOffset bytes in the source buffer chain */
182 if (SkipToOffset(SrcBuffer
, SrcOffset
, &SrcData
, &SrcSize
) == -1)
185 /* Start copying the data */
188 BytesToCopy
= MIN(SrcSize
, Length
);
190 TI_DbgPrint(DEBUG_PBUFFER
, ("Copying (%d) bytes from 0x%X to 0x%X\n", BytesToCopy
, SrcData
, DstData
));
192 RtlCopyMemory((PVOID
)DstData
, (PVOID
)SrcData
, BytesToCopy
);
193 BytesCopied
+= BytesToCopy
;
194 DstData
= (PCHAR
)((ULONG_PTR
)DstData
+ BytesToCopy
);
196 Length
-= BytesToCopy
;
200 SrcSize
-= BytesToCopy
;
202 /* No more bytes in source buffer. Proceed to
203 the next buffer in the source buffer chain */
204 NdisGetNextBuffer(SrcBuffer
, &SrcBuffer
);
208 XNdisQueryBuffer(SrcBuffer
, (PVOID
)&SrcData
, &SrcSize
);
216 UINT
CopyPacketToBuffer(
218 PNDIS_PACKET SrcPacket
,
222 * FUNCTION: Copies data from an NDIS packet to a buffer
224 * DstData = Pointer to destination buffer
225 * SrcPacket = Pointer to source NDIS packet
226 * SrcOffset = Source start offset
227 * Length = Number of bytes to copy
229 * Number of bytes copied to destination buffer
231 * The number of bytes copied may be limited by the source
235 PNDIS_BUFFER FirstBuffer
;
240 TI_DbgPrint(DEBUG_PBUFFER
, ("DstData (0x%X) SrcPacket (0x%X) SrcOffset (0x%X) Length (%d)\n", DstData
, SrcPacket
, SrcOffset
, Length
));
242 XNdisGetFirstBufferFromPacket(SrcPacket
,
248 return CopyBufferChainToBuffer(DstData
, FirstBuffer
, SrcOffset
, Length
);
252 UINT
CopyPacketToBufferChain(
253 PNDIS_BUFFER DstBuffer
,
255 PNDIS_PACKET SrcPacket
,
259 * FUNCTION: Copies data from an NDIS packet to an NDIS buffer chain
261 * DstBuffer = Pointer to destination NDIS buffer
262 * DstOffset = Destination start offset
263 * SrcPacket = Pointer to source NDIS packet
264 * SrcOffset = Source start offset
265 * Length = Number of bytes to copy
267 * Number of bytes copied to destination buffer
269 * The number of bytes copied may be limited by the source and
270 * destination buffer sizes
273 PNDIS_BUFFER SrcBuffer
;
274 PCHAR DstData
, SrcData
;
275 UINT DstSize
, SrcSize
;
278 TI_DbgPrint(DEBUG_PBUFFER
, ("DstBuffer (0x%X) DstOffset (0x%X) SrcPacket (0x%X) SrcOffset (0x%X) Length (%d)\n", DstBuffer
, DstOffset
, SrcPacket
, SrcOffset
, Length
));
280 /* Skip DstOffset bytes in the destination buffer chain */
281 XNdisQueryBuffer(DstBuffer
, (PVOID
)&DstData
, &DstSize
);
282 if (SkipToOffset(DstBuffer
, DstOffset
, &DstData
, &DstSize
) == -1)
285 /* Skip SrcOffset bytes in the source packet */
286 XNdisGetFirstBufferFromPacket(SrcPacket
, &SrcBuffer
, (PVOID
*)&SrcData
, &SrcSize
, &Total
);
287 if (SkipToOffset(SrcBuffer
, SrcOffset
, &SrcData
, &SrcSize
) == -1)
292 /* Find out how many bytes we can copy at one time */
293 if (Length
< SrcSize
)
300 RtlCopyMemory((PVOID
)DstData
, (PVOID
)SrcData
, Count
);
309 /* No more bytes in destination buffer. Proceed to
310 the next buffer in the destination buffer chain */
311 NdisGetNextBuffer(DstBuffer
, &DstBuffer
);
315 XNdisQueryBuffer(DstBuffer
, (PVOID
)&DstData
, &DstSize
);
320 /* No more bytes in source buffer. Proceed to
321 the next buffer in the source buffer chain */
322 NdisGetNextBuffer(SrcBuffer
, &SrcBuffer
);
326 XNdisQueryBuffer(SrcBuffer
, (PVOID
)&SrcData
, &SrcSize
);
339 * FUNCTION: Adjusts the amount of unused space at the beginning of the packet
341 * Packet = Pointer to packet
342 * Available = Number of bytes available at start of first buffer
343 * Needed = Number of bytes needed for the header
345 * Pointer to start of packet
348 PNDIS_BUFFER NdisBuffer
;
351 TI_DbgPrint(DEBUG_PBUFFER
, ("Available = %d, Needed = %d.\n", Available
, Needed
));
353 Adjust
= Available
- Needed
;
355 NdisQueryPacket(Packet
, NULL
, NULL
, &NdisBuffer
, NULL
);
357 /* If Adjust is zero there is no need to adjust this packet as
358 there is no additional space at start the of first buffer */
360 NdisBuffer
->MappedSystemVa
= (PVOID
) ((ULONG_PTR
)(NdisBuffer
->MappedSystemVa
) + Adjust
);
361 NdisBuffer
->ByteOffset
+= Adjust
;
362 NdisBuffer
->ByteCount
-= Adjust
;
365 return NdisBuffer
->MappedSystemVa
;
373 * FUNCTION: Resizes an NDIS packet
375 * Packet = Pointer to packet
376 * Size = Number of bytes in first buffer
378 * Previous size of first buffer
381 PNDIS_BUFFER NdisBuffer
;
384 NdisQueryPacket(Packet
, NULL
, NULL
, &NdisBuffer
, NULL
);
386 OldSize
= NdisBuffer
->ByteCount
;
389 NdisBuffer
->ByteCount
= Size
;
394 NDIS_STATUS
PrependPacket( PNDIS_PACKET Packet
, PCHAR Data
, UINT Length
,
401 NewBuf
= PoolAllocateBuffer( Length
);
402 if( !NewBuf
) return STATUS_NO_MEMORY
;
403 RtlCopyMemory( NewBuf
, Data
, Length
);
404 } else NewBuf
= Data
;
406 NdisAllocateBuffer( &Status
, &Buffer
, GlobalBufferPool
, Data
, Length
);
407 if( Status
!= NDIS_STATUS_SUCCESS
) return Status
;
409 NdisChainBufferAtFront( Packet
, Buffer
);
411 return STATUS_SUCCESS
;
414 void GetDataPtr( PNDIS_PACKET Packet
,
420 NdisQueryPacket(Packet
, NULL
, NULL
, &Buffer
, NULL
);
421 if( !Buffer
) return;
422 SkipToOffset( Buffer
, Offset
, DataOut
, Size
);
425 NDIS_STATUS
AllocatePacketWithBufferX( PNDIS_PACKET
*NdisPacket
,
426 PCHAR Data
, UINT Len
,
427 PCHAR File
, UINT Line
) {
433 NewData
= ExAllocatePool( NonPagedPool
, Len
);
434 if( !NewData
) return NDIS_STATUS_NOT_ACCEPTED
; // XXX
435 TrackWithTag(EXALLOC_TAG
, NewData
, File
, Line
);
438 RtlCopyMemory(NewData
, Data
, Len
);
440 NdisAllocatePacket( &Status
, &Packet
, GlobalPacketPool
);
441 if( Status
!= NDIS_STATUS_SUCCESS
) {
442 ExFreePool( NewData
);
445 TrackWithTag(NDIS_PACKET_TAG
, Packet
, File
, Line
);
447 NdisAllocateBuffer( &Status
, &Buffer
, GlobalBufferPool
, NewData
, Len
);
448 if( Status
!= NDIS_STATUS_SUCCESS
) {
449 ExFreePool( NewData
);
450 FreeNdisPacket( Packet
);
452 TrackWithTag(NDIS_BUFFER_TAG
, Buffer
, File
, Line
);
454 NdisChainBufferAtFront( Packet
, Buffer
);
455 *NdisPacket
= Packet
;
457 return NDIS_STATUS_SUCCESS
;
462 ( PNDIS_PACKET Packet
,
466 * FUNCTION: Frees an NDIS packet
468 * Packet = Pointer to NDIS packet to be freed
471 PNDIS_BUFFER Buffer
, NextBuffer
;
473 TI_DbgPrint(DEBUG_PBUFFER
, ("Packet (0x%X)\n", Packet
));
475 /* Free all the buffers in the packet first */
476 NdisQueryPacket(Packet
, NULL
, NULL
, &Buffer
, NULL
);
477 for (; Buffer
!= NULL
; Buffer
= NextBuffer
) {
481 NdisGetNextBuffer(Buffer
, &NextBuffer
);
482 XNdisQueryBuffer(Buffer
, &Data
, &Length
);
483 UntrackFL(File
,Line
,Buffer
);
484 NdisFreeBuffer(Buffer
);
485 UntrackFL(File
,Line
,Data
);
489 /* Finally free the NDIS packet discriptor */
490 UntrackFL(File
,Line
,Packet
);
491 NdisFreePacket(Packet
);