Initial revision
[reactos.git] / reactos / drivers / net / ndis / ndis / buffer.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS NDIS library
4 * FILE: ndis/buffer.c
5 * PURPOSE: Buffer management routines
6 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
7 * REVISIONS:
8 * CSH 01/08-2000 Created
9 */
10 #include <buffer.h>
11
12
13 VOID
14 EXPORT
15 NdisAdjustBufferLength(
16 IN PNDIS_BUFFER Buffer,
17 IN UINT Length)
18 /*
19 * FUNCTION: Modifies the length of an NDIS buffer
20 * ARGUMENTS:
21 * Buffer = Pointer to NDIS buffer descriptor
22 * Length = New size of buffer
23 */
24 {
25 Buffer->ByteCount = Length;
26 }
27
28
29 ULONG
30 EXPORT
31 NDIS_BUFFER_TO_SPAN_PAGES(
32 IN PNDIS_BUFFER Buffer)
33 /*
34 * FUNCTION: Determines how many physical pages a buffer is made of
35 * ARGUMENTS:
36 * Buffer = Pointer to NDIS buffer descriptor
37 */
38 {
39 if (MmGetMdlByteCount(Buffer) == 0)
40 return 1;
41
42 return ADDRESS_AND_SIZE_TO_SPAN_PAGES(
43 MmGetMdlVirtualAddress(Buffer),
44 MmGetMdlByteCount(Buffer));
45 }
46
47
48 VOID
49 EXPORT
50 NdisAllocateBuffer(
51 OUT PNDIS_STATUS Status,
52 OUT PNDIS_BUFFER * Buffer,
53 IN NDIS_HANDLE PoolHandle,
54 IN PVOID VirtualAddress,
55 IN UINT Length)
56 /*
57 * FUNCTION: Allocates an NDIS buffer descriptor
58 * ARGUMENTS:
59 * Status = Address of buffer for status
60 * Buffer = Address of buffer for NDIS buffer descriptor
61 * PoolHandle = Handle returned by NdisAllocateBufferPool
62 * VirtualAddress = Pointer to virtual address of data buffer
63 * Length = Number of bytes in data buffer
64 */
65 {
66 KIRQL OldIrql;
67 PNETWORK_HEADER Temp;
68 PNDIS_BUFFER_POOL Pool = (PNDIS_BUFFER_POOL)PoolHandle;
69
70 NDIS_DbgPrint(MAX_TRACE, ("Status (0x%X) Buffer (0x%X) PoolHandle (0x%X) "
71 "VirtualAddress (0x%X) Length (%d)\n",
72 Status, Buffer, PoolHandle, VirtualAddress, Length));
73
74 KeAcquireSpinLock(&Pool->SpinLock, &OldIrql);
75
76 if (Pool->FreeList) {
77 Temp = Pool->FreeList;
78 Pool->FreeList = Temp->Next;
79
80 KeReleaseSpinLock(&Pool->SpinLock, OldIrql);
81
82 Temp->Next = NULL;
83
84 #ifdef _MSC_VER
85 MmInitializeMdl(&Temp->Mdl, VirtualAddress, Length);
86 Temp->Mdl.MdlFlags |= (MDL_SOURCE_IS_NONPAGED_POOL | MDL_ALLOCATED_FIXED_SIZE);
87 Temp->Mdl.MappedSystemVa = VirtualAddress;
88 #else
89 Temp->Mdl.Next = (PMDL)NULL;
90 Temp->Mdl.Size = (CSHORT)(sizeof(MDL) +
91 (ADDRESS_AND_SIZE_TO_SPAN_PAGES(VirtualAddress, Length) * sizeof(ULONG)));
92 Temp->Mdl.MdlFlags = (MDL_SOURCE_IS_NONPAGED_POOL | MDL_ALLOCATED_FIXED_SIZE);
93 ; Temp->Mdl.StartVa = (PVOID)PAGE_ROUND_DOWN(VirtualAddress);
94 Temp->Mdl.ByteOffset = (ULONG_PTR)(VirtualAddress - PAGE_ROUND_DOWN(VirtualAddress));
95 Temp->Mdl.ByteCount = Length;
96 Temp->Mdl.MappedSystemVa = VirtualAddress;
97 #if 0
98 //Temp->Mdl.Process = PsGetCurrentProcess();
99 #else
100 Temp->Mdl.Process = NULL;
101 #endif
102 #endif
103
104 Temp->BufferPool = Pool;
105
106 *Buffer = (PNDIS_BUFFER)Temp;
107 *Status = NDIS_STATUS_SUCCESS;
108 } else {
109 KeReleaseSpinLock(&Pool->SpinLock, OldIrql);
110 *Status = NDIS_STATUS_FAILURE;
111 }
112 }
113
114
115 VOID
116 EXPORT
117 NdisAllocateBufferPool(
118 OUT PNDIS_STATUS Status,
119 OUT PNDIS_HANDLE PoolHandle,
120 IN UINT NumberOfDescriptors)
121 /*
122 * FUNCTION: Allocates storage for an NDIS buffer pool
123 * ARGUMENTS:
124 * Status = Address of buffer for status
125 * PoolHandle = Address of buffer for pool handle
126 * NumberOfDescriptors = Size of buffer pool in number of descriptors
127 */
128 {
129 UINT i;
130 PNDIS_BUFFER_POOL Pool;
131 PNETWORK_HEADER Buffer;
132
133 NDIS_DbgPrint(MAX_TRACE, ("Status (0x%X) PoolHandle (0x%X) NumberOfDescriptors (%d).\n",
134 Status, PoolHandle, NumberOfDescriptors));
135
136 Pool = ExAllocatePool(NonPagedPool,
137 sizeof(NDIS_BUFFER_POOL) +
138 sizeof(NETWORK_HEADER) *
139 NumberOfDescriptors);
140 if (Pool) {
141 KeInitializeSpinLock(&Pool->SpinLock);
142
143 if (NumberOfDescriptors > 0) {
144 Buffer = &Pool->Buffers[0];
145 Pool->FreeList = Buffer;
146 for (i = 1; i < NumberOfDescriptors; i++) {
147 Buffer->Next = &Pool->Buffers[i];
148 Buffer = Buffer->Next;
149 }
150 Buffer->Next = NULL;
151 } else
152 Pool->FreeList = NULL;
153
154 *Status = NDIS_STATUS_SUCCESS;
155 *PoolHandle = (PNDIS_HANDLE)Pool;
156 } else
157 *Status = NDIS_STATUS_RESOURCES;
158 }
159
160
161 VOID
162 EXPORT
163 NdisAllocatePacket(
164 OUT PNDIS_STATUS Status,
165 OUT PNDIS_PACKET * Packet,
166 IN NDIS_HANDLE PoolHandle)
167 /*
168 * FUNCTION: Allocates an NDIS packet descriptor
169 * ARGUMENTS:
170 * Status = Address of buffer for status
171 * Packet = Address of buffer for packet descriptor
172 * PoolHandle = Handle returned by NdisAllocatePacketPool
173 */
174 {
175 KIRQL OldIrql;
176 PNDIS_PACKET Temp;
177 PNDIS_PACKET_POOL Pool = (PNDIS_PACKET_POOL)PoolHandle;
178
179 NDIS_DbgPrint(MAX_TRACE, ("Status (0x%X) Packet (0x%X) PoolHandle (0x%X).\n",
180 Status, Packet, PoolHandle));
181
182 KeAcquireSpinLock(&Pool->SpinLock.SpinLock, &OldIrql);
183
184 if (Pool->FreeList) {
185 Temp = Pool->FreeList;
186 Pool->FreeList = (PNDIS_PACKET)Temp->Private.Head;
187
188 KeReleaseSpinLock(&Pool->SpinLock.SpinLock, OldIrql);
189
190 RtlZeroMemory(&Temp->Private, sizeof(NDIS_PACKET_PRIVATE));
191 Temp->Private.Pool = Pool;
192
193 *Packet = Temp;
194 *Status = NDIS_STATUS_SUCCESS;
195 } else {
196 *Status = NDIS_STATUS_RESOURCES;
197 KeReleaseSpinLock(&Pool->SpinLock.SpinLock, OldIrql);
198 }
199 }
200
201
202 VOID
203 EXPORT
204 NdisAllocatePacketPool(
205 OUT PNDIS_STATUS Status,
206 OUT PNDIS_HANDLE PoolHandle,
207 IN UINT NumberOfDescriptors,
208 IN UINT ProtocolReservedLength)
209 /*
210 * FUNCTION: Allocates storage for an NDIS packet pool
211 * ARGUMENTS:
212 * Status = Address of buffer for status
213 * PoolHandle = Address of buffer for pool handle
214 * NumberOfDescriptors = Size of packet pool in number of descriptors
215 * ProtocolReservedLength = Size of protocol reserved area in bytes
216 */
217 {
218 PNDIS_PACKET_POOL Pool;
219 UINT Size, Length, i;
220 PNDIS_PACKET Packet, NextPacket;
221
222 NDIS_DbgPrint(MAX_TRACE, ("Status (0x%X) PoolHandle (0x%X) "
223 "NumberOfDescriptors (%d) ProtocolReservedLength (%d).\n",
224 Status, PoolHandle, NumberOfDescriptors, ProtocolReservedLength));
225
226 Length = sizeof(NDIS_PACKET) + ProtocolReservedLength;
227 Size = sizeof(NDIS_PACKET_POOL) + Length * NumberOfDescriptors;
228
229 Pool = ExAllocatePool(NonPagedPool, Size);
230 if (Pool) {
231 KeInitializeSpinLock(&Pool->SpinLock.SpinLock);
232 Pool->PacketLength = Length;
233
234 if (NumberOfDescriptors > 0) {
235 Packet = (PNDIS_PACKET)&Pool->Buffer;
236 Pool->FreeList = Packet;
237
238 NextPacket = (PNDIS_PACKET)((ULONG_PTR)Packet + Length);
239 for (i = 1; i < NumberOfDescriptors; i++) {
240 Packet->Private.Head = (PNDIS_BUFFER)NextPacket;
241 Packet = NextPacket;
242 NextPacket = (PNDIS_PACKET)((ULONG_PTR)Packet + Length);
243 }
244 Packet->Private.Head = NULL;
245 } else
246 Pool->FreeList = NULL;
247
248 *Status = NDIS_STATUS_SUCCESS;
249 *PoolHandle = (PNDIS_HANDLE)Pool;
250 } else
251 *Status = NDIS_STATUS_RESOURCES;
252 }
253
254
255 VOID
256 EXPORT
257 NdisAllocatePacketPoolEx(
258 OUT PNDIS_STATUS Status,
259 OUT PNDIS_HANDLE PoolHandle,
260 IN UINT NumberOfDescriptors,
261 IN UINT NumberOfOverflowDescriptors,
262 IN UINT ProtocolReservedLength)
263 /*
264 * FUNCTION:
265 * ARGUMENTS:
266 * NOTES:
267 * NDIS 5.0
268 */
269 {
270 UNIMPLEMENTED
271 }
272
273
274 ULONG
275 EXPORT
276 NdisBufferLength(
277 IN PNDIS_BUFFER Buffer)
278 /*
279 * FUNCTION:
280 * ARGUMENTS:
281 * NOTES:
282 * NDIS 5.0
283 */
284 {
285 UNIMPLEMENTED
286
287 return 0;
288 }
289
290
291 PVOID
292 EXPORT
293 NdisBufferVirtualAddress(
294 IN PNDIS_BUFFER Buffer)
295 /*
296 * FUNCTION:
297 * ARGUMENTS:
298 * NOTES:
299 * NDIS 5.0
300 */
301 {
302 UNIMPLEMENTED
303
304 return NULL;
305 }
306
307
308 VOID
309 EXPORT
310 NdisCopyBuffer(
311 OUT PNDIS_STATUS Status,
312 OUT PNDIS_BUFFER *Buffer,
313 IN NDIS_HANDLE PoolHandle,
314 IN PVOID MemoryDescriptor,
315 IN UINT Offset,
316 IN UINT Length)
317 /*
318 * FUNCTION: Returns a new buffer descriptor for a (partial) buffer
319 * ARGUMENTS:
320 * Status = Address of a buffer to place status of operation
321 * Buffer = Address of a buffer to place new buffer descriptor
322 * PoolHandle = Handle returned by NdisAllocateBufferPool
323 * MemoryDescriptor = Pointer to a memory descriptor (possibly NDIS_BUFFER)
324 * Offset = Offset in buffer to start copying
325 * Length = Number of bytes to copy
326 */
327 {
328 *Status = NDIS_STATUS_FAILURE;
329 }
330
331
332 __inline ULONG SkipToOffset(
333 PNDIS_BUFFER Buffer,
334 UINT Offset,
335 PVOID *Data,
336 PUINT Size)
337 /*
338 * FUNCTION: Skips Offset bytes into a buffer chain
339 * ARGUMENTS:
340 * Buffer = Pointer to NDIS buffer
341 * Offset = Number of bytes to skip
342 * Data = Address of a pointer that on return will contain the
343 * address of the offset in the buffer
344 * Size = Address of a pointer that on return will contain the
345 * size of the destination buffer
346 * RETURNS:
347 * Offset into buffer, -1 if buffer chain was smaller than Offset bytes
348 * NOTES:
349 * Buffer may be NULL
350 */
351 {
352 ULONG Address = 0;
353
354 for (;;) {
355
356 if (!Buffer)
357 return -1;
358
359 NdisQueryBuffer(Buffer, Data, Size);
360
361 if (Offset < *Size) {
362 Address += Offset;
363 *Size -= Offset;
364 break;
365 }
366
367 Offset -= *Size;
368
369 NdisGetNextBuffer(Buffer, &Buffer);
370 }
371
372 *Data = (PVOID)Address;
373
374 return Offset;
375 }
376
377
378 VOID
379 EXPORT
380 NdisCopyFromPacketToPacket(
381 IN PNDIS_PACKET Destination,
382 IN UINT DestinationOffset,
383 IN UINT BytesToCopy,
384 IN PNDIS_PACKET Source,
385 IN UINT SourceOffset,
386 OUT PUINT BytesCopied)
387 /*
388 * FUNCTION: Copies data from one packet to another
389 * ARGUMENTS:
390 * Destination = Pointer to packet to copy data to
391 * DestinationOffset = Offset in destination packet to copy data to
392 * BytesToCopy = Number of bytes to copy
393 * Source = Pointer to packet descriptor to copy from
394 * SourceOffset = Offset in source packet to start copying from
395 * BytesCopied = Address of buffer to place number of bytes copied
396 */
397 {
398 PNDIS_BUFFER SrcBuffer;
399 PNDIS_BUFFER DstBuffer;
400 PVOID DstData, SrcData;
401 UINT DstSize, SrcSize;
402 UINT Count, Total;
403
404 *BytesCopied = 0;
405
406 /* Skip DestinationOffset bytes in the destination packet */
407 NdisGetFirstBufferFromPacket(Destination, &DstBuffer, &DstData, &DstSize, &Total);
408 if (SkipToOffset(DstBuffer, DestinationOffset, &DstData, &DstSize) == -1)
409 return;
410
411 /* Skip SourceOffset bytes in the source packet */
412 NdisGetFirstBufferFromPacket(Source, &SrcBuffer, &SrcData, &SrcSize, &Total);
413 if (SkipToOffset(SrcBuffer, SourceOffset, &SrcData, &SrcSize) == -1)
414 return;
415
416 /* Copy the data */
417 for (Total = 0;;) {
418 /* Find out how many bytes we can copy at one time */
419 if (BytesToCopy < SrcSize)
420 Count = BytesToCopy;
421 else
422 Count = SrcSize;
423 if (DstSize < Count)
424 Count = DstSize;
425
426 RtlCopyMemory(DstData, SrcData, Count);
427
428 Total += Count;
429 BytesToCopy -= Count;
430 if (BytesToCopy == 0)
431 break;
432
433 DstSize -= Count;
434 if (DstSize == 0) {
435 /* No more bytes in destination buffer. Proceed to
436 the next buffer in the destination buffer chain */
437 NdisGetNextBuffer(DstBuffer, &DstBuffer);
438 if (!DstBuffer)
439 break;
440
441 NdisQueryBuffer(DstBuffer, &DstData, &DstSize);
442 }
443
444 SrcSize -= Count;
445 if (SrcSize == 0) {
446 /* No more bytes in source buffer. Proceed to
447 the next buffer in the source buffer chain */
448 NdisGetNextBuffer(SrcBuffer, &SrcBuffer);
449 if (!SrcBuffer)
450 break;
451
452 NdisQueryBuffer(SrcBuffer, &SrcData, &SrcSize);
453 }
454 }
455
456 *BytesCopied = Total;
457 }
458
459
460 VOID
461 EXPORT
462 NdisDprAllocatePacket(
463 OUT PNDIS_STATUS Status,
464 OUT PNDIS_PACKET *Packet,
465 IN NDIS_HANDLE PoolHandle)
466 /*
467 * FUNCTION: Allocates a packet at IRQL DISPATCH_LEVEL
468 * ARGUMENTS:
469 * Status = Address of buffer to place status of operation
470 * Packet = Address of buffer to place a pointer to a packet descriptor
471 * PoolHandle = Handle returned by NdisAllocatePacketPool
472 */
473 {
474 }
475
476
477 VOID
478 EXPORT
479 NdisDprAllocatePacketNonInterlocked(
480 OUT PNDIS_STATUS Status,
481 OUT PNDIS_PACKET *Packet,
482 IN NDIS_HANDLE PoolHandle)
483 /*
484 * FUNCTION: Allocates a packet at IRQL DISPATCH_LEVEL (w/o synchronization)
485 * ARGUMENTS:
486 * Status = Address of buffer to place status of operation
487 * Packet = Address of buffer to place a pointer to a packet descriptor
488 * PoolHandle = Handle returned by NdisAllocatePacketPool
489 */
490 {
491 *Status = NDIS_STATUS_FAILURE;
492 }
493
494
495 VOID
496 EXPORT
497 NdisDprFreePacket(
498 IN PNDIS_PACKET Packet)
499 /*
500 * FUNCTION: Frees a packet at IRQL DISPATCH_LEVEL
501 * ARGUMENTS:
502 * Packet = Pointer to packet to free
503 */
504 {
505 }
506
507
508 VOID
509 EXPORT
510 NdisDprFreePacketNonInterlocked(
511 IN PNDIS_PACKET Packet)
512 /*
513 * FUNCTION: Frees a packet at IRQL DISPATCH_LEVEL (w/o synchronization)
514 * ARGUMENTS:
515 * Packet = Pointer to packet to free
516 */
517 {
518 }
519
520
521 VOID
522 EXPORT
523 NdisFreeBufferPool(
524 IN NDIS_HANDLE PoolHandle)
525 /*
526 * FUNCTION: Frees storage allocated for an NDIS buffer pool
527 * ARGUMENTS:
528 * PoolHandle = Handle returned by NdisAllocateBufferPool
529 */
530 {
531 ExFreePool((PVOID)PoolHandle);
532 }
533
534
535 VOID
536 EXPORT
537 NdisFreePacketPool(
538 IN NDIS_HANDLE PoolHandle)
539 /*
540 * FUNCTION: Frees storage allocated for an NDIS packet pool
541 * ARGUMENTS:
542 * PoolHandle = Handle returned by NdisAllocatePacketPool
543 */
544 {
545 ExFreePool((PVOID)PoolHandle);
546 }
547
548
549 VOID
550 EXPORT
551 NdisFreeBuffer(
552 IN PNDIS_BUFFER Buffer)
553 /*
554 * FUNCTION: Puts an NDIS buffer descriptor back in it's pool
555 * ARGUMENTS:
556 * Buffer = Pointer to buffer descriptor
557 */
558 {
559 KIRQL OldIrql;
560 PNDIS_BUFFER_POOL Pool;
561 PNETWORK_HEADER Temp = (PNETWORK_HEADER)Buffer;
562
563 NDIS_DbgPrint(MAX_TRACE, ("Buffer (0x%X).\n", Buffer));
564
565 Pool = Temp->BufferPool;
566
567 KeAcquireSpinLock(&Pool->SpinLock, &OldIrql);
568 Buffer->Next = (PMDL)Pool->FreeList;
569 Pool->FreeList = (PNETWORK_HEADER)Buffer;
570 KeReleaseSpinLock(&Pool->SpinLock, OldIrql);
571 }
572
573
574 VOID
575 EXPORT
576 NdisFreePacket(
577 IN PNDIS_PACKET Packet)
578 /*
579 * FUNCTION: Puts an NDIS packet descriptor back in it's pool
580 * ARGUMENTS:
581 * Packet = Pointer to packet descriptor
582 */
583 {
584 KIRQL OldIrql;
585
586 NDIS_DbgPrint(MAX_TRACE, ("Packet (0x%X).\n", Packet));
587
588 KeAcquireSpinLock(&Packet->Private.Pool->SpinLock.SpinLock, &OldIrql);
589 Packet->Private.Head = (PNDIS_BUFFER)Packet->Private.Pool->FreeList;
590 Packet->Private.Pool->FreeList = Packet;
591 KeReleaseSpinLock(&Packet->Private.Pool->SpinLock.SpinLock, OldIrql);
592 }
593
594
595 VOID
596 EXPORT
597 NdisGetBufferPhysicalArraySize(
598 IN PNDIS_BUFFER Buffer,
599 OUT PUINT ArraySize)
600 /*
601 * FUNCTION: Returns number of discontiguous physical blocks backing a buffer
602 * ARGUMENTS:
603 * Buffer = Pointer to buffer descriptor
604 * ArraySize = Address of buffer to place number of physical blocks
605 */
606 {
607 UNIMPLEMENTED
608 }
609
610
611 VOID
612 EXPORT
613 NdisGetFirstBufferFromPacket(
614 IN PNDIS_PACKET _Packet,
615 OUT PNDIS_BUFFER *_FirstBuffer,
616 OUT PVOID *_FirstBufferVA,
617 OUT PUINT _FirstBufferLength,
618 OUT PUINT _TotalBufferLength)
619 {
620 UNIMPLEMENTED
621 }
622
623
624 VOID
625 EXPORT
626 NdisReturnPackets(
627 IN PNDIS_PACKET *PacketsToReturn,
628 IN UINT NumberOfPackets)
629 /*
630 * FUNCTION: Releases ownership of one or more packets
631 * ARGUMENTS:
632 * PacketsToReturn = Pointer to an array of pointers to packet descriptors
633 * NumberOfPackets = Number of pointers in descriptor pointer array
634 */
635 {
636 UNIMPLEMENTED
637 }
638
639
640 UINT
641 EXPORT
642 NdisPacketPoolUsage(
643 IN NDIS_HANDLE PoolHandle)
644 /*
645 * FUNCTION:
646 * ARGUMENTS:
647 * NOTES:
648 * NDIS 5.0
649 */
650 {
651 UNIMPLEMENTED
652
653 return 0;
654 }
655
656
657 VOID
658 EXPORT
659 NdisQueryBuffer(
660 IN PNDIS_BUFFER Buffer,
661 OUT PVOID *VirtualAddress OPTIONAL,
662 OUT PUINT Length)
663 /*
664 * FUNCTION:
665 * Queries an NDIS buffer for information
666 * ARGUMENTS:
667 * Buffer = Pointer to NDIS buffer to query
668 * VirtualAddress = Address of buffer to place virtual address
669 * Length = Address of buffer to place length of buffer
670 */
671 {
672 if (VirtualAddress != NULL)
673 *(PVOID*)VirtualAddress = MmGetSystemAddressForMdl(Buffer);
674
675 *Length = MmGetMdlByteCount(Buffer);
676 }
677
678
679 VOID
680 EXPORT
681 NdisQueryBufferOffset(
682 IN PNDIS_BUFFER Buffer,
683 OUT PUINT Offset,
684 OUT PUINT Length)
685 {
686 UNIMPLEMENTED
687 }
688
689
690 VOID
691 EXPORT
692 NdisUnchainBufferAtBack(
693 IN OUT PNDIS_PACKET Packet,
694 OUT PNDIS_BUFFER *Buffer)
695 /*
696 * FUNCTION:
697 * Removes the last buffer in a packet
698 * ARGUMENTS:
699 * Packet = Pointer to NDIS packet
700 * Buffer = Address of buffer to place pointer to removed NDIS buffer
701 */
702 {
703 PNDIS_BUFFER NdisBuffer, Previous;
704
705 NdisQueryPacket(Packet,
706 NULL,
707 NULL,
708 &NdisBuffer,
709 NULL);
710 if (!NdisBuffer) {
711 *Buffer = NULL;
712 return;
713 }
714
715 Previous = NULL;
716 while (NdisBuffer->Next) {
717 Previous = NdisBuffer;
718 NdisBuffer = NdisBuffer->Next;
719 }
720
721 if (Previous) {
722 Previous->Next = NULL;
723 Packet->Private.Tail = Previous;
724 } else {
725 Packet->Private.Head = NULL;
726 Packet->Private.Tail = NULL;
727 }
728
729 Packet->Private.ValidCounts = FALSE;
730
731 *Buffer = NdisBuffer;
732 }
733
734
735 VOID
736 EXPORT
737 NdisUnchainBufferAtFront(
738 IN OUT PNDIS_PACKET Packet,
739 OUT PNDIS_BUFFER *Buffer)
740 /*
741 * FUNCTION:
742 * Removes the first buffer in a packet
743 * ARGUMENTS:
744 * Packet = Pointer to NDIS packet
745 * Buffer = Address of buffer to place pointer to removed NDIS buffer
746 */
747 {
748 PNDIS_BUFFER NdisBuffer;
749
750 NdisQueryPacket(Packet,
751 NULL,
752 NULL,
753 &NdisBuffer,
754 NULL);
755 if (!NdisBuffer) {
756 *Buffer = NULL;
757 return;
758 }
759
760 Packet->Private.Head = NdisBuffer->Next;
761
762 if (!NdisBuffer->Next)
763 Packet->Private.Tail = NULL;
764
765 NdisBuffer->Next = NULL;
766
767 Packet->Private.ValidCounts = FALSE;
768
769 *Buffer = NdisBuffer;
770 }
771
772 /* EOF */