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