Fix a copy-paste mistake and remove an unused variable
[reactos.git] / reactos / drivers / network / afd / afd / read.c
index f98fd17..447f09f 100644 (file)
 #include "tdiconn.h"
 #include "debug.h"
 
-static NTSTATUS RefillSocketBuffer( PAFD_FCB FCB ) {
-       NTSTATUS Status = STATUS_PENDING;
+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));
+}
+
+static VOID RefillSocketBuffer( PAFD_FCB FCB ) {
+       NTSTATUS Status;
 
        if( !FCB->ReceiveIrp.InFlightRequest ) {
                AFD_DbgPrint(MID_TRACE,("Replenishing buffer\n"));
@@ -41,25 +61,20 @@ static NTSTATUS RefillSocketBuffer( PAFD_FCB FCB ) {
                                                         ReceiveComplete,
                                                         FCB );
 
-        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;
-            FCB->Overread = TRUE;
-            Status = STATUS_FILE_CLOSED;
-        }
-        else if( Status == STATUS_SUCCESS )
+        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 );
         }
-        PollReeval( FCB->DeviceExt, FCB->FileObject );
+               else
+               {
+                       /* Check for EOF */
+                       HandleEOFOnIrp(FCB, Status, FCB->ReceiveIrp.Iosb.Information);
+               }
        }
-
-       return Status;
 }
 
 static NTSTATUS TryToSatisfyRecvRequestFromBuffer( PAFD_FCB FCB,
@@ -69,29 +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( FCB->Overread ) return STATUS_FILE_CLOSED;
-    if( !BytesAvailable ) {
-        FCB->Recv.Content = FCB->Recv.BytesUsed = 0;
-               Status = RefillSocketBuffer( FCB );
-               if ( Status != STATUS_SUCCESS )
-                       return Status;
-
-        /* If RefillSocketBuffer returns STATUS_SUCCESS, we're good to go
-         * If RefillSocketBuffer returns STATUS_PENDING, then it's waiting on the transport for data
-         * If RefillSocketBuffer returns STATUS_FILE_CLOSED, then the connection was terminated
-         */
-
-        /* Recalculate BytesAvailable based on new data */
-        BytesAvailable = FCB->Recv.Content - FCB->Recv.BytesUsed;
-        ASSERT(BytesAvailable);
-    }
+    if( CantReadMore(FCB) ) return STATUS_SUCCESS;
+    if( !BytesAvailable ) return STATUS_PENDING;
 
     Map = (PAFD_MAPBUF)(RecvReq->BufferArray + RecvReq->BufferCount);
 
@@ -156,37 +156,74 @@ 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( FCB->Recv.Content ) {
@@ -249,6 +286,8 @@ NTSTATUS NTAPI ReceiveComplete
         SocketStateUnlock( FCB );
         return STATUS_INVALID_PARAMETER;
     }
+       
+       HandleEOFOnIrp( FCB, Irp->IoStatus.Status, Irp->IoStatus.Information );
 
        ReceiveActivity( FCB, NULL );