Fix a copy-paste mistake and remove an unused variable
[reactos.git] / reactos / drivers / network / afd / afd / read.c
index e7e9a6e..447f09f 100644 (file)
 #include "tdiconn.h"
 #include "debug.h"
 
+static VOID HandleEOFOnIrp( PAFD_FCB FCB, NTSTATUS Status, ULONG_PTR Information )
+{
+       if( ( Status == STATUS_SUCCESS && !FCB->ReceiveIrp.Iosb.Information ) ||
+          ( !NT_SUCCESS( Status ) ) )
+       {
+               /* The socket has been closed */
+               FCB->PollState |= AFD_EVENT_DISCONNECT;
+               FCB->PollStatus[FD_CLOSE_BIT] = Status;
+               
+               PollReeval( FCB->DeviceExt, FCB->FileObject );
+       }
+}
+
 static BOOLEAN CantReadMore( PAFD_FCB FCB ) {
     UINT BytesAvailable = FCB->Recv.Content - FCB->Recv.BytesUsed;
+       
+    return !BytesAvailable &&
+       (FCB->PollState & (AFD_EVENT_CLOSE | AFD_EVENT_DISCONNECT));
+}
 
-    return !BytesAvailable;
+static VOID RefillSocketBuffer( PAFD_FCB FCB ) {
+       NTSTATUS Status;
+
+       if( !FCB->ReceiveIrp.InFlightRequest ) {
+               AFD_DbgPrint(MID_TRACE,("Replenishing buffer\n"));
+
+               Status = TdiReceive( &FCB->ReceiveIrp.InFlightRequest,
+                                                        FCB->Connection.Object,
+                                                        TDI_RECEIVE_NORMAL,
+                                                        FCB->Recv.Window,
+                                                        FCB->Recv.Size,
+                                                        &FCB->ReceiveIrp.Iosb,
+                                                        ReceiveComplete,
+                                                        FCB );
+
+        if( Status == STATUS_SUCCESS && FCB->ReceiveIrp.Iosb.Information )
+        {
+            FCB->Recv.Content = FCB->ReceiveIrp.Iosb.Information;
+            FCB->PollState |= AFD_EVENT_RECEIVE;
+            FCB->PollStatus[FD_READ_BIT] = STATUS_SUCCESS;
+                       
+                       PollReeval( FCB->DeviceExt, FCB->FileObject );
+        }
+               else
+               {
+                       /* Check for EOF */
+                       HandleEOFOnIrp(FCB, Status, FCB->ReceiveIrp.Iosb.Information);
+               }
+       }
 }
 
 static NTSTATUS TryToSatisfyRecvRequestFromBuffer( PAFD_FCB FCB,
@@ -39,14 +84,14 @@ static NTSTATUS TryToSatisfyRecvRequestFromBuffer( PAFD_FCB FCB,
                BytesAvailable =
                FCB->Recv.Content - FCB->Recv.BytesUsed;
     PAFD_MAPBUF Map;
-    NTSTATUS Status;
     *TotalBytesCopied = 0;
 
 
     AFD_DbgPrint(MID_TRACE,("Called, BytesAvailable = %d\n",
                                                        BytesAvailable));
 
-    if( CantReadMore(FCB) ) return STATUS_PENDING;
+    if( CantReadMore(FCB) ) return STATUS_SUCCESS;
+    if( !BytesAvailable ) return STATUS_PENDING;
 
     Map = (PAFD_MAPBUF)(RecvReq->BufferArray + RecvReq->BufferCount);
 
@@ -88,23 +133,8 @@ static NTSTATUS TryToSatisfyRecvRequestFromBuffer( PAFD_FCB FCB,
     if( FCB->Recv.BytesUsed == FCB->Recv.Content ) {
                FCB->Recv.BytesUsed = FCB->Recv.Content = 0;
         FCB->PollState &= ~AFD_EVENT_RECEIVE;
-               PollReeval( FCB->DeviceExt, FCB->FileObject );
-
-               if( !FCB->ReceiveIrp.InFlightRequest ) {
-                       AFD_DbgPrint(MID_TRACE,("Replenishing buffer\n"));
 
-                       Status = TdiReceive( &FCB->ReceiveIrp.InFlightRequest,
-                                                                FCB->Connection.Object,
-                                                                TDI_RECEIVE_NORMAL,
-                                                                FCB->Recv.Window,
-                                                                FCB->Recv.Size,
-                                                                &FCB->ReceiveIrp.Iosb,
-                                                                ReceiveComplete,
-                                                                FCB );
-
-            if( Status == STATUS_SUCCESS )
-                FCB->Recv.Content = FCB->ReceiveIrp.Iosb.Information;
-               }
+        RefillSocketBuffer( FCB );
     }
 
     return STATUS_SUCCESS;
@@ -126,45 +156,82 @@ static NTSTATUS ReceiveActivity( PAFD_FCB FCB, PIRP Irp ) {
     AFD_DbgPrint(MID_TRACE,("FCB %x Receive data waiting %d\n",
                                                FCB, FCB->Recv.Content));
 
-    /* Try to clear some requests */
-    while( !IsListEmpty( &FCB->PendingIrpList[FUNCTION_RECV] ) ) {
-          NextIrpEntry = RemoveHeadList(&FCB->PendingIrpList[FUNCTION_RECV]);
-          NextIrp = CONTAINING_RECORD(NextIrpEntry, IRP, Tail.Overlay.ListEntry);
-          NextIrpSp = IoGetCurrentIrpStackLocation( NextIrp );
-          RecvReq = NextIrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
-
-          AFD_DbgPrint(MID_TRACE,("RecvReq @ %x\n", RecvReq));
-
-          Status = TryToSatisfyRecvRequestFromBuffer( FCB, RecvReq, &TotalBytesCopied );
-
-          if( Status == STATUS_PENDING ) {
-               AFD_DbgPrint(MID_TRACE,("Ran out of data for %x\n", NextIrp));
-               InsertHeadList(&FCB->PendingIrpList[FUNCTION_RECV],
-                                          &NextIrp->Tail.Overlay.ListEntry);
-               break;
-          } else {
-               AFD_DbgPrint(MID_TRACE,("Completing recv %x (%d)\n", NextIrp,
-                                                               TotalBytesCopied));
-               UnlockBuffers( RecvReq->BufferArray,
-                                          RecvReq->BufferCount, FALSE );
-               NextIrp->IoStatus.Status = Status;
-               NextIrp->IoStatus.Information = TotalBytesCopied;
-               if( NextIrp == Irp ) { 
-                       RetStatus = Status;
-                       RetBytesCopied = TotalBytesCopied;
+    if( CantReadMore( FCB ) ) {
+        /* Success here means that we got an EOF.  Complete a pending read
+         * with zero bytes if we haven't yet overread, then kill the others.
+         */
+        while( !IsListEmpty( &FCB->PendingIrpList[FUNCTION_RECV] ) ) {
+            NextIrpEntry =
+                       RemoveHeadList(&FCB->PendingIrpList[FUNCTION_RECV]);
+            NextIrp =
+                       CONTAINING_RECORD(NextIrpEntry, IRP, Tail.Overlay.ListEntry);
+            NextIrpSp = IoGetCurrentIrpStackLocation( NextIrp );
+            RecvReq = NextIrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
+                       
+            AFD_DbgPrint(MID_TRACE,("Completing recv %x (%d)\n", NextIrp,
+                                    TotalBytesCopied));
+            UnlockBuffers( RecvReq->BufferArray,
+                                                 RecvReq->BufferCount, FALSE );
+            Status = NextIrp->IoStatus.Status =
+                       FCB->Overread ? STATUS_END_OF_FILE : STATUS_SUCCESS;
+            NextIrp->IoStatus.Information = 0;
+            if( NextIrp == Irp ) RetStatus = Status;
+            if( NextIrp->MdlAddress ) UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) );
+                       (void)IoSetCancelRoutine(NextIrp, NULL);
+            IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT );
+            FCB->Overread = TRUE;
+        }
+    } else {
+               /* Kick the user that receive would be possible now */
+               /* XXX Not implemented yet */
+               
+               AFD_DbgPrint(MID_TRACE,("FCB %x Receive data waiting %d\n",
+                                                               FCB, FCB->Recv.Content));
+               /*OskitDumpBuffer( FCB->Recv.Window, FCB->Recv.Content );*/
+               
+               /* Try to clear some requests */
+               while( !IsListEmpty( &FCB->PendingIrpList[FUNCTION_RECV] ) ) {
+                       NextIrpEntry =
+                       RemoveHeadList(&FCB->PendingIrpList[FUNCTION_RECV]);
+                       NextIrp =
+                       CONTAINING_RECORD(NextIrpEntry, IRP, Tail.Overlay.ListEntry);
+                       NextIrpSp = IoGetCurrentIrpStackLocation( NextIrp );
+                       RecvReq = NextIrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
+                       
+                       AFD_DbgPrint(MID_TRACE,("RecvReq @ %x\n", RecvReq));
+                       
+                       Status = TryToSatisfyRecvRequestFromBuffer
+                       ( FCB, RecvReq, &TotalBytesCopied );
+                       
+                       if( Status == STATUS_PENDING ) {
+                               AFD_DbgPrint(MID_TRACE,("Ran out of data for %x\n", NextIrp));
+                               InsertHeadList(&FCB->PendingIrpList[FUNCTION_RECV],
+                                                          &NextIrp->Tail.Overlay.ListEntry);
+                               break;
+                       } else {
+                               AFD_DbgPrint(MID_TRACE,("Completing recv %x (%d)\n", NextIrp,
+                                                                               TotalBytesCopied));
+                               UnlockBuffers( RecvReq->BufferArray,
+                                                         RecvReq->BufferCount, FALSE );
+                               NextIrp->IoStatus.Status = Status;
+                               NextIrp->IoStatus.Information = TotalBytesCopied;
+                               if( NextIrp == Irp ) { 
+                                       RetStatus = Status;
+                                       RetBytesCopied = TotalBytesCopied;
+                               }
+                               if( NextIrp->MdlAddress ) UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) );
+                               (void)IoSetCancelRoutine(NextIrp, NULL);
+                               IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT );
+                       }
                }
-               if( NextIrp->MdlAddress ) UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) );
-                (void)IoSetCancelRoutine(NextIrp, NULL);
-               IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT );
-          }
     }
 
-    if( !CantReadMore(FCB) ) {
+    if( FCB->Recv.Content ) {
                FCB->PollState |= AFD_EVENT_RECEIVE;
+        FCB->PollStatus[FD_READ_BIT] = STATUS_SUCCESS;
+        PollReeval( FCB->DeviceExt, FCB->FileObject );
     } else
-               FCB->PollState &= ~AFD_EVENT_RECEIVE;
-
-    PollReeval( FCB->DeviceExt, FCB->FileObject );
+        FCB->PollState &= ~AFD_EVENT_RECEIVE;
 
     AFD_DbgPrint(MID_TRACE,("RetStatus for irp %x is %x\n", Irp, RetStatus));
 
@@ -219,6 +286,8 @@ NTSTATUS NTAPI ReceiveComplete
         SocketStateUnlock( FCB );
         return STATUS_INVALID_PARAMETER;
     }
+       
+       HandleEOFOnIrp( FCB, Irp->IoStatus.Status, Irp->IoStatus.Information );
 
        ReceiveActivity( FCB, NULL );
                
@@ -510,10 +579,10 @@ PacketSocketRecvComplete(
     if( !IsListEmpty( &FCB->DatagramList ) ) {
                AFD_DbgPrint(MID_TRACE,("Signalling\n"));
                FCB->PollState |= AFD_EVENT_RECEIVE;
+        FCB->PollStatus[FD_READ_BIT] = STATUS_SUCCESS;
+        PollReeval( FCB->DeviceExt, FCB->FileObject );
     } else
-               FCB->PollState &= ~AFD_EVENT_RECEIVE;
-
-    PollReeval( FCB->DeviceExt, FCB->FileObject );
+        FCB->PollState &= ~AFD_EVENT_RECEIVE;
 
     if( NT_SUCCESS(Irp->IoStatus.Status) ) {
                /* Now relaunch the datagram request */
@@ -580,12 +649,12 @@ AfdPacketSocketReadData(PDEVICE_OBJECT DeviceObject, PIRP Irp,
                        Status = Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
                        Irp->IoStatus.Information = DatagramRecv->Len;
 
-                       if( IsListEmpty( &FCB->DatagramList ) )
-                               FCB->PollState &= ~AFD_EVENT_RECEIVE;
-                       else
+                       if( !IsListEmpty( &FCB->DatagramList ) ) {
                                FCB->PollState |= AFD_EVENT_RECEIVE;
-
-                       PollReeval( FCB->DeviceExt, FCB->FileObject );
+                FCB->PollStatus[FD_READ_BIT] = STATUS_SUCCESS;
+                           PollReeval( FCB->DeviceExt, FCB->FileObject );
+            } else
+                FCB->PollState &= ~AFD_EVENT_RECEIVE;
 
                        UnlockBuffers( RecvReq->BufferArray, RecvReq->BufferCount, TRUE );
 
@@ -596,12 +665,12 @@ AfdPacketSocketReadData(PDEVICE_OBJECT DeviceObject, PIRP Irp,
                                ( FCB, Irp, DatagramRecv,
                                  (PUINT)&Irp->IoStatus.Information );
 
-                       if( IsListEmpty( &FCB->DatagramList ) )
-                               FCB->PollState &= ~AFD_EVENT_RECEIVE;
-                       else
+                       if( !IsListEmpty( &FCB->DatagramList ) ) {
                                FCB->PollState |= AFD_EVENT_RECEIVE;
-
-                       PollReeval( FCB->DeviceExt, FCB->FileObject );
+                FCB->PollStatus[FD_READ_BIT] = STATUS_SUCCESS;
+                           PollReeval( FCB->DeviceExt, FCB->FileObject );
+            } else
+                FCB->PollState &= ~AFD_EVENT_RECEIVE;
 
                        UnlockBuffers( RecvReq->BufferArray, RecvReq->BufferCount, TRUE );
 
@@ -612,12 +681,10 @@ AfdPacketSocketReadData(PDEVICE_OBJECT DeviceObject, PIRP Irp,
                AFD_DbgPrint(MID_TRACE,("Nonblocking\n"));
                Status = STATUS_CANT_WAIT;
                FCB->PollState &= ~AFD_EVENT_RECEIVE;
-               PollReeval( FCB->DeviceExt, FCB->FileObject );
                UnlockBuffers( RecvReq->BufferArray, RecvReq->BufferCount, TRUE );
                return UnlockAndMaybeComplete( FCB, Status, Irp, 0 );
     } else {
                FCB->PollState &= ~AFD_EVENT_RECEIVE;
-               PollReeval( FCB->DeviceExt, FCB->FileObject );
                return LeaveIrpUntilLater( FCB, Irp, FUNCTION_RECV );
     }
 }