[AFD]: Fix read data corruption when peeking at network data (TDI_RECEIVE_PEEK is...
[reactos.git] / reactos / drivers / network / afd / afd / read.c
1 ter/* $Id$
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: drivers/net/afd/afd/read.c
5 * PURPOSE: Ancillary functions driver
6 * PROGRAMMER: Art Yerkes (ayerkes@speakeasy.net)
7 * UPDATE HISTORY:
8 * 20040708 Created
9 *
10 * Improve buffering code
11 *
12 * We're keeping data receiving in one of two states:
13 * A) Some data available in the FCB
14 * FCB->Recv.BytesUsed != FCB->Recv.Content
15 * FCB->ReceiveIrp.InFlightRequest == NULL
16 * AFD_EVENT_RECEIVE set in FCB->PollState
17 * B) No data available in the FCB
18 * FCB->Recv.BytesUsed == FCB->Recv.Content (== 0)
19 * FCB->RecieveIrp.InFlightRequest != NULL
20 * AFD_EVENT_RECEIVED not set in FCB->PollState
21 * So basically we either have data available or a TDI receive
22 * in flight.
23 */
24 #include "afd.h"
25 #include "tdi_proto.h"
26 #include "tdiconn.h"
27 #include "debug.h"
28
29 static VOID HandleEOFOnIrp( PAFD_FCB FCB, NTSTATUS Status, ULONG_PTR Information )
30 {
31 if( ( Status == STATUS_SUCCESS && !Information ) ||
32 ( !NT_SUCCESS( Status ) ) )
33 {
34 /* The socket has been closed */
35 FCB->PollState |= AFD_EVENT_DISCONNECT;
36 FCB->PollStatus[FD_CLOSE_BIT] = Status;
37
38 PollReeval( FCB->DeviceExt, FCB->FileObject );
39 }
40 }
41
42 static BOOLEAN CantReadMore( PAFD_FCB FCB ) {
43 UINT BytesAvailable = FCB->Recv.Content - FCB->Recv.BytesUsed;
44
45 return !BytesAvailable &&
46 (FCB->PollState & (AFD_EVENT_CLOSE | AFD_EVENT_DISCONNECT));
47 }
48
49 static VOID RefillSocketBuffer( PAFD_FCB FCB ) {
50 NTSTATUS Status;
51
52 if( !FCB->ReceiveIrp.InFlightRequest ) {
53 AFD_DbgPrint(MID_TRACE,("Replenishing buffer\n"));
54
55 Status = TdiReceive( &FCB->ReceiveIrp.InFlightRequest,
56 FCB->Connection.Object,
57 TDI_RECEIVE_NORMAL,
58 FCB->Recv.Window,
59 FCB->Recv.Size,
60 &FCB->ReceiveIrp.Iosb,
61 ReceiveComplete,
62 FCB );
63
64 if( Status == STATUS_SUCCESS && FCB->ReceiveIrp.Iosb.Information )
65 {
66 FCB->Recv.Content = FCB->ReceiveIrp.Iosb.Information;
67 FCB->PollState |= AFD_EVENT_RECEIVE;
68 FCB->PollStatus[FD_READ_BIT] = STATUS_SUCCESS;
69
70 PollReeval( FCB->DeviceExt, FCB->FileObject );
71 }
72 else
73 {
74 /* Check for EOF */
75 HandleEOFOnIrp(FCB, Status, FCB->ReceiveIrp.Iosb.Information);
76 }
77 }
78 }
79
80 static NTSTATUS TryToSatisfyRecvRequestFromBuffer( PAFD_FCB FCB,
81 PAFD_RECV_INFO RecvReq,
82 PUINT TotalBytesCopied ) {
83 UINT i, BytesToCopy = 0, FcbBytesCopied = FCB->Recv.BytesUsed;
84 BytesAvailable =
85 FCB->Recv.Content - FCB->Recv.BytesUsed;
86 PAFD_MAPBUF Map;
87 *TotalBytesCopied = 0;
88
89
90 AFD_DbgPrint(MID_TRACE,("Called, BytesAvailable = %d\n",
91 BytesAvailable));
92
93 if( CantReadMore(FCB) ) return STATUS_SUCCESS;
94 if( !BytesAvailable ) return STATUS_PENDING;
95
96 Map = (PAFD_MAPBUF)(RecvReq->BufferArray + RecvReq->BufferCount);
97
98 AFD_DbgPrint(MID_TRACE,("Buffer Count: %d @ %x\n",
99 RecvReq->BufferCount,
100 RecvReq->BufferArray));
101 for( i = 0;
102 RecvReq->BufferArray &&
103 BytesAvailable &&
104 i < RecvReq->BufferCount;
105 i++ ) {
106 BytesToCopy =
107 MIN( RecvReq->BufferArray[i].len, BytesAvailable );
108
109 if( Map[i].Mdl ) {
110 Map[i].BufferAddress = MmMapLockedPages( Map[i].Mdl, KernelMode );
111
112 AFD_DbgPrint(MID_TRACE,("Buffer %d: %x:%d\n",
113 i,
114 Map[i].BufferAddress,
115 BytesToCopy));
116
117 RtlCopyMemory( Map[i].BufferAddress,
118 FCB->Recv.Window + FcbBytesCopied,
119 BytesToCopy );
120
121 MmUnmapLockedPages( Map[i].BufferAddress, Map[i].Mdl );
122
123 *TotalBytesCopied += BytesToCopy;
124 FcbBytesCopied += BytesToCopy;
125
126 if (!(RecvReq->TdiFlags & TDI_RECEIVE_PEEK)) {
127 FCB->Recv.BytesUsed += BytesToCopy;
128 BytesAvailable -= BytesToCopy;
129 }
130 }
131 }
132
133 /* If there's nothing left in our buffer start a new request */
134 if( FCB->Recv.BytesUsed == FCB->Recv.Content ) {
135 FCB->Recv.BytesUsed = FCB->Recv.Content = 0;
136 FCB->PollState &= ~AFD_EVENT_RECEIVE;
137
138 RefillSocketBuffer( FCB );
139 }
140
141 return STATUS_SUCCESS;
142 }
143
144 static NTSTATUS ReceiveActivity( PAFD_FCB FCB, PIRP Irp ) {
145 PLIST_ENTRY NextIrpEntry;
146 PIRP NextIrp;
147 PIO_STACK_LOCATION NextIrpSp;
148 PAFD_RECV_INFO RecvReq;
149 UINT TotalBytesCopied = 0, RetBytesCopied = 0;
150 NTSTATUS Status = STATUS_SUCCESS, RetStatus = STATUS_PENDING;
151
152 AFD_DbgPrint(MID_TRACE,("%x %x\n", FCB, Irp));
153
154 /* Kick the user that receive would be possible now */
155 /* XXX Not implemented yet */
156
157 AFD_DbgPrint(MID_TRACE,("FCB %x Receive data waiting %d\n",
158 FCB, FCB->Recv.Content));
159
160 if( CantReadMore( FCB ) ) {
161 /* Success here means that we got an EOF. Complete a pending read
162 * with zero bytes if we haven't yet overread, then kill the others.
163 */
164 while( !IsListEmpty( &FCB->PendingIrpList[FUNCTION_RECV] ) ) {
165 NextIrpEntry =
166 RemoveHeadList(&FCB->PendingIrpList[FUNCTION_RECV]);
167 NextIrp =
168 CONTAINING_RECORD(NextIrpEntry, IRP, Tail.Overlay.ListEntry);
169 NextIrpSp = IoGetCurrentIrpStackLocation( NextIrp );
170 RecvReq = NextIrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
171
172 AFD_DbgPrint(MID_TRACE,("Completing recv %x (%d)\n", NextIrp,
173 TotalBytesCopied));
174 UnlockBuffers( RecvReq->BufferArray,
175 RecvReq->BufferCount, FALSE );
176 Status = NextIrp->IoStatus.Status =
177 FCB->Overread ? STATUS_END_OF_FILE : STATUS_SUCCESS;
178 NextIrp->IoStatus.Information = 0;
179 if( NextIrp == Irp ) RetStatus = Status;
180 if( NextIrp->MdlAddress ) UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) );
181 (void)IoSetCancelRoutine(NextIrp, NULL);
182 IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT );
183 FCB->Overread = TRUE;
184 }
185 } else {
186 /* Kick the user that receive would be possible now */
187 /* XXX Not implemented yet */
188
189 AFD_DbgPrint(MID_TRACE,("FCB %x Receive data waiting %d\n",
190 FCB, FCB->Recv.Content));
191 /*OskitDumpBuffer( FCB->Recv.Window, FCB->Recv.Content );*/
192
193 /* Try to clear some requests */
194 while( !IsListEmpty( &FCB->PendingIrpList[FUNCTION_RECV] ) ) {
195 NextIrpEntry =
196 RemoveHeadList(&FCB->PendingIrpList[FUNCTION_RECV]);
197 NextIrp =
198 CONTAINING_RECORD(NextIrpEntry, IRP, Tail.Overlay.ListEntry);
199 NextIrpSp = IoGetCurrentIrpStackLocation( NextIrp );
200 RecvReq = NextIrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
201
202 AFD_DbgPrint(MID_TRACE,("RecvReq @ %x\n", RecvReq));
203
204 Status = TryToSatisfyRecvRequestFromBuffer
205 ( FCB, RecvReq, &TotalBytesCopied );
206
207 if( Status == STATUS_PENDING ) {
208 AFD_DbgPrint(MID_TRACE,("Ran out of data for %x\n", NextIrp));
209 InsertHeadList(&FCB->PendingIrpList[FUNCTION_RECV],
210 &NextIrp->Tail.Overlay.ListEntry);
211 break;
212 } else {
213 AFD_DbgPrint(MID_TRACE,("Completing recv %x (%d)\n", NextIrp,
214 TotalBytesCopied));
215 UnlockBuffers( RecvReq->BufferArray,
216 RecvReq->BufferCount, FALSE );
217 NextIrp->IoStatus.Status = Status;
218 NextIrp->IoStatus.Information = TotalBytesCopied;
219 if( NextIrp == Irp ) {
220 RetStatus = Status;
221 RetBytesCopied = TotalBytesCopied;
222 }
223 if( NextIrp->MdlAddress ) UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) );
224 (void)IoSetCancelRoutine(NextIrp, NULL);
225 IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT );
226 }
227 }
228 }
229
230 if( FCB->Recv.Content ) {
231 FCB->PollState |= AFD_EVENT_RECEIVE;
232 FCB->PollStatus[FD_READ_BIT] = STATUS_SUCCESS;
233 PollReeval( FCB->DeviceExt, FCB->FileObject );
234 } else
235 FCB->PollState &= ~AFD_EVENT_RECEIVE;
236
237 AFD_DbgPrint(MID_TRACE,("RetStatus for irp %x is %x\n", Irp, RetStatus));
238
239 /* Sometimes we're called with a NULL Irp */
240 if( Irp ) {
241 Irp->IoStatus.Status = RetStatus;
242 Irp->IoStatus.Information = RetBytesCopied;
243 }
244
245 return RetStatus;
246 }
247
248 NTSTATUS NTAPI ReceiveComplete
249 ( PDEVICE_OBJECT DeviceObject,
250 PIRP Irp,
251 PVOID Context ) {
252 PAFD_FCB FCB = (PAFD_FCB)Context;
253 PLIST_ENTRY NextIrpEntry;
254 PIRP NextIrp;
255 PAFD_RECV_INFO RecvReq;
256 PIO_STACK_LOCATION NextIrpSp;
257
258 AFD_DbgPrint(MID_TRACE,("Called\n"));
259
260 if( !SocketAcquireStateLock( FCB ) )
261 return STATUS_FILE_CLOSED;
262
263 FCB->ReceiveIrp.InFlightRequest = NULL;
264
265 FCB->Recv.Content = Irp->IoStatus.Information;
266 FCB->Recv.BytesUsed = 0;
267
268 if( FCB->State == SOCKET_STATE_CLOSED ) {
269 AFD_DbgPrint(MIN_TRACE,("!!! CLOSING SOCK GOT A RECEIVE COMPLETE !!!\n"));
270 /* Cleanup our IRP queue because the FCB is being destroyed */
271 while( !IsListEmpty( &FCB->PendingIrpList[FUNCTION_RECV] ) ) {
272 NextIrpEntry = RemoveHeadList(&FCB->PendingIrpList[FUNCTION_RECV]);
273 NextIrp = CONTAINING_RECORD(NextIrpEntry, IRP, Tail.Overlay.ListEntry);
274 NextIrpSp = IoGetCurrentIrpStackLocation(NextIrp);
275 RecvReq = NextIrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
276 NextIrp->IoStatus.Status = STATUS_FILE_CLOSED;
277 NextIrp->IoStatus.Information = 0;
278 UnlockBuffers(RecvReq->BufferArray, RecvReq->BufferCount, FALSE);
279 if( NextIrp->MdlAddress ) UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) );
280 (void)IoSetCancelRoutine(NextIrp, NULL);
281 IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT );
282 }
283 SocketStateUnlock( FCB );
284 return STATUS_FILE_CLOSED;
285 } else if( FCB->State == SOCKET_STATE_LISTENING ) {
286 AFD_DbgPrint(MIN_TRACE,("!!! LISTENER GOT A RECEIVE COMPLETE !!!\n"));
287 SocketStateUnlock( FCB );
288 return STATUS_INVALID_PARAMETER;
289 }
290
291 HandleEOFOnIrp( FCB, Irp->IoStatus.Status, Irp->IoStatus.Information );
292
293 ReceiveActivity( FCB, NULL );
294
295 SocketStateUnlock( FCB );
296
297 return STATUS_SUCCESS;
298 }
299
300 NTSTATUS NTAPI
301 AfdConnectedSocketReadData(PDEVICE_OBJECT DeviceObject, PIRP Irp,
302 PIO_STACK_LOCATION IrpSp, BOOLEAN Short) {
303 NTSTATUS Status = STATUS_INVALID_PARAMETER;
304 PFILE_OBJECT FileObject = IrpSp->FileObject;
305 PAFD_FCB FCB = FileObject->FsContext;
306 PAFD_RECV_INFO RecvReq;
307 UINT TotalBytesCopied = 0;
308
309 AFD_DbgPrint(MID_TRACE,("Called on %x\n", FCB));
310
311 if( !SocketAcquireStateLock( FCB ) ) return LostSocket( Irp );
312
313 if( FCB->State != SOCKET_STATE_CONNECTED &&
314 FCB->State != SOCKET_STATE_CONNECTING ) {
315 AFD_DbgPrint(MID_TRACE,("Called recv on wrong kind of socket (s%x)\n",
316 FCB->State));
317 return UnlockAndMaybeComplete( FCB, STATUS_INVALID_PARAMETER,
318 Irp, 0 );
319 }
320
321 if( FCB->Flags & AFD_ENDPOINT_CONNECTIONLESS )
322 {
323 AFD_DbgPrint(MID_TRACE,("Receive on connection-less sockets not implemented\n"));
324 return UnlockAndMaybeComplete( FCB, STATUS_NOT_IMPLEMENTED,
325 Irp, 0 );
326 }
327
328 if( !(RecvReq = LockRequest( Irp, IrpSp )) )
329 return UnlockAndMaybeComplete( FCB, STATUS_NO_MEMORY,
330 Irp, 0 );
331
332 AFD_DbgPrint(MID_TRACE,("Recv flags %x\n", RecvReq->AfdFlags));
333
334 RecvReq->BufferArray = LockBuffers( RecvReq->BufferArray,
335 RecvReq->BufferCount,
336 NULL, NULL,
337 TRUE, FALSE );
338
339 if( !RecvReq->BufferArray ) {
340 return UnlockAndMaybeComplete( FCB, STATUS_ACCESS_VIOLATION,
341 Irp, 0 );
342 }
343
344 Irp->IoStatus.Status = STATUS_PENDING;
345 Irp->IoStatus.Information = 0;
346
347 InsertTailList( &FCB->PendingIrpList[FUNCTION_RECV],
348 &Irp->Tail.Overlay.ListEntry );
349
350 /************ From this point, the IRP is not ours ************/
351
352 Status = ReceiveActivity( FCB, Irp );
353
354 if( Status == STATUS_PENDING && (RecvReq->AfdFlags & AFD_IMMEDIATE) ) {
355 AFD_DbgPrint(MID_TRACE,("Nonblocking\n"));
356 Status = STATUS_CANT_WAIT;
357 TotalBytesCopied = 0;
358 RemoveEntryList( &Irp->Tail.Overlay.ListEntry );
359 UnlockBuffers( RecvReq->BufferArray, RecvReq->BufferCount, FALSE );
360 return UnlockAndMaybeComplete( FCB, Status, Irp,
361 TotalBytesCopied );
362 } else if( Status == STATUS_PENDING ) {
363 AFD_DbgPrint(MID_TRACE,("Leaving read irp\n"));
364 IoMarkIrpPending( Irp );
365 (void)IoSetCancelRoutine(Irp, AfdCancelHandler);
366 } else {
367 AFD_DbgPrint(MID_TRACE,("Completed with status %x\n", Status));
368 }
369
370 SocketStateUnlock( FCB );
371 return Status;
372 }
373
374
375 static NTSTATUS NTAPI
376 SatisfyPacketRecvRequest( PAFD_FCB FCB, PIRP Irp,
377 PAFD_STORED_DATAGRAM DatagramRecv,
378 PUINT TotalBytesCopied ) {
379 NTSTATUS Status = STATUS_SUCCESS;
380 PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp );
381 PAFD_RECV_INFO RecvReq =
382 IrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
383 UINT BytesToCopy = 0, BytesAvailable = DatagramRecv->Len, AddrLen = 0;
384 PAFD_MAPBUF Map;
385
386 Map = (PAFD_MAPBUF)(RecvReq->BufferArray +
387 RecvReq->BufferCount +
388 EXTRA_LOCK_BUFFERS);
389
390 BytesToCopy =
391 MIN( RecvReq->BufferArray[0].len, BytesAvailable );
392
393 AFD_DbgPrint(MID_TRACE,("BytesToCopy: %d len %d\n", BytesToCopy,
394 RecvReq->BufferArray[0].len));
395
396 if( Map[0].Mdl ) {
397 /* Copy the address */
398 if( Map[1].Mdl && Map[2].Mdl ) {
399 AFD_DbgPrint(MID_TRACE,("Checking TAAddressCount\n"));
400
401 if( DatagramRecv->Address->TAAddressCount != 1 ) {
402 AFD_DbgPrint
403 (MID_TRACE,
404 ("Wierd address count %d\n",
405 DatagramRecv->Address->TAAddressCount));
406 }
407
408 AFD_DbgPrint(MID_TRACE,("Computing addr len\n"));
409
410 AddrLen = MIN(DatagramRecv->Address->Address->AddressLength +
411 sizeof(USHORT),
412 RecvReq->BufferArray[1].len);
413
414 AFD_DbgPrint(MID_TRACE,("Copying %d bytes of address\n", AddrLen));
415
416 Map[1].BufferAddress = MmMapLockedPages( Map[1].Mdl, KernelMode );
417
418 AFD_DbgPrint(MID_TRACE,("Done mapping, copying address\n"));
419
420 RtlCopyMemory( Map[1].BufferAddress,
421 &DatagramRecv->Address->Address->AddressType,
422 AddrLen );
423
424 MmUnmapLockedPages( Map[1].BufferAddress, Map[1].Mdl );
425
426 AFD_DbgPrint(MID_TRACE,("Copying address len\n"));
427
428 Map[2].BufferAddress = MmMapLockedPages( Map[2].Mdl, KernelMode );
429 *((PINT)Map[2].BufferAddress) = AddrLen;
430 MmUnmapLockedPages( Map[2].BufferAddress, Map[2].Mdl );
431 }
432
433 AFD_DbgPrint(MID_TRACE,("Mapping data buffer pages\n"));
434
435 Map[0].BufferAddress = MmMapLockedPages( Map[0].Mdl, KernelMode );
436
437 AFD_DbgPrint(MID_TRACE,("Buffer %d: %x:%d\n",
438 0,
439 Map[0].BufferAddress,
440 BytesToCopy));
441
442 /* OskitDumpBuffer
443 ( FCB->Recv.Window + FCB->Recv.BytesUsed, BytesToCopy ); */
444
445 RtlCopyMemory( Map[0].BufferAddress,
446 FCB->Recv.Window + FCB->Recv.BytesUsed,
447 BytesToCopy );
448
449 MmUnmapLockedPages( Map[0].BufferAddress, Map[0].Mdl );
450
451 *TotalBytesCopied = BytesToCopy;
452
453 if (!(RecvReq->TdiFlags & TDI_RECEIVE_PEEK)) {
454 FCB->Recv.BytesUsed = 0;
455 }
456 }
457
458 Status = Irp->IoStatus.Status = STATUS_SUCCESS;
459 Irp->IoStatus.Information = BytesToCopy;
460 ExFreePool( DatagramRecv->Address );
461 ExFreePool( DatagramRecv );
462
463 AFD_DbgPrint(MID_TRACE,("Done\n"));
464
465 return Status;
466 }
467
468 NTSTATUS NTAPI
469 PacketSocketRecvComplete(
470 PDEVICE_OBJECT DeviceObject,
471 PIRP Irp,
472 PVOID Context ) {
473 NTSTATUS Status = STATUS_SUCCESS;
474 PAFD_FCB FCB = Context;
475 PIRP NextIrp;
476 PIO_STACK_LOCATION NextIrpSp;
477 PLIST_ENTRY ListEntry;
478 PAFD_RECV_INFO RecvReq;
479 PAFD_STORED_DATAGRAM DatagramRecv;
480 UINT DGSize = Irp->IoStatus.Information + sizeof( AFD_STORED_DATAGRAM );
481 PLIST_ENTRY NextIrpEntry, DatagramRecvEntry;
482
483 AFD_DbgPrint(MID_TRACE,("Called on %x\n", FCB));
484
485 if( !SocketAcquireStateLock( FCB ) )
486 return STATUS_FILE_CLOSED;
487
488 FCB->ReceiveIrp.InFlightRequest = NULL;
489
490 if( FCB->State == SOCKET_STATE_CLOSED ) {
491 /* Cleanup our IRP queue because the FCB is being destroyed */
492 while( !IsListEmpty( &FCB->PendingIrpList[FUNCTION_RECV] ) ) {
493 NextIrpEntry = RemoveHeadList(&FCB->PendingIrpList[FUNCTION_RECV]);
494 NextIrp = CONTAINING_RECORD(NextIrpEntry, IRP, Tail.Overlay.ListEntry);
495 NextIrpSp = IoGetCurrentIrpStackLocation( NextIrp );
496 RecvReq = NextIrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
497 NextIrp->IoStatus.Status = STATUS_FILE_CLOSED;
498 NextIrp->IoStatus.Information = 0;
499 UnlockBuffers(RecvReq->BufferArray, RecvReq->BufferCount, FALSE);
500 if( NextIrp->MdlAddress ) UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) );
501 (void)IoSetCancelRoutine(NextIrp, NULL);
502 IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT );
503 }
504
505 /* Free all items on the datagram list */
506 while( !IsListEmpty( &FCB->DatagramList ) ) {
507 DatagramRecvEntry = RemoveHeadList(&FCB->DatagramList);
508 DatagramRecv = CONTAINING_RECORD(DatagramRecvEntry, AFD_STORED_DATAGRAM, ListEntry);
509 ExFreePool( DatagramRecv->Address );
510 ExFreePool( DatagramRecv );
511 }
512
513 SocketStateUnlock( FCB );
514 return STATUS_FILE_CLOSED;
515 }
516
517 DatagramRecv = ExAllocatePool( NonPagedPool, DGSize );
518
519 if( DatagramRecv ) {
520 DatagramRecv->Len = Irp->IoStatus.Information;
521 RtlCopyMemory( DatagramRecv->Buffer, FCB->Recv.Window,
522 DatagramRecv->Len );
523 AFD_DbgPrint(MID_TRACE,("Received (A %x)\n",
524 FCB->AddressFrom->RemoteAddress));
525 DatagramRecv->Address =
526 TaCopyTransportAddress( FCB->AddressFrom->RemoteAddress );
527
528 if( !DatagramRecv->Address ) Status = STATUS_NO_MEMORY;
529
530 } else Status = STATUS_NO_MEMORY;
531
532 if( !NT_SUCCESS( Status ) ) {
533 if( DatagramRecv ) ExFreePool( DatagramRecv );
534 SocketStateUnlock( FCB );
535 return Status;
536 } else {
537 InsertTailList( &FCB->DatagramList, &DatagramRecv->ListEntry );
538 }
539
540 /* Satisfy as many requests as we can */
541
542 while( !IsListEmpty( &FCB->DatagramList ) &&
543 !IsListEmpty( &FCB->PendingIrpList[FUNCTION_RECV] ) ) {
544 AFD_DbgPrint(MID_TRACE,("Looping trying to satisfy request\n"));
545 ListEntry = RemoveHeadList( &FCB->DatagramList );
546 DatagramRecv = CONTAINING_RECORD( ListEntry, AFD_STORED_DATAGRAM,
547 ListEntry );
548 ListEntry = RemoveHeadList( &FCB->PendingIrpList[FUNCTION_RECV] );
549 NextIrp = CONTAINING_RECORD( ListEntry, IRP, Tail.Overlay.ListEntry );
550 NextIrpSp = IoGetCurrentIrpStackLocation( NextIrp );
551 RecvReq = NextIrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
552
553 AFD_DbgPrint(MID_TRACE,("RecvReq: %x, DatagramRecv: %x\n",
554 RecvReq, DatagramRecv));
555
556 if( DatagramRecv->Len > RecvReq->BufferArray[0].len &&
557 !(RecvReq->TdiFlags & TDI_RECEIVE_PARTIAL) ) {
558 InsertHeadList( &FCB->DatagramList,
559 &DatagramRecv->ListEntry );
560 Status = NextIrp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
561 NextIrp->IoStatus.Information = DatagramRecv->Len;
562 UnlockBuffers( RecvReq->BufferArray, RecvReq->BufferCount, TRUE );
563 if ( NextIrp->MdlAddress ) UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) );
564 (void)IoSetCancelRoutine(NextIrp, NULL);
565 IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT );
566 } else {
567 AFD_DbgPrint(MID_TRACE,("Satisfying\n"));
568 Status = SatisfyPacketRecvRequest
569 ( FCB, NextIrp, DatagramRecv,
570 (PUINT)&NextIrp->IoStatus.Information );
571 AFD_DbgPrint(MID_TRACE,("Unlocking\n"));
572 UnlockBuffers( RecvReq->BufferArray, RecvReq->BufferCount, TRUE );
573 if ( NextIrp->MdlAddress ) UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) );
574 AFD_DbgPrint(MID_TRACE,("Completing\n"));
575 (void)IoSetCancelRoutine(NextIrp, NULL);
576 IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT );
577 }
578 }
579
580 if( !IsListEmpty( &FCB->DatagramList ) ) {
581 AFD_DbgPrint(MID_TRACE,("Signalling\n"));
582 FCB->PollState |= AFD_EVENT_RECEIVE;
583 FCB->PollStatus[FD_READ_BIT] = STATUS_SUCCESS;
584 PollReeval( FCB->DeviceExt, FCB->FileObject );
585 } else
586 FCB->PollState &= ~AFD_EVENT_RECEIVE;
587
588 if( NT_SUCCESS(Irp->IoStatus.Status) ) {
589 /* Now relaunch the datagram request */
590 Status = TdiReceiveDatagram
591 ( &FCB->ReceiveIrp.InFlightRequest,
592 FCB->AddressFile.Object,
593 0,
594 FCB->Recv.Window,
595 FCB->Recv.Size,
596 FCB->AddressFrom,
597 &FCB->ReceiveIrp.Iosb,
598 PacketSocketRecvComplete,
599 FCB );
600 }
601
602 SocketStateUnlock( FCB );
603
604 return STATUS_SUCCESS;
605 }
606
607 NTSTATUS NTAPI
608 AfdPacketSocketReadData(PDEVICE_OBJECT DeviceObject, PIRP Irp,
609 PIO_STACK_LOCATION IrpSp ) {
610 NTSTATUS Status = STATUS_SUCCESS;
611 PFILE_OBJECT FileObject = IrpSp->FileObject;
612 PAFD_FCB FCB = FileObject->FsContext;
613 PAFD_RECV_INFO_UDP RecvReq;
614 PLIST_ENTRY ListEntry;
615 PAFD_STORED_DATAGRAM DatagramRecv;
616
617 AFD_DbgPrint(MID_TRACE,("Called on %x\n", FCB));
618
619 if( !SocketAcquireStateLock( FCB ) ) return LostSocket( Irp );
620
621 /* Check that the socket is bound */
622 if( FCB->State != SOCKET_STATE_BOUND )
623 return UnlockAndMaybeComplete
624 ( FCB, STATUS_INVALID_PARAMETER, Irp, 0 );
625 if( !(RecvReq = LockRequest( Irp, IrpSp )) )
626 return UnlockAndMaybeComplete
627 ( FCB, STATUS_NO_MEMORY, Irp, 0 );
628
629 AFD_DbgPrint(MID_TRACE,("Recv flags %x\n", RecvReq->AfdFlags));
630
631 RecvReq->BufferArray = LockBuffers( RecvReq->BufferArray,
632 RecvReq->BufferCount,
633 RecvReq->Address,
634 RecvReq->AddressLength,
635 TRUE, TRUE );
636
637 if( !RecvReq->BufferArray ) { /* access violation in userspace */
638 return UnlockAndMaybeComplete
639 ( FCB, STATUS_ACCESS_VIOLATION, Irp, 0 );
640 }
641
642 if( !IsListEmpty( &FCB->DatagramList ) ) {
643 ListEntry = RemoveHeadList( &FCB->DatagramList );
644 DatagramRecv = CONTAINING_RECORD
645 ( ListEntry, AFD_STORED_DATAGRAM, ListEntry );
646 if( DatagramRecv->Len > RecvReq->BufferArray[0].len &&
647 !(RecvReq->TdiFlags & TDI_RECEIVE_PARTIAL) ) {
648 InsertHeadList( &FCB->DatagramList,
649 &DatagramRecv->ListEntry );
650 Status = Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
651 Irp->IoStatus.Information = DatagramRecv->Len;
652
653 if( !IsListEmpty( &FCB->DatagramList ) ) {
654 FCB->PollState |= AFD_EVENT_RECEIVE;
655 FCB->PollStatus[FD_READ_BIT] = STATUS_SUCCESS;
656 PollReeval( FCB->DeviceExt, FCB->FileObject );
657 } else
658 FCB->PollState &= ~AFD_EVENT_RECEIVE;
659
660 UnlockBuffers( RecvReq->BufferArray, RecvReq->BufferCount, TRUE );
661
662 return UnlockAndMaybeComplete
663 ( FCB, Status, Irp, Irp->IoStatus.Information );
664 } else {
665 Status = SatisfyPacketRecvRequest
666 ( FCB, Irp, DatagramRecv,
667 (PUINT)&Irp->IoStatus.Information );
668
669 if( !IsListEmpty( &FCB->DatagramList ) ) {
670 FCB->PollState |= AFD_EVENT_RECEIVE;
671 FCB->PollStatus[FD_READ_BIT] = STATUS_SUCCESS;
672 PollReeval( FCB->DeviceExt, FCB->FileObject );
673 } else
674 FCB->PollState &= ~AFD_EVENT_RECEIVE;
675
676 UnlockBuffers( RecvReq->BufferArray, RecvReq->BufferCount, TRUE );
677
678 return UnlockAndMaybeComplete
679 ( FCB, Status, Irp, Irp->IoStatus.Information );
680 }
681 } else if( RecvReq->AfdFlags & AFD_IMMEDIATE ) {
682 AFD_DbgPrint(MID_TRACE,("Nonblocking\n"));
683 Status = STATUS_CANT_WAIT;
684 FCB->PollState &= ~AFD_EVENT_RECEIVE;
685 UnlockBuffers( RecvReq->BufferArray, RecvReq->BufferCount, TRUE );
686 return UnlockAndMaybeComplete( FCB, Status, Irp, 0 );
687 } else {
688 FCB->PollState &= ~AFD_EVENT_RECEIVE;
689 return LeaveIrpUntilLater( FCB, Irp, FUNCTION_RECV );
690 }
691 }