- Cancel pending user IRPs when we get a IRP_MJ_CLEANUP request
[reactos.git] / reactos / drivers / network / afd / afd / main.c
index 099e158..b827eed 100644 (file)
@@ -91,11 +91,15 @@ AfdCreateSocket(PDEVICE_OBJECT DeviceObject, PIRP Irp,
     RtlZeroMemory( FCB, sizeof( *FCB ) );
 
     FCB->Flags = ConnectInfo ? ConnectInfo->EndpointFlags : 0;
+    FCB->GroupID = ConnectInfo ? ConnectInfo->GroupID : 0;
+    FCB->GroupType = 0; /* FIXME */
     FCB->State = SOCKET_STATE_CREATED;
     FCB->FileObject = FileObject;
     FCB->DeviceExt = DeviceExt;
     FCB->Recv.Size = DEFAULT_RECEIVE_WINDOW_SIZE;
     FCB->Send.Size = DEFAULT_SEND_WINDOW_SIZE;
+    FCB->AddressFile.Handle = INVALID_HANDLE_VALUE;
+    FCB->Connection.Handle = INVALID_HANDLE_VALUE;
 
     KeInitializeSpinLock( &FCB->SpinLock );
     ExInitializeFastMutex( &FCB->Mutex );
@@ -167,15 +171,55 @@ AfdCreateSocket(PDEVICE_OBJECT DeviceObject, PIRP Irp,
     return Status;
 }
 
-VOID CleanupSocket( PAFD_FCB FCB ) {
+static NTSTATUS NTAPI
+AfdCleanupSocket(PDEVICE_OBJECT DeviceObject, PIRP Irp,
+                 PIO_STACK_LOCATION IrpSp)
+{
+    PFILE_OBJECT FileObject = IrpSp->FileObject;
+    PAFD_FCB FCB = FileObject->FsContext;
+    PLIST_ENTRY CurrentEntry, NextEntry;
+    UINT Function;
+    PIRP CurrentIrp;
+
+    if( !SocketAcquireStateLock( FCB ) ) return LostSocket(Irp);
+
+    for (Function = 0; Function < MAX_FUNCTIONS; Function++)
+    {
+        CurrentEntry = FCB->PendingIrpList[Function].Flink;
+        while (CurrentEntry != &FCB->PendingIrpList[Function])
+        {
+           NextEntry = CurrentEntry->Flink;
+           CurrentIrp = CONTAINING_RECORD(CurrentEntry, IRP, Tail.Overlay.ListEntry);
+
+           /* The cancel routine will remove the IRP from the list */
+           IoCancelIrp(CurrentIrp);
+
+           CurrentEntry = NextEntry;
+        }
+    }
+
+    KillSelectsForFCB( FCB->DeviceExt, FileObject, FALSE );
+
+    return UnlockAndMaybeComplete(FCB, STATUS_SUCCESS, Irp, 0);
+}
+
+static NTSTATUS NTAPI
+AfdCloseSocket(PDEVICE_OBJECT DeviceObject, PIRP Irp,
+              PIO_STACK_LOCATION IrpSp)
+{
+    PFILE_OBJECT FileObject = IrpSp->FileObject;
+    PAFD_FCB FCB = FileObject->FsContext;
     UINT i;
     PAFD_IN_FLIGHT_REQUEST InFlightRequest[IN_FLIGHT_REQUESTS];
 
-    AFD_DbgPrint(MIN_TRACE,("Called (%x)\n", FCB));
+    AFD_DbgPrint(MID_TRACE,
+                ("AfdClose(DeviceObject %p Irp %p)\n", DeviceObject, Irp));
 
-    if( !SocketAcquireStateLock( FCB ) ) return;
+    if( !SocketAcquireStateLock( FCB ) ) return STATUS_FILE_CLOSED;
 
     FCB->State = SOCKET_STATE_CLOSED;
+    FCB->PollState = AFD_EVENT_CLOSE;
+    PollReeval( FCB->DeviceExt, FCB->FileObject );
 
     InFlightRequest[0] = &FCB->ListenIrp;
     InFlightRequest[1] = &FCB->ReceiveIrp;
@@ -191,76 +235,57 @@ VOID CleanupSocket( PAFD_FCB FCB ) {
        }
     }
 
-    FCB->State = SOCKET_STATE_CREATED;
+    KillSelectsForFCB( FCB->DeviceExt, FileObject, FALSE );
 
-    if( FCB->EventSelect ) {
+    SocketStateUnlock( FCB );
+
+    if( FCB->EventSelect )
         ObDereferenceObject( FCB->EventSelect );
-        FCB->EventSelect = NULL;
-    }
-    if( FCB->Context ) {
+
+    if( FCB->Context )
         ExFreePool( FCB->Context );
-        FCB->Context = NULL;
-    }
-    if( FCB->Recv.Window ) {
+
+    if( FCB->Recv.Window )
        ExFreePool( FCB->Recv.Window );
-        FCB->Recv.Window = NULL;
-    }
-    if( FCB->Send.Window ) {
+
+    if( FCB->Send.Window )
        ExFreePool( FCB->Send.Window );
-        FCB->Send.Window = NULL;
-    }
-    if( FCB->AddressFrom ) {
+
+    if( FCB->AddressFrom )
        ExFreePool( FCB->AddressFrom );
-        FCB->AddressFrom = NULL;
-    }
-    if( FCB->LocalAddress ) {
+
+    if( FCB->LocalAddress )
        ExFreePool( FCB->LocalAddress );
-        FCB->LocalAddress = NULL;
-    }
-    if( FCB->RemoteAddress ) {
+
+    if( FCB->RemoteAddress )
        ExFreePool( FCB->RemoteAddress );
-        FCB->RemoteAddress = NULL;
-    }
-    if( FCB->Connection.Object ) {
-       ZwClose(FCB->Connection.Handle);
+
+    if( FCB->Connection.Object )
        ObDereferenceObject(FCB->Connection.Object);
-        FCB->Connection.Object = NULL;
-    }
-    if( FCB->AddressFile.Object ) {
-       ZwClose(FCB->AddressFile.Handle);
+
+    if( FCB->AddressFile.Object )
        ObDereferenceObject(FCB->AddressFile.Object);
-        FCB->AddressFile.Object = NULL;
+
+    if( FCB->AddressFile.Handle != INVALID_HANDLE_VALUE )
+    {
+        if (ZwClose(FCB->AddressFile.Handle) == STATUS_INVALID_HANDLE)
+        {
+            DbgPrint("INVALID ADDRESS FILE HANDLE VALUE: %x %x\n", FCB->AddressFile.Handle, FCB->AddressFile.Object);
+        }
     }
 
-    SocketStateUnlock( FCB );
-}
+    if( FCB->Connection.Handle != INVALID_HANDLE_VALUE )
+    {
+        if (ZwClose(FCB->Connection.Handle) == STATUS_INVALID_HANDLE)
+        {
+            DbgPrint("INVALID CONNECTION HANDLE VALUE: %x %x\n", FCB->Connection.Handle, FCB->Connection.Object);
+        }
+    }
 
-VOID DestroySocket( PAFD_FCB FCB ) {
     if( FCB->TdiDeviceName.Buffer )
        ExFreePool(FCB->TdiDeviceName.Buffer);
 
     ExFreePool(FCB);
-    AFD_DbgPrint(MIN_TRACE,("Deleted (%x)\n", FCB));
-}
-
-static NTSTATUS NTAPI
-AfdCloseSocket(PDEVICE_OBJECT DeviceObject, PIRP Irp,
-              PIO_STACK_LOCATION IrpSp)
-{
-    PFILE_OBJECT FileObject = IrpSp->FileObject;
-    PAFD_FCB FCB = FileObject->FsContext;
-
-    AFD_DbgPrint(MID_TRACE,
-                ("AfdClose(DeviceObject %p Irp %p)\n", DeviceObject, Irp));
-
-    if( !SocketAcquireStateLock( FCB ) ) return LostSocket( Irp );
-
-    AFD_DbgPrint(MID_TRACE,("FCB %x\n", FCB));
-
-    FileObject->FsContext = NULL;
-    SocketStateUnlock( FCB );
-
-    DestroySocket( FCB );
 
     Irp->IoStatus.Status = STATUS_SUCCESS;
     Irp->IoStatus.Information = 0;
@@ -271,28 +296,6 @@ AfdCloseSocket(PDEVICE_OBJECT DeviceObject, PIRP Irp,
     return STATUS_SUCCESS;
 }
 
-static NTSTATUS NTAPI
-AfdCleanupSocket(PDEVICE_OBJECT DeviceObject, PIRP Irp,
-                 PIO_STACK_LOCATION IrpSp)
-{
-    PFILE_OBJECT FileObject = IrpSp->FileObject;
-    PAFD_FCB FCB = FileObject->FsContext;
-
-    if( !SocketAcquireStateLock( FCB ) ) return LostSocket( Irp );
-
-    CleanupSocket( FCB );
-
-    KillSelectsForFCB( FCB->DeviceExt, FileObject, FALSE );
-
-    SocketStateUnlock( FCB );
-
-    Irp->IoStatus.Status = STATUS_SUCCESS;
-    Irp->IoStatus.Information = 0;
-    IoCompleteRequest(Irp, IO_NETWORK_INCREMENT);
-
-    return STATUS_SUCCESS;
-}
-
 static NTSTATUS NTAPI
 AfdDisconnect(PDEVICE_OBJECT DeviceObject, PIRP Irp,
              PIO_STACK_LOCATION IrpSp) {
@@ -341,6 +344,9 @@ AfdDisconnect(PDEVICE_OBJECT DeviceObject, PIRP Irp,
 
     if (ConnInfo) ExFreePool( ConnInfo );
 
+    FCB->PollState |= AFD_EVENT_DISCONNECT;
+    PollReeval( FCB->DeviceExt, FCB->FileObject );
+
     return UnlockAndMaybeComplete( FCB, Status, Irp, 0 );
 }
 
@@ -534,6 +540,111 @@ AfdDispatch(PDEVICE_OBJECT DeviceObject, PIRP Irp)
     return (Status);
 }
 
+VOID NTAPI
+AfdCancelHandler(PDEVICE_OBJECT DeviceObject,
+                 PIRP Irp)
+{
+    PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
+    PFILE_OBJECT FileObject = IrpSp->FileObject;
+    PAFD_FCB FCB = FileObject->FsContext;
+    UINT Function;
+    PAFD_RECV_INFO RecvReq;
+    PAFD_SEND_INFO SendReq;
+    PLIST_ENTRY CurrentEntry;
+    PIRP CurrentIrp;
+    PAFD_DEVICE_EXTENSION DeviceExt = DeviceObject->DeviceExtension;
+    KIRQL OldIrql;
+    PAFD_ACTIVE_POLL Poll;
+    PAFD_POLL_INFO PollReq;
+
+    IoReleaseCancelSpinLock(Irp->CancelIrql);
+
+    if (!SocketAcquireStateLock(FCB))
+        return;
+
+    ASSERT(IrpSp->MajorFunction == IRP_MJ_DEVICE_CONTROL);
+
+    switch (IrpSp->Parameters.DeviceIoControl.IoControlCode)
+    {
+        case IOCTL_AFD_RECV:
+        RecvReq = IrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
+       UnlockBuffers(RecvReq->BufferArray, RecvReq->BufferCount, FALSE);
+        /* Fall through */
+
+        case IOCTL_AFD_RECV_DATAGRAM:
+        Function = FUNCTION_RECV;
+        break;
+
+        case IOCTL_AFD_SEND:
+        SendReq = IrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
+        UnlockBuffers(SendReq->BufferArray, SendReq->BufferCount, FALSE);
+        /* Fall through */
+
+        case IOCTL_AFD_SEND_DATAGRAM:
+        Function = FUNCTION_SEND;
+        break;
+
+        case IOCTL_AFD_CONNECT:
+        Function = FUNCTION_CONNECT;
+        break;
+
+        case IOCTL_AFD_WAIT_FOR_LISTEN:
+        Function = FUNCTION_PREACCEPT;
+        break;
+
+        case IOCTL_AFD_SELECT:
+        KeAcquireSpinLock(&DeviceExt->Lock, &OldIrql);
+
+        CurrentEntry = DeviceExt->Polls.Flink;
+        while (CurrentEntry != &DeviceExt->Polls)
+        {
+            Poll = CONTAINING_RECORD(CurrentEntry, AFD_ACTIVE_POLL, ListEntry);
+            CurrentIrp = Poll->Irp;
+            PollReq = CurrentIrp->AssociatedIrp.SystemBuffer;
+
+            if (CurrentIrp == Irp)
+            {
+                ZeroEvents(PollReq->Handles, PollReq->HandleCount);
+                SignalSocket(Poll, NULL, PollReq, STATUS_CANCELLED);
+                break;
+            }
+            else
+            {
+                CurrentEntry = CurrentEntry->Flink;
+            }
+        }
+
+        KeReleaseSpinLock(&DeviceExt->Lock, OldIrql);
+
+        /* IRP already completed by SignalSocket */
+        SocketStateUnlock(FCB);
+        return;
+            
+        default:
+        ASSERT(FALSE);
+        UnlockAndMaybeComplete(FCB, STATUS_CANCELLED, Irp, 0);
+        return;
+    }
+
+    CurrentEntry = FCB->PendingIrpList[Function].Flink;
+    while (CurrentEntry != &FCB->PendingIrpList[Function])
+    {
+        CurrentIrp = CONTAINING_RECORD(CurrentEntry, IRP, Tail.Overlay.ListEntry);
+
+        if (CurrentIrp == Irp)
+        {
+            RemoveEntryList(CurrentEntry);
+            break;
+        }
+        else
+        {
+            CurrentEntry = CurrentEntry->Flink;
+        }
+    }
+    
+    UnlockAndMaybeComplete(FCB, STATUS_CANCELLED, Irp, 0);
+}
+
 static VOID NTAPI
 AfdUnload(PDRIVER_OBJECT DriverObject)
 {