2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS NDIS library
5 * PURPOSE: Buffer management routines
6 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
8 * CSH 01/08-2000 Created
14 __inline ULONG SkipToOffset(
20 * FUNCTION: Skips Offset bytes into a buffer chain
22 * Buffer = Pointer to NDIS buffer
23 * Offset = Number of bytes to skip
24 * Data = Address of a pointer that on return will contain the
25 * address of the offset in the buffer
26 * Size = Address of a pointer that on return will contain the
27 * size of the destination buffer
29 * Offset into buffer, -1 if buffer chain was smaller than Offset bytes
39 NdisQueryBuffer(Buffer, (PVOID)Data, Size);
42 ((ULONG_PTR)*Data) += Offset;
49 NdisGetNextBuffer(Buffer, &Buffer);
56 UINT CopyBufferToBufferChain(
57 PNDIS_BUFFER DstBuffer,
62 * FUNCTION: Copies data from a buffer to an NDIS buffer chain
64 * DstBuffer = Pointer to destination NDIS buffer
65 * DstOffset = Destination start offset
66 * SrcData = Pointer to source buffer
67 * Length = Number of bytes to copy
69 * Number of bytes copied to destination buffer
71 * The number of bytes copied may be limited by the destination
75 UINT BytesCopied, BytesToCopy, DstSize;
78 NDIS_DbgPrint(MAX_TRACE, ("DstBuffer (0x%X) DstOffset (0x%X) SrcData (0x%X) Length (%d)\n", DstBuffer, DstOffset, SrcData, Length));
80 /* Skip DstOffset bytes in the destination buffer chain */
81 if (SkipToOffset(DstBuffer, DstOffset, &DstData, &DstSize) == -1)
84 /* Start copying the data */
87 BytesToCopy = MIN(DstSize, Length);
89 RtlCopyMemory((PVOID)DstData, (PVOID)SrcData, BytesToCopy);
90 BytesCopied += BytesToCopy;
91 (ULONG_PTR)SrcData += BytesToCopy;
93 Length -= BytesToCopy;
97 DstSize -= BytesToCopy;
99 /* No more bytes in desination buffer. Proceed to
100 the next buffer in the destination buffer chain */
101 NdisGetNextBuffer(DstBuffer, &DstBuffer);
105 NdisQueryBuffer(DstBuffer, (PVOID)&DstData, &DstSize);
113 UINT CopyBufferChainToBuffer(
115 PNDIS_BUFFER SrcBuffer,
119 * FUNCTION: Copies data from an NDIS buffer chain to a buffer
121 * DstData = Pointer to destination buffer
122 * SrcBuffer = Pointer to source NDIS buffer
123 * SrcOffset = Source start offset
124 * Length = Number of bytes to copy
126 * Number of bytes copied to destination buffer
128 * The number of bytes copied may be limited by the source
132 UINT BytesCopied, BytesToCopy, SrcSize;
135 NDIS_DbgPrint(MAX_TRACE, ("DstData 0x%X SrcBuffer 0x%X SrcOffset 0x%X Length %d\n",DstData,SrcBuffer, SrcOffset, Length));
137 /* Skip SrcOffset bytes in the source buffer chain */
138 if (SkipToOffset(SrcBuffer, SrcOffset, &SrcData, &SrcSize) == -1)
141 /* Start copying the data */
144 BytesToCopy = MIN(SrcSize, Length);
146 NDIS_DbgPrint(MAX_TRACE, ("Copying (%d) bytes from 0x%X to 0x%X\n", BytesToCopy, SrcData, DstData));
148 RtlCopyMemory((PVOID)DstData, (PVOID)SrcData, BytesToCopy);
149 BytesCopied += BytesToCopy;
150 (ULONG_PTR)DstData += BytesToCopy;
152 Length -= BytesToCopy;
156 SrcSize -= BytesToCopy;
158 /* No more bytes in source buffer. Proceed to
159 the next buffer in the source buffer chain */
160 NdisGetNextBuffer(SrcBuffer, &SrcBuffer);
164 NdisQueryBuffer(SrcBuffer, (PVOID)&SrcData, &SrcSize);
172 UINT CopyPacketToBuffer(
174 PNDIS_PACKET SrcPacket,
178 * FUNCTION: Copies data from an NDIS packet to a buffer
180 * DstData = Pointer to destination buffer
181 * SrcPacket = Pointer to source NDIS packet
182 * SrcOffset = Source start offset
183 * Length = Number of bytes to copy
185 * Number of bytes copied to destination buffer
187 * The number of bytes copied may be limited by the source
191 PNDIS_BUFFER FirstBuffer;
196 NDIS_DbgPrint(MAX_TRACE, ("DstData (0x%X) SrcPacket (0x%X) SrcOffset (0x%X) Length (%d)\n", DstData, SrcPacket, SrcOffset, Length));
198 NdisGetFirstBufferFromPacket(SrcPacket,
204 return CopyBufferChainToBuffer(DstData, FirstBuffer, SrcOffset, Length);
208 UINT CopyPacketToBufferChain(
209 PNDIS_BUFFER DstBuffer,
211 PNDIS_PACKET SrcPacket,
215 * FUNCTION: Copies data from an NDIS packet to an NDIS buffer chain
217 * DstBuffer = Pointer to destination NDIS buffer
218 * DstOffset = Destination start offset
219 * SrcPacket = Pointer to source NDIS packet
220 * SrcOffset = Source start offset
221 * Length = Number of bytes to copy
223 * Number of bytes copied to destination buffer
225 * The number of bytes copied may be limited by the source and
226 * destination buffer sizes
229 PNDIS_BUFFER SrcBuffer;
230 PUCHAR DstData, SrcData;
231 UINT DstSize, SrcSize;
234 NDIS_DbgPrint(MAX_TRACE, ("DstBuffer (0x%X) DstOffset (0x%X) SrcPacket (0x%X) SrcOffset (0x%X) Length (%d)\n", DstBuffer, DstOffset, SrcPacket, SrcOffset, Length));
236 /* Skip DstOffset bytes in the destination buffer chain */
237 NdisQueryBuffer(DstBuffer, (PVOID)&DstData, &DstSize);
238 if (SkipToOffset(DstBuffer, DstOffset, &DstData, &DstSize) == -1)
241 /* Skip SrcOffset bytes in the source packet */
242 NdisGetFirstBufferFromPacket(SrcPacket, &SrcBuffer, (PVOID)&SrcData, &SrcSize, &Total);
243 if (SkipToOffset(SrcBuffer, SrcOffset, &SrcData, &SrcSize) == -1)
248 /* Find out how many bytes we can copy at one time */
249 if (Length < SrcSize)
256 RtlCopyMemory((PVOID)DstData, (PVOID)SrcData, Count);
265 /* No more bytes in destination buffer. Proceed to
266 the next buffer in the destination buffer chain */
267 NdisGetNextBuffer(DstBuffer, &DstBuffer);
271 NdisQueryBuffer(DstBuffer, (PVOID)&DstData, &DstSize);
276 /* No more bytes in source buffer. Proceed to
277 the next buffer in the source buffer chain */
278 NdisGetNextBuffer(SrcBuffer, &SrcBuffer);
282 NdisQueryBuffer(SrcBuffer, (PVOID)&SrcData, &SrcSize);
293 NdisAdjustBufferLength(
294 IN PNDIS_BUFFER Buffer,
297 * FUNCTION: Modifies the length of an NDIS buffer
299 * Buffer = Pointer to NDIS buffer descriptor
300 * Length = New size of buffer
303 Buffer->ByteCount = Length;
309 NDIS_BUFFER_TO_SPAN_PAGES(
310 IN PNDIS_BUFFER Buffer)
312 * FUNCTION: Determines how many physical pages a buffer is made of
314 * Buffer = Pointer to NDIS buffer descriptor
317 if (MmGetMdlByteCount(Buffer) == 0)
320 return ADDRESS_AND_SIZE_TO_SPAN_PAGES(
321 MmGetMdlVirtualAddress(Buffer),
322 MmGetMdlByteCount(Buffer));
329 OUT PNDIS_STATUS Status,
330 OUT PNDIS_BUFFER * Buffer,
331 IN NDIS_HANDLE PoolHandle,
332 IN PVOID VirtualAddress,
335 * FUNCTION: Allocates an NDIS buffer descriptor
337 * Status = Address of buffer for status
338 * Buffer = Address of buffer for NDIS buffer descriptor
339 * PoolHandle = Handle returned by NdisAllocateBufferPool
340 * VirtualAddress = Pointer to virtual address of data buffer
341 * Length = Number of bytes in data buffer
345 PNETWORK_HEADER Temp;
346 PNDIS_BUFFER_POOL Pool = (PNDIS_BUFFER_POOL)PoolHandle;
348 NDIS_DbgPrint(MAX_TRACE, ("Status (0x%X) Buffer (0x%X) PoolHandle (0x%X) "
349 "VirtualAddress (0x%X) Length (%d)\n",
350 Status, Buffer, PoolHandle, VirtualAddress, Length));
352 KeAcquireSpinLock(&Pool->SpinLock, &OldIrql);
354 if (Pool->FreeList) {
355 Temp = Pool->FreeList;
356 Pool->FreeList = Temp->Next;
358 KeReleaseSpinLock(&Pool->SpinLock, OldIrql);
363 MmInitializeMdl(&Temp->Mdl, VirtualAddress, Length);
364 Temp->Mdl.MdlFlags |= (MDL_SOURCE_IS_NONPAGED_POOL | MDL_ALLOCATED_FIXED_SIZE);
365 Temp->Mdl.MappedSystemVa = VirtualAddress;
367 Temp->Mdl.Next = (PMDL)NULL;
368 Temp->Mdl.Size = (CSHORT)(sizeof(MDL) +
369 (ADDRESS_AND_SIZE_TO_SPAN_PAGES(VirtualAddress, Length) * sizeof(ULONG)));
370 Temp->Mdl.MdlFlags = (MDL_SOURCE_IS_NONPAGED_POOL | MDL_ALLOCATED_FIXED_SIZE);
371 ; Temp->Mdl.StartVa = (PVOID)PAGE_ROUND_DOWN(VirtualAddress);
372 Temp->Mdl.ByteOffset = (ULONG_PTR)(VirtualAddress - PAGE_ROUND_DOWN(VirtualAddress));
373 Temp->Mdl.ByteCount = Length;
374 Temp->Mdl.MappedSystemVa = VirtualAddress;
376 //Temp->Mdl.Process = PsGetCurrentProcess();
378 Temp->Mdl.Process = NULL;
382 Temp->BufferPool = Pool;
384 *Buffer = (PNDIS_BUFFER)Temp;
385 *Status = NDIS_STATUS_SUCCESS;
387 KeReleaseSpinLock(&Pool->SpinLock, OldIrql);
388 *Status = NDIS_STATUS_FAILURE;
395 NdisAllocateBufferPool(
396 OUT PNDIS_STATUS Status,
397 OUT PNDIS_HANDLE PoolHandle,
398 IN UINT NumberOfDescriptors)
400 * FUNCTION: Allocates storage for an NDIS buffer pool
402 * Status = Address of buffer for status
403 * PoolHandle = Address of buffer for pool handle
404 * NumberOfDescriptors = Size of buffer pool in number of descriptors
408 PNDIS_BUFFER_POOL Pool;
409 PNETWORK_HEADER Buffer;
411 NDIS_DbgPrint(MAX_TRACE, ("Status (0x%X) PoolHandle (0x%X) NumberOfDescriptors (%d).\n",
412 Status, PoolHandle, NumberOfDescriptors));
414 Pool = ExAllocatePool(NonPagedPool,
415 sizeof(NDIS_BUFFER_POOL) +
416 sizeof(NETWORK_HEADER) *
417 NumberOfDescriptors);
419 KeInitializeSpinLock(&Pool->SpinLock);
421 if (NumberOfDescriptors > 0) {
422 Buffer = &Pool->Buffers[0];
423 Pool->FreeList = Buffer;
424 for (i = 1; i < NumberOfDescriptors; i++) {
425 Buffer->Next = &Pool->Buffers[i];
426 Buffer = Buffer->Next;
430 Pool->FreeList = NULL;
432 *Status = NDIS_STATUS_SUCCESS;
433 *PoolHandle = (PNDIS_HANDLE)Pool;
435 *Status = NDIS_STATUS_RESOURCES;
442 OUT PNDIS_STATUS Status,
443 OUT PNDIS_PACKET * Packet,
444 IN NDIS_HANDLE PoolHandle)
446 * FUNCTION: Allocates an NDIS packet descriptor
448 * Status = Address of buffer for status
449 * Packet = Address of buffer for packet descriptor
450 * PoolHandle = Handle returned by NdisAllocatePacketPool
455 PNDIS_PACKET_POOL Pool = (PNDIS_PACKET_POOL)PoolHandle;
457 NDIS_DbgPrint(MAX_TRACE, ("Status (0x%X) Packet (0x%X) PoolHandle (0x%X).\n",
458 Status, Packet, PoolHandle));
460 KeAcquireSpinLock(&Pool->SpinLock.SpinLock, &OldIrql);
462 if (Pool->FreeList) {
463 Temp = Pool->FreeList;
464 Pool->FreeList = (PNDIS_PACKET)Temp->Private.Head;
466 KeReleaseSpinLock(&Pool->SpinLock.SpinLock, OldIrql);
468 RtlZeroMemory(&Temp->Private, sizeof(NDIS_PACKET_PRIVATE));
469 Temp->Private.Pool = Pool;
472 *Status = NDIS_STATUS_SUCCESS;
474 *Status = NDIS_STATUS_RESOURCES;
475 KeReleaseSpinLock(&Pool->SpinLock.SpinLock, OldIrql);
482 NdisAllocatePacketPool(
483 OUT PNDIS_STATUS Status,
484 OUT PNDIS_HANDLE PoolHandle,
485 IN UINT NumberOfDescriptors,
486 IN UINT ProtocolReservedLength)
488 * FUNCTION: Allocates storage for an NDIS packet pool
490 * Status = Address of buffer for status
491 * PoolHandle = Address of buffer for pool handle
492 * NumberOfDescriptors = Size of packet pool in number of descriptors
493 * ProtocolReservedLength = Size of protocol reserved area in bytes
496 PNDIS_PACKET_POOL Pool;
497 UINT Size, Length, i;
498 PNDIS_PACKET Packet, NextPacket;
500 NDIS_DbgPrint(MAX_TRACE, ("Status (0x%X) PoolHandle (0x%X) "
501 "NumberOfDescriptors (%d) ProtocolReservedLength (%d).\n",
502 Status, PoolHandle, NumberOfDescriptors, ProtocolReservedLength));
504 Length = sizeof(NDIS_PACKET) + ProtocolReservedLength;
505 Size = sizeof(NDIS_PACKET_POOL) + Length * NumberOfDescriptors;
507 Pool = ExAllocatePool(NonPagedPool, Size);
509 KeInitializeSpinLock(&Pool->SpinLock.SpinLock);
510 Pool->PacketLength = Length;
512 if (NumberOfDescriptors > 0) {
513 Packet = (PNDIS_PACKET)&Pool->Buffer;
514 Pool->FreeList = Packet;
516 NextPacket = (PNDIS_PACKET)((ULONG_PTR)Packet + Length);
517 for (i = 1; i < NumberOfDescriptors; i++) {
518 Packet->Private.Head = (PNDIS_BUFFER)NextPacket;
520 NextPacket = (PNDIS_PACKET)((ULONG_PTR)Packet + Length);
522 Packet->Private.Head = NULL;
524 Pool->FreeList = NULL;
526 *Status = NDIS_STATUS_SUCCESS;
527 *PoolHandle = (PNDIS_HANDLE)Pool;
529 *Status = NDIS_STATUS_RESOURCES;
535 NdisAllocatePacketPoolEx(
536 OUT PNDIS_STATUS Status,
537 OUT PNDIS_HANDLE PoolHandle,
538 IN UINT NumberOfDescriptors,
539 IN UINT NumberOfOverflowDescriptors,
540 IN UINT ProtocolReservedLength)
555 IN PNDIS_BUFFER Buffer)
557 * FUNCTION: Modifies the length of an NDIS buffer
559 * Buffer = Pointer to NDIS buffer descriptor
560 * Length = New size of buffer
564 * Length of NDIS buffer
567 return Buffer->ByteCount;
573 NdisBufferVirtualAddress(
574 IN PNDIS_BUFFER Buffer)
591 OUT PNDIS_STATUS Status,
592 OUT PNDIS_BUFFER *Buffer,
593 IN NDIS_HANDLE PoolHandle,
594 IN PVOID MemoryDescriptor,
598 * FUNCTION: Returns a new buffer descriptor for a (partial) buffer
600 * Status = Address of a buffer to place status of operation
601 * Buffer = Address of a buffer to place new buffer descriptor
602 * PoolHandle = Handle returned by NdisAllocateBufferPool
603 * MemoryDescriptor = Pointer to a memory descriptor (possibly NDIS_BUFFER)
604 * Offset = Offset in buffer to start copying
605 * Length = Number of bytes to copy
608 *Status = NDIS_STATUS_FAILURE;
614 NdisCopyFromPacketToPacket(
615 IN PNDIS_PACKET Destination,
616 IN UINT DestinationOffset,
618 IN PNDIS_PACKET Source,
619 IN UINT SourceOffset,
620 OUT PUINT BytesCopied)
622 * FUNCTION: Copies data from one packet to another
624 * Destination = Pointer to packet to copy data to
625 * DestinationOffset = Offset in destination packet to copy data to
626 * BytesToCopy = Number of bytes to copy
627 * Source = Pointer to packet descriptor to copy from
628 * SourceOffset = Offset in source packet to start copying from
629 * BytesCopied = Address of buffer to place number of bytes copied
632 PNDIS_BUFFER SrcBuffer;
633 PNDIS_BUFFER DstBuffer;
634 PUCHAR DstData, SrcData;
635 UINT DstSize, SrcSize;
640 /* Skip DestinationOffset bytes in the destination packet */
641 NdisGetFirstBufferFromPacket(Destination, &DstBuffer, (PVOID)&DstData, &DstSize, &Total);
642 if (SkipToOffset(DstBuffer, DestinationOffset, &DstData, &DstSize) == -1)
645 /* Skip SourceOffset bytes in the source packet */
646 NdisGetFirstBufferFromPacket(Source, &SrcBuffer, (PVOID)&SrcData, &SrcSize, &Total);
647 if (SkipToOffset(SrcBuffer, SourceOffset, &SrcData, &SrcSize) == -1)
652 /* Find out how many bytes we can copy at one time */
653 if (BytesToCopy < SrcSize)
660 RtlCopyMemory(DstData, SrcData, Count);
663 BytesToCopy -= Count;
664 if (BytesToCopy == 0)
669 /* No more bytes in destination buffer. Proceed to
670 the next buffer in the destination buffer chain */
671 NdisGetNextBuffer(DstBuffer, &DstBuffer);
675 NdisQueryBuffer(DstBuffer, (PVOID)&DstData, &DstSize);
680 /* No more bytes in source buffer. Proceed to
681 the next buffer in the source buffer chain */
682 NdisGetNextBuffer(SrcBuffer, &SrcBuffer);
686 NdisQueryBuffer(SrcBuffer, (PVOID)&SrcData, &SrcSize);
690 *BytesCopied = Total;
696 NdisDprAllocatePacket(
697 OUT PNDIS_STATUS Status,
698 OUT PNDIS_PACKET *Packet,
699 IN NDIS_HANDLE PoolHandle)
701 * FUNCTION: Allocates a packet at IRQL DISPATCH_LEVEL
703 * Status = Address of buffer to place status of operation
704 * Packet = Address of buffer to place a pointer to a packet descriptor
705 * PoolHandle = Handle returned by NdisAllocatePacketPool
713 NdisDprAllocatePacketNonInterlocked(
714 OUT PNDIS_STATUS Status,
715 OUT PNDIS_PACKET *Packet,
716 IN NDIS_HANDLE PoolHandle)
718 * FUNCTION: Allocates a packet at IRQL DISPATCH_LEVEL (w/o synchronization)
720 * Status = Address of buffer to place status of operation
721 * Packet = Address of buffer to place a pointer to a packet descriptor
722 * PoolHandle = Handle returned by NdisAllocatePacketPool
725 *Status = NDIS_STATUS_FAILURE;
732 IN PNDIS_PACKET Packet)
734 * FUNCTION: Frees a packet at IRQL DISPATCH_LEVEL
736 * Packet = Pointer to packet to free
744 NdisDprFreePacketNonInterlocked(
745 IN PNDIS_PACKET Packet)
747 * FUNCTION: Frees a packet at IRQL DISPATCH_LEVEL (w/o synchronization)
749 * Packet = Pointer to packet to free
758 IN NDIS_HANDLE PoolHandle)
760 * FUNCTION: Frees storage allocated for an NDIS buffer pool
762 * PoolHandle = Handle returned by NdisAllocateBufferPool
765 ExFreePool((PVOID)PoolHandle);
772 IN NDIS_HANDLE PoolHandle)
774 * FUNCTION: Frees storage allocated for an NDIS packet pool
776 * PoolHandle = Handle returned by NdisAllocatePacketPool
779 ExFreePool((PVOID)PoolHandle);
786 IN PNDIS_BUFFER Buffer)
788 * FUNCTION: Puts an NDIS buffer descriptor back in it's pool
790 * Buffer = Pointer to buffer descriptor
794 PNDIS_BUFFER_POOL Pool;
795 PNETWORK_HEADER Temp = (PNETWORK_HEADER)Buffer;
797 NDIS_DbgPrint(MAX_TRACE, ("Buffer (0x%X).\n", Buffer));
799 Pool = Temp->BufferPool;
801 KeAcquireSpinLock(&Pool->SpinLock, &OldIrql);
802 Buffer->Next = (PMDL)Pool->FreeList;
803 Pool->FreeList = (PNETWORK_HEADER)Buffer;
804 KeReleaseSpinLock(&Pool->SpinLock, OldIrql);
811 IN PNDIS_PACKET Packet)
813 * FUNCTION: Puts an NDIS packet descriptor back in it's pool
815 * Packet = Pointer to packet descriptor
820 NDIS_DbgPrint(MAX_TRACE, ("Packet (0x%X).\n", Packet));
822 KeAcquireSpinLock(&Packet->Private.Pool->SpinLock.SpinLock, &OldIrql);
823 Packet->Private.Head = (PNDIS_BUFFER)Packet->Private.Pool->FreeList;
824 Packet->Private.Pool->FreeList = Packet;
825 KeReleaseSpinLock(&Packet->Private.Pool->SpinLock.SpinLock, OldIrql);
831 NdisGetBufferPhysicalArraySize(
832 IN PNDIS_BUFFER Buffer,
835 * FUNCTION: Returns number of discontiguous physical blocks backing a buffer
837 * Buffer = Pointer to buffer descriptor
838 * ArraySize = Address of buffer to place number of physical blocks
847 NdisGetFirstBufferFromPacket(
848 IN PNDIS_PACKET _Packet,
849 OUT PNDIS_BUFFER *_FirstBuffer,
850 OUT PVOID *_FirstBufferVA,
851 OUT PUINT _FirstBufferLength,
852 OUT PUINT _TotalBufferLength)
854 * FUNCTION: Retrieves information about an NDIS packet
856 * _Packet = Pointer to NDIS packet
857 * _FirstBuffer = Address of buffer for pointer to first NDIS buffer
858 * _FirstBufferVA = Address of buffer for address of first NDIS buffer
859 * _FirstBufferLength = Address of buffer for length of first buffer
860 * _TotalBufferLength = Address of buffer for total length of packet
865 Buffer = _Packet->Private.Head;
866 *_FirstBuffer = Buffer;
867 *_FirstBufferVA = MmGetMdlVirtualAddress(Buffer);
869 if (Buffer != NULL) {
870 *_FirstBufferLength = MmGetMdlByteCount(Buffer);
871 Buffer = Buffer->Next;
873 *_FirstBufferLength = 0;
875 *_TotalBufferLength = *_FirstBufferLength;
877 while (Buffer != NULL) {
878 *_TotalBufferLength += MmGetMdlByteCount(Buffer);
879 Buffer = Buffer->Next;
887 IN PNDIS_PACKET *PacketsToReturn,
888 IN UINT NumberOfPackets)
890 * FUNCTION: Releases ownership of one or more packets
892 * PacketsToReturn = Pointer to an array of pointers to packet descriptors
893 * NumberOfPackets = Number of pointers in descriptor pointer array
903 IN NDIS_HANDLE PoolHandle)
920 IN PNDIS_BUFFER Buffer,
921 OUT PVOID *VirtualAddress OPTIONAL,
925 * Queries an NDIS buffer for information
927 * Buffer = Pointer to NDIS buffer to query
928 * VirtualAddress = Address of buffer to place virtual address
929 * Length = Address of buffer to place length of buffer
932 if (VirtualAddress != NULL)
933 *(PVOID*)VirtualAddress = MmGetSystemAddressForMdl(Buffer);
935 *Length = MmGetMdlByteCount(Buffer);
941 NdisQueryBufferOffset(
942 IN PNDIS_BUFFER Buffer,
946 *((PUINT)Offset) = MmGetMdlByteOffset(Buffer);
947 *((PUINT)Length) = MmGetMdlByteCount(Buffer);
953 NdisUnchainBufferAtBack(
954 IN OUT PNDIS_PACKET Packet,
955 OUT PNDIS_BUFFER *Buffer)
958 * Removes the last buffer in a packet
960 * Packet = Pointer to NDIS packet
961 * Buffer = Address of buffer to place pointer to removed NDIS buffer
964 PNDIS_BUFFER NdisBuffer, Previous;
966 NdisQueryPacket(Packet,
977 while (NdisBuffer->Next) {
978 Previous = NdisBuffer;
979 NdisBuffer = NdisBuffer->Next;
983 Previous->Next = NULL;
984 Packet->Private.Tail = Previous;
986 Packet->Private.Head = NULL;
987 Packet->Private.Tail = NULL;
990 Packet->Private.ValidCounts = FALSE;
992 *Buffer = NdisBuffer;
998 NdisUnchainBufferAtFront(
999 IN OUT PNDIS_PACKET Packet,
1000 OUT PNDIS_BUFFER *Buffer)
1003 * Removes the first buffer in a packet
1005 * Packet = Pointer to NDIS packet
1006 * Buffer = Address of buffer to place pointer to removed NDIS buffer
1009 PNDIS_BUFFER NdisBuffer;
1011 NdisQueryPacket(Packet,
1021 Packet->Private.Head = NdisBuffer->Next;
1023 if (!NdisBuffer->Next)
1024 Packet->Private.Tail = NULL;
1026 NdisBuffer->Next = NULL;
1028 Packet->Private.ValidCounts = FALSE;
1030 *Buffer = NdisBuffer;