Author: cgutman
Date: Wed Jun 22 00:17:19 2011
New Revision: 52415

URL: http://svn.reactos.org/svn/reactos?rev=52415&view=rev
Log:
[AFD]
- Hold on to the disconnect IRP until all pending sending IRPs are sent to the 
transport driver if a controlled disconnect was requested

Modified:
    trunk/reactos/drivers/network/afd/afd/main.c
    trunk/reactos/drivers/network/afd/afd/write.c
    trunk/reactos/drivers/network/afd/include/afd.h

Modified: trunk/reactos/drivers/network/afd/afd/main.c
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/network/afd/afd/main.c?rev=52415&r1=52414&r2=52415&view=diff
==============================================================================
--- trunk/reactos/drivers/network/afd/afd/main.c [iso-8859-1] (original)
+++ trunk/reactos/drivers/network/afd/afd/main.c [iso-8859-1] Wed Jun 22 
00:17:19 2011
@@ -440,6 +440,7 @@
     ASSERT(IsListEmpty(&FCB->PendingIrpList[FUNCTION_SEND]));
     ASSERT(IsListEmpty(&FCB->PendingIrpList[FUNCTION_RECV]));
     ASSERT(IsListEmpty(&FCB->PendingIrpList[FUNCTION_PREACCEPT]));
+    ASSERT(IsListEmpty(&FCB->PendingIrpList[FUNCTION_DISCONNECT]))
 
     while (!IsListEmpty(&FCB->PendingConnections))
     {
@@ -531,58 +532,44 @@
     return STATUS_SUCCESS;
 }
 
-static NTSTATUS NTAPI
-AfdDisconnect(PDEVICE_OBJECT DeviceObject, PIRP Irp,
-             PIO_STACK_LOCATION IrpSp) {
-    PFILE_OBJECT FileObject = IrpSp->FileObject;
-    PAFD_FCB FCB = FileObject->FsContext;
+static
+NTSTATUS
+DoDisconnect(PAFD_FCB FCB, PIRP CurrentIrp)
+{
     PAFD_DISCONNECT_INFO DisReq;
     IO_STATUS_BLOCK Iosb;
     PTDI_CONNECTION_INFORMATION ConnectionReturnInfo;
-    NTSTATUS Status = STATUS_SUCCESS;
+    PIO_STACK_LOCATION CurrentIrpSp;
     USHORT Flags = 0;
-
-    if( !SocketAcquireStateLock( FCB ) ) return LostSocket( Irp );
-
-    if( !(DisReq = LockRequest( Irp, IrpSp )) )
-       return UnlockAndMaybeComplete( FCB, STATUS_NO_MEMORY,
-                                      Irp, 0 );
+    NTSTATUS Status;
+    
+    CurrentIrpSp = IoGetCurrentIrpStackLocation(CurrentIrp);
+    DisReq = GetLockedData(CurrentIrp, CurrentIrpSp);
     
     if( DisReq->DisconnectType & AFD_DISCONNECT_SEND )
            Flags |= TDI_DISCONNECT_RELEASE;
     if( DisReq->DisconnectType & AFD_DISCONNECT_RECV ||
        DisReq->DisconnectType & AFD_DISCONNECT_ABORT )
            Flags |= TDI_DISCONNECT_ABORT;
-
-    if (!(FCB->Flags & AFD_ENDPOINT_CONNECTIONLESS))
-    {
-        if( !FCB->ConnectInfo )
-            return UnlockAndMaybeComplete( FCB, STATUS_INVALID_PARAMETER,
-                                           Irp, 0 );
-
-        ASSERT(FCB->RemoteAddress);
-
-        Status = TdiBuildNullConnectionInfo
-              ( &ConnectionReturnInfo, 
FCB->RemoteAddress->Address[0].AddressType );
-
-        if( !NT_SUCCESS(Status) )
-           return UnlockAndMaybeComplete( FCB, Status,
-                                          Irp, 0 );
-
+    
+    Status = TdiBuildNullConnectionInfo(&ConnectionReturnInfo,
+                                        
FCB->RemoteAddress->Address[0].AddressType);
+    if (NT_SUCCESS(Status))
+    {
         FCB->ConnectInfo->UserData = FCB->DisconnectData;
         FCB->ConnectInfo->UserDataLength = FCB->DisconnectDataSize;
         FCB->ConnectInfo->Options = FCB->DisconnectOptions;
         FCB->ConnectInfo->OptionsLength = FCB->DisconnectOptionsSize;
-
-        Status = TdiDisconnect( FCB->Connection.Object,
-                               &DisReq->Timeout,
-                               Flags,
-                               &Iosb,
-                               NULL,
-                               NULL,
-                               FCB->ConnectInfo,
-                               ConnectionReturnInfo);
-
+        
+        Status = TdiDisconnect(FCB->Connection.Object,
+                               &DisReq->Timeout,
+                               Flags,
+                               &Iosb,
+                               NULL,
+                               NULL,
+                               FCB->ConnectInfo,
+                               ConnectionReturnInfo);
+        
         if (NT_SUCCESS(Status)) {
             FCB->FilledDisconnectData = MIN(FCB->DisconnectDataSize, 
ConnectionReturnInfo->UserDataLength);
             if (FCB->FilledDisconnectData)
@@ -591,7 +578,7 @@
                               ConnectionReturnInfo->UserData,
                               FCB->FilledDisconnectData);
             }
-
+            
             FCB->FilledDisconnectOptions = MIN(FCB->DisconnectOptionsSize, 
ConnectionReturnInfo->OptionsLength);
             if (FCB->FilledDisconnectOptions)
             {
@@ -600,15 +587,90 @@
                               FCB->FilledDisconnectOptions);
             }
         }
-
+        
         ExFreePool( ConnectionReturnInfo );
-
+        
         if (Flags & TDI_DISCONNECT_RELEASE)
             FCB->PollState |= AFD_EVENT_DISCONNECT;
         else
             FCB->PollState |= AFD_EVENT_ABORT;
-        FCB->PollStatus[FD_CLOSE_BIT] = STATUS_SUCCESS;
+        FCB->PollStatus[FD_CLOSE_BIT] = Status;
         PollReeval( FCB->DeviceExt, FCB->FileObject );
+    }
+    
+    CurrentIrp->IoStatus.Status = Status;
+    CurrentIrp->IoStatus.Information = 0;
+    UnlockRequest(CurrentIrp, CurrentIrpSp);
+    (void)IoSetCancelRoutine(CurrentIrp, NULL);
+    
+    IoCompleteRequest(CurrentIrp, IO_NETWORK_INCREMENT);
+    
+    return Status;
+}
+
+VOID
+RetryDisconnectCompletion(PAFD_FCB FCB)
+{
+    if (IsListEmpty(&FCB->PendingIrpList[FUNCTION_SEND]))
+    {
+        PIRP CurrentIrp;
+        PLIST_ENTRY CurrentEntry;
+        
+        ASSERT(FCB->RemoteAddress);
+        
+        while (!IsListEmpty(&FCB->PendingIrpList[FUNCTION_DISCONNECT]))
+        {
+            CurrentEntry = 
RemoveHeadList(&FCB->PendingIrpList[FUNCTION_DISCONNECT]);
+            CurrentIrp = CONTAINING_RECORD(CurrentEntry, IRP, 
Tail.Overlay.ListEntry);
+            
+            DoDisconnect(FCB, CurrentIrp);
+        }
+    }
+}
+
+static NTSTATUS NTAPI
+AfdDisconnect(PDEVICE_OBJECT DeviceObject, PIRP Irp,
+             PIO_STACK_LOCATION IrpSp) {
+    PFILE_OBJECT FileObject = IrpSp->FileObject;
+    PAFD_FCB FCB = FileObject->FsContext;
+    PAFD_DISCONNECT_INFO DisReq;
+    NTSTATUS Status = STATUS_SUCCESS;
+    USHORT Flags = 0;
+
+    if( !SocketAcquireStateLock( FCB ) ) return LostSocket( Irp );
+
+    if( !(DisReq = LockRequest( Irp, IrpSp )) )
+       return UnlockAndMaybeComplete( FCB, STATUS_NO_MEMORY,
+                                      Irp, 0 );
+    
+    if( DisReq->DisconnectType & AFD_DISCONNECT_SEND )
+           Flags |= TDI_DISCONNECT_RELEASE;
+    if( DisReq->DisconnectType & AFD_DISCONNECT_RECV ||
+       DisReq->DisconnectType & AFD_DISCONNECT_ABORT )
+           Flags |= TDI_DISCONNECT_ABORT;
+
+    if (!(FCB->Flags & AFD_ENDPOINT_CONNECTIONLESS))
+    {
+        if( !FCB->ConnectInfo )
+            return UnlockAndMaybeComplete( FCB, STATUS_INVALID_PARAMETER,
+                                           Irp, 0 );
+        
+        if (IsListEmpty(&FCB->PendingIrpList[FUNCTION_SEND]) || (Flags & 
TDI_DISCONNECT_ABORT))
+        {
+            /* Go ahead an execute the disconnect because we're ready for it */
+            Status = DoDisconnect(FCB, Irp);
+            
+            /* DoDisconnect takes care of the IRP */
+            SocketStateUnlock(FCB);
+            
+            return Status;
+        }
+        else
+        {
+            /* We have a graceful disconnect waiting on pending sends to 
complete */
+            return LeaveIrpUntilLater(FCB, Irp, FUNCTION_DISCONNECT);
+        }
+
     }
     else
     {
@@ -924,6 +986,10 @@
         DbgPrint("WARNING!!! IRP cancellation race could lead to a process 
hang! (IOCTL_AFD_SELECT)\n");
         return;
             
+        case IOCTL_AFD_DISCONNECT:
+        Function = FUNCTION_DISCONNECT;
+        break;
+            
         default:
         ASSERT(FALSE);
         UnlockAndMaybeComplete(FCB, STATUS_CANCELLED, Irp, 0);

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=52415&r1=52414&r2=52415&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] Wed Jun 22 
00:17:19 2011
@@ -59,8 +59,11 @@
                (void)IoSetCancelRoutine(NextIrp, NULL);
               IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT );
         }
-       SocketStateUnlock( FCB );
-       return STATUS_FILE_CLOSED;
+        
+        RetryDisconnectCompletion(FCB);
+        
+        SocketStateUnlock( FCB );
+        return STATUS_FILE_CLOSED;
     }
 
     if( !NT_SUCCESS(Status) ) {
@@ -85,6 +88,8 @@
                         (void)IoSetCancelRoutine(NextIrp, NULL);
                        IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT );
                }
+        
+        RetryDisconnectCompletion(FCB);
 
                SocketStateUnlock( FCB );
 
@@ -164,6 +169,8 @@
                                                  &FCB->SendIrp.Iosb,
                                                  SendComplete,
                                                  FCB );
+        
+        RetryDisconnectCompletion(FCB);
     } else {
                FCB->PollState |= AFD_EVENT_SEND;
                FCB->PollStatus[FD_WRITE_BIT] = STATUS_SUCCESS;
@@ -410,6 +417,8 @@
                                 Status, TotalBytesCopied));
     }
     
+    RetryDisconnectCompletion(FCB);
+    
     return UnlockAndMaybeComplete
     ( FCB, Status, Irp, TotalBytesCopied );
 }

Modified: trunk/reactos/drivers/network/afd/include/afd.h
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/network/afd/include/afd.h?rev=52415&r1=52414&r2=52415&view=diff
==============================================================================
--- trunk/reactos/drivers/network/afd/include/afd.h [iso-8859-1] (original)
+++ trunk/reactos/drivers/network/afd/include/afd.h [iso-8859-1] Wed Jun 22 
00:17:19 2011
@@ -99,8 +99,9 @@
 #define FUNCTION_SEND                   2
 #define FUNCTION_PREACCEPT              3
 #define FUNCTION_ACCEPT                 4
-#define FUNCTION_CLOSE                  5
-#define MAX_FUNCTIONS                   6
+#define FUNCTION_DISCONNECT             5
+#define FUNCTION_CLOSE                  6
+#define MAX_FUNCTIONS                   7
 
 #define IN_FLIGHT_REQUESTS              4
 
@@ -309,6 +310,7 @@
 VOID DestroySocket( PAFD_FCB FCB );
 VOID NTAPI AfdCancelHandler(PDEVICE_OBJECT DeviceObject,
                  PIRP Irp);
+VOID RetryDisconnectCompletion(PAFD_FCB FCB);
 
 /* read.c */
 


Reply via email to