xref: /reactos/drivers/network/afd/afd/read.c (revision f4d29a74)
1 /*
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 
11 #include "afd.h"
12 
13 static VOID RefillSocketBuffer( PAFD_FCB FCB )
14 {
15     /* Make sure nothing's in flight first */
16     if (FCB->ReceiveIrp.InFlightRequest) return;
17 
18     /* Now ensure that receive is still allowed */
19     if (FCB->TdiReceiveClosed) return;
20 
21     /* Check if the buffer is full */
22     if (FCB->Recv.Content == FCB->Recv.Size)
23     {
24         /* If there are bytes used, we can solve this problem */
25         if (FCB->Recv.BytesUsed != 0)
26         {
27             /* Reposition the unused portion to the beginning of the receive window */
28             RtlMoveMemory(FCB->Recv.Window,
29                           FCB->Recv.Window + FCB->Recv.BytesUsed,
30                           FCB->Recv.Content - FCB->Recv.BytesUsed);
31 
32             FCB->Recv.Content -= FCB->Recv.BytesUsed;
33             FCB->Recv.BytesUsed = 0;
34         }
35         else
36         {
37             /* No space in the buffer to receive */
38             return;
39         }
40     }
41 
42     AFD_DbgPrint(MID_TRACE,("Replenishing buffer\n"));
43 
44     TdiReceive( &FCB->ReceiveIrp.InFlightRequest,
45                 FCB->Connection.Object,
46                 TDI_RECEIVE_NORMAL,
47                 FCB->Recv.Window + FCB->Recv.Content,
48                 FCB->Recv.Size - FCB->Recv.Content,
49                 ReceiveComplete,
50                 FCB );
51 }
52 
53 static VOID HandleReceiveComplete( PAFD_FCB FCB, NTSTATUS Status, ULONG_PTR Information )
54 {
55     FCB->LastReceiveStatus = Status;
56 
57     /* We got closed while the receive was in progress */
58     if (FCB->TdiReceiveClosed)
59     {
60         /* The received data is discarded */
61     }
62     /* Receive successful */
63     else if (Status == STATUS_SUCCESS)
64     {
65         FCB->Recv.Content += Information;
66         ASSERT(FCB->Recv.Content <= FCB->Recv.Size);
67 
68         /* Check for graceful closure */
69         if (Information == 0)
70         {
71             /* Receive is closed */
72             FCB->TdiReceiveClosed = TRUE;
73         }
74         else
75         {
76             /* Issue another receive IRP to keep the buffer well stocked */
77             RefillSocketBuffer(FCB);
78         }
79     }
80     /* Receive failed with no data (unexpected closure) */
81     else
82     {
83         /* Previously received data remains intact */
84         FCB->TdiReceiveClosed = TRUE;
85     }
86 }
87 
88 static BOOLEAN CantReadMore( PAFD_FCB FCB ) {
89     UINT BytesAvailable = FCB->Recv.Content - FCB->Recv.BytesUsed;
90 
91     return !BytesAvailable && FCB->TdiReceiveClosed;
92 }
93 
94 static NTSTATUS TryToSatisfyRecvRequestFromBuffer( PAFD_FCB FCB,
95                                                    PAFD_RECV_INFO RecvReq,
96                                                    PUINT TotalBytesCopied ) {
97     UINT i, BytesToCopy = 0, FcbBytesCopied = FCB->Recv.BytesUsed,
98         BytesAvailable =
99         FCB->Recv.Content - FCB->Recv.BytesUsed;
100     PAFD_MAPBUF Map;
101     *TotalBytesCopied = 0;
102 
103 
104     AFD_DbgPrint(MID_TRACE,("Called, BytesAvailable = %u\n", BytesAvailable));
105 
106     if( CantReadMore(FCB) ) return STATUS_SUCCESS;
107     if( !BytesAvailable ) return STATUS_PENDING;
108 
109     Map = (PAFD_MAPBUF)(RecvReq->BufferArray + RecvReq->BufferCount);
110 
111     AFD_DbgPrint(MID_TRACE,("Buffer Count: %u @ %p\n",
112                             RecvReq->BufferCount,
113                             RecvReq->BufferArray));
114     for( i = 0;
115          RecvReq->BufferArray &&
116              BytesAvailable &&
117              i < RecvReq->BufferCount;
118          i++ ) {
119         BytesToCopy =
120             MIN( RecvReq->BufferArray[i].len, BytesAvailable );
121 
122         if( Map[i].Mdl ) {
123             Map[i].BufferAddress = MmMapLockedPages( Map[i].Mdl, KernelMode );
124 
125             AFD_DbgPrint(MID_TRACE,("Buffer %u: %p:%u\n",
126                                     i,
127                                     Map[i].BufferAddress,
128                                     BytesToCopy));
129 
130             RtlCopyMemory( Map[i].BufferAddress,
131                            FCB->Recv.Window + FcbBytesCopied,
132                            BytesToCopy );
133 
134             MmUnmapLockedPages( Map[i].BufferAddress, Map[i].Mdl );
135 
136             *TotalBytesCopied += BytesToCopy;
137             FcbBytesCopied += BytesToCopy;
138             BytesAvailable -= BytesToCopy;
139 
140             if (!(RecvReq->TdiFlags & TDI_RECEIVE_PEEK))
141                 FCB->Recv.BytesUsed += BytesToCopy;
142         }
143     }
144 
145     /* Issue another receive IRP to keep the buffer well stocked */
146     RefillSocketBuffer(FCB);
147 
148     return STATUS_SUCCESS;
149 }
150 
151 static NTSTATUS ReceiveActivity( PAFD_FCB FCB, PIRP Irp ) {
152     PLIST_ENTRY NextIrpEntry;
153     PIRP NextIrp;
154     PIO_STACK_LOCATION NextIrpSp;
155     PAFD_RECV_INFO RecvReq;
156     UINT TotalBytesCopied = 0;
157     NTSTATUS Status = STATUS_SUCCESS, RetStatus = STATUS_PENDING;
158 
159     AFD_DbgPrint(MID_TRACE,("%p %p\n", FCB, Irp));
160 
161     AFD_DbgPrint(MID_TRACE,("FCB %p Receive data waiting %u\n",
162                             FCB, FCB->Recv.Content));
163 
164     if( CantReadMore( FCB ) ) {
165         /* Success here means that we got an EOF.  Complete a pending read
166          * with zero bytes if we haven't yet overread, then kill the others.
167          */
168         while( !IsListEmpty( &FCB->PendingIrpList[FUNCTION_RECV] ) ) {
169             NextIrpEntry = RemoveHeadList(&FCB->PendingIrpList[FUNCTION_RECV]);
170             NextIrp = CONTAINING_RECORD(NextIrpEntry, IRP, Tail.Overlay.ListEntry);
171             NextIrpSp = IoGetCurrentIrpStackLocation( NextIrp );
172             RecvReq = GetLockedData(NextIrp, NextIrpSp);
173 
174             AFD_DbgPrint(MID_TRACE,("Completing recv %p (%u)\n", NextIrp,
175                                     TotalBytesCopied));
176             UnlockBuffers( RecvReq->BufferArray,
177                            RecvReq->BufferCount, FALSE );
178             if (FCB->Overread && FCB->LastReceiveStatus == STATUS_SUCCESS)
179             {
180                 /* Overread after a graceful disconnect so complete with an error */
181                 Status = STATUS_FILE_CLOSED;
182             }
183             else
184             {
185                 /* Unexpected disconnect by the remote host or initial read after a graceful disconnect */
186                 Status = FCB->LastReceiveStatus;
187             }
188             NextIrp->IoStatus.Status = Status;
189             NextIrp->IoStatus.Information = 0;
190             if( NextIrp == Irp ) RetStatus = Status;
191             if( NextIrp->MdlAddress ) UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) );
192             (void)IoSetCancelRoutine(NextIrp, NULL);
193             IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT );
194             FCB->Overread = TRUE;
195         }
196     } else {
197         /* Kick the user that receive would be possible now */
198         /* XXX Not implemented yet */
199 
200         AFD_DbgPrint(MID_TRACE,("FCB %p Receive data waiting %u\n",
201                                 FCB, FCB->Recv.Content));
202         /*OskitDumpBuffer( FCB->Recv.Window, FCB->Recv.Content );*/
203 
204         /* Try to clear some requests */
205         while( !IsListEmpty( &FCB->PendingIrpList[FUNCTION_RECV] ) ) {
206             NextIrpEntry = RemoveHeadList(&FCB->PendingIrpList[FUNCTION_RECV]);
207             NextIrp = CONTAINING_RECORD(NextIrpEntry, IRP, Tail.Overlay.ListEntry);
208             NextIrpSp = IoGetCurrentIrpStackLocation( NextIrp );
209             RecvReq = GetLockedData(NextIrp, NextIrpSp);
210 
211             AFD_DbgPrint(MID_TRACE,("RecvReq @ %p\n", RecvReq));
212 
213             Status = TryToSatisfyRecvRequestFromBuffer
214             ( FCB, RecvReq, &TotalBytesCopied );
215 
216             if( Status == STATUS_PENDING ) {
217                 AFD_DbgPrint(MID_TRACE,("Ran out of data for %p\n", NextIrp));
218                 InsertHeadList(&FCB->PendingIrpList[FUNCTION_RECV],
219                                &NextIrp->Tail.Overlay.ListEntry);
220                 break;
221             } else {
222                 AFD_DbgPrint(MID_TRACE,("Completing recv %p (%u)\n", NextIrp,
223                                         TotalBytesCopied));
224                 UnlockBuffers( RecvReq->BufferArray,
225                                RecvReq->BufferCount, FALSE );
226                 NextIrp->IoStatus.Status = Status;
227                 NextIrp->IoStatus.Information = TotalBytesCopied;
228                 if( NextIrp == Irp ) {
229                     RetStatus = Status;
230                 }
231                 if( NextIrp->MdlAddress ) UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) );
232                 (void)IoSetCancelRoutine(NextIrp, NULL);
233                 IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT );
234             }
235         }
236     }
237 
238     if( FCB->Recv.Content - FCB->Recv.BytesUsed &&
239         IsListEmpty(&FCB->PendingIrpList[FUNCTION_RECV]) ) {
240         FCB->PollState |= AFD_EVENT_RECEIVE;
241         FCB->PollStatus[FD_READ_BIT] = STATUS_SUCCESS;
242         PollReeval( FCB->DeviceExt, FCB->FileObject );
243     }
244     else
245     {
246         FCB->PollState &= ~AFD_EVENT_RECEIVE;
247     }
248 
249     /* Signal FD_CLOSE if no buffered data remains and the socket can't receive any more */
250     if (CantReadMore(FCB))
251     {
252         if (FCB->LastReceiveStatus == STATUS_SUCCESS)
253         {
254             FCB->PollState |= AFD_EVENT_DISCONNECT;
255         }
256         else
257         {
258             FCB->PollState |= AFD_EVENT_CLOSE;
259         }
260         FCB->PollStatus[FD_CLOSE_BIT] = FCB->LastReceiveStatus;
261         PollReeval(FCB->DeviceExt, FCB->FileObject);
262     }
263 
264     AFD_DbgPrint(MID_TRACE,("RetStatus for irp %p is %x\n", Irp, RetStatus));
265 
266     return RetStatus;
267 }
268 
269 NTSTATUS NTAPI ReceiveComplete
270 ( PDEVICE_OBJECT DeviceObject,
271   PIRP Irp,
272   PVOID Context ) {
273     PAFD_FCB FCB = (PAFD_FCB)Context;
274     PLIST_ENTRY NextIrpEntry;
275     PIRP NextIrp;
276     PAFD_RECV_INFO RecvReq;
277     PIO_STACK_LOCATION NextIrpSp;
278 
279     UNREFERENCED_PARAMETER(DeviceObject);
280 
281     AFD_DbgPrint(MID_TRACE,("Called\n"));
282 
283     if( !SocketAcquireStateLock( FCB ) )
284         return STATUS_FILE_CLOSED;
285 
286     ASSERT(FCB->ReceiveIrp.InFlightRequest == Irp);
287     FCB->ReceiveIrp.InFlightRequest = NULL;
288 
289     if( FCB->State == SOCKET_STATE_CLOSED ) {
290         /* Cleanup our IRP queue because the FCB is being destroyed */
291         while( !IsListEmpty( &FCB->PendingIrpList[FUNCTION_RECV] ) ) {
292             NextIrpEntry = RemoveHeadList(&FCB->PendingIrpList[FUNCTION_RECV]);
293             NextIrp = CONTAINING_RECORD(NextIrpEntry, IRP, Tail.Overlay.ListEntry);
294             NextIrpSp = IoGetCurrentIrpStackLocation(NextIrp);
295             RecvReq = GetLockedData(NextIrp, NextIrpSp);
296             NextIrp->IoStatus.Status = STATUS_FILE_CLOSED;
297             NextIrp->IoStatus.Information = 0;
298             UnlockBuffers(RecvReq->BufferArray, RecvReq->BufferCount, FALSE);
299             if( NextIrp->MdlAddress ) UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) );
300             (void)IoSetCancelRoutine(NextIrp, NULL);
301             IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT );
302         }
303         SocketStateUnlock( FCB );
304         return STATUS_FILE_CLOSED;
305     } else if( FCB->State == SOCKET_STATE_LISTENING ) {
306         AFD_DbgPrint(MIN_TRACE,("!!! LISTENER GOT A RECEIVE COMPLETE !!!\n"));
307         SocketStateUnlock( FCB );
308         return STATUS_INVALID_PARAMETER;
309     }
310 
311     HandleReceiveComplete( FCB, Irp->IoStatus.Status, Irp->IoStatus.Information );
312 
313     ReceiveActivity( FCB, NULL );
314 
315     SocketStateUnlock( FCB );
316 
317     return STATUS_SUCCESS;
318 }
319 
320 static NTSTATUS NTAPI
321 SatisfyPacketRecvRequest( PAFD_FCB FCB, PIRP Irp,
322                          PAFD_STORED_DATAGRAM DatagramRecv,
323                          PUINT TotalBytesCopied ) {
324     NTSTATUS Status = STATUS_SUCCESS;
325     PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp );
326     PAFD_RECV_INFO RecvReq =
327     GetLockedData(Irp, IrpSp);
328     UINT BytesToCopy = 0, BytesAvailable = DatagramRecv->Len, AddrLen = 0;
329     PAFD_MAPBUF Map;
330     BOOLEAN ExtraBuffers = CheckUnlockExtraBuffers(FCB, IrpSp);
331 
332     Map = (PAFD_MAPBUF)(RecvReq->BufferArray +
333                         RecvReq->BufferCount +
334                         (ExtraBuffers ? EXTRA_LOCK_BUFFERS : 0));
335 
336     BytesToCopy = MIN( RecvReq->BufferArray[0].len, BytesAvailable );
337 
338     AFD_DbgPrint(MID_TRACE,("BytesToCopy: %u len %u\n", BytesToCopy,
339                             RecvReq->BufferArray[0].len));
340 
341     if( Map[0].Mdl ) {
342         /* Copy the address */
343         if( ExtraBuffers && Map[1].Mdl && Map[2].Mdl ) {
344             AFD_DbgPrint(MID_TRACE,("Checking TAAddressCount\n"));
345 
346             if( DatagramRecv->Address->TAAddressCount != 1 ) {
347                 AFD_DbgPrint
348                 (MIN_TRACE,
349                  ("Wierd address count %d\n",
350                   DatagramRecv->Address->TAAddressCount));
351             }
352 
353             AFD_DbgPrint(MID_TRACE,("Computing addr len\n"));
354 
355             AddrLen = MIN(DatagramRecv->Address->Address->AddressLength +
356                           sizeof(USHORT),
357                           RecvReq->BufferArray[1].len);
358 
359             AFD_DbgPrint(MID_TRACE,("Copying %u bytes of address\n", AddrLen));
360 
361             Map[1].BufferAddress = MmMapLockedPages( Map[1].Mdl, KernelMode );
362 
363             AFD_DbgPrint(MID_TRACE,("Done mapping, copying address\n"));
364 
365             RtlCopyMemory( Map[1].BufferAddress,
366                           &DatagramRecv->Address->Address->AddressType,
367                           AddrLen );
368 
369             MmUnmapLockedPages( Map[1].BufferAddress, Map[1].Mdl );
370 
371             AFD_DbgPrint(MID_TRACE,("Copying address len\n"));
372 
373             Map[2].BufferAddress = MmMapLockedPages( Map[2].Mdl, KernelMode );
374             *((PINT)Map[2].BufferAddress) = AddrLen;
375             MmUnmapLockedPages( Map[2].BufferAddress, Map[2].Mdl );
376         }
377 
378         AFD_DbgPrint(MID_TRACE,("Mapping data buffer pages\n"));
379 
380         Map[0].BufferAddress = MmMapLockedPages( Map[0].Mdl, KernelMode );
381 
382         AFD_DbgPrint(MID_TRACE,("Buffer %d: %p:%u\n",
383                                 0,
384                                 Map[0].BufferAddress,
385                                 BytesToCopy));
386 
387         RtlCopyMemory( Map[0].BufferAddress,
388                       DatagramRecv->Buffer,
389                       BytesToCopy );
390 
391         MmUnmapLockedPages( Map[0].BufferAddress, Map[0].Mdl );
392 
393         *TotalBytesCopied = BytesToCopy;
394     }
395 
396     if (*TotalBytesCopied == DatagramRecv->Len)
397     {
398         /* We copied the whole datagram */
399         Status = Irp->IoStatus.Status = STATUS_SUCCESS;
400     }
401     else
402     {
403         /* We only copied part of the datagram */
404         Status = Irp->IoStatus.Status = STATUS_BUFFER_OVERFLOW;
405     }
406 
407     Irp->IoStatus.Information = *TotalBytesCopied;
408 
409     if (!(RecvReq->TdiFlags & TDI_RECEIVE_PEEK))
410     {
411         FCB->Recv.Content -= DatagramRecv->Len;
412         ExFreePoolWithTag(DatagramRecv->Address, TAG_AFD_TRANSPORT_ADDRESS);
413         ExFreePoolWithTag(DatagramRecv, TAG_AFD_STORED_DATAGRAM);
414     }
415 
416     AFD_DbgPrint(MID_TRACE,("Done\n"));
417 
418     return Status;
419 }
420 
421 NTSTATUS NTAPI
422 AfdConnectedSocketReadData(PDEVICE_OBJECT DeviceObject, PIRP Irp,
423                            PIO_STACK_LOCATION IrpSp, BOOLEAN Short) {
424     NTSTATUS Status = STATUS_INVALID_PARAMETER;
425     PFILE_OBJECT FileObject = IrpSp->FileObject;
426     PAFD_FCB FCB = FileObject->FsContext;
427     PAFD_RECV_INFO RecvReq;
428     UINT TotalBytesCopied = 0;
429     PAFD_STORED_DATAGRAM DatagramRecv;
430     PLIST_ENTRY ListEntry;
431     KPROCESSOR_MODE LockMode;
432 
433     UNREFERENCED_PARAMETER(DeviceObject);
434     UNREFERENCED_PARAMETER(Short);
435 
436     AFD_DbgPrint(MID_TRACE,("Called on %p\n", FCB));
437 
438     if( !SocketAcquireStateLock( FCB ) ) return LostSocket( Irp );
439 
440     FCB->EventSelectDisabled &= ~AFD_EVENT_RECEIVE;
441 
442     if( !(FCB->Flags & AFD_ENDPOINT_CONNECTIONLESS) &&
443         FCB->State != SOCKET_STATE_CONNECTED &&
444         FCB->State != SOCKET_STATE_CONNECTING ) {
445         AFD_DbgPrint(MIN_TRACE,("Called recv on wrong kind of socket (s%x)\n",
446                                 FCB->State));
447         return UnlockAndMaybeComplete( FCB, STATUS_INVALID_PARAMETER,
448                                        Irp, 0 );
449     }
450 
451     if( !(RecvReq = LockRequest( Irp, IrpSp, FALSE, &LockMode )) )
452         return UnlockAndMaybeComplete( FCB, STATUS_NO_MEMORY,
453                                        Irp, 0 );
454 
455     AFD_DbgPrint(MID_TRACE,("Recv flags %x\n", RecvReq->AfdFlags));
456 
457     RecvReq->BufferArray = LockBuffers( RecvReq->BufferArray,
458                                        RecvReq->BufferCount,
459                                        NULL, NULL,
460                                        TRUE, FALSE, LockMode );
461 
462     if( !RecvReq->BufferArray ) {
463         return UnlockAndMaybeComplete( FCB, STATUS_ACCESS_VIOLATION,
464                                       Irp, 0 );
465     }
466 
467     if( FCB->Flags & AFD_ENDPOINT_CONNECTIONLESS )
468     {
469         if (!IsListEmpty(&FCB->DatagramList))
470         {
471             ListEntry = RemoveHeadList(&FCB->DatagramList);
472             DatagramRecv = CONTAINING_RECORD(ListEntry, AFD_STORED_DATAGRAM, ListEntry);
473             Status = SatisfyPacketRecvRequest(FCB, Irp, DatagramRecv,
474                                               (PUINT)&Irp->IoStatus.Information);
475 
476             if (RecvReq->TdiFlags & TDI_RECEIVE_PEEK)
477             {
478                 InsertHeadList(&FCB->DatagramList,
479                                &DatagramRecv->ListEntry);
480             }
481 
482             if (!IsListEmpty(&FCB->DatagramList))
483             {
484                 FCB->PollState |= AFD_EVENT_RECEIVE;
485                 FCB->PollStatus[FD_READ_BIT] = STATUS_SUCCESS;
486                 PollReeval( FCB->DeviceExt, FCB->FileObject );
487             }
488             else
489                 FCB->PollState &= ~AFD_EVENT_RECEIVE;
490 
491             UnlockBuffers(RecvReq->BufferArray, RecvReq->BufferCount, FALSE);
492 
493             return UnlockAndMaybeComplete(FCB, Status, Irp, Irp->IoStatus.Information);
494         }
495         else if (!(RecvReq->AfdFlags & AFD_OVERLAPPED) &&
496                 ((RecvReq->AfdFlags & AFD_IMMEDIATE) || (FCB->NonBlocking)))
497         {
498             AFD_DbgPrint(MID_TRACE,("Nonblocking\n"));
499             Status = STATUS_CANT_WAIT;
500             FCB->PollState &= ~AFD_EVENT_RECEIVE;
501             UnlockBuffers( RecvReq->BufferArray, RecvReq->BufferCount, FALSE );
502             return UnlockAndMaybeComplete( FCB, Status, Irp, 0 );
503         }
504         else
505         {
506             FCB->PollState &= ~AFD_EVENT_RECEIVE;
507             return LeaveIrpUntilLater( FCB, Irp, FUNCTION_RECV );
508         }
509     }
510 
511     Irp->IoStatus.Status = STATUS_PENDING;
512     Irp->IoStatus.Information = 0;
513 
514     InsertTailList( &FCB->PendingIrpList[FUNCTION_RECV],
515                     &Irp->Tail.Overlay.ListEntry );
516 
517     /************ From this point, the IRP is not ours ************/
518 
519     Status = ReceiveActivity( FCB, Irp );
520 
521     if( Status == STATUS_PENDING &&
522         !(RecvReq->AfdFlags & AFD_OVERLAPPED) &&
523         ((RecvReq->AfdFlags & AFD_IMMEDIATE) || (FCB->NonBlocking))) {
524         AFD_DbgPrint(MID_TRACE,("Nonblocking\n"));
525         Status = STATUS_CANT_WAIT;
526         TotalBytesCopied = 0;
527         RemoveEntryList( &Irp->Tail.Overlay.ListEntry );
528         UnlockBuffers( RecvReq->BufferArray, RecvReq->BufferCount, FALSE );
529         return UnlockAndMaybeComplete( FCB, Status, Irp,
530                                        TotalBytesCopied );
531     } else if( Status == STATUS_PENDING ) {
532         AFD_DbgPrint(MID_TRACE,("Leaving read irp\n"));
533         IoMarkIrpPending( Irp );
534         (void)IoSetCancelRoutine(Irp, AfdCancelHandler);
535     } else {
536         AFD_DbgPrint(MID_TRACE,("Completed with status %x\n", Status));
537     }
538 
539     SocketStateUnlock( FCB );
540     return Status;
541 }
542 
543 NTSTATUS NTAPI
544 PacketSocketRecvComplete(
545         PDEVICE_OBJECT DeviceObject,
546         PIRP Irp,
547         PVOID Context ) {
548     NTSTATUS Status = STATUS_SUCCESS;
549     PAFD_FCB FCB = Context;
550     PIRP NextIrp;
551     PIO_STACK_LOCATION NextIrpSp;
552     PLIST_ENTRY ListEntry;
553     PAFD_RECV_INFO RecvReq;
554     PAFD_STORED_DATAGRAM DatagramRecv;
555     UINT DGSize = Irp->IoStatus.Information + sizeof( AFD_STORED_DATAGRAM );
556     PLIST_ENTRY NextIrpEntry, DatagramRecvEntry;
557 
558     UNREFERENCED_PARAMETER(DeviceObject);
559 
560     AFD_DbgPrint(MID_TRACE,("Called on %p\n", FCB));
561 
562     if( !SocketAcquireStateLock( FCB ) )
563         return STATUS_FILE_CLOSED;
564 
565     ASSERT(FCB->ReceiveIrp.InFlightRequest == Irp);
566     FCB->ReceiveIrp.InFlightRequest = NULL;
567 
568     if( FCB->State == SOCKET_STATE_CLOSED ) {
569         /* Cleanup our IRP queue because the FCB is being destroyed */
570         while( !IsListEmpty( &FCB->PendingIrpList[FUNCTION_RECV] ) ) {
571             NextIrpEntry = RemoveHeadList(&FCB->PendingIrpList[FUNCTION_RECV]);
572             NextIrp = CONTAINING_RECORD(NextIrpEntry, IRP, Tail.Overlay.ListEntry);
573             NextIrpSp = IoGetCurrentIrpStackLocation( NextIrp );
574             RecvReq = GetLockedData(NextIrp, NextIrpSp);
575             NextIrp->IoStatus.Status = STATUS_FILE_CLOSED;
576             NextIrp->IoStatus.Information = 0;
577             UnlockBuffers(RecvReq->BufferArray, RecvReq->BufferCount, CheckUnlockExtraBuffers(FCB, NextIrpSp));
578             if( NextIrp->MdlAddress ) UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) );
579             (void)IoSetCancelRoutine(NextIrp, NULL);
580             IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT );
581         }
582 
583         /* Free all items on the datagram list */
584         while( !IsListEmpty( &FCB->DatagramList ) ) {
585                DatagramRecvEntry = RemoveHeadList(&FCB->DatagramList);
586                DatagramRecv = CONTAINING_RECORD(DatagramRecvEntry, AFD_STORED_DATAGRAM, ListEntry);
587                ExFreePoolWithTag(DatagramRecv->Address, TAG_AFD_TRANSPORT_ADDRESS);
588                ExFreePoolWithTag(DatagramRecv, TAG_AFD_STORED_DATAGRAM);
589         }
590 
591         SocketStateUnlock( FCB );
592         return STATUS_FILE_CLOSED;
593     }
594 
595     if (Irp->IoStatus.Status != STATUS_SUCCESS)
596     {
597         SocketStateUnlock(FCB);
598         return Irp->IoStatus.Status;
599     }
600 
601     if (FCB->TdiReceiveClosed)
602     {
603         SocketStateUnlock(FCB);
604         return STATUS_FILE_CLOSED;
605     }
606 
607     DatagramRecv = ExAllocatePoolWithTag(NonPagedPool,
608                                          DGSize,
609                                          TAG_AFD_STORED_DATAGRAM);
610 
611     if( DatagramRecv ) {
612         DatagramRecv->Len = Irp->IoStatus.Information;
613         RtlCopyMemory( DatagramRecv->Buffer, FCB->Recv.Window,
614                        DatagramRecv->Len );
615         AFD_DbgPrint(MID_TRACE,("Received (A %p)\n",
616                                 FCB->AddressFrom->RemoteAddress));
617         DatagramRecv->Address =
618             TaCopyTransportAddress( FCB->AddressFrom->RemoteAddress );
619 
620         if( !DatagramRecv->Address ) Status = STATUS_NO_MEMORY;
621 
622     } else Status = STATUS_NO_MEMORY;
623 
624     if( !NT_SUCCESS( Status ) ) {
625 
626         if (DatagramRecv)
627         {
628             ExFreePoolWithTag(DatagramRecv, TAG_AFD_STORED_DATAGRAM);
629         }
630 
631         SocketStateUnlock( FCB );
632         return Status;
633     } else {
634         FCB->Recv.Content += DatagramRecv->Len;
635         InsertTailList( &FCB->DatagramList, &DatagramRecv->ListEntry );
636     }
637 
638     /* Satisfy as many requests as we can */
639 
640     while( !IsListEmpty( &FCB->DatagramList ) &&
641            !IsListEmpty( &FCB->PendingIrpList[FUNCTION_RECV] ) ) {
642         AFD_DbgPrint(MID_TRACE,("Looping trying to satisfy request\n"));
643         ListEntry = RemoveHeadList( &FCB->DatagramList );
644         DatagramRecv = CONTAINING_RECORD( ListEntry, AFD_STORED_DATAGRAM,
645                                           ListEntry );
646         ListEntry = RemoveHeadList( &FCB->PendingIrpList[FUNCTION_RECV] );
647         NextIrp = CONTAINING_RECORD( ListEntry, IRP, Tail.Overlay.ListEntry );
648         NextIrpSp = IoGetCurrentIrpStackLocation( NextIrp );
649         RecvReq = GetLockedData(NextIrp, NextIrpSp);
650 
651         AFD_DbgPrint(MID_TRACE,("RecvReq: %p, DatagramRecv: %p\n",
652                                 RecvReq, DatagramRecv));
653 
654         AFD_DbgPrint(MID_TRACE,("Satisfying\n"));
655         Status = SatisfyPacketRecvRequest
656         ( FCB, NextIrp, DatagramRecv,
657          (PUINT)&NextIrp->IoStatus.Information );
658 
659         if (RecvReq->TdiFlags & TDI_RECEIVE_PEEK)
660         {
661             InsertHeadList(&FCB->DatagramList,
662                            &DatagramRecv->ListEntry);
663         }
664 
665         AFD_DbgPrint(MID_TRACE,("Unlocking\n"));
666         UnlockBuffers( RecvReq->BufferArray, RecvReq->BufferCount, CheckUnlockExtraBuffers(FCB, NextIrpSp) );
667         if ( NextIrp->MdlAddress ) UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) );
668 
669         AFD_DbgPrint(MID_TRACE,("Completing\n"));
670         (void)IoSetCancelRoutine(NextIrp, NULL);
671         NextIrp->IoStatus.Status = Status;
672 
673         IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT );
674     }
675 
676     if( !IsListEmpty( &FCB->DatagramList ) && IsListEmpty(&FCB->PendingIrpList[FUNCTION_RECV]) ) {
677         AFD_DbgPrint(MID_TRACE,("Signalling\n"));
678         FCB->PollState |= AFD_EVENT_RECEIVE;
679         FCB->PollStatus[FD_READ_BIT] = STATUS_SUCCESS;
680         PollReeval( FCB->DeviceExt, FCB->FileObject );
681     } else
682         FCB->PollState &= ~AFD_EVENT_RECEIVE;
683 
684     if( NT_SUCCESS(Irp->IoStatus.Status) && FCB->Recv.Content < FCB->Recv.Size ) {
685         /* Now relaunch the datagram request */
686         Status = TdiReceiveDatagram
687             ( &FCB->ReceiveIrp.InFlightRequest,
688               FCB->AddressFile.Object,
689               0,
690               FCB->Recv.Window,
691               FCB->Recv.Size,
692               FCB->AddressFrom,
693               PacketSocketRecvComplete,
694               FCB );
695     }
696 
697     SocketStateUnlock( FCB );
698 
699     return STATUS_SUCCESS;
700 }
701 
702 NTSTATUS NTAPI
703 AfdPacketSocketReadData(PDEVICE_OBJECT DeviceObject, PIRP Irp,
704                         PIO_STACK_LOCATION IrpSp ) {
705     NTSTATUS Status = STATUS_SUCCESS;
706     PFILE_OBJECT FileObject = IrpSp->FileObject;
707     PAFD_FCB FCB = FileObject->FsContext;
708     PAFD_RECV_INFO_UDP RecvReq;
709     PLIST_ENTRY ListEntry;
710     PAFD_STORED_DATAGRAM DatagramRecv;
711     KPROCESSOR_MODE LockMode;
712 
713     UNREFERENCED_PARAMETER(DeviceObject);
714 
715     AFD_DbgPrint(MID_TRACE,("Called on %p\n", FCB));
716 
717     if( !SocketAcquireStateLock( FCB ) ) return LostSocket( Irp );
718 
719     FCB->EventSelectDisabled &= ~AFD_EVENT_RECEIVE;
720 
721     /* Check that the socket is bound */
722     if( FCB->State != SOCKET_STATE_BOUND )
723     {
724         AFD_DbgPrint(MIN_TRACE,("Invalid socket state\n"));
725         return UnlockAndMaybeComplete(FCB, STATUS_INVALID_PARAMETER, Irp, 0);
726     }
727 
728     if (FCB->TdiReceiveClosed)
729     {
730         AFD_DbgPrint(MIN_TRACE,("Receive closed\n"));
731         return UnlockAndMaybeComplete(FCB, STATUS_FILE_CLOSED, Irp, 0);
732     }
733 
734     if( !(RecvReq = LockRequest( Irp, IrpSp, FALSE, &LockMode )) )
735         return UnlockAndMaybeComplete(FCB, STATUS_NO_MEMORY, Irp, 0);
736 
737     AFD_DbgPrint(MID_TRACE,("Recv flags %x\n", RecvReq->AfdFlags));
738 
739     RecvReq->BufferArray = LockBuffers( RecvReq->BufferArray,
740                                         RecvReq->BufferCount,
741                                         RecvReq->Address,
742                                         RecvReq->AddressLength,
743                                         TRUE, TRUE, LockMode );
744 
745     if( !RecvReq->BufferArray ) { /* access violation in userspace */
746         return UnlockAndMaybeComplete(FCB, STATUS_ACCESS_VIOLATION, Irp, 0);
747     }
748 
749     if (!IsListEmpty(&FCB->DatagramList))
750     {
751         ListEntry = RemoveHeadList(&FCB->DatagramList);
752         DatagramRecv = CONTAINING_RECORD(ListEntry, AFD_STORED_DATAGRAM, ListEntry);
753         Status = SatisfyPacketRecvRequest(FCB, Irp, DatagramRecv,
754                                           (PUINT)&Irp->IoStatus.Information);
755 
756         if (RecvReq->TdiFlags & TDI_RECEIVE_PEEK)
757         {
758             InsertHeadList(&FCB->DatagramList,
759                            &DatagramRecv->ListEntry);
760         }
761 
762         if (!IsListEmpty(&FCB->DatagramList))
763         {
764             FCB->PollState |= AFD_EVENT_RECEIVE;
765             FCB->PollStatus[FD_READ_BIT] = STATUS_SUCCESS;
766             PollReeval( FCB->DeviceExt, FCB->FileObject );
767         }
768         else
769             FCB->PollState &= ~AFD_EVENT_RECEIVE;
770 
771         UnlockBuffers(RecvReq->BufferArray, RecvReq->BufferCount, TRUE);
772 
773         return UnlockAndMaybeComplete(FCB, Status, Irp, Irp->IoStatus.Information);
774     }
775     else if (!(RecvReq->AfdFlags & AFD_OVERLAPPED) &&
776             ((RecvReq->AfdFlags & AFD_IMMEDIATE) || (FCB->NonBlocking)))
777     {
778         AFD_DbgPrint(MID_TRACE,("Nonblocking\n"));
779         Status = STATUS_CANT_WAIT;
780         FCB->PollState &= ~AFD_EVENT_RECEIVE;
781         UnlockBuffers( RecvReq->BufferArray, RecvReq->BufferCount, TRUE );
782         return UnlockAndMaybeComplete( FCB, Status, Irp, 0 );
783     }
784     else
785     {
786         FCB->PollState &= ~AFD_EVENT_RECEIVE;
787         return LeaveIrpUntilLater( FCB, Irp, FUNCTION_RECV );
788     }
789 }
790