- Forgot to commit these for MSVC build...
[reactos.git] / reactos / drivers / net / tcpip / tcpip / mockbuffer.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS TCP/IP protocol driver
4 * FILE: tcpip/buffer.c
5 * PURPOSE: Miscellaneous operations on NDIS_BUFFERs and packets.
6 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
7 * REVISIONS:
8 * CSH 01/08-2000 Created
9 */
10
11 #include "precomp.h"
12
13 VOID XNdisGetFirstBufferFromPacket(PNDIS_PACKET Packet,
14 PNDIS_BUFFER *FirstBuffer,
15 PVOID *FirstBufferVA,
16 PUINT FirstBufferLength,
17 PUINT TotalBufferLength)
18 {
19 PNDIS_BUFFER _Buffer;
20
21 _Buffer = (Packet)->Private.Head;
22 *(FirstBuffer) = _Buffer;
23 *(FirstBufferVA) = MmGetMdlVirtualAddress(_Buffer);
24 if (_Buffer != NULL) {
25 *(FirstBufferLength) = MmGetMdlByteCount(_Buffer);
26 _Buffer = _Buffer->Next;
27 } else
28 *(FirstBufferLength) = 0;
29 *(TotalBufferLength) = *(FirstBufferLength);
30 while (_Buffer != NULL) {
31 *(TotalBufferLength) += MmGetMdlByteCount(_Buffer);
32 _Buffer = _Buffer->Next;
33 }
34 }
35
36 /*
37 * @implemented
38 */
39 VOID XNdisQueryBuffer
40 (PNDIS_BUFFER Buffer,
41 PVOID *VirtualAddress,
42 PUINT Length)
43 /*
44 * FUNCTION:
45 * Queries an NDIS buffer for information
46 * ARGUMENTS:
47 * Buffer = Pointer to NDIS buffer to query
48 * VirtualAddress = Address of buffer to place virtual address
49 * Length = Address of buffer to place length of buffer
50 */
51 {
52 if (VirtualAddress != NULL)
53 *(PVOID*)VirtualAddress = Buffer->MappedSystemVa;
54
55 *Length = ((PMDL)Buffer)->ByteCount;
56 }
57
58 __inline INT SkipToOffset(
59 PNDIS_BUFFER Buffer,
60 UINT Offset,
61 PCHAR *Data,
62 PUINT Size)
63 /*
64 * FUNCTION: Skip Offset bytes into a buffer chain
65 * ARGUMENTS:
66 * Buffer = Pointer to NDIS buffer
67 * Offset = Number of bytes to skip
68 * Data = Address of a pointer that on return will contain the
69 * address of the offset in the buffer
70 * Size = Address of a pointer that on return will contain the
71 * size of the destination buffer
72 * RETURNS:
73 * Offset into buffer, -1 if buffer chain was smaller than Offset bytes
74 * NOTES:
75 * Buffer may be NULL
76 */
77 {
78 for (;;) {
79
80 if (!Buffer)
81 return -1;
82
83 XNdisQueryBuffer(Buffer, (PVOID)Data, Size);
84
85 if (Offset < *Size) {
86 *Data = (PCHAR)((ULONG_PTR) *Data + Offset);
87 *Size -= Offset;
88 break;
89 }
90
91 Offset -= *Size;
92
93 NdisGetNextBuffer(Buffer, &Buffer);
94 }
95
96 return Offset;
97 }
98
99
100 UINT CopyBufferToBufferChain(
101 PNDIS_BUFFER DstBuffer,
102 UINT DstOffset,
103 PCHAR SrcData,
104 UINT Length)
105 /*
106 * FUNCTION: Copies data from a buffer to an NDIS buffer chain
107 * ARGUMENTS:
108 * DstBuffer = Pointer to destination NDIS buffer
109 * DstOffset = Destination start offset
110 * SrcData = Pointer to source buffer
111 * Length = Number of bytes to copy
112 * RETURNS:
113 * Number of bytes copied to destination buffer
114 * NOTES:
115 * The number of bytes copied may be limited by the destination
116 * buffer size
117 */
118 {
119 UINT BytesCopied, BytesToCopy, DstSize;
120 PCHAR DstData;
121
122 TI_DbgPrint(DEBUG_PBUFFER, ("DstBuffer (0x%X) DstOffset (0x%X) SrcData (0x%X) Length (%d)\n", DstBuffer, DstOffset, SrcData, Length));
123
124 /* Skip DstOffset bytes in the destination buffer chain */
125 if (SkipToOffset(DstBuffer, DstOffset, &DstData, &DstSize) == -1)
126 return 0;
127
128 /* Start copying the data */
129 BytesCopied = 0;
130 for (;;) {
131 BytesToCopy = MIN(DstSize, Length);
132
133 RtlCopyMemory((PVOID)DstData, (PVOID)SrcData, BytesToCopy);
134 BytesCopied += BytesToCopy;
135 SrcData = (PCHAR)((ULONG_PTR)SrcData + BytesToCopy);
136
137 Length -= BytesToCopy;
138 if (Length == 0)
139 break;
140
141 DstSize -= BytesToCopy;
142 if (DstSize == 0) {
143 /* No more bytes in desination buffer. Proceed to
144 the next buffer in the destination buffer chain */
145 NdisGetNextBuffer(DstBuffer, &DstBuffer);
146 if (!DstBuffer)
147 break;
148
149 XNdisQueryBuffer(DstBuffer, (PVOID)&DstData, &DstSize);
150 }
151 }
152
153 return BytesCopied;
154 }
155
156
157 UINT CopyBufferChainToBuffer(
158 PCHAR DstData,
159 PNDIS_BUFFER SrcBuffer,
160 UINT SrcOffset,
161 UINT Length)
162 /*
163 * FUNCTION: Copies data from an NDIS buffer chain to a buffer
164 * ARGUMENTS:
165 * DstData = Pointer to destination buffer
166 * SrcBuffer = Pointer to source NDIS buffer
167 * SrcOffset = Source start offset
168 * Length = Number of bytes to copy
169 * RETURNS:
170 * Number of bytes copied to destination buffer
171 * NOTES:
172 * The number of bytes copied may be limited by the source
173 * buffer size
174 */
175 {
176 UINT BytesCopied, BytesToCopy, SrcSize;
177 PCHAR SrcData;
178
179 TI_DbgPrint(DEBUG_PBUFFER, ("DstData 0x%X SrcBuffer 0x%X SrcOffset 0x%X Length %d\n",DstData,SrcBuffer, SrcOffset, Length));
180
181 /* Skip SrcOffset bytes in the source buffer chain */
182 if (SkipToOffset(SrcBuffer, SrcOffset, &SrcData, &SrcSize) == -1)
183 return 0;
184
185 /* Start copying the data */
186 BytesCopied = 0;
187 for (;;) {
188 BytesToCopy = MIN(SrcSize, Length);
189
190 TI_DbgPrint(DEBUG_PBUFFER, ("Copying (%d) bytes from 0x%X to 0x%X\n", BytesToCopy, SrcData, DstData));
191
192 RtlCopyMemory((PVOID)DstData, (PVOID)SrcData, BytesToCopy);
193 BytesCopied += BytesToCopy;
194 DstData = (PCHAR)((ULONG_PTR)DstData + BytesToCopy);
195
196 Length -= BytesToCopy;
197 if (Length == 0)
198 break;
199
200 SrcSize -= BytesToCopy;
201 if (SrcSize == 0) {
202 /* No more bytes in source buffer. Proceed to
203 the next buffer in the source buffer chain */
204 NdisGetNextBuffer(SrcBuffer, &SrcBuffer);
205 if (!SrcBuffer)
206 break;
207
208 XNdisQueryBuffer(SrcBuffer, (PVOID)&SrcData, &SrcSize);
209 }
210 }
211
212 return BytesCopied;
213 }
214
215
216 UINT CopyPacketToBuffer(
217 PCHAR DstData,
218 PNDIS_PACKET SrcPacket,
219 UINT SrcOffset,
220 UINT Length)
221 /*
222 * FUNCTION: Copies data from an NDIS packet to a buffer
223 * ARGUMENTS:
224 * DstData = Pointer to destination buffer
225 * SrcPacket = Pointer to source NDIS packet
226 * SrcOffset = Source start offset
227 * Length = Number of bytes to copy
228 * RETURNS:
229 * Number of bytes copied to destination buffer
230 * NOTES:
231 * The number of bytes copied may be limited by the source
232 * buffer size
233 */
234 {
235 PNDIS_BUFFER FirstBuffer;
236 PVOID Address;
237 UINT FirstLength;
238 UINT TotalLength;
239
240 TI_DbgPrint(DEBUG_PBUFFER, ("DstData (0x%X) SrcPacket (0x%X) SrcOffset (0x%X) Length (%d)\n", DstData, SrcPacket, SrcOffset, Length));
241
242 XNdisGetFirstBufferFromPacket(SrcPacket,
243 &FirstBuffer,
244 &Address,
245 &FirstLength,
246 &TotalLength);
247
248 return CopyBufferChainToBuffer(DstData, FirstBuffer, SrcOffset, Length);
249 }
250
251
252 UINT CopyPacketToBufferChain(
253 PNDIS_BUFFER DstBuffer,
254 UINT DstOffset,
255 PNDIS_PACKET SrcPacket,
256 UINT SrcOffset,
257 UINT Length)
258 /*
259 * FUNCTION: Copies data from an NDIS packet to an NDIS buffer chain
260 * ARGUMENTS:
261 * DstBuffer = Pointer to destination NDIS buffer
262 * DstOffset = Destination start offset
263 * SrcPacket = Pointer to source NDIS packet
264 * SrcOffset = Source start offset
265 * Length = Number of bytes to copy
266 * RETURNS:
267 * Number of bytes copied to destination buffer
268 * NOTES:
269 * The number of bytes copied may be limited by the source and
270 * destination buffer sizes
271 */
272 {
273 PNDIS_BUFFER SrcBuffer;
274 PCHAR DstData, SrcData;
275 UINT DstSize, SrcSize;
276 UINT Count, Total;
277
278 TI_DbgPrint(DEBUG_PBUFFER, ("DstBuffer (0x%X) DstOffset (0x%X) SrcPacket (0x%X) SrcOffset (0x%X) Length (%d)\n", DstBuffer, DstOffset, SrcPacket, SrcOffset, Length));
279
280 /* Skip DstOffset bytes in the destination buffer chain */
281 XNdisQueryBuffer(DstBuffer, (PVOID)&DstData, &DstSize);
282 if (SkipToOffset(DstBuffer, DstOffset, &DstData, &DstSize) == -1)
283 return 0;
284
285 /* Skip SrcOffset bytes in the source packet */
286 XNdisGetFirstBufferFromPacket(SrcPacket, &SrcBuffer, (PVOID *)&SrcData, &SrcSize, &Total);
287 if (SkipToOffset(SrcBuffer, SrcOffset, &SrcData, &SrcSize) == -1)
288 return 0;
289
290 /* Copy the data */
291 for (Total = 0;;) {
292 /* Find out how many bytes we can copy at one time */
293 if (Length < SrcSize)
294 Count = Length;
295 else
296 Count = SrcSize;
297 if (DstSize < Count)
298 Count = DstSize;
299
300 RtlCopyMemory((PVOID)DstData, (PVOID)SrcData, Count);
301
302 Total += Count;
303 Length -= Count;
304 if (Length == 0)
305 break;
306
307 DstSize -= Count;
308 if (DstSize == 0) {
309 /* No more bytes in destination buffer. Proceed to
310 the next buffer in the destination buffer chain */
311 NdisGetNextBuffer(DstBuffer, &DstBuffer);
312 if (!DstBuffer)
313 break;
314
315 XNdisQueryBuffer(DstBuffer, (PVOID)&DstData, &DstSize);
316 }
317
318 SrcSize -= Count;
319 if (SrcSize == 0) {
320 /* No more bytes in source buffer. Proceed to
321 the next buffer in the source buffer chain */
322 NdisGetNextBuffer(SrcBuffer, &SrcBuffer);
323 if (!SrcBuffer)
324 break;
325
326 XNdisQueryBuffer(SrcBuffer, (PVOID)&SrcData, &SrcSize);
327 }
328 }
329
330 return Total;
331 }
332
333
334 PVOID AdjustPacket(
335 PNDIS_PACKET Packet,
336 UINT Available,
337 UINT Needed)
338 /*
339 * FUNCTION: Adjusts the amount of unused space at the beginning of the packet
340 * ARGUMENTS:
341 * Packet = Pointer to packet
342 * Available = Number of bytes available at start of first buffer
343 * Needed = Number of bytes needed for the header
344 * RETURNS:
345 * Pointer to start of packet
346 */
347 {
348 PNDIS_BUFFER NdisBuffer;
349 INT Adjust;
350
351 TI_DbgPrint(DEBUG_PBUFFER, ("Available = %d, Needed = %d.\n", Available, Needed));
352
353 Adjust = Available - Needed;
354
355 NdisQueryPacket(Packet, NULL, NULL, &NdisBuffer, NULL);
356
357 /* If Adjust is zero there is no need to adjust this packet as
358 there is no additional space at start the of first buffer */
359 if (Adjust != 0) {
360 NdisBuffer->MappedSystemVa = (PVOID) ((ULONG_PTR)(NdisBuffer->MappedSystemVa) + Adjust);
361 NdisBuffer->ByteOffset += Adjust;
362 NdisBuffer->ByteCount -= Adjust;
363 }
364
365 return NdisBuffer->MappedSystemVa;
366 }
367
368
369 UINT ResizePacket(
370 PNDIS_PACKET Packet,
371 UINT Size)
372 /*
373 * FUNCTION: Resizes an NDIS packet
374 * ARGUMENTS:
375 * Packet = Pointer to packet
376 * Size = Number of bytes in first buffer
377 * RETURNS:
378 * Previous size of first buffer
379 */
380 {
381 PNDIS_BUFFER NdisBuffer;
382 UINT OldSize;
383
384 NdisQueryPacket(Packet, NULL, NULL, &NdisBuffer, NULL);
385
386 OldSize = NdisBuffer->ByteCount;
387
388 if (Size != OldSize)
389 NdisBuffer->ByteCount = Size;
390
391 return OldSize;
392 }
393
394 NDIS_STATUS PrependPacket( PNDIS_PACKET Packet, PCHAR Data, UINT Length,
395 BOOLEAN Copy ) {
396 PNDIS_BUFFER Buffer;
397 NDIS_STATUS Status;
398 PCHAR NewBuf;
399
400 if( Copy ) {
401 NewBuf = PoolAllocateBuffer( Length );
402 if( !NewBuf ) return STATUS_NO_MEMORY;
403 RtlCopyMemory( NewBuf, Data, Length );
404 } else NewBuf = Data;
405
406 NdisAllocateBuffer( &Status, &Buffer, GlobalBufferPool, Data, Length );
407 if( Status != NDIS_STATUS_SUCCESS ) return Status;
408
409 NdisChainBufferAtFront( Packet, Buffer );
410
411 return STATUS_SUCCESS;
412 }
413
414 void GetDataPtr( PNDIS_PACKET Packet,
415 UINT Offset,
416 PCHAR *DataOut,
417 PUINT Size ) {
418 PNDIS_BUFFER Buffer;
419
420 NdisQueryPacket(Packet, NULL, NULL, &Buffer, NULL);
421 if( !Buffer ) return;
422 SkipToOffset( Buffer, Offset, DataOut, Size );
423 }
424
425 NDIS_STATUS AllocatePacketWithBufferX( PNDIS_PACKET *NdisPacket,
426 PCHAR Data, UINT Len,
427 PCHAR File, UINT Line ) {
428 PNDIS_PACKET Packet;
429 PNDIS_BUFFER Buffer;
430 NDIS_STATUS Status;
431 PCHAR NewData;
432
433 NewData = ExAllocatePool( NonPagedPool, Len );
434 if( !NewData ) return NDIS_STATUS_NOT_ACCEPTED; // XXX
435 TrackWithTag(EXALLOC_TAG, NewData, File, Line);
436
437 if( Data )
438 RtlCopyMemory(NewData, Data, Len);
439
440 NdisAllocatePacket( &Status, &Packet, GlobalPacketPool );
441 if( Status != NDIS_STATUS_SUCCESS ) {
442 ExFreePool( NewData );
443 return Status;
444 }
445 TrackWithTag(NDIS_PACKET_TAG, Packet, File, Line);
446
447 NdisAllocateBuffer( &Status, &Buffer, GlobalBufferPool, NewData, Len );
448 if( Status != NDIS_STATUS_SUCCESS ) {
449 ExFreePool( NewData );
450 FreeNdisPacket( Packet );
451 }
452 TrackWithTag(NDIS_BUFFER_TAG, Buffer, File, Line);
453
454 NdisChainBufferAtFront( Packet, Buffer );
455 *NdisPacket = Packet;
456
457 return NDIS_STATUS_SUCCESS;
458 }
459
460
461 VOID FreeNdisPacketX
462 ( PNDIS_PACKET Packet,
463 PCHAR File,
464 UINT Line )
465 /*
466 * FUNCTION: Frees an NDIS packet
467 * ARGUMENTS:
468 * Packet = Pointer to NDIS packet to be freed
469 */
470 {
471 PNDIS_BUFFER Buffer, NextBuffer;
472
473 TI_DbgPrint(DEBUG_PBUFFER, ("Packet (0x%X)\n", Packet));
474
475 /* Free all the buffers in the packet first */
476 NdisQueryPacket(Packet, NULL, NULL, &Buffer, NULL);
477 for (; Buffer != NULL; Buffer = NextBuffer) {
478 PVOID Data;
479 UINT Length;
480
481 NdisGetNextBuffer(Buffer, &NextBuffer);
482 XNdisQueryBuffer(Buffer, &Data, &Length);
483 UntrackFL(File,Line,Buffer);
484 NdisFreeBuffer(Buffer);
485 UntrackFL(File,Line,Data);
486 ExFreePool(Data);
487 }
488
489 /* Finally free the NDIS packet discriptor */
490 UntrackFL(File,Line,Packet);
491 NdisFreePacket(Packet);
492 }