Author: cgutman
Date: Thu Jul  7 00:29:30 2011
New Revision: 52552

URL: http://svn.reactos.org/svn/reactos?rev=52552&view=rev
Log:
[AFD]
- Rewrite user-mode send IRP handling so send errors get returned to the user 
properly
- Fixes OskitTCP: ESHUTDOWN/EPIPE debug log spam when a chargen telnet session 
is terminated by the remote side

Modified:
    trunk/reactos/drivers/network/afd/afd/write.c

Modified: trunk/reactos/drivers/network/afd/afd/write.c
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/network/afd/afd/write.c?rev=52552&r1=52551&r2=52552&view=diff
==============================================================================
--- trunk/reactos/drivers/network/afd/afd/write.c [iso-8859-1] (original)
+++ trunk/reactos/drivers/network/afd/afd/write.c [iso-8859-1] Thu Jul  7 
00:29:30 2011
@@ -23,7 +23,7 @@
     PIO_STACK_LOCATION NextIrpSp;
     PAFD_SEND_INFO SendReq = NULL;
     PAFD_MAPBUF Map;
-    UINT TotalBytesCopied = 0, SpaceAvail, i;
+    UINT TotalBytesCopied = 0, TotalBytesProcessed = 0, SpaceAvail, i;
 
     /*
      * The Irp parameter passed in is the IRP of the stream between AFD and
@@ -99,7 +99,42 @@
     RtlMoveMemory( FCB->Send.Window,
                                   FCB->Send.Window + FCB->Send.BytesUsed,
                                   FCB->Send.BytesUsed - 
Irp->IoStatus.Information );
-    FCB->Send.BytesUsed -= Irp->IoStatus.Information;
+
+    TotalBytesProcessed = 0;
+    while (!IsListEmpty(&FCB->PendingIrpList[FUNCTION_SEND]) &&
+           TotalBytesProcessed != Irp->IoStatus.Information) {
+               NextIrpEntry =
+        RemoveHeadList(&FCB->PendingIrpList[FUNCTION_SEND]);
+               NextIrp =
+        CONTAINING_RECORD(NextIrpEntry, IRP, Tail.Overlay.ListEntry);
+               NextIrpSp = IoGetCurrentIrpStackLocation( NextIrp );
+               SendReq = GetLockedData(NextIrp, NextIrpSp);
+               Map = (PAFD_MAPBUF)(SendReq->BufferArray + 
SendReq->BufferCount);
+        
+        TotalBytesCopied = 0;
+        
+               for( i = 0; i < SendReq->BufferCount; i++ )
+                       TotalBytesCopied += SendReq->BufferArray[i].len;
+            
+        NextIrp->IoStatus.Status = Irp->IoStatus.Status;
+        NextIrp->IoStatus.Information = TotalBytesCopied;
+        
+        TotalBytesProcessed += TotalBytesCopied;
+            
+        (void)IoSetCancelRoutine(NextIrp, NULL);
+            
+        UnlockBuffers( SendReq->BufferArray,
+                       SendReq->BufferCount,
+                       FALSE );
+            
+        if (NextIrp->MdlAddress) UnlockRequest(NextIrp, NextIrpSp);
+            
+        IoCompleteRequest(NextIrp, IO_NETWORK_INCREMENT);
+    }
+
+    ASSERT(TotalBytesProcessed == Irp->IoStatus.Information);
+    
+    FCB->Send.BytesUsed -= TotalBytesProcessed;
 
     while( !IsListEmpty( &FCB->PendingIrpList[FUNCTION_SEND] ) ) {
                NextIrpEntry =
@@ -139,19 +174,6 @@
         if (NextIrp != NULL)
         {
             FCB->Send.BytesUsed += TotalBytesCopied;
-
-            NextIrp->IoStatus.Status = STATUS_SUCCESS;
-            NextIrp->IoStatus.Information = TotalBytesCopied;
-
-            (void)IoSetCancelRoutine(NextIrp, NULL);
-
-            UnlockBuffers( SendReq->BufferArray,
-                           SendReq->BufferCount,
-                           FALSE );
-
-            if (NextIrp->MdlAddress) UnlockRequest(NextIrp, NextIrpSp);
-
-            IoCompleteRequest(NextIrp, IO_NETWORK_INCREMENT);
         }
         else
             break;
@@ -198,6 +220,7 @@
     PAFD_FCB FCB = (PAFD_FCB)Context;
     PLIST_ENTRY NextIrpEntry;
     PIRP NextIrp;
+    PAFD_SEND_INFO SendReq;
 
     AFD_DbgPrint(MID_TRACE,("Called, status %x, %d bytes used\n",
                                                        Irp->IoStatus.Status,
@@ -210,29 +233,47 @@
     FCB->SendIrp.InFlightRequest = NULL;
     /* Request is not in flight any longer */
 
-    if (Irp->IoStatus.Status == STATUS_SUCCESS)
-    {
-        FCB->PollState |= AFD_EVENT_SEND;
-        FCB->PollStatus[FD_WRITE_BIT] = STATUS_SUCCESS;
-        PollReeval( FCB->DeviceExt, FCB->FileObject );
-    }
-
     if( FCB->State == SOCKET_STATE_CLOSED ) {
         /* Cleanup our IRP queue because the FCB is being destroyed */
         while( !IsListEmpty( &FCB->PendingIrpList[FUNCTION_SEND] ) ) {
-              NextIrpEntry = 
RemoveHeadList(&FCB->PendingIrpList[FUNCTION_SEND]);
-              NextIrp = CONTAINING_RECORD(NextIrpEntry, IRP, 
Tail.Overlay.ListEntry);
-              NextIrp->IoStatus.Status = STATUS_FILE_CLOSED;
-              NextIrp->IoStatus.Information = 0;
-              if( NextIrp->MdlAddress ) UnlockRequest( NextIrp, 
IoGetCurrentIrpStackLocation( NextIrp ) );
-               (void)IoSetCancelRoutine(NextIrp, NULL);
-              IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT );
-        }
-       SocketStateUnlock( FCB );
-       return STATUS_FILE_CLOSED;
-    }
-
-    SocketStateUnlock( FCB );
+            NextIrpEntry = RemoveHeadList(&FCB->PendingIrpList[FUNCTION_SEND]);
+            NextIrp = CONTAINING_RECORD(NextIrpEntry, IRP, 
Tail.Overlay.ListEntry);
+            SendReq = GetLockedData(NextIrp, 
IoGetCurrentIrpStackLocation(NextIrp));
+            NextIrp->IoStatus.Status = STATUS_FILE_CLOSED;
+            NextIrp->IoStatus.Information = 0;
+            (void)IoSetCancelRoutine(NextIrp, NULL);
+            UnlockBuffers(SendReq->BufferArray, SendReq->BufferCount, FALSE);
+            UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) );
+            IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT );
+        }
+        SocketStateUnlock( FCB );
+        return STATUS_FILE_CLOSED;
+    }
+    
+    ASSERT(!IsListEmpty(&FCB->PendingIrpList[FUNCTION_SEND]));
+    
+    /* TDI spec guarantees FIFO ordering on IRPs */
+    NextIrpEntry = RemoveHeadList(&FCB->PendingIrpList[FUNCTION_SEND]);
+    NextIrp = CONTAINING_RECORD(NextIrpEntry, IRP, Tail.Overlay.ListEntry);
+    
+    SendReq = GetLockedData(NextIrp, IoGetCurrentIrpStackLocation(NextIrp));
+    
+    NextIrp->IoStatus.Status = Irp->IoStatus.Status;
+    NextIrp->IoStatus.Information = Irp->IoStatus.Information;
+    
+    (void)IoSetCancelRoutine(NextIrp, NULL);
+    
+    UnlockBuffers(SendReq->BufferArray, SendReq->BufferCount, FALSE);
+    
+    UnlockRequest(NextIrp, IoGetCurrentIrpStackLocation(NextIrp));
+    
+    IoCompleteRequest(NextIrp, IO_NETWORK_INCREMENT);
+
+    FCB->PollState |= AFD_EVENT_SEND;
+    FCB->PollStatus[FD_WRITE_BIT] = STATUS_SUCCESS;
+    PollReeval(FCB->DeviceExt, FCB->FileObject);
+
+    SocketStateUnlock(FCB);
 
     return STATUS_SUCCESS;
 }
@@ -244,7 +285,6 @@
     PFILE_OBJECT FileObject = IrpSp->FileObject;
     PAFD_FCB FCB = FileObject->FsContext;
     PAFD_SEND_INFO SendReq;
-       ULONG Information;
     UINT TotalBytesCopied = 0, i, SpaceAvail = 0;
     BOOLEAN NoSpace = FALSE;
 
@@ -278,29 +318,33 @@
 
         Status = TdiBuildConnectionInfo( &TargetAddress, FCB->RemoteAddress );
 
-               if( NT_SUCCESS(Status) ) {
-            Status = TdiSendDatagram
-                ( &FCB->SendIrp.InFlightRequest,
-                  FCB->AddressFile.Object,
-                  SendReq->BufferArray[0].buf,
-                  SendReq->BufferArray[0].len,
-                  TargetAddress,
-                  &FCB->SendIrp.Iosb,
-                  PacketSocketSendComplete,
-                  FCB );
-
-                       ExFreePool( TargetAddress );
-               }
-
-        if( Status == STATUS_PENDING ) Status = STATUS_SUCCESS;
-
-        AFD_DbgPrint(MID_TRACE,("Dismissing request: %x\n", Status));
-
-               /* Even if we were pended, we're done with the user buffer at 
this
-                * point. */
-               Information = SendReq->BufferArray[0].len;
-               UnlockBuffers(SendReq->BufferArray, SendReq->BufferCount, 
FALSE);
-        return UnlockAndMaybeComplete( FCB, Status, Irp, Information );
+        if( NT_SUCCESS(Status) ) {
+            FCB->PollState &= ~AFD_EVENT_SEND;
+            
+            Status = QueueUserModeIrp(FCB, Irp, FUNCTION_SEND);
+            if (Status == STATUS_PENDING)
+            {
+                TdiSendDatagram(&FCB->SendIrp.InFlightRequest,
+                                FCB->AddressFile.Object,
+                                SendReq->BufferArray[0].buf,
+                                SendReq->BufferArray[0].len,
+                                TargetAddress,
+                                &FCB->SendIrp.Iosb,
+                                PacketSocketSendComplete,
+                                FCB);
+            }
+            
+            ExFreePool( TargetAddress );
+            
+            SocketStateUnlock(FCB);
+            
+            return STATUS_PENDING;
+        }
+        else
+        {
+            UnlockBuffers(SendReq->BufferArray, SendReq->BufferCount, FALSE);
+            return UnlockAndMaybeComplete( FCB, Status, Irp, 0 );
+        }
     }
     
     if (FCB->DisconnectPending && (FCB->DisconnectFlags & 
TDI_DISCONNECT_RELEASE))
@@ -370,6 +414,7 @@
                 
                 return UnlockAndMaybeComplete(FCB, STATUS_BUFFER_OVERFLOW, 
Irp, 0);
             }
+            SpaceAvail += TotalBytesCopied;
             NoSpace = TRUE;
             break;
         }
@@ -394,12 +439,38 @@
         return UnlockAndMaybeComplete
         ( FCB, STATUS_SUCCESS, Irp, TotalBytesCopied );
     }
-    
+
+    if (SpaceAvail)
+    {
+        FCB->PollState |= AFD_EVENT_SEND;
+               FCB->PollStatus[FD_WRITE_BIT] = STATUS_SUCCESS;
+               PollReeval( FCB->DeviceExt, FCB->FileObject );
+    }
+    else
+    {
+        FCB->PollState &= ~AFD_EVENT_SEND;
+    }
+
     if (!NoSpace)
     {
-        UnlockBuffers( SendReq->BufferArray, SendReq->BufferCount, FALSE );
         FCB->Send.BytesUsed += TotalBytesCopied;
-        AFD_DbgPrint(MID_TRACE,("Completed %d bytes\n", TotalBytesCopied));
+        AFD_DbgPrint(MID_TRACE,("Copied %d bytes\n", TotalBytesCopied));
+        
+        Status = QueueUserModeIrp(FCB, Irp, FUNCTION_SEND);
+        if (Status == STATUS_PENDING && !FCB->SendIrp.InFlightRequest)
+        {
+            TdiSend(&FCB->SendIrp.InFlightRequest,
+                    FCB->Connection.Object,
+                    0,
+                    FCB->Send.Window,
+                    FCB->Send.BytesUsed,
+                    &FCB->SendIrp.Iosb,
+                    SendComplete,
+                    FCB);
+        }
+        SocketStateUnlock(FCB);
+        
+        return STATUS_PENDING;
     }
     else
     {
@@ -414,38 +485,6 @@
             return LeaveIrpUntilLater( FCB, Irp, FUNCTION_SEND );
         }
     }
-        
-    if (!FCB->SendIrp.InFlightRequest)
-    {
-        Status = TdiSend( &FCB->SendIrp.InFlightRequest,
-                         FCB->Connection.Object,
-                         0,
-                         FCB->Send.Window,
-                         FCB->Send.BytesUsed,
-                         &FCB->SendIrp.Iosb,
-                         SendComplete,
-                         FCB );
-        
-        if( Status == STATUS_PENDING )
-            Status = STATUS_SUCCESS;
-        
-        AFD_DbgPrint(MID_TRACE,("Dismissing request: %x (%d)\n",
-                                Status, TotalBytesCopied));
-    }
-    
-    if (SpaceAvail)
-    {
-        FCB->PollState |= AFD_EVENT_SEND;
-               FCB->PollStatus[FD_WRITE_BIT] = STATUS_SUCCESS;
-               PollReeval( FCB->DeviceExt, FCB->FileObject );
-    }
-    else
-    {
-        FCB->PollState &= ~AFD_EVENT_SEND;
-    }
-    
-    return UnlockAndMaybeComplete
-    ( FCB, Status, Irp, TotalBytesCopied );
 }
 
 NTSTATUS NTAPI
@@ -456,7 +495,6 @@
     PFILE_OBJECT FileObject = IrpSp->FileObject;
     PAFD_FCB FCB = FileObject->FsContext;
     PAFD_SEND_INFO_UDP SendReq;
-       ULONG Information;
 
     AFD_DbgPrint(MID_TRACE,("Called on %x\n", FCB));
 
@@ -514,27 +552,29 @@
     if( NT_SUCCESS(Status) ) {
                FCB->PollState &= ~AFD_EVENT_SEND;
 
-               Status = TdiSendDatagram
-                       ( &FCB->SendIrp.InFlightRequest,
-                         FCB->AddressFile.Object,
-                         SendReq->BufferArray[0].buf,
-                         SendReq->BufferArray[0].len,
-                         TargetAddress,
-                         &FCB->SendIrp.Iosb,
-                         PacketSocketSendComplete,
-                         FCB );
+        Status = QueueUserModeIrp(FCB, Irp, FUNCTION_SEND);
+        if (Status == STATUS_PENDING)
+        {
+            TdiSendDatagram(&FCB->SendIrp.InFlightRequest,
+                            FCB->AddressFile.Object,
+                            SendReq->BufferArray[0].buf,
+                            SendReq->BufferArray[0].len,
+                            TargetAddress,
+                            &FCB->SendIrp.Iosb,
+                            PacketSocketSendComplete,
+                            FCB);
+        }
 
                ExFreePool( TargetAddress );
-    }
-
-    if( Status == STATUS_PENDING ) Status = STATUS_SUCCESS;
-
-    AFD_DbgPrint(MID_TRACE,("Dismissing request: %x\n", Status));
-
-       /* Even if we were pended, we're done with the user buffer at this
-        * point. */
-       Information = SendReq->BufferArray[0].len;
-       UnlockBuffers(SendReq->BufferArray, SendReq->BufferCount, FALSE);
-    return UnlockAndMaybeComplete( FCB, Status, Irp, Information );
+        
+        SocketStateUnlock(FCB);
+        
+        return STATUS_PENDING;
+    }
+    else
+    {
+        UnlockBuffers(SendReq->BufferArray, SendReq->BufferCount, FALSE);
+        return UnlockAndMaybeComplete( FCB, Status, Irp, 0 );
+    }
 }
 


Reply via email to