ReactOS  0.4.14-dev-57-g333b8f1
buffer.c
Go to the documentation of this file.
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 __inline INT SkipToOffset(
15  UINT Offset,
16  PCHAR *Data,
17  PUINT Size)
18 /*
19  * FUNCTION: Skip Offset bytes into a buffer chain
20  * ARGUMENTS:
21  * Buffer = Pointer to NDIS buffer
22  * Offset = Number of bytes to skip
23  * Data = Address of a pointer that on return will contain the
24  * address of the offset in the buffer
25  * Size = Address of a pointer that on return will contain the
26  * size of the destination buffer
27  * RETURNS:
28  * Offset into buffer, -1 if buffer chain was smaller than Offset bytes
29  * NOTES:
30  * Buffer may be NULL
31  */
32 {
33  for (;;) {
34 
35  if (!Buffer)
36  return -1;
37 
39 
40  if (Offset < *Size) {
41  *Data = (PCHAR)((ULONG_PTR) *Data + Offset);
42  *Size -= Offset;
43  break;
44  }
45 
46  Offset -= *Size;
47 
49  }
50 
51  return Offset;
52 }
53 
54 
56  PNDIS_BUFFER DstBuffer,
57  UINT DstOffset,
58  PCHAR SrcData,
59  UINT Length)
60 /*
61  * FUNCTION: Copies data from a buffer to an NDIS buffer chain
62  * ARGUMENTS:
63  * DstBuffer = Pointer to destination NDIS buffer
64  * DstOffset = Destination start offset
65  * SrcData = Pointer to source buffer
66  * Length = Number of bytes to copy
67  * RETURNS:
68  * Number of bytes copied to destination buffer
69  * NOTES:
70  * The number of bytes copied may be limited by the destination
71  * buffer size
72  */
73 {
74  UINT BytesCopied, BytesToCopy, DstSize;
75  PCHAR DstData;
76 
77  TI_DbgPrint(DEBUG_PBUFFER, ("DstBuffer (0x%X) DstOffset (0x%X) SrcData (0x%X) Length (%d)\n", DstBuffer, DstOffset, SrcData, Length));
78 
79  /* Skip DstOffset bytes in the destination buffer chain */
80  if (SkipToOffset(DstBuffer, DstOffset, &DstData, &DstSize) == -1)
81  return 0;
82 
83  /* Start copying the data */
84  BytesCopied = 0;
85  for (;;) {
86  BytesToCopy = MIN(DstSize, Length);
87 
88  RtlCopyMemory((PVOID)DstData, (PVOID)SrcData, BytesToCopy);
90  SrcData = (PCHAR)((ULONG_PTR)SrcData + BytesToCopy);
91 
93  if (Length == 0)
94  break;
95 
96  DstSize -= BytesToCopy;
97  if (DstSize == 0) {
98  /* No more bytes in destination buffer. Proceed to
99  the next buffer in the destination buffer chain */
100  NdisGetNextBuffer(DstBuffer, &DstBuffer);
101  if (!DstBuffer)
102  break;
103 
104  NdisQueryBuffer(DstBuffer, (PVOID)&DstData, &DstSize);
105  }
106  }
107 
108  return BytesCopied;
109 }
110 
111 
113  PCHAR DstData,
114  PNDIS_BUFFER SrcBuffer,
115  UINT SrcOffset,
116  UINT Length)
117 /*
118  * FUNCTION: Copies data from an NDIS buffer chain to a buffer
119  * ARGUMENTS:
120  * DstData = Pointer to destination buffer
121  * SrcBuffer = Pointer to source NDIS buffer
122  * SrcOffset = Source start offset
123  * Length = Number of bytes to copy
124  * RETURNS:
125  * Number of bytes copied to destination buffer
126  * NOTES:
127  * The number of bytes copied may be limited by the source
128  * buffer size
129  */
130 {
131  UINT BytesCopied, BytesToCopy, SrcSize;
132  PCHAR SrcData;
133 
134  TI_DbgPrint(DEBUG_PBUFFER, ("DstData 0x%X SrcBuffer 0x%X SrcOffset 0x%X Length %d\n",DstData,SrcBuffer, SrcOffset, Length));
135 
136  /* Skip SrcOffset bytes in the source buffer chain */
137  if (SkipToOffset(SrcBuffer, SrcOffset, &SrcData, &SrcSize) == -1)
138  return 0;
139 
140  /* Start copying the data */
141  BytesCopied = 0;
142  for (;;) {
143  BytesToCopy = MIN(SrcSize, Length);
144 
145  TI_DbgPrint(DEBUG_PBUFFER, ("Copying (%d) bytes from 0x%X to 0x%X\n", BytesToCopy, SrcData, DstData));
146 
147  RtlCopyMemory((PVOID)DstData, (PVOID)SrcData, BytesToCopy);
149  DstData = (PCHAR)((ULONG_PTR)DstData + BytesToCopy);
150 
151  Length -= BytesToCopy;
152  if (Length == 0)
153  break;
154 
155  SrcSize -= BytesToCopy;
156  if (SrcSize == 0) {
157  /* No more bytes in source buffer. Proceed to
158  the next buffer in the source buffer chain */
159  NdisGetNextBuffer(SrcBuffer, &SrcBuffer);
160  if (!SrcBuffer)
161  break;
162 
163  NdisQueryBuffer(SrcBuffer, (PVOID)&SrcData, &SrcSize);
164  }
165  }
166 
167  return BytesCopied;
168 }
169 
170 
172  PCHAR DstData,
173  PNDIS_PACKET SrcPacket,
174  UINT SrcOffset,
175  UINT Length)
176 /*
177  * FUNCTION: Copies data from an NDIS packet to a buffer
178  * ARGUMENTS:
179  * DstData = Pointer to destination buffer
180  * SrcPacket = Pointer to source NDIS packet
181  * SrcOffset = Source start offset
182  * Length = Number of bytes to copy
183  * RETURNS:
184  * Number of bytes copied to destination buffer
185  * NOTES:
186  * The number of bytes copied may be limited by the source
187  * buffer size
188  */
189 {
190  PNDIS_BUFFER FirstBuffer;
191  PVOID Address;
192  UINT FirstLength;
194 
195  TI_DbgPrint(DEBUG_PBUFFER, ("DstData (0x%X) SrcPacket (0x%X) SrcOffset (0x%X) Length (%d)\n", DstData, SrcPacket, SrcOffset, Length));
196 
198  &FirstBuffer,
199  &Address,
200  &FirstLength,
201  &TotalLength);
202 
203  return CopyBufferChainToBuffer(DstData, FirstBuffer, SrcOffset, Length);
204 }
205 
206 
208  PNDIS_BUFFER DstBuffer,
209  UINT DstOffset,
210  PNDIS_PACKET SrcPacket,
211  UINT SrcOffset,
212  UINT Length)
213 /*
214  * FUNCTION: Copies data from an NDIS packet to an NDIS buffer chain
215  * ARGUMENTS:
216  * DstBuffer = Pointer to destination NDIS buffer
217  * DstOffset = Destination start offset
218  * SrcPacket = Pointer to source NDIS packet
219  * SrcOffset = Source start offset
220  * Length = Number of bytes to copy
221  * RETURNS:
222  * Number of bytes copied to destination buffer
223  * NOTES:
224  * The number of bytes copied may be limited by the source and
225  * destination buffer sizes
226  */
227 {
228  PNDIS_BUFFER SrcBuffer;
229  PCHAR DstData, SrcData;
230  UINT DstSize, SrcSize;
231  UINT Count, Total;
232 
233  TI_DbgPrint(DEBUG_PBUFFER, ("DstBuffer (0x%X) DstOffset (0x%X) SrcPacket (0x%X) SrcOffset (0x%X) Length (%d)\n", DstBuffer, DstOffset, SrcPacket, SrcOffset, Length));
234 
235  /* Skip DstOffset bytes in the destination buffer chain */
236  NdisQueryBuffer(DstBuffer, (PVOID)&DstData, &DstSize);
237  if (SkipToOffset(DstBuffer, DstOffset, &DstData, &DstSize) == -1)
238  return 0;
239 
240  /* Skip SrcOffset bytes in the source packet */
241  NdisGetFirstBufferFromPacket(SrcPacket, &SrcBuffer, (PVOID)&SrcData, &SrcSize, &Total);
242  if (SkipToOffset(SrcBuffer, SrcOffset, &SrcData, &SrcSize) == -1)
243  return 0;
244 
245  /* Copy the data */
246  for (Total = 0;;) {
247  /* Find out how many bytes we can copy at one time */
248  if (Length < SrcSize)
249  Count = Length;
250  else
251  Count = SrcSize;
252  if (DstSize < Count)
253  Count = DstSize;
254 
255  RtlCopyMemory((PVOID)DstData, (PVOID)SrcData, Count);
256 
257  Total += Count;
258  Length -= Count;
259  if (Length == 0)
260  break;
261 
262  DstSize -= Count;
263  if (DstSize == 0) {
264  /* No more bytes in destination buffer. Proceed to
265  the next buffer in the destination buffer chain */
266  NdisGetNextBuffer(DstBuffer, &DstBuffer);
267  if (!DstBuffer)
268  break;
269 
270  NdisQueryBuffer(DstBuffer, (PVOID)&DstData, &DstSize);
271  }
272 
273  SrcSize -= Count;
274  if (SrcSize == 0) {
275  /* No more bytes in source buffer. Proceed to
276  the next buffer in the source buffer chain */
277  NdisGetNextBuffer(SrcBuffer, &SrcBuffer);
278  if (!SrcBuffer)
279  break;
280 
281  NdisQueryBuffer(SrcBuffer, (PVOID)&SrcData, &SrcSize);
282  }
283  }
284 
285  return Total;
286 }
287 
288 
291  UINT Size)
292 /*
293  * FUNCTION: Resizes an NDIS packet
294  * ARGUMENTS:
295  * Packet = Pointer to packet
296  * Size = Number of bytes in first buffer
297  * RETURNS:
298  * Previous size of first buffer
299  */
300 {
301  PNDIS_BUFFER NdisBuffer;
302  UINT OldSize;
303 
304  NdisQueryPacket(Packet, NULL, NULL, &NdisBuffer, NULL);
305 
306  OldSize = NdisBuffer->ByteCount;
307 
308  if (Size != OldSize)
309  NdisBuffer->ByteCount = Size;
310 
311  return OldSize;
312 }
313 
315  UINT Offset,
316  PCHAR *DataOut,
317  PUINT Size ) {
319 
321  if( !Buffer ) return;
322  SkipToOffset( Buffer, Offset, DataOut, Size );
323 }
324 
326  PCHAR Data, UINT Len ) {
330  PCHAR NewData;
331 
333  if( !NewData ) return NDIS_STATUS_RESOURCES;
334 
335  if( Data ) RtlCopyMemory(NewData, Data, Len);
336 
338  if( Status != NDIS_STATUS_SUCCESS ) {
340  return Status;
341  }
342 
344  if( Status != NDIS_STATUS_SUCCESS ) {
347  return Status;
348  }
349 
351  *NdisPacket = Packet;
352 
353  return NDIS_STATUS_SUCCESS;
354 }
355 
356 
359 /*
360  * FUNCTION: Frees an NDIS packet
361  * ARGUMENTS:
362  * Packet = Pointer to NDIS packet to be freed
363  */
364 {
365  PNDIS_BUFFER Buffer, NextBuffer;
366 
367  TI_DbgPrint(DEBUG_PBUFFER, ("Packet (0x%X)\n", Packet));
368 
369  /* Free all the buffers in the packet first */
371  for (; Buffer != NULL; Buffer = NextBuffer) {
372  PVOID Data;
373  UINT Length;
374 
375  NdisGetNextBuffer(Buffer, &NextBuffer);
377  TI_DbgPrint(DEBUG_PBUFFER, ("Freeing ndis buffer (0x%X)\n", Buffer));
379  TI_DbgPrint(DEBUG_PBUFFER, ("Freeing exal buffer (0x%X)\n", Data));
381  }
382 
383  /* Finally free the NDIS packet descriptor */
385 }
signed char * PCHAR
Definition: retypes.h:7
#define TI_DbgPrint(_t_, _x_)
Definition: debug.h:45
VOID EXPORT NdisAllocatePacket(OUT PNDIS_STATUS Status, OUT PNDIS_PACKET *Packet, IN NDIS_HANDLE PoolHandle)
Definition: buffer.c:392
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
_In_ NDIS_HANDLE _In_ PNDIS_PACKET Packet
Definition: ndis.h:1548
MDL * PNDIS_BUFFER
Definition: ndis.h:343
_Inout_ __drv_aliasesMem PSLIST_ENTRY _Inout_ PSLIST_ENTRY _In_ ULONG Count
Definition: exfuncs.h:1015
VOID EXPORT NdisFreeBuffer(IN PNDIS_BUFFER Buffer)
Definition: buffer.c:809
#define NdisChainBufferAtFront(Packet, Buffer)
Definition: ndis.h:3106
_In_ ULONG TotalLength
Definition: usbdlib.h:145
int32_t INT
Definition: typedefs.h:56
_In_ UINT _In_ UINT BytesToCopy
Definition: ndis.h:3167
#define NdisGetNextBuffer(CurrentBuffer, NextBuffer)
Definition: ndis.h:3386
int NDIS_STATUS
Definition: ntddndis.h:471
uint32_t ULONG_PTR
Definition: typedefs.h:63
T MIN(T a, T b)
Definition: polytest.cpp:79
_In_ ULONG _In_ ULONG Offset
Definition: ntddpcm.h:101
UINT ResizePacket(PNDIS_PACKET Packet, UINT Size)
Definition: buffer.c:289
smooth NULL
Definition: ftsmooth.c:416
_In_ UINT _In_ UINT _In_ PNDIS_PACKET _In_ UINT _Out_ PUINT BytesCopied
Definition: ndis.h:3167
static WCHAR Address[46]
Definition: ping.c:68
_In_ LPGUID _In_ PVOID Data
Definition: classpnp.h:778
NDIS_STATUS AllocatePacketWithBuffer(PNDIS_PACKET *NdisPacket, PCHAR Data, UINT Len)
Definition: buffer.c:325
Definition: bufpool.h:45
VOID EXPORT NdisAllocateBuffer(OUT PNDIS_STATUS Status, OUT PNDIS_BUFFER *Buffer, IN NDIS_HANDLE PoolHandle, IN PVOID VirtualAddress, IN UINT Length)
Definition: buffer.c:334
UINT CopyPacketToBuffer(PUCHAR DstData, PNDIS_PACKET SrcPacket, UINT SrcOffset, UINT Length)
Definition: buffer.c:170
VOID EXPORT NdisGetFirstBufferFromPacket(IN PNDIS_PACKET _Packet, OUT PNDIS_BUFFER *_FirstBuffer, OUT PVOID *_FirstBufferVA, OUT PUINT _FirstBufferLength, OUT PUINT _TotalBufferLength)
Definition: buffer.c:871
#define PCHAR
Definition: match.c:90
VOID FreeNdisPacket(PNDIS_PACKET Packet)
Definition: buffer.c:358
UINT CopyPacketToBufferChain(PNDIS_BUFFER DstBuffer, UINT DstOffset, PNDIS_PACKET SrcPacket, UINT SrcOffset, UINT Length)
Definition: buffer.c:206
VOID EXPORT NdisFreePacket(IN PNDIS_PACKET Packet)
Definition: buffer.c:826
#define Len
Definition: deflate.h:82
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:101
#define DEBUG_PBUFFER
Definition: debug.h:20
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define NDIS_STATUS_SUCCESS
Definition: ndis.h:346
__inline ULONG SkipToOffset(IN PNDIS_BUFFER Buffer, IN UINT Offset, IN OUT PUCHAR *Data, IN OUT PUINT Size)
Definition: buffer.c:13
NDIS_HANDLE GlobalBufferPool
Definition: routines.c:4
IN PVOID IN PVOID IN USHORT IN USHORT Size
Definition: pci.h:359
Status
Definition: gdiplustypes.h:24
UINT CopyBufferToBufferChain(PNDIS_BUFFER DstBuffer, UINT DstOffset, PUCHAR SrcData, UINT Length)
Definition: buffer.c:54
void GetDataPtr(PNDIS_PACKET Packet, UINT Offset, PCHAR *DataOut, PUINT Size)
Definition: buffer.c:314
unsigned int UINT
Definition: ndis.h:50
static __inline VOID NdisQueryPacket(IN PNDIS_PACKET Packet, OUT PUINT PhysicalBufferCount OPTIONAL, OUT PUINT BufferCount OPTIONAL, OUT PNDIS_BUFFER *FirstBuffer OPTIONAL, OUT PUINT TotalPacketLength OPTIONAL)
Definition: ndis.h:3593
VOID EXPORT NdisQueryBuffer(IN PNDIS_BUFFER Buffer, OUT PVOID *VirtualAddress OPTIONAL, OUT PUINT Length)
Definition: buffer.c:953
NDIS_HANDLE GlobalPacketPool
Definition: routines.c:3
#define NDIS_STATUS_RESOURCES
Definition: ndis.h:466
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1099
IN BOOLEAN OUT PSTR Buffer
Definition: progress.h:34
#define PACKET_BUFFER_TAG
Definition: tags.h:27
unsigned int * PUINT
Definition: ndis.h:50
UINT CopyBufferChainToBuffer(PUCHAR DstData, PNDIS_BUFFER SrcBuffer, UINT SrcOffset, UINT Length)
Definition: buffer.c:111