xref: /reactos/drivers/network/ndis/ndis/buffer.c (revision 378642eb)
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 
11 #include <ndissys.h>
12 
13 FORCEINLINE
14 ULONG
SkipToOffset(IN PNDIS_BUFFER Buffer,IN UINT Offset,IN OUT PUCHAR * Data,IN OUT PUINT Size)15 SkipToOffset(
16     IN PNDIS_BUFFER Buffer,
17     IN UINT Offset,
18     IN OUT PUCHAR *Data,
19     IN OUT PUINT Size)
20 /*
21  * FUNCTION: Skips Offset bytes into a buffer chain
22  * ARGUMENTS:
23  *     Buffer = Pointer to NDIS buffer
24  *     Offset = Number of bytes to skip
25  *     Data   = Address of a pointer that on return will contain the
26  *              address of the offset in the buffer
27  *     Size   = Address of a pointer that on return will contain the
28  *              size of the destination buffer
29  * RETURNS:
30  *     Offset into buffer, -1 if buffer chain was smaller than Offset bytes
31  * NOTES:
32  *     Buffer may be NULL
33  */
34 {
35     for (;;) {
36 
37         if (!Buffer)
38             return 0xFFFFFFFF;
39 
40         NdisQueryBuffer(Buffer, (PVOID)Data, Size);
41 
42         if (Offset < *Size) {
43             *Data  = (PUCHAR) ((ULONG_PTR) *Data + Offset);
44             *Size -= Offset;
45             break;
46         }
47 
48         Offset -= *Size;
49 
50         NdisGetNextBuffer(Buffer, &Buffer);
51     }
52 
53     return Offset;
54 }
55 
CopyBufferToBufferChain(PNDIS_BUFFER DstBuffer,UINT DstOffset,PUCHAR SrcData,UINT Length)56 UINT CopyBufferToBufferChain(
57     PNDIS_BUFFER DstBuffer,
58     UINT DstOffset,
59     PUCHAR SrcData,
60     UINT Length)
61 /*
62  * FUNCTION: Copies data from a buffer to an NDIS buffer chain
63  * ARGUMENTS:
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
68  * RETURNS:
69  *     Number of bytes copied to destination buffer
70  * NOTES:
71  *     The number of bytes copied may be limited by the destination
72  *     buffer size
73  */
74 {
75     UINT BytesCopied, BytesToCopy, DstSize;
76     PUCHAR DstData;
77 
78     NDIS_DbgPrint(MAX_TRACE, ("DstBuffer (0x%X)  DstOffset (0x%X)  SrcData (0x%X)  Length (%d)\n", DstBuffer, DstOffset, SrcData, Length));
79 
80     /* Skip DstOffset bytes in the destination buffer chain */
81     if (SkipToOffset(DstBuffer, DstOffset, &DstData, &DstSize) == 0xFFFFFFFF)
82         return 0;
83 
84     /* Start copying the data */
85     BytesCopied = 0;
86     for (;;) {
87         BytesToCopy = MIN(DstSize, Length);
88 
89         RtlCopyMemory((PVOID)DstData, (PVOID)SrcData, BytesToCopy);
90         BytesCopied += BytesToCopy;
91         SrcData      = (PUCHAR) ((ULONG_PTR) SrcData + BytesToCopy);
92 
93         Length -= BytesToCopy;
94         if (Length == 0)
95             break;
96 
97         DstSize -= BytesToCopy;
98         if (DstSize == 0) {
99             /* No more bytes in destination buffer. Proceed to
100                the next buffer in the destination buffer chain */
101             NdisGetNextBuffer(DstBuffer, &DstBuffer);
102             if (!DstBuffer)
103                 break;
104 
105             NdisQueryBuffer(DstBuffer, (PVOID)&DstData, &DstSize);
106         }
107     }
108 
109     return BytesCopied;
110 }
111 
112 
CopyBufferChainToBuffer(PUCHAR DstData,PNDIS_BUFFER SrcBuffer,UINT SrcOffset,UINT Length)113 UINT CopyBufferChainToBuffer(
114     PUCHAR DstData,
115     PNDIS_BUFFER SrcBuffer,
116     UINT SrcOffset,
117     UINT Length)
118 /*
119  * FUNCTION: Copies data from an NDIS buffer chain to a buffer
120  * ARGUMENTS:
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
125  * RETURNS:
126  *     Number of bytes copied to destination buffer
127  * NOTES:
128  *     The number of bytes copied may be limited by the source
129  *     buffer size
130  */
131 {
132     UINT BytesCopied, BytesToCopy, SrcSize;
133     PUCHAR SrcData;
134 
135     NDIS_DbgPrint(MAX_TRACE, ("DstData 0x%X  SrcBuffer 0x%X  SrcOffset 0x%X  Length %d\n",DstData,SrcBuffer, SrcOffset, Length));
136 
137     /* Skip SrcOffset bytes in the source buffer chain */
138     if (SkipToOffset(SrcBuffer, SrcOffset, &SrcData, &SrcSize) == 0xFFFFFFFF)
139         return 0;
140 
141     /* Start copying the data */
142     BytesCopied = 0;
143     for (;;) {
144         BytesToCopy = MIN(SrcSize, Length);
145 
146         NDIS_DbgPrint(MAX_TRACE, ("Copying (%d) bytes from 0x%X to 0x%X\n", BytesToCopy, SrcData, DstData));
147 
148         RtlCopyMemory((PVOID)DstData, (PVOID)SrcData, BytesToCopy);
149         BytesCopied += BytesToCopy;
150         DstData      = (PUCHAR)((ULONG_PTR) DstData + BytesToCopy);
151 
152         Length -= BytesToCopy;
153         if (Length == 0)
154             break;
155 
156         SrcSize -= BytesToCopy;
157         if (SrcSize == 0) {
158             /* No more bytes in source buffer. Proceed to
159                the next buffer in the source buffer chain */
160             NdisGetNextBuffer(SrcBuffer, &SrcBuffer);
161             if (!SrcBuffer)
162                 break;
163 
164             NdisQueryBuffer(SrcBuffer, (PVOID)&SrcData, &SrcSize);
165         }
166     }
167 
168     return BytesCopied;
169 }
170 
171 
CopyPacketToBuffer(PUCHAR DstData,PNDIS_PACKET SrcPacket,UINT SrcOffset,UINT Length)172 UINT CopyPacketToBuffer(
173     PUCHAR DstData,
174     PNDIS_PACKET SrcPacket,
175     UINT SrcOffset,
176     UINT Length)
177 /*
178  * FUNCTION: Copies data from an NDIS packet to a buffer
179  * ARGUMENTS:
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
184  * RETURNS:
185  *     Number of bytes copied to destination buffer
186  * NOTES:
187  *     The number of bytes copied may be limited by the source
188  *     buffer size
189  */
190 {
191     PNDIS_BUFFER FirstBuffer;
192     PVOID Address;
193     UINT FirstLength;
194     UINT TotalLength;
195 
196     NDIS_DbgPrint(MAX_TRACE, ("DstData (0x%X)  SrcPacket (0x%X)  SrcOffset (0x%X)  Length (%d)\n", DstData, SrcPacket, SrcOffset, Length));
197 
198     NdisGetFirstBufferFromPacket(SrcPacket,
199                                  &FirstBuffer,
200                                  &Address,
201                                  &FirstLength,
202                                  &TotalLength);
203 
204     return CopyBufferChainToBuffer(DstData, FirstBuffer, SrcOffset, Length);
205 }
206 
207 
CopyPacketToBufferChain(PNDIS_BUFFER DstBuffer,UINT DstOffset,PNDIS_PACKET SrcPacket,UINT SrcOffset,UINT Length)208 UINT CopyPacketToBufferChain(
209     PNDIS_BUFFER DstBuffer,
210     UINT DstOffset,
211     PNDIS_PACKET SrcPacket,
212     UINT SrcOffset,
213     UINT Length)
214 /*
215  * FUNCTION: Copies data from an NDIS packet to an NDIS buffer chain
216  * ARGUMENTS:
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
222  * RETURNS:
223  *     Number of bytes copied to destination buffer
224  * NOTES:
225  *     The number of bytes copied may be limited by the source and
226  *     destination buffer sizes
227  */
228 {
229     PNDIS_BUFFER SrcBuffer;
230     PUCHAR DstData, SrcData;
231     UINT DstSize, SrcSize;
232     UINT Count, Total;
233 
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));
235 
236     /* Skip DstOffset bytes in the destination buffer chain */
237     NdisQueryBuffer(DstBuffer, (PVOID)&DstData, &DstSize);
238     if (SkipToOffset(DstBuffer, DstOffset, &DstData, &DstSize) == 0xFFFFFFFF)
239         return 0;
240     /* Skip SrcOffset bytes in the source packet */
241     NdisGetFirstBufferFromPacket(SrcPacket, &SrcBuffer, (PVOID*)&SrcData, &SrcSize, &Total);
242     if (SkipToOffset(SrcBuffer, SrcOffset, &SrcData, &SrcSize) == 0xFFFFFFFF)
243         return 0;
244     /* Copy the data */
245     for (Total = 0;;) {
246         /* Find out how many bytes we can copy at one time */
247         if (Length < SrcSize)
248             Count = Length;
249         else
250             Count = SrcSize;
251         if (DstSize < Count)
252             Count = DstSize;
253 
254         RtlCopyMemory((PVOID)DstData, (PVOID)SrcData, Count);
255 
256         Total  += Count;
257         Length -= Count;
258         if (Length == 0)
259             break;
260 
261         DstSize -= Count;
262         if (DstSize == 0) {
263             /* No more bytes in destination buffer. Proceed to
264                the next buffer in the destination buffer chain */
265             NdisGetNextBuffer(DstBuffer, &DstBuffer);
266             if (!DstBuffer)
267                 break;
268 
269             NdisQueryBuffer(DstBuffer, (PVOID)&DstData, &DstSize);
270         }
271 
272         SrcSize -= Count;
273         if (SrcSize == 0) {
274             /* No more bytes in source buffer. Proceed to
275                the next buffer in the source buffer chain */
276             NdisGetNextBuffer(SrcBuffer, &SrcBuffer);
277             if (!SrcBuffer)
278                 break;
279 
280             NdisQueryBuffer(SrcBuffer, (PVOID)&SrcData, &SrcSize);
281         }
282     }
283 
284     return Total;
285 }
286 
287 
288 /*
289  * @implemented
290  */
291 #undef NdisAdjustBufferLength
292 VOID
293 EXPORT
NdisAdjustBufferLength(IN PNDIS_BUFFER Buffer,IN UINT Length)294 NdisAdjustBufferLength(
295     IN PNDIS_BUFFER Buffer,
296     IN UINT         Length)
297 /*
298  * FUNCTION: Modifies the length of an NDIS buffer
299  * ARGUMENTS:
300  *     Buffer = Pointer to NDIS buffer descriptor
301  *     Length = New size of buffer
302  */
303 {
304     Buffer->ByteCount = Length;
305 }
306 
307 
308 /*
309  * @implemented
310  */
311 #undef NDIS_BUFFER_TO_SPAN_PAGES
312 ULONG
313 EXPORT
NDIS_BUFFER_TO_SPAN_PAGES(IN PNDIS_BUFFER Buffer)314 NDIS_BUFFER_TO_SPAN_PAGES(
315     IN  PNDIS_BUFFER    Buffer)
316 /*
317  * FUNCTION: Determines how many physical pages a buffer is made of
318  * ARGUMENTS:
319  *     Buffer = Pointer to NDIS buffer descriptor
320  */
321 {
322     if (MmGetMdlByteCount(Buffer) == 0)
323         return 1;
324 
325     return ADDRESS_AND_SIZE_TO_SPAN_PAGES(
326             MmGetMdlVirtualAddress(Buffer),
327             MmGetMdlByteCount(Buffer));
328 }
329 
330 
331 /*
332  * @implemented
333  */
334 VOID
335 EXPORT
NdisAllocateBuffer(OUT PNDIS_STATUS Status,OUT PNDIS_BUFFER * Buffer,IN NDIS_HANDLE PoolHandle,IN PVOID VirtualAddress,IN UINT Length)336 NdisAllocateBuffer(
337     OUT PNDIS_STATUS    Status,
338     OUT PNDIS_BUFFER    * Buffer,
339     IN  NDIS_HANDLE     PoolHandle,
340     IN  PVOID           VirtualAddress,
341     IN  UINT            Length)
342 /*
343  * FUNCTION: Allocates an NDIS buffer descriptor
344  * ARGUMENTS:
345  *     Status         = Address of buffer for status
346  *     Buffer         = Address of buffer for NDIS buffer descriptor
347  *     PoolHandle     = Handle returned by NdisAllocateBufferPool
348  *     VirtualAddress = Pointer to virtual address of data buffer
349  *     Length         = Number of bytes in data buffer
350  */
351 {
352     ASSERT(VirtualAddress != NULL);
353     ASSERT(Length > 0);
354 
355     *Buffer = IoAllocateMdl(VirtualAddress, Length, FALSE, FALSE, NULL);
356     if (*Buffer != NULL) {
357         MmBuildMdlForNonPagedPool(*Buffer);
358         (*Buffer)->Next = NULL;
359         *Status = NDIS_STATUS_SUCCESS;
360     } else {
361         NDIS_DbgPrint(MIN_TRACE, ("IoAllocateMdl failed (%x, %lx)\n", VirtualAddress, Length));
362         *Status = NDIS_STATUS_FAILURE;
363     }
364 }
365 
366 
367 /*
368  * @implemented
369  */
370 VOID
371 EXPORT
NdisAllocateBufferPool(OUT PNDIS_STATUS Status,OUT PNDIS_HANDLE PoolHandle,IN UINT NumberOfDescriptors)372 NdisAllocateBufferPool(
373     OUT PNDIS_STATUS    Status,
374     OUT PNDIS_HANDLE    PoolHandle,
375     IN  UINT            NumberOfDescriptors)
376 /*
377  * FUNCTION: Allocates storage for an NDIS buffer pool
378  * ARGUMENTS:
379  *     Status              = Address of buffer for status
380  *     PoolHandle          = Address of buffer for pool handle
381  *     NumberOfDescriptors = Size of buffer pool in number of descriptors
382  */
383 {
384     *Status = NDIS_STATUS_SUCCESS;
385     *PoolHandle = 0;
386 }
387 
388 
389 /*
390  * @implemented
391  */
392 VOID
393 EXPORT
NdisAllocatePacket(OUT PNDIS_STATUS Status,OUT PNDIS_PACKET * Packet,IN NDIS_HANDLE PoolHandle)394 NdisAllocatePacket(
395     OUT PNDIS_STATUS    Status,
396     OUT PNDIS_PACKET    * Packet,
397     IN  NDIS_HANDLE     PoolHandle)
398 /*
399  * FUNCTION: Allocates an NDIS packet descriptor
400  * ARGUMENTS:
401  *     Status     = Address of buffer for status
402  *     Packet     = Address of buffer for packet descriptor
403  *     PoolHandle = Handle returned by NdisAllocatePacketPool
404  */
405 {
406     PNDISI_PACKET_POOL Pool = (PNDISI_PACKET_POOL)PoolHandle;
407 
408     KeAcquireSpinLock(&Pool->SpinLock.SpinLock, &Pool->SpinLock.OldIrql);
409     NdisDprAllocatePacketNonInterlocked(Status,
410                                         Packet,
411                                         PoolHandle);
412     KeReleaseSpinLock(&Pool->SpinLock.SpinLock, Pool->SpinLock.OldIrql);
413 }
414 
415 
416 /*
417  * @implemented
418  */
419 VOID
420 EXPORT
NdisAllocatePacketPool(OUT PNDIS_STATUS Status,OUT PNDIS_HANDLE PoolHandle,IN UINT NumberOfDescriptors,IN UINT ProtocolReservedLength)421 NdisAllocatePacketPool(
422     OUT PNDIS_STATUS    Status,
423     OUT PNDIS_HANDLE    PoolHandle,
424     IN  UINT            NumberOfDescriptors,
425     IN  UINT            ProtocolReservedLength)
426 /*
427  * FUNCTION: Allocates storage for an NDIS packet pool
428  * ARGUMENTS:
429  *     Status                 = Address of buffer for status
430  *     PoolHandle             = Address of buffer for pool handle
431  *     NumberOfDescriptors    = Size of packet pool in number of descriptors
432  *     ProtocolReservedLength = Size of protocol reserved area in bytes
433  */
434 {
435     NdisAllocatePacketPoolEx(
436         Status,
437         PoolHandle,
438         NumberOfDescriptors,
439         0,
440         ProtocolReservedLength);
441 }
442 
443 
444 /*
445  * @implemented
446  */
447 VOID
448 EXPORT
NdisAllocatePacketPoolEx(OUT PNDIS_STATUS Status,OUT PNDIS_HANDLE PoolHandle,IN UINT NumberOfDescriptors,IN UINT NumberOfOverflowDescriptors,IN UINT ProtocolReservedLength)449 NdisAllocatePacketPoolEx(
450     OUT PNDIS_STATUS    Status,
451     OUT PNDIS_HANDLE    PoolHandle,
452     IN  UINT            NumberOfDescriptors,
453     IN  UINT            NumberOfOverflowDescriptors,
454     IN  UINT            ProtocolReservedLength)
455 /*
456  * FUNCTION:
457  * ARGUMENTS:
458  * NOTES:
459  *    NDIS 5.0
460  */
461 {
462     PNDISI_PACKET_POOL Pool;
463     UINT Size, Length, i;
464     PNDIS_PACKET Packet, NextPacket;
465 
466     NDIS_DbgPrint(MAX_TRACE, ("Status (0x%X)  PoolHandle (0x%X)  "
467         "NumberOfDescriptors (%d)  ProtocolReservedLength (%d).\n",
468         Status, PoolHandle, NumberOfDescriptors, ProtocolReservedLength));
469 
470     *PoolHandle = NULL;
471 
472     if (NumberOfDescriptors > 0xffff)
473     {
474         NDIS_DbgPrint(MIN_TRACE, ("Invalid number of descriptors (%lx)\n", NumberOfDescriptors))
475         *Status = NDIS_STATUS_RESOURCES;
476     }
477     else
478     {
479         NumberOfDescriptors += NumberOfOverflowDescriptors;
480         if (NumberOfDescriptors > 0xffff)
481         {
482             NDIS_DbgPrint(MIN_TRACE, ("Total number of descriptors > 0xffff (%lx)\n", NumberOfDescriptors));
483             NumberOfDescriptors = 0xffff;
484         }
485 
486         Length = sizeof(NDIS_PACKET) + sizeof(NDIS_PACKET_OOB_DATA) +
487                  sizeof(NDIS_PACKET_EXTENSION) + ProtocolReservedLength;
488         Size   = sizeof(NDISI_PACKET_POOL) + Length * NumberOfDescriptors;
489 
490         Pool   = ExAllocatePool(NonPagedPool, Size);
491         if (Pool)
492         {
493             KeInitializeSpinLock(&Pool->SpinLock.SpinLock);
494             Pool->PacketLength = Length;
495 
496             if (NumberOfDescriptors > 0)
497             {
498                 Packet         = (PNDIS_PACKET)&Pool->Buffer;
499                 Pool->FreeList = Packet;
500 
501                 NextPacket = (PNDIS_PACKET)((ULONG_PTR)Packet + Length);
502                 for (i = 1; i < NumberOfDescriptors; i++)
503                 {
504                     Packet->Reserved[0]  = (ULONG_PTR)NextPacket;
505                     Packet               = NextPacket;
506                     NextPacket           = (PNDIS_PACKET)((ULONG_PTR)Packet + Length);
507                 }
508                 Packet->Reserved[0] = 0;
509             }
510             else {
511                 NDIS_DbgPrint(MIN_TRACE, ("Attempted to allocate a packet pool with 0 descriptors\n"));
512                 Pool->FreeList = NULL;
513             }
514 
515             *Status     = NDIS_STATUS_SUCCESS;
516             *PoolHandle = (PNDIS_HANDLE)Pool;
517         } else {
518             *Status = NDIS_STATUS_RESOURCES;
519         }
520     }
521 }
522 
523 
524 /*
525  * @implemented
526  */
527 #undef NdisBufferLength
528 ULONG
529 EXPORT
NdisBufferLength(IN PNDIS_BUFFER Buffer)530 NdisBufferLength(
531     IN  PNDIS_BUFFER    Buffer)
532 /*
533  * FUNCTION: Modifies the length of an NDIS buffer
534  * ARGUMENTS:
535  *     Buffer = Pointer to NDIS buffer descriptor
536  *     Length = New size of buffer
537  * NOTES:
538  *    NDIS 5.0
539  * RETURNS:
540  *     Length of NDIS buffer
541  */
542 {
543     return MmGetMdlByteCount(Buffer);
544 }
545 
546 
547 /*
548  * @implemented
549  */
550 #undef NdisBufferVirtualAddress
551 PVOID
552 EXPORT
NdisBufferVirtualAddress(IN PNDIS_BUFFER Buffer)553 NdisBufferVirtualAddress(
554     IN  PNDIS_BUFFER    Buffer)
555 /*
556  * FUNCTION:
557  * ARGUMENTS:
558  * NOTES:
559  *    NDIS 5.0
560  */
561 {
562     return MmGetSystemAddressForMdl(Buffer);
563 }
564 
565 
566 /*
567  * @implemented
568  */
569 VOID
570 EXPORT
NdisCopyFromPacketToPacket(IN PNDIS_PACKET Destination,IN UINT DestinationOffset,IN UINT BytesToCopy,IN PNDIS_PACKET Source,IN UINT SourceOffset,OUT PUINT BytesCopied)571 NdisCopyFromPacketToPacket(
572     IN  PNDIS_PACKET    Destination,
573     IN  UINT            DestinationOffset,
574     IN  UINT            BytesToCopy,
575     IN  PNDIS_PACKET    Source,
576     IN  UINT            SourceOffset,
577     OUT PUINT           BytesCopied)
578 /*
579  * FUNCTION: Copies data from one packet to another
580  * ARGUMENTS:
581  *     Destination       = Pointer to packet to copy data to
582  *     DestinationOffset = Offset in destination packet to copy data to
583  *     BytesToCopy       = Number of bytes to copy
584  *     Source            = Pointer to packet descriptor to copy from
585  *     SourceOffset      = Offset in source packet to start copying from
586  *     BytesCopied       = Address of buffer to place number of bytes copied
587  */
588 {
589     PNDIS_BUFFER SrcBuffer;
590     PNDIS_BUFFER DstBuffer;
591     PUCHAR DstData, SrcData;
592     UINT DstSize, SrcSize;
593     UINT Count, Total;
594 
595     *BytesCopied = 0;
596 
597     /* Skip DestinationOffset bytes in the destination packet */
598     NdisGetFirstBufferFromPacket(Destination, &DstBuffer, (PVOID*)&DstData, &DstSize, &Total);
599     if (SkipToOffset(DstBuffer, DestinationOffset, &DstData, &DstSize) == 0xFFFFFFFF)
600         return;
601 
602     /* Skip SourceOffset bytes in the source packet */
603     NdisGetFirstBufferFromPacket(Source, &SrcBuffer, (PVOID*)&SrcData, &SrcSize, &Total);
604     if (SkipToOffset(SrcBuffer, SourceOffset, &SrcData, &SrcSize) == 0xFFFFFFFF)
605         return;
606 
607     /* Copy the data */
608     for (Total = 0;;) {
609         /* Find out how many bytes we can copy at one time */
610         if (BytesToCopy < SrcSize)
611             Count = BytesToCopy;
612         else
613             Count = SrcSize;
614         if (DstSize < Count)
615             Count = DstSize;
616 
617         RtlCopyMemory(DstData, SrcData, Count);
618 
619         Total       += Count;
620         BytesToCopy -= Count;
621         if (BytesToCopy == 0)
622             break;
623 
624         DstSize -= Count;
625         if (DstSize == 0) {
626             /* No more bytes in destination buffer. Proceed to
627                the next buffer in the destination buffer chain */
628             NdisGetNextBuffer(DstBuffer, &DstBuffer);
629             if (!DstBuffer)
630                 break;
631 
632             NdisQueryBuffer(DstBuffer, (PVOID)&DstData, &DstSize);
633         }
634 
635         SrcSize -= Count;
636         if (SrcSize == 0) {
637             /* No more bytes in source buffer. Proceed to
638                the next buffer in the source buffer chain */
639             NdisGetNextBuffer(SrcBuffer, &SrcBuffer);
640             if (!SrcBuffer)
641                 break;
642 
643             NdisQueryBuffer(SrcBuffer, (PVOID)&SrcData, &SrcSize);
644         }
645     }
646 
647     *BytesCopied = Total;
648 }
649 
650 
651 /*
652  * @implemented
653  */
654 VOID
655 EXPORT
NdisDprAllocatePacket(OUT PNDIS_STATUS Status,OUT PNDIS_PACKET * Packet,IN NDIS_HANDLE PoolHandle)656 NdisDprAllocatePacket(
657     OUT PNDIS_STATUS    Status,
658     OUT PNDIS_PACKET    *Packet,
659     IN  NDIS_HANDLE     PoolHandle)
660 /*
661  * FUNCTION: Allocates a packet at IRQL DISPATCH_LEVEL
662  * ARGUMENTS:
663  *     Status     = Address of buffer to place status of operation
664  *     Packet     = Address of buffer to place a pointer to a packet descriptor
665  *     PoolHandle = Handle returned by NdisAllocatePacketPool
666  */
667 {
668     PNDISI_PACKET_POOL Pool = (PNDISI_PACKET_POOL)PoolHandle;
669 
670     KeAcquireSpinLockAtDpcLevel(&Pool->SpinLock.SpinLock);
671     NdisDprAllocatePacketNonInterlocked(Status,
672                                         Packet,
673                                         PoolHandle);
674     KeReleaseSpinLockFromDpcLevel(&Pool->SpinLock.SpinLock);
675 }
676 
677 
678 /*
679  * @implemented
680  */
681 VOID
682 EXPORT
NdisDprAllocatePacketNonInterlocked(OUT PNDIS_STATUS Status,OUT PNDIS_PACKET * Packet,IN NDIS_HANDLE PoolHandle)683 NdisDprAllocatePacketNonInterlocked(
684     OUT PNDIS_STATUS    Status,
685     OUT PNDIS_PACKET    *Packet,
686     IN NDIS_HANDLE      PoolHandle)
687 /*
688  * FUNCTION: Allocates a packet at IRQL DISPATCH_LEVEL (w/o synchronization)
689  * ARGUMENTS:
690  *     Status     = Address of buffer to place status of operation
691  *     Packet     = Address of buffer to place a pointer to a packet descriptor
692  *     PoolHandle = Handle returned by NdisAllocatePacketPool
693  */
694 {
695     PNDIS_PACKET Temp;
696     PNDISI_PACKET_POOL Pool = (PNDISI_PACKET_POOL)PoolHandle;
697 
698     NDIS_DbgPrint(MAX_TRACE, ("Status (0x%X)  Packet (0x%X)  PoolHandle (0x%X).\n",
699         Status, Packet, PoolHandle));
700 
701     *Packet = NULL;
702 
703     if (Pool == NULL)
704     {
705         *Status = NDIS_STATUS_FAILURE;
706         NDIS_DbgPrint(MIN_TRACE, ("Called passed a bad pool handle\n"));
707         return;
708     }
709 
710     if (Pool->FreeList) {
711         Temp           = Pool->FreeList;
712         Pool->FreeList = (PNDIS_PACKET)Temp->Reserved[0];
713 
714         RtlZeroMemory(Temp, Pool->PacketLength);
715         Temp->Private.Pool = Pool;
716         Temp->Private.ValidCounts = TRUE;
717         Temp->Private.NdisPacketFlags = fPACKET_ALLOCATED_BY_NDIS;
718         Temp->Private.NdisPacketOobOffset = Pool->PacketLength -
719                                             (sizeof(NDIS_PACKET_OOB_DATA) +
720                                              sizeof(NDIS_PACKET_EXTENSION));
721 
722         *Packet = Temp;
723         *Status = NDIS_STATUS_SUCCESS;
724     } else {
725         NDIS_DbgPrint(MIN_TRACE, ("No more free descriptors\n"));
726         *Status = NDIS_STATUS_RESOURCES;
727     }
728 }
729 
730 
731 /*
732  * @implemented
733  */
734 VOID
735 EXPORT
NdisDprFreePacket(IN PNDIS_PACKET Packet)736 NdisDprFreePacket(
737     IN  PNDIS_PACKET    Packet)
738 /*
739  * FUNCTION: Frees a packet at IRQL DISPATCH_LEVEL
740  * ARGUMENTS:
741  *     Packet = Pointer to packet to free
742  */
743 {
744     PNDISI_PACKET_POOL Pool = (PNDISI_PACKET_POOL)Packet->Private.Pool;
745 
746     KeAcquireSpinLockAtDpcLevel(&Pool->SpinLock.SpinLock);
747     NdisDprFreePacketNonInterlocked(Packet);
748     KeReleaseSpinLockFromDpcLevel(&Pool->SpinLock.SpinLock);
749 }
750 
751 
752 /*
753  * @implemented
754  */
755 VOID
756 EXPORT
NdisDprFreePacketNonInterlocked(IN PNDIS_PACKET Packet)757 NdisDprFreePacketNonInterlocked(
758     IN  PNDIS_PACKET    Packet)
759 /*
760  * FUNCTION: Frees a packet at IRQL DISPATCH_LEVEL (w/o synchronization)
761  * ARGUMENTS:
762  *     Packet = Pointer to packet to free
763  */
764 {
765     NDIS_DbgPrint(MAX_TRACE, ("Packet (0x%X).\n", Packet));
766 
767     Packet->Reserved[0]          = (ULONG_PTR)((NDISI_PACKET_POOL*)Packet->Private.Pool)->FreeList;
768     ((NDISI_PACKET_POOL*)Packet->Private.Pool)->FreeList = Packet;
769 }
770 
771 
772 /*
773  * @implemented
774  */
775 VOID
776 EXPORT
NdisFreeBufferPool(IN NDIS_HANDLE PoolHandle)777 NdisFreeBufferPool(
778     IN  NDIS_HANDLE PoolHandle)
779 /*
780  * FUNCTION: Frees storage allocated for an NDIS buffer pool
781  * ARGUMENTS:
782  *     PoolHandle = Handle returned by NdisAllocateBufferPool
783  */
784 {
785 }
786 
787 
788 /*
789  * @implemented
790  */
791 VOID
792 EXPORT
NdisFreePacketPool(IN NDIS_HANDLE PoolHandle)793 NdisFreePacketPool(
794     IN  NDIS_HANDLE PoolHandle)
795 /*
796  * FUNCTION: Frees storage allocated for an NDIS packet pool
797  * ARGUMENTS:
798  *     PoolHandle = Handle returned by NdisAllocatePacketPool
799  */
800 {
801     ExFreePool((PVOID)PoolHandle);
802 }
803 
804 
805 /*
806  * @implemented
807  */
808 #undef NdisFreeBuffer
809 VOID
810 EXPORT
NdisFreeBuffer(IN PNDIS_BUFFER Buffer)811 NdisFreeBuffer(
812     IN   PNDIS_BUFFER   Buffer)
813 /*
814  * FUNCTION: Puts an NDIS buffer descriptor back in it's pool
815  * ARGUMENTS:
816  *     Buffer = Pointer to buffer descriptor
817  */
818 {
819     IoFreeMdl(Buffer);
820 }
821 
822 
823 /*
824  * @implemented
825  */
826 VOID
827 EXPORT
NdisFreePacket(IN PNDIS_PACKET Packet)828 NdisFreePacket(
829     IN   PNDIS_PACKET   Packet)
830 /*
831  * FUNCTION: Puts an NDIS packet descriptor back in it's pool
832  * ARGUMENTS:
833  *     Packet = Pointer to packet descriptor
834  */
835 {
836     PNDISI_PACKET_POOL Pool = (PNDISI_PACKET_POOL)Packet->Private.Pool;
837 
838     KeAcquireSpinLock(&Pool->SpinLock.SpinLock, &Pool->SpinLock.OldIrql);
839     NdisDprFreePacketNonInterlocked(Packet);
840     KeReleaseSpinLock(&Pool->SpinLock.SpinLock, Pool->SpinLock.OldIrql);
841 }
842 
843 
844 /*
845  * @implemented
846  */
847 #undef NdisGetBufferPhysicalArraySize
848 VOID
849 EXPORT
NdisGetBufferPhysicalArraySize(IN PNDIS_BUFFER Buffer,OUT PUINT ArraySize)850 NdisGetBufferPhysicalArraySize(
851     IN  PNDIS_BUFFER    Buffer,
852     OUT PUINT           ArraySize)
853 /*
854  * FUNCTION: Returns number of discontiguous physical blocks backing a buffer
855  * ARGUMENTS:
856  *     Buffer    = Pointer to buffer descriptor
857  *     ArraySize = Address of buffer to place number of physical blocks
858  */
859 {
860   ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
861   ASSERT(Buffer && ArraySize);
862 
863   *ArraySize = NDIS_BUFFER_TO_SPAN_PAGES(Buffer);
864 }
865 
866 
867 /*
868  * @implemented
869  */
870 #undef NdisGetFirstBufferFromPacket
871 VOID
872 EXPORT
NdisGetFirstBufferFromPacket(IN PNDIS_PACKET _Packet,OUT PNDIS_BUFFER * _FirstBuffer,OUT PVOID * _FirstBufferVA,OUT PUINT _FirstBufferLength,OUT PUINT _TotalBufferLength)873 NdisGetFirstBufferFromPacket(
874     IN  PNDIS_PACKET    _Packet,
875     OUT PNDIS_BUFFER    *_FirstBuffer,
876     OUT PVOID           *_FirstBufferVA,
877     OUT PUINT           _FirstBufferLength,
878     OUT PUINT           _TotalBufferLength)
879 /*
880  * FUNCTION: Retrieves information about an NDIS packet
881  * ARGUMENTS:
882  *     _Packet            = Pointer to NDIS packet
883  *     _FirstBuffer       = Address of buffer for pointer to first NDIS buffer
884  *     _FirstBufferVA     = Address of buffer for address of first NDIS buffer
885  *     _FirstBufferLength = Address of buffer for length of first buffer
886  *     _TotalBufferLength = Address of buffer for total length of packet
887  */
888 {
889     PNDIS_BUFFER Buffer;
890 
891     Buffer          = _Packet->Private.Head;
892     *_FirstBuffer   = Buffer;
893 
894     if (Buffer != NULL) {
895         *_FirstBufferLength = MmGetMdlByteCount(Buffer);
896         *_FirstBufferVA = MmGetSystemAddressForMdl(Buffer);
897         Buffer = Buffer->Next;
898     } else {
899         NDIS_DbgPrint(MID_TRACE, ("No buffers linked to this packet\n"));
900         *_FirstBufferLength = 0;
901         *_FirstBufferVA = NULL;
902     }
903 
904     *_TotalBufferLength = *_FirstBufferLength;
905 
906     while (Buffer != NULL) {
907         *_TotalBufferLength += MmGetMdlByteCount(Buffer);
908         Buffer = Buffer->Next;
909     }
910 }
911 
912 #undef NdisGetFirstBufferFromPacketSafe
913 /*
914  * @implemented
915  */
916 VOID
917 EXPORT
NdisGetFirstBufferFromPacketSafe(IN PNDIS_PACKET _Packet,OUT PNDIS_BUFFER * _FirstBuffer,OUT PVOID * _FirstBufferVA,OUT PUINT _FirstBufferLength,OUT PUINT _TotalBufferLength,IN MM_PAGE_PRIORITY Priority)918 NdisGetFirstBufferFromPacketSafe(
919     IN  PNDIS_PACKET     _Packet,
920     OUT PNDIS_BUFFER     *_FirstBuffer,
921     OUT PVOID            *_FirstBufferVA,
922     OUT PUINT            _FirstBufferLength,
923     OUT PUINT            _TotalBufferLength,
924     IN  MM_PAGE_PRIORITY Priority)
925 {
926     PNDIS_BUFFER Buffer;
927 
928     Buffer          = _Packet->Private.Head;
929     *_FirstBuffer   = Buffer;
930 
931     if (Buffer != NULL) {
932         *_FirstBufferLength = MmGetMdlByteCount(Buffer);
933         *_FirstBufferVA = MmGetSystemAddressForMdlSafe(Buffer, Priority);
934         Buffer = Buffer->Next;
935     } else {
936         NDIS_DbgPrint(MID_TRACE, ("No buffers linked to this packet\n"));
937         *_FirstBufferLength = 0;
938         *_FirstBufferVA = NULL;
939     }
940 
941     *_TotalBufferLength = *_FirstBufferLength;
942 
943     while (Buffer != NULL) {
944         *_TotalBufferLength += MmGetMdlByteCount(Buffer);
945         Buffer = Buffer->Next;
946     }
947 }
948 
949 /*
950  * @implemented
951  */
952 #undef NdisQueryBuffer
953 VOID
954 EXPORT
NdisQueryBuffer(IN PNDIS_BUFFER Buffer,OUT PVOID * VirtualAddress OPTIONAL,OUT PUINT Length)955 NdisQueryBuffer(
956     IN  PNDIS_BUFFER    Buffer,
957     OUT PVOID           *VirtualAddress OPTIONAL,
958     OUT PUINT           Length)
959 /*
960  * FUNCTION:
961  *     Queries an NDIS buffer for information
962  * ARGUMENTS:
963  *     Buffer         = Pointer to NDIS buffer to query
964  *     VirtualAddress = Address of buffer to place virtual address
965  *     Length         = Address of buffer to place length of buffer
966  */
967 {
968 	if (VirtualAddress != NULL)
969 		*(PVOID*)VirtualAddress = MmGetSystemAddressForMdl(Buffer);
970 
971 	*Length = MmGetMdlByteCount(Buffer);
972 }
973 
974 
975 /*
976  * @implemented
977  */
978 #undef NdisQueryBufferSafe
979 VOID
980 EXPORT
NdisQueryBufferSafe(IN PNDIS_BUFFER Buffer,OUT PVOID * VirtualAddress OPTIONAL,OUT PUINT Length,IN UINT Priority)981 NdisQueryBufferSafe(
982     IN  PNDIS_BUFFER    Buffer,
983     OUT PVOID           *VirtualAddress OPTIONAL,
984     OUT PUINT           Length,
985     IN  UINT            Priority)
986 /*
987  * FUNCTION:
988  * ARGUMENTS:
989  * NOTES:
990  *    NDIS 5.0
991  */
992 {
993     if (VirtualAddress != NULL)
994         *VirtualAddress = MmGetSystemAddressForMdlSafe(Buffer, Priority);
995     *Length = MmGetMdlByteCount(Buffer);
996 }
997 
998 
999 /*
1000  * @implemented
1001  */
1002 #undef NdisQueryBufferOffset
1003 VOID
1004 EXPORT
NdisQueryBufferOffset(IN PNDIS_BUFFER Buffer,OUT PUINT Offset,OUT PUINT Length)1005 NdisQueryBufferOffset(
1006     IN  PNDIS_BUFFER    Buffer,
1007     OUT PUINT           Offset,
1008     OUT PUINT           Length)
1009 {
1010     *((PUINT)Offset) = MmGetMdlByteOffset(Buffer);
1011     *((PUINT)Length) = MmGetMdlByteCount(Buffer);
1012 }
1013 
1014 
1015 /*
1016  * @implemented
1017  */
1018 VOID
1019 EXPORT
NdisUnchainBufferAtBack(IN OUT PNDIS_PACKET Packet,OUT PNDIS_BUFFER * Buffer)1020 NdisUnchainBufferAtBack(
1021     IN OUT  PNDIS_PACKET    Packet,
1022     OUT     PNDIS_BUFFER    *Buffer)
1023 /*
1024  * FUNCTION:
1025  *     Removes the last buffer in a packet
1026  * ARGUMENTS:
1027  *     Packet = Pointer to NDIS packet
1028  *     Buffer = Address of buffer to place pointer to removed NDIS buffer
1029  */
1030 {
1031 	PNDIS_BUFFER NdisBuffer, Previous;
1032 
1033     NdisQueryPacket(Packet,
1034                     NULL,
1035                     NULL,
1036                     &NdisBuffer,
1037                     NULL);
1038     if (!NdisBuffer) {
1039         NDIS_DbgPrint(MID_TRACE, ("No buffer to unchain\n"));
1040         *Buffer = NULL;
1041         return;
1042     }
1043 
1044     Previous = NULL;
1045     while (NdisBuffer->Next) {
1046         Previous   = NdisBuffer;
1047         NdisBuffer = NdisBuffer->Next;
1048     }
1049 
1050     if (Previous) {
1051         Previous->Next       = NULL;
1052         Packet->Private.Tail = Previous;
1053     } else {
1054         Packet->Private.Head = NULL;
1055         Packet->Private.Tail = NULL;
1056     }
1057 
1058     Packet->Private.ValidCounts = FALSE;
1059 
1060     *Buffer = NdisBuffer;
1061 }
1062 
1063 
1064 /*
1065  * @implemented
1066  */
1067 VOID
1068 EXPORT
NdisUnchainBufferAtFront(IN OUT PNDIS_PACKET Packet,OUT PNDIS_BUFFER * Buffer)1069 NdisUnchainBufferAtFront(
1070     IN OUT  PNDIS_PACKET    Packet,
1071     OUT     PNDIS_BUFFER    *Buffer)
1072 /*
1073  * FUNCTION:
1074  *     Removes the first buffer in a packet
1075  * ARGUMENTS:
1076  *     Packet = Pointer to NDIS packet
1077  *     Buffer = Address of buffer to place pointer to removed NDIS buffer
1078  */
1079 {
1080 	PNDIS_BUFFER NdisBuffer;
1081 
1082     NdisQueryPacket(Packet,
1083                     NULL,
1084                     NULL,
1085                     &NdisBuffer,
1086                     NULL);
1087     if (!NdisBuffer) {
1088         NDIS_DbgPrint(MID_TRACE, ("No buffer to unchain\n"));
1089         *Buffer = NULL;
1090         return;
1091     }
1092 
1093     Packet->Private.Head = NdisBuffer->Next;
1094 
1095     if (!NdisBuffer->Next)
1096         Packet->Private.Tail = NULL;
1097 
1098     NdisBuffer->Next = NULL;
1099 
1100     Packet->Private.ValidCounts = FALSE;
1101 
1102     *Buffer = NdisBuffer;
1103 }
1104 
1105 /*
1106  * @implemented
1107  */
1108 VOID
1109 EXPORT
NdisCopyBuffer(OUT PNDIS_STATUS Status,OUT PNDIS_BUFFER * Buffer,IN NDIS_HANDLE PoolHandle,IN PVOID MemoryDescriptor,IN UINT Offset,IN UINT Length)1110 NdisCopyBuffer(
1111     OUT PNDIS_STATUS    Status,
1112     OUT PNDIS_BUFFER    *Buffer,
1113     IN  NDIS_HANDLE     PoolHandle,
1114     IN  PVOID           MemoryDescriptor,
1115     IN  UINT            Offset,
1116     IN  UINT            Length)
1117 /*
1118  * FUNCTION: Returns a new buffer descriptor for a (partial) buffer
1119  * ARGUMENTS:
1120  *     Status           = Address of a buffer to place status of operation
1121  *     Buffer           = Address of a buffer to place new buffer descriptor
1122  *     PoolHandle       = Handle returned by NdisAllocateBufferPool
1123  *     MemoryDescriptor = Pointer to a memory descriptor (possibly NDIS_BUFFER)
1124  *     Offset           = Offset in buffer to start copying
1125  *     Length           = Number of bytes to copy
1126  */
1127 {
1128     PVOID CurrentVa = (PUCHAR)(MmGetMdlVirtualAddress((PNDIS_BUFFER)MemoryDescriptor)) + Offset;
1129 
1130     NDIS_DbgPrint(MAX_TRACE, ("Called\n"));
1131 
1132     *Buffer = IoAllocateMdl(CurrentVa, Length, FALSE, FALSE, NULL);
1133     if (!*Buffer)
1134     {
1135         NDIS_DbgPrint(MIN_TRACE, ("IoAllocateMdl failed (%x, %lx)\n", CurrentVa, Length));
1136         *Status = NDIS_STATUS_FAILURE;
1137         return;
1138     }
1139 
1140     IoBuildPartialMdl((PNDIS_BUFFER)MemoryDescriptor,
1141                       *Buffer,
1142                       CurrentVa,
1143                       Length);
1144 
1145     (*Buffer)->Next = NULL;
1146     *Status = NDIS_STATUS_SUCCESS;
1147 }
1148 
1149 /*
1150  * @implemented
1151  */
1152 NDIS_HANDLE
1153 EXPORT
NdisGetPoolFromPacket(IN PNDIS_PACKET Packet)1154 NdisGetPoolFromPacket(
1155     IN PNDIS_PACKET  Packet)
1156 {
1157     return Packet->Private.Pool;
1158 }
1159 
1160 /*
1161  * @implemented
1162  */
1163 UINT
1164 EXPORT
NdisPacketSize(IN UINT ProtocolReservedSize)1165 NdisPacketSize(
1166     IN UINT  ProtocolReservedSize)
1167 {
1168     return sizeof(NDIS_PACKET) + sizeof(NDIS_PACKET_OOB_DATA) +
1169                  sizeof(NDIS_PACKET_EXTENSION) + ProtocolReservedSize;
1170 }
1171 
1172 /*
1173  * @implemented
1174  */
1175 #undef NdisGetPacketCancelId
1176 PVOID
1177 EXPORT
NdisGetPacketCancelId(IN PNDIS_PACKET Packet)1178 NdisGetPacketCancelId(
1179     IN PNDIS_PACKET  Packet)
1180 {
1181     return NDIS_GET_PACKET_CANCEL_ID(Packet);
1182 }
1183 
1184 /*
1185  * @implemented
1186  */
1187 #undef NdisSetPacketCancelId
1188 VOID
1189 EXPORT
NdisSetPacketCancelId(IN PNDIS_PACKET Packet,IN PVOID CancelId)1190 NdisSetPacketCancelId(
1191     IN PNDIS_PACKET  Packet,
1192     IN PVOID  CancelId)
1193 {
1194     NDIS_SET_PACKET_CANCEL_ID(Packet, CancelId);
1195 }
1196 
1197 /*
1198  * @implemented
1199  */
1200 VOID
1201 EXPORT
NdisCopyFromPacketToPacketSafe(IN PNDIS_PACKET Destination,IN UINT DestinationOffset,IN UINT BytesToCopy,IN PNDIS_PACKET Source,IN UINT SourceOffset,OUT PUINT BytesCopied,IN MM_PAGE_PRIORITY Priority)1202 NdisCopyFromPacketToPacketSafe(
1203     IN  PNDIS_PACKET     Destination,
1204     IN  UINT             DestinationOffset,
1205     IN  UINT             BytesToCopy,
1206     IN  PNDIS_PACKET     Source,
1207     IN  UINT             SourceOffset,
1208     OUT PUINT            BytesCopied,
1209     IN  MM_PAGE_PRIORITY Priority)
1210 {
1211     PNDIS_BUFFER SrcBuffer;
1212     PNDIS_BUFFER DstBuffer;
1213     PUCHAR DstData, SrcData;
1214     UINT DstSize, SrcSize;
1215     UINT Count, Total;
1216 
1217     *BytesCopied = 0;
1218 
1219     /* Skip DestinationOffset bytes in the destination packet */
1220     NdisGetFirstBufferFromPacketSafe(Destination, &DstBuffer, (PVOID*)&DstData, &DstSize, &Total, Priority);
1221     if (!DstData || SkipToOffset(DstBuffer, DestinationOffset, &DstData, &DstSize) == 0xFFFFFFFF)
1222         return;
1223 
1224     /* Skip SourceOffset bytes in the source packet */
1225     NdisGetFirstBufferFromPacketSafe(Source, &SrcBuffer, (PVOID*)&SrcData, &SrcSize, &Total, Priority);
1226     if (!SrcData || SkipToOffset(SrcBuffer, SourceOffset, &SrcData, &SrcSize) == 0xFFFFFFFF)
1227         return;
1228 
1229     /* Copy the data */
1230     for (Total = 0;;) {
1231         /* Find out how many bytes we can copy at one time */
1232         if (BytesToCopy < SrcSize)
1233             Count = BytesToCopy;
1234         else
1235             Count = SrcSize;
1236         if (DstSize < Count)
1237             Count = DstSize;
1238 
1239         RtlCopyMemory(DstData, SrcData, Count);
1240 
1241         Total       += Count;
1242         BytesToCopy -= Count;
1243         if (BytesToCopy == 0)
1244             break;
1245 
1246         DstSize -= Count;
1247         if (DstSize == 0) {
1248             /* No more bytes in destination buffer. Proceed to
1249                the next buffer in the destination buffer chain */
1250             NdisGetNextBuffer(DstBuffer, &DstBuffer);
1251             if (!DstBuffer)
1252                 break;
1253 
1254             NdisQueryBufferSafe(DstBuffer, (PVOID)&DstData, &DstSize, Priority);
1255             if (!DstData)
1256                 break;
1257         }
1258 
1259         SrcSize -= Count;
1260         if (SrcSize == 0) {
1261             /* No more bytes in source buffer. Proceed to
1262                the next buffer in the source buffer chain */
1263             NdisGetNextBuffer(SrcBuffer, &SrcBuffer);
1264             if (!SrcBuffer)
1265                 break;
1266 
1267             NdisQueryBufferSafe(SrcBuffer, (PVOID)&SrcData, &SrcSize, Priority);
1268             if (!SrcData)
1269                 break;
1270         }
1271     }
1272 
1273     *BytesCopied = Total;
1274 }
1275 
1276 /*
1277  * @implemented
1278  */
1279 VOID
1280 EXPORT
NdisIMCopySendCompletePerPacketInfo(IN PNDIS_PACKET DstPacket,IN PNDIS_PACKET SrcPacket)1281 NdisIMCopySendCompletePerPacketInfo(
1282     IN  PNDIS_PACKET    DstPacket,
1283     IN  PNDIS_PACKET    SrcPacket)
1284 /*
1285  * FUNCTION:
1286  * ARGUMENTS:
1287  * NOTES:
1288  *    NDIS 5.0
1289  */
1290 {
1291     /* FIXME: What is the difference between NdisIMCopySendPerPacketInfo and
1292      * NdisIMCopySendCompletePerPacketInfo?
1293      */
1294 
1295     NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
1296 
1297     RtlCopyMemory(NDIS_PACKET_EXTENSION_FROM_PACKET(DstPacket),
1298                   NDIS_PACKET_EXTENSION_FROM_PACKET(SrcPacket),
1299                   sizeof(NDIS_PACKET_EXTENSION));
1300 }
1301 
1302 
1303 /*
1304  * @implemented
1305  */
1306 VOID
1307 EXPORT
NdisIMCopySendPerPacketInfo(IN PNDIS_PACKET DstPacket,IN PNDIS_PACKET SrcPacket)1308 NdisIMCopySendPerPacketInfo(
1309     IN  PNDIS_PACKET    DstPacket,
1310     IN  PNDIS_PACKET    SrcPacket)
1311 /*
1312  * FUNCTION:
1313  * ARGUMENTS:
1314  * NOTES:
1315  *    NDIS 5.0
1316  */
1317 {
1318     /* FIXME: What is the difference between NdisIMCopySendPerPacketInfo and
1319      * NdisIMCopySendCompletePerPacketInfo?
1320      */
1321 
1322     NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
1323 
1324     RtlCopyMemory(NDIS_PACKET_EXTENSION_FROM_PACKET(DstPacket),
1325                   NDIS_PACKET_EXTENSION_FROM_PACKET(SrcPacket),
1326                   sizeof(NDIS_PACKET_EXTENSION));
1327 }
1328 
1329 /* EOF */
1330