xref: /reactos/drivers/network/afd/afd/read.c (revision 9f9b81e3)
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 
RefillSocketBuffer(PAFD_FCB FCB)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 
HandleReceiveComplete(PAFD_FCB FCB,NTSTATUS Status,ULONG_PTR Information)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 
CantReadMore(PAFD_FCB FCB)88 static BOOLEAN CantReadMore( PAFD_FCB FCB ) {
89     UINT BytesAvailable = FCB->Recv.Content - FCB->Recv.BytesUsed;
90 
91     return !BytesAvailable && FCB->TdiReceiveClosed;
92 }
93 
TryToSatisfyRecvRequestFromBuffer(PAFD_FCB FCB,PAFD_RECV_INFO RecvReq,PUINT TotalBytesCopied)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 
ReceiveActivity(PAFD_FCB FCB,PIRP Irp)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 
179             /* Unexpected disconnect by the remote host or graceful disconnect */
180             Status = FCB->LastReceiveStatus;
181 
182             NextIrp->IoStatus.Status = Status;
183             NextIrp->IoStatus.Information = 0;
184             if( NextIrp == Irp ) RetStatus = Status;
185             if( NextIrp->MdlAddress ) UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) );
186             (void)IoSetCancelRoutine(NextIrp, NULL);
187             IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT );
188         }
189     } else {
190         /* Kick the user that receive would be possible now */
191         /* XXX Not implemented yet */
192 
193         AFD_DbgPrint(MID_TRACE,("FCB %p Receive data waiting %u\n",
194                                 FCB, FCB->Recv.Content));
195         /*OskitDumpBuffer( FCB->Recv.Window, FCB->Recv.Content );*/
196 
197         /* Try to clear some requests */
198         while( !IsListEmpty( &FCB->PendingIrpList[FUNCTION_RECV] ) ) {
199             NextIrpEntry = RemoveHeadList(&FCB->PendingIrpList[FUNCTION_RECV]);
200             NextIrp = CONTAINING_RECORD(NextIrpEntry, IRP, Tail.Overlay.ListEntry);
201             NextIrpSp = IoGetCurrentIrpStackLocation( NextIrp );
202             RecvReq = GetLockedData(NextIrp, NextIrpSp);
203 
204             AFD_DbgPrint(MID_TRACE,("RecvReq @ %p\n", RecvReq));
205 
206             Status = TryToSatisfyRecvRequestFromBuffer
207             ( FCB, RecvReq, &TotalBytesCopied );
208 
209             if( Status == STATUS_PENDING ) {
210                 AFD_DbgPrint(MID_TRACE,("Ran out of data for %p\n", NextIrp));
211                 InsertHeadList(&FCB->PendingIrpList[FUNCTION_RECV],
212                                &NextIrp->Tail.Overlay.ListEntry);
213                 break;
214             } else {
215                 AFD_DbgPrint(MID_TRACE,("Completing recv %p (%u)\n", NextIrp,
216                                         TotalBytesCopied));
217                 UnlockBuffers( RecvReq->BufferArray,
218                                RecvReq->BufferCount, FALSE );
219                 NextIrp->IoStatus.Status = Status;
220                 NextIrp->IoStatus.Information = TotalBytesCopied;
221                 if( NextIrp == Irp ) {
222                     RetStatus = Status;
223                 }
224                 if( NextIrp->MdlAddress ) UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) );
225                 (void)IoSetCancelRoutine(NextIrp, NULL);
226                 IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT );
227             }
228         }
229     }
230 
231     if( FCB->Recv.Content - FCB->Recv.BytesUsed &&
232         IsListEmpty(&FCB->PendingIrpList[FUNCTION_RECV]) ) {
233         FCB->PollState |= AFD_EVENT_RECEIVE;
234         FCB->PollStatus[FD_READ_BIT] = STATUS_SUCCESS;
235         PollReeval( FCB->DeviceExt, FCB->FileObject );
236     }
237     else
238     {
239         FCB->PollState &= ~AFD_EVENT_RECEIVE;
240     }
241 
242     /* Signal FD_CLOSE if no buffered data remains and the socket can't receive any more */
243     if (CantReadMore(FCB))
244     {
245         if (FCB->LastReceiveStatus == STATUS_SUCCESS)
246         {
247             FCB->PollState |= AFD_EVENT_DISCONNECT;
248         }
249         else
250         {
251             FCB->PollState |= AFD_EVENT_CLOSE;
252         }
253         FCB->PollStatus[FD_CLOSE_BIT] = FCB->LastReceiveStatus;
254         PollReeval(FCB->DeviceExt, FCB->FileObject);
255     }
256 
257     AFD_DbgPrint(MID_TRACE,("RetStatus for irp %p is %x\n", Irp, RetStatus));
258 
259     return RetStatus;
260 }
261 
ReceiveComplete(PDEVICE_OBJECT DeviceObject,PIRP Irp,PVOID Context)262 NTSTATUS NTAPI ReceiveComplete
263 ( PDEVICE_OBJECT DeviceObject,
264   PIRP Irp,
265   PVOID Context ) {
266     PAFD_FCB FCB = (PAFD_FCB)Context;
267     PLIST_ENTRY NextIrpEntry;
268     PIRP NextIrp;
269     PAFD_RECV_INFO RecvReq;
270     PIO_STACK_LOCATION NextIrpSp;
271 
272     UNREFERENCED_PARAMETER(DeviceObject);
273 
274     AFD_DbgPrint(MID_TRACE,("Called\n"));
275 
276     if( !SocketAcquireStateLock( FCB ) )
277         return STATUS_FILE_CLOSED;
278 
279     ASSERT(FCB->ReceiveIrp.InFlightRequest == Irp);
280     FCB->ReceiveIrp.InFlightRequest = NULL;
281 
282     if( FCB->State == SOCKET_STATE_CLOSED ) {
283         /* Cleanup our IRP queue because the FCB is being destroyed */
284         while( !IsListEmpty( &FCB->PendingIrpList[FUNCTION_RECV] ) ) {
285             NextIrpEntry = RemoveHeadList(&FCB->PendingIrpList[FUNCTION_RECV]);
286             NextIrp = CONTAINING_RECORD(NextIrpEntry, IRP, Tail.Overlay.ListEntry);
287             NextIrpSp = IoGetCurrentIrpStackLocation(NextIrp);
288             RecvReq = GetLockedData(NextIrp, NextIrpSp);
289             NextIrp->IoStatus.Status = STATUS_FILE_CLOSED;
290             NextIrp->IoStatus.Information = 0;
291             UnlockBuffers(RecvReq->BufferArray, RecvReq->BufferCount, FALSE);
292             if( NextIrp->MdlAddress ) UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) );
293             (void)IoSetCancelRoutine(NextIrp, NULL);
294             IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT );
295         }
296         SocketStateUnlock( FCB );
297         return STATUS_FILE_CLOSED;
298     } else if( FCB->State == SOCKET_STATE_LISTENING ) {
299         AFD_DbgPrint(MIN_TRACE,("!!! LISTENER GOT A RECEIVE COMPLETE !!!\n"));
300         SocketStateUnlock( FCB );
301         return STATUS_INVALID_PARAMETER;
302     }
303 
304     HandleReceiveComplete( FCB, Irp->IoStatus.Status, Irp->IoStatus.Information );
305 
306     ReceiveActivity( FCB, NULL );
307 
308     SocketStateUnlock( FCB );
309 
310     return STATUS_SUCCESS;
311 }
312 
313 static NTSTATUS NTAPI
SatisfyPacketRecvRequest(PAFD_FCB FCB,PIRP Irp,PAFD_STORED_DATAGRAM DatagramRecv,PUINT TotalBytesCopied)314 SatisfyPacketRecvRequest( PAFD_FCB FCB, PIRP Irp,
315                          PAFD_STORED_DATAGRAM DatagramRecv,
316                          PUINT TotalBytesCopied ) {
317     NTSTATUS Status = STATUS_SUCCESS;
318     PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp );
319     PAFD_RECV_INFO RecvReq =
320     GetLockedData(Irp, IrpSp);
321     UINT BytesToCopy = 0, BytesAvailable = DatagramRecv->Len, AddrLen = 0;
322     PAFD_MAPBUF Map;
323     BOOLEAN ExtraBuffers = CheckUnlockExtraBuffers(FCB, IrpSp);
324 
325     Map = (PAFD_MAPBUF)(RecvReq->BufferArray +
326                         RecvReq->BufferCount +
327                         (ExtraBuffers ? EXTRA_LOCK_BUFFERS : 0));
328 
329     BytesToCopy = MIN( RecvReq->BufferArray[0].len, BytesAvailable );
330 
331     AFD_DbgPrint(MID_TRACE,("BytesToCopy: %u len %u\n", BytesToCopy,
332                             RecvReq->BufferArray[0].len));
333 
334     if( Map[0].Mdl ) {
335         /* Copy the address */
336         if( ExtraBuffers && Map[1].Mdl && Map[2].Mdl ) {
337             AFD_DbgPrint(MID_TRACE,("Checking TAAddressCount\n"));
338 
339             if( DatagramRecv->Address->TAAddressCount != 1 ) {
340                 AFD_DbgPrint
341                 (MIN_TRACE,
342                  ("Wierd address count %d\n",
343                   DatagramRecv->Address->TAAddressCount));
344             }
345 
346             AFD_DbgPrint(MID_TRACE,("Computing addr len\n"));
347 
348             AddrLen = MIN(DatagramRecv->Address->Address->AddressLength +
349                           sizeof(USHORT),
350                           RecvReq->BufferArray[1].len);
351 
352             AFD_DbgPrint(MID_TRACE,("Copying %u bytes of address\n", AddrLen));
353 
354             Map[1].BufferAddress = MmMapLockedPages( Map[1].Mdl, KernelMode );
355 
356             AFD_DbgPrint(MID_TRACE,("Done mapping, copying address\n"));
357 
358             RtlCopyMemory( Map[1].BufferAddress,
359                           &DatagramRecv->Address->Address->AddressType,
360                           AddrLen );
361 
362             MmUnmapLockedPages( Map[1].BufferAddress, Map[1].Mdl );
363 
364             AFD_DbgPrint(MID_TRACE,("Copying address len\n"));
365 
366             Map[2].BufferAddress = MmMapLockedPages( Map[2].Mdl, KernelMode );
367             *((PINT)Map[2].BufferAddress) = AddrLen;
368             MmUnmapLockedPages( Map[2].BufferAddress, Map[2].Mdl );
369         }
370 
371         AFD_DbgPrint(MID_TRACE,("Mapping data buffer pages\n"));
372 
373         Map[0].BufferAddress = MmMapLockedPages( Map[0].Mdl, KernelMode );
374 
375         AFD_DbgPrint(MID_TRACE,("Buffer %d: %p:%u\n",
376                                 0,
377                                 Map[0].BufferAddress,
378                                 BytesToCopy));
379 
380         RtlCopyMemory( Map[0].BufferAddress,
381                       DatagramRecv->Buffer,
382                       BytesToCopy );
383 
384         MmUnmapLockedPages( Map[0].BufferAddress, Map[0].Mdl );
385 
386         *TotalBytesCopied = BytesToCopy;
387     }
388 
389     if (*TotalBytesCopied == DatagramRecv->Len)
390     {
391         /* We copied the whole datagram */
392         Status = Irp->IoStatus.Status = STATUS_SUCCESS;
393     }
394     else
395     {
396         /* We only copied part of the datagram */
397         Status = Irp->IoStatus.Status = STATUS_BUFFER_OVERFLOW;
398     }
399 
400     Irp->IoStatus.Information = *TotalBytesCopied;
401 
402     if (!(RecvReq->TdiFlags & TDI_RECEIVE_PEEK))
403     {
404         FCB->Recv.Content -= DatagramRecv->Len;
405         ExFreePoolWithTag(DatagramRecv->Address, TAG_AFD_TRANSPORT_ADDRESS);
406         ExFreePoolWithTag(DatagramRecv, TAG_AFD_STORED_DATAGRAM);
407     }
408 
409     AFD_DbgPrint(MID_TRACE,("Done\n"));
410 
411     return Status;
412 }
413 
414 NTSTATUS NTAPI
AfdConnectedSocketReadData(PDEVICE_OBJECT DeviceObject,PIRP Irp,PIO_STACK_LOCATION IrpSp,BOOLEAN Short)415 AfdConnectedSocketReadData(PDEVICE_OBJECT DeviceObject, PIRP Irp,
416                            PIO_STACK_LOCATION IrpSp, BOOLEAN Short) {
417     NTSTATUS Status = STATUS_INVALID_PARAMETER;
418     PFILE_OBJECT FileObject = IrpSp->FileObject;
419     PAFD_FCB FCB = FileObject->FsContext;
420     PAFD_RECV_INFO RecvReq;
421     UINT TotalBytesCopied = 0;
422     PAFD_STORED_DATAGRAM DatagramRecv;
423     PLIST_ENTRY ListEntry;
424     KPROCESSOR_MODE LockMode;
425 
426     UNREFERENCED_PARAMETER(DeviceObject);
427     UNREFERENCED_PARAMETER(Short);
428 
429     AFD_DbgPrint(MID_TRACE,("Called on %p\n", FCB));
430 
431     if( !SocketAcquireStateLock( FCB ) ) return LostSocket( Irp );
432 
433     FCB->EventSelectDisabled &= ~AFD_EVENT_RECEIVE;
434 
435     if( !(FCB->Flags & AFD_ENDPOINT_CONNECTIONLESS) &&
436         FCB->State != SOCKET_STATE_CONNECTED &&
437         FCB->State != SOCKET_STATE_CONNECTING ) {
438         AFD_DbgPrint(MIN_TRACE,("Called recv on wrong kind of socket (s%x)\n",
439                                 FCB->State));
440         return UnlockAndMaybeComplete( FCB, STATUS_INVALID_PARAMETER,
441                                        Irp, 0 );
442     }
443 
444     if( !(RecvReq = LockRequest( Irp, IrpSp, FALSE, &LockMode )) )
445         return UnlockAndMaybeComplete( FCB, STATUS_NO_MEMORY,
446                                        Irp, 0 );
447 
448     AFD_DbgPrint(MID_TRACE,("Recv flags %x\n", RecvReq->AfdFlags));
449 
450     RecvReq->BufferArray = LockBuffers( RecvReq->BufferArray,
451                                        RecvReq->BufferCount,
452                                        NULL, NULL,
453                                        TRUE, FALSE, LockMode );
454 
455     if( !RecvReq->BufferArray ) {
456         return UnlockAndMaybeComplete( FCB, STATUS_ACCESS_VIOLATION,
457                                       Irp, 0 );
458     }
459 
460     if( FCB->Flags & AFD_ENDPOINT_CONNECTIONLESS )
461     {
462         if (!IsListEmpty(&FCB->DatagramList))
463         {
464             ListEntry = RemoveHeadList(&FCB->DatagramList);
465             DatagramRecv = CONTAINING_RECORD(ListEntry, AFD_STORED_DATAGRAM, ListEntry);
466             Status = SatisfyPacketRecvRequest(FCB, Irp, DatagramRecv,
467                                               (PUINT)&Irp->IoStatus.Information);
468 
469             if (RecvReq->TdiFlags & TDI_RECEIVE_PEEK)
470             {
471                 InsertHeadList(&FCB->DatagramList,
472                                &DatagramRecv->ListEntry);
473             }
474 
475             if (!IsListEmpty(&FCB->DatagramList))
476             {
477                 FCB->PollState |= AFD_EVENT_RECEIVE;
478                 FCB->PollStatus[FD_READ_BIT] = STATUS_SUCCESS;
479                 PollReeval( FCB->DeviceExt, FCB->FileObject );
480             }
481             else
482                 FCB->PollState &= ~AFD_EVENT_RECEIVE;
483 
484             UnlockBuffers(RecvReq->BufferArray, RecvReq->BufferCount, FALSE);
485 
486             return UnlockAndMaybeComplete(FCB, Status, Irp, Irp->IoStatus.Information);
487         }
488         else if (!(RecvReq->AfdFlags & AFD_OVERLAPPED) &&
489                 ((RecvReq->AfdFlags & AFD_IMMEDIATE) || (FCB->NonBlocking)))
490         {
491             AFD_DbgPrint(MID_TRACE,("Nonblocking\n"));
492             Status = STATUS_CANT_WAIT;
493             FCB->PollState &= ~AFD_EVENT_RECEIVE;
494             UnlockBuffers( RecvReq->BufferArray, RecvReq->BufferCount, FALSE );
495             return UnlockAndMaybeComplete( FCB, Status, Irp, 0 );
496         }
497         else
498         {
499             FCB->PollState &= ~AFD_EVENT_RECEIVE;
500             return LeaveIrpUntilLater( FCB, Irp, FUNCTION_RECV );
501         }
502     }
503 
504     Irp->IoStatus.Status = STATUS_PENDING;
505     Irp->IoStatus.Information = 0;
506 
507     InsertTailList( &FCB->PendingIrpList[FUNCTION_RECV],
508                     &Irp->Tail.Overlay.ListEntry );
509 
510     /************ From this point, the IRP is not ours ************/
511 
512     Status = ReceiveActivity( FCB, Irp );
513 
514     if( Status == STATUS_PENDING &&
515         !(RecvReq->AfdFlags & AFD_OVERLAPPED) &&
516         ((RecvReq->AfdFlags & AFD_IMMEDIATE) || (FCB->NonBlocking))) {
517         AFD_DbgPrint(MID_TRACE,("Nonblocking\n"));
518         Status = STATUS_CANT_WAIT;
519         TotalBytesCopied = 0;
520         RemoveEntryList( &Irp->Tail.Overlay.ListEntry );
521         UnlockBuffers( RecvReq->BufferArray, RecvReq->BufferCount, FALSE );
522         return UnlockAndMaybeComplete( FCB, Status, Irp,
523                                        TotalBytesCopied );
524     } else if( Status == STATUS_PENDING ) {
525         AFD_DbgPrint(MID_TRACE,("Leaving read irp\n"));
526         IoMarkIrpPending( Irp );
527         (void)IoSetCancelRoutine(Irp, AfdCancelHandler);
528     } else {
529         AFD_DbgPrint(MID_TRACE,("Completed with status %x\n", Status));
530     }
531 
532     SocketStateUnlock( FCB );
533     return Status;
534 }
535 
536 NTSTATUS NTAPI
PacketSocketRecvComplete(PDEVICE_OBJECT DeviceObject,PIRP Irp,PVOID Context)537 PacketSocketRecvComplete(
538         PDEVICE_OBJECT DeviceObject,
539         PIRP Irp,
540         PVOID Context ) {
541     NTSTATUS Status = STATUS_SUCCESS;
542     PAFD_FCB FCB = Context;
543     PIRP NextIrp;
544     PIO_STACK_LOCATION NextIrpSp;
545     PLIST_ENTRY ListEntry;
546     PAFD_RECV_INFO RecvReq;
547     PAFD_STORED_DATAGRAM DatagramRecv;
548     UINT DGSize = Irp->IoStatus.Information + sizeof( AFD_STORED_DATAGRAM );
549     PLIST_ENTRY NextIrpEntry, DatagramRecvEntry;
550 
551     UNREFERENCED_PARAMETER(DeviceObject);
552 
553     AFD_DbgPrint(MID_TRACE,("Called on %p\n", FCB));
554 
555     if( !SocketAcquireStateLock( FCB ) )
556         return STATUS_FILE_CLOSED;
557 
558     ASSERT(FCB->ReceiveIrp.InFlightRequest == Irp);
559     FCB->ReceiveIrp.InFlightRequest = NULL;
560 
561     if( FCB->State == SOCKET_STATE_CLOSED ) {
562         /* Cleanup our IRP queue because the FCB is being destroyed */
563         while( !IsListEmpty( &FCB->PendingIrpList[FUNCTION_RECV] ) ) {
564             NextIrpEntry = RemoveHeadList(&FCB->PendingIrpList[FUNCTION_RECV]);
565             NextIrp = CONTAINING_RECORD(NextIrpEntry, IRP, Tail.Overlay.ListEntry);
566             NextIrpSp = IoGetCurrentIrpStackLocation( NextIrp );
567             RecvReq = GetLockedData(NextIrp, NextIrpSp);
568             NextIrp->IoStatus.Status = STATUS_FILE_CLOSED;
569             NextIrp->IoStatus.Information = 0;
570             UnlockBuffers(RecvReq->BufferArray, RecvReq->BufferCount, CheckUnlockExtraBuffers(FCB, NextIrpSp));
571             if( NextIrp->MdlAddress ) UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) );
572             (void)IoSetCancelRoutine(NextIrp, NULL);
573             IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT );
574         }
575 
576         /* Free all items on the datagram list */
577         while( !IsListEmpty( &FCB->DatagramList ) ) {
578                DatagramRecvEntry = RemoveHeadList(&FCB->DatagramList);
579                DatagramRecv = CONTAINING_RECORD(DatagramRecvEntry, AFD_STORED_DATAGRAM, ListEntry);
580                ExFreePoolWithTag(DatagramRecv->Address, TAG_AFD_TRANSPORT_ADDRESS);
581                ExFreePoolWithTag(DatagramRecv, TAG_AFD_STORED_DATAGRAM);
582         }
583 
584         SocketStateUnlock( FCB );
585         return STATUS_FILE_CLOSED;
586     }
587 
588     if (Irp->IoStatus.Status != STATUS_SUCCESS)
589     {
590         SocketStateUnlock(FCB);
591         return Irp->IoStatus.Status;
592     }
593 
594     if (FCB->TdiReceiveClosed)
595     {
596         SocketStateUnlock(FCB);
597         return STATUS_FILE_CLOSED;
598     }
599 
600     DatagramRecv = ExAllocatePoolWithTag(NonPagedPool,
601                                          DGSize,
602                                          TAG_AFD_STORED_DATAGRAM);
603 
604     if( DatagramRecv ) {
605         DatagramRecv->Len = Irp->IoStatus.Information;
606         RtlCopyMemory( DatagramRecv->Buffer, FCB->Recv.Window,
607                        DatagramRecv->Len );
608         AFD_DbgPrint(MID_TRACE,("Received (A %p)\n",
609                                 FCB->AddressFrom->RemoteAddress));
610         DatagramRecv->Address =
611             TaCopyTransportAddress( FCB->AddressFrom->RemoteAddress );
612 
613         if( !DatagramRecv->Address ) Status = STATUS_NO_MEMORY;
614 
615     } else Status = STATUS_NO_MEMORY;
616 
617     if( !NT_SUCCESS( Status ) ) {
618 
619         if (DatagramRecv)
620         {
621             ExFreePoolWithTag(DatagramRecv, TAG_AFD_STORED_DATAGRAM);
622         }
623 
624         SocketStateUnlock( FCB );
625         return Status;
626     } else {
627         FCB->Recv.Content += DatagramRecv->Len;
628         InsertTailList( &FCB->DatagramList, &DatagramRecv->ListEntry );
629     }
630 
631     /* Satisfy as many requests as we can */
632 
633     while( !IsListEmpty( &FCB->DatagramList ) &&
634            !IsListEmpty( &FCB->PendingIrpList[FUNCTION_RECV] ) ) {
635         AFD_DbgPrint(MID_TRACE,("Looping trying to satisfy request\n"));
636         ListEntry = RemoveHeadList( &FCB->DatagramList );
637         DatagramRecv = CONTAINING_RECORD( ListEntry, AFD_STORED_DATAGRAM,
638                                           ListEntry );
639         ListEntry = RemoveHeadList( &FCB->PendingIrpList[FUNCTION_RECV] );
640         NextIrp = CONTAINING_RECORD( ListEntry, IRP, Tail.Overlay.ListEntry );
641         NextIrpSp = IoGetCurrentIrpStackLocation( NextIrp );
642         RecvReq = GetLockedData(NextIrp, NextIrpSp);
643 
644         AFD_DbgPrint(MID_TRACE,("RecvReq: %p, DatagramRecv: %p\n",
645                                 RecvReq, DatagramRecv));
646 
647         AFD_DbgPrint(MID_TRACE,("Satisfying\n"));
648         Status = SatisfyPacketRecvRequest
649         ( FCB, NextIrp, DatagramRecv,
650          (PUINT)&NextIrp->IoStatus.Information );
651 
652         if (RecvReq->TdiFlags & TDI_RECEIVE_PEEK)
653         {
654             InsertHeadList(&FCB->DatagramList,
655                            &DatagramRecv->ListEntry);
656         }
657 
658         AFD_DbgPrint(MID_TRACE,("Unlocking\n"));
659         UnlockBuffers( RecvReq->BufferArray, RecvReq->BufferCount, CheckUnlockExtraBuffers(FCB, NextIrpSp) );
660         if ( NextIrp->MdlAddress ) UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) );
661 
662         AFD_DbgPrint(MID_TRACE,("Completing\n"));
663         (void)IoSetCancelRoutine(NextIrp, NULL);
664         NextIrp->IoStatus.Status = Status;
665 
666         IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT );
667     }
668 
669     if( !IsListEmpty( &FCB->DatagramList ) && IsListEmpty(&FCB->PendingIrpList[FUNCTION_RECV]) ) {
670         AFD_DbgPrint(MID_TRACE,("Signalling\n"));
671         FCB->PollState |= AFD_EVENT_RECEIVE;
672         FCB->PollStatus[FD_READ_BIT] = STATUS_SUCCESS;
673         PollReeval( FCB->DeviceExt, FCB->FileObject );
674     } else
675         FCB->PollState &= ~AFD_EVENT_RECEIVE;
676 
677     if( NT_SUCCESS(Irp->IoStatus.Status) && FCB->Recv.Content < FCB->Recv.Size ) {
678         /* Now relaunch the datagram request */
679         Status = TdiReceiveDatagram
680             ( &FCB->ReceiveIrp.InFlightRequest,
681               FCB->AddressFile.Object,
682               0,
683               FCB->Recv.Window,
684               FCB->Recv.Size,
685               FCB->AddressFrom,
686               PacketSocketRecvComplete,
687               FCB );
688     }
689 
690     SocketStateUnlock( FCB );
691 
692     return STATUS_SUCCESS;
693 }
694 
695 NTSTATUS NTAPI
AfdPacketSocketReadData(PDEVICE_OBJECT DeviceObject,PIRP Irp,PIO_STACK_LOCATION IrpSp)696 AfdPacketSocketReadData(PDEVICE_OBJECT DeviceObject, PIRP Irp,
697                         PIO_STACK_LOCATION IrpSp ) {
698     NTSTATUS Status = STATUS_SUCCESS;
699     PFILE_OBJECT FileObject = IrpSp->FileObject;
700     PAFD_FCB FCB = FileObject->FsContext;
701     PAFD_RECV_INFO_UDP RecvReq;
702     PLIST_ENTRY ListEntry;
703     PAFD_STORED_DATAGRAM DatagramRecv;
704     KPROCESSOR_MODE LockMode;
705 
706     UNREFERENCED_PARAMETER(DeviceObject);
707 
708     AFD_DbgPrint(MID_TRACE,("Called on %p\n", FCB));
709 
710     if( !SocketAcquireStateLock( FCB ) ) return LostSocket( Irp );
711 
712     FCB->EventSelectDisabled &= ~AFD_EVENT_RECEIVE;
713 
714     /* Check that the socket is bound */
715     if( FCB->State != SOCKET_STATE_BOUND )
716     {
717         AFD_DbgPrint(MIN_TRACE,("Invalid socket state\n"));
718         return UnlockAndMaybeComplete(FCB, STATUS_INVALID_PARAMETER, Irp, 0);
719     }
720 
721     if (FCB->TdiReceiveClosed)
722     {
723         AFD_DbgPrint(MIN_TRACE,("Receive closed\n"));
724         return UnlockAndMaybeComplete(FCB, STATUS_FILE_CLOSED, Irp, 0);
725     }
726 
727     if( !(RecvReq = LockRequest( Irp, IrpSp, FALSE, &LockMode )) )
728         return UnlockAndMaybeComplete(FCB, STATUS_NO_MEMORY, Irp, 0);
729 
730     AFD_DbgPrint(MID_TRACE,("Recv flags %x\n", RecvReq->AfdFlags));
731 
732     RecvReq->BufferArray = LockBuffers( RecvReq->BufferArray,
733                                         RecvReq->BufferCount,
734                                         RecvReq->Address,
735                                         RecvReq->AddressLength,
736                                         TRUE, TRUE, LockMode );
737 
738     if( !RecvReq->BufferArray ) { /* access violation in userspace */
739         return UnlockAndMaybeComplete(FCB, STATUS_ACCESS_VIOLATION, Irp, 0);
740     }
741 
742     if (!IsListEmpty(&FCB->DatagramList))
743     {
744         ListEntry = RemoveHeadList(&FCB->DatagramList);
745         DatagramRecv = CONTAINING_RECORD(ListEntry, AFD_STORED_DATAGRAM, ListEntry);
746         Status = SatisfyPacketRecvRequest(FCB, Irp, DatagramRecv,
747                                           (PUINT)&Irp->IoStatus.Information);
748 
749         if (RecvReq->TdiFlags & TDI_RECEIVE_PEEK)
750         {
751             InsertHeadList(&FCB->DatagramList,
752                            &DatagramRecv->ListEntry);
753         }
754 
755         if (!IsListEmpty(&FCB->DatagramList))
756         {
757             FCB->PollState |= AFD_EVENT_RECEIVE;
758             FCB->PollStatus[FD_READ_BIT] = STATUS_SUCCESS;
759             PollReeval( FCB->DeviceExt, FCB->FileObject );
760         }
761         else
762             FCB->PollState &= ~AFD_EVENT_RECEIVE;
763 
764         UnlockBuffers(RecvReq->BufferArray, RecvReq->BufferCount, TRUE);
765 
766         return UnlockAndMaybeComplete(FCB, Status, Irp, Irp->IoStatus.Information);
767     }
768     else if (!(RecvReq->AfdFlags & AFD_OVERLAPPED) &&
769             ((RecvReq->AfdFlags & AFD_IMMEDIATE) || (FCB->NonBlocking)))
770     {
771         AFD_DbgPrint(MID_TRACE,("Nonblocking\n"));
772         Status = STATUS_CANT_WAIT;
773         FCB->PollState &= ~AFD_EVENT_RECEIVE;
774         UnlockBuffers( RecvReq->BufferArray, RecvReq->BufferCount, TRUE );
775         return UnlockAndMaybeComplete( FCB, Status, Irp, 0 );
776     }
777     else
778     {
779         FCB->PollState &= ~AFD_EVENT_RECEIVE;
780         return LeaveIrpUntilLater( FCB, Irp, FUNCTION_RECV );
781     }
782 }
783