- Allocate send and receive buffers from paged pool (saves 32KB of non-paged pool...
[reactos.git] / drivers / network / afd / afd / main.c
index d931d6d..fb4fc91 100644 (file)
@@ -17,7 +17,7 @@
 #include "tdiconn.h"
 #include "debug.h"
 
-#ifdef DBG
+#if DBG
 
 /* See debug.h for debug/trace constants */
 //DWORD DebugTraceLevel = DEBUG_ULTRA;
@@ -38,10 +38,10 @@ void OskitDumpBuffer( PCHAR Data, UINT Len ) {
 
 /* FUNCTIONS */
 
-NTSTATUS STDCALL
+NTSTATUS NTAPI
 DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath);
 
-static NTSTATUS STDCALL
+static NTSTATUS NTAPI
 AfdCreateSocket(PDEVICE_OBJECT DeviceObject, PIRP Irp,
                PIO_STACK_LOCATION IrpSp) {
     PAFD_FCB FCB;
@@ -52,6 +52,7 @@ AfdCreateSocket(PDEVICE_OBJECT DeviceObject, PIRP Irp,
     ULONG EaLength;
     PWCHAR EaInfoValue = NULL;
     UINT Disposition, i;
+    NTSTATUS Status = STATUS_SUCCESS;
 
     AFD_DbgPrint(MID_TRACE,
                 ("AfdCreate(DeviceObject %p Irp %p)\n", DeviceObject, Irp));
@@ -90,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 );
@@ -139,121 +144,159 @@ AfdCreateSocket(PDEVICE_OBJECT DeviceObject, PIRP Irp,
     if( FCB->Flags & SGID_CONNECTIONLESS ) {
         AFD_DbgPrint(MID_TRACE,("Packet oriented socket\n"));
        /* Allocate our backup buffer */
-       FCB->Recv.Window = ExAllocatePool( NonPagedPool, FCB->Recv.Size );
-        FCB->Send.Window = ExAllocatePool( NonPagedPool, FCB->Send.Size );
+       FCB->Recv.Window = ExAllocatePool( PagedPool, FCB->Recv.Size );
+       if( !FCB->Recv.Window ) Status = STATUS_NO_MEMORY;
+        if( NT_SUCCESS(Status) )
+        {
+            FCB->Send.Window = ExAllocatePool( PagedPool, FCB->Send.Size );
+           if( !FCB->Send.Window ) {
+                if( FCB->Recv.Window ) ExFreePool( FCB->Recv.Window );
+                Status = STATUS_NO_MEMORY;
+            }
+            }
        /* A datagram socket is always sendable */
        FCB->PollState |= AFD_EVENT_SEND;
         PollReeval( FCB->DeviceExt, FCB->FileObject );
     }
 
-    Irp->IoStatus.Status = STATUS_SUCCESS;
+    if( !NT_SUCCESS(Status) ) {
+       if( FCB->TdiDeviceName.Buffer ) ExFreePool( FCB->TdiDeviceName.Buffer );
+       ExFreePool( FCB );
+       FileObject->FsContext = NULL;
+    }
+
+    Irp->IoStatus.Status = Status;
     IoCompleteRequest( Irp, IO_NETWORK_INCREMENT );
 
-    return STATUS_SUCCESS;
+    return Status;
 }
 
-VOID DestroySocket( PAFD_FCB FCB ) {
-    AFD_DbgPrint(MIN_TRACE,("Called (%x)\n", 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( FCB->Recv.Window )
-       ExFreePool( FCB->Recv.Window );
-    if( FCB->Send.Window )
-       ExFreePool( FCB->Send.Window );
-    if( FCB->AddressFrom )
-       ExFreePool( FCB->AddressFrom );
-    if( FCB->LocalAddress )
-       ExFreePool( FCB->LocalAddress );
-    if( FCB->RemoteAddress )
-       ExFreePool( FCB->RemoteAddress );
-    if( FCB->ListenIrp.ConnectionReturnInfo )
-       ExFreePool( FCB->ListenIrp.ConnectionReturnInfo );
-    if( FCB->ListenIrp.ConnectionCallInfo )
-       ExFreePool( FCB->ListenIrp.ConnectionCallInfo );
-    if( FCB->TdiDeviceName.Buffer )
-       ExFreePool(FCB->TdiDeviceName.Buffer);
+    if( !SocketAcquireStateLock( FCB ) ) return LostSocket(Irp);
 
-    ExFreePool(FCB);
-    AFD_DbgPrint(MIN_TRACE,("Deleted (%x)\n", FCB));
+    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 );
 
-    AFD_DbgPrint(MIN_TRACE,("Leaving\n"));
+    return UnlockAndMaybeComplete(FCB, STATUS_SUCCESS, Irp, 0);
 }
 
-static NTSTATUS STDCALL
+static NTSTATUS NTAPI
 AfdCloseSocket(PDEVICE_OBJECT DeviceObject, PIRP Irp,
               PIO_STACK_LOCATION IrpSp)
 {
-    UINT i;
-    AFD_IN_FLIGHT_REQUEST InFlightRequest[IN_FLIGHT_REQUESTS];
     PFILE_OBJECT FileObject = IrpSp->FileObject;
     PAFD_FCB FCB = FileObject->FsContext;
-
-    if (!SocketAcquireStateLock(FCB)) return LostSocket(Irp, FALSE);
+    UINT i;
+    PAFD_IN_FLIGHT_REQUEST InFlightRequest[IN_FLIGHT_REQUESTS];
 
     AFD_DbgPrint(MID_TRACE,
                 ("AfdClose(DeviceObject %p Irp %p)\n", DeviceObject, Irp));
 
-    AFD_DbgPrint(MID_TRACE,("FCB %x\n", FCB));
+    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;
+    InFlightRequest[2] = &FCB->SendIrp;
+    InFlightRequest[3] = &FCB->ConnectIrp;
+
+    /* Cancel our pending requests */
+    for( i = 0; i < IN_FLIGHT_REQUESTS; i++ ) {
+       if( InFlightRequest[i]->InFlightRequest ) {
+           AFD_DbgPrint(MID_TRACE,("Cancelling in flight irp %d (%x)\n",
+                                   i, InFlightRequest[i]->InFlightRequest));
+            IoCancelIrp(InFlightRequest[i]->InFlightRequest);
+       }
+    }
 
-    FCB->PollState |= AFD_EVENT_CLOSE;
-    PollReeval( FCB->DeviceExt, FileObject );
     KillSelectsForFCB( FCB->DeviceExt, FileObject, FALSE );
 
-    if( FCB->EventSelect ) ObDereferenceObject( FCB->EventSelect );
+    SocketStateUnlock( FCB );
 
-    FileObject->FsContext = NULL;
+    if( FCB->EventSelect )
+        ObDereferenceObject( FCB->EventSelect );
 
-    FCB->State = SOCKET_STATE_CLOSED;
-    SocketStateUnlock(FCB);
-
-    InFlightRequest[0] = FCB->ListenIrp;
-    InFlightRequest[1] = FCB->ReceiveIrp;
-    InFlightRequest[2] = FCB->SendIrp;
-
-    /* Return early here because we might be called in the mean time. */
-    if( !(FCB->Critical ||
-          FCB->ListenIrp.InFlightRequest ||
-          FCB->ReceiveIrp.InFlightRequest ||
-          FCB->SendIrp.InFlightRequest) ) {
-       AFD_DbgPrint(MIN_TRACE,("Leaving socket alive (%x %x %x)\n",
-                               FCB->ListenIrp.InFlightRequest,
-                               FCB->ReceiveIrp.InFlightRequest,
-                               FCB->SendIrp.InFlightRequest));
-        SocketStateUnlock(FCB);
-        DestroySocket(FCB);
-        Irp->IoStatus.Status = STATUS_SUCCESS;
-        Irp->IoStatus.Information = 0;
-        IoCompleteRequest(Irp, IO_NO_INCREMENT);
-    }
-    else
+    if( FCB->Context )
+        ExFreePool( FCB->Context );
+
+    if( FCB->Recv.Window )
+       ExFreePool( FCB->Recv.Window );
+
+    if( FCB->Send.Window )
+       ExFreePool( FCB->Send.Window );
+
+    if( FCB->AddressFrom )
+       ExFreePool( FCB->AddressFrom );
+
+    if( FCB->LocalAddress )
+       ExFreePool( FCB->LocalAddress );
+
+    if( FCB->RemoteAddress )
+       ExFreePool( FCB->RemoteAddress );
+
+    if( FCB->Connection.Object )
+       ObDereferenceObject(FCB->Connection.Object);
+
+    if( FCB->AddressFile.Object )
+       ObDereferenceObject(FCB->AddressFile.Object);
+
+    if( FCB->AddressFile.Handle != INVALID_HANDLE_VALUE )
     {
-        /* After PoolReeval, this FCB should not be involved in any outstanding
-         * poll requests */
-        
-        /* Cancel our pending requests */
-        for( i = 0; i < IN_FLIGHT_REQUESTS; i++ ) {
-            NTSTATUS Status = STATUS_NO_SUCH_FILE;
-            if( InFlightRequest[i].InFlightRequest ) {
-                AFD_DbgPrint(MID_TRACE,("Cancelling in flight irp %d (%x)\n",
-                                        i, InFlightRequest[i].InFlightRequest));
-                InFlightRequest[i].InFlightRequest->IoStatus.Status = Status;
-                InFlightRequest[i].InFlightRequest->IoStatus.Information = 0;
-                IoCancelIrp( InFlightRequest[i].InFlightRequest );
-            }
+        if (ZwClose(FCB->AddressFile.Handle) == STATUS_INVALID_HANDLE)
+        {
+            DbgPrint("INVALID ADDRESS FILE HANDLE VALUE: %x %x\n", FCB->AddressFile.Handle, FCB->AddressFile.Object);
         }
+    }
 
-        FCB->PendingClose = Irp;
-        Irp->IoStatus.Status = STATUS_SUCCESS;
-        Irp->IoStatus.Information = 0;
-        IoCompleteRequest(Irp, IO_NO_INCREMENT);
+    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);
+        }
     }
 
-    DestroySocket( FCB );
+    if( FCB->TdiDeviceName.Buffer )
+       ExFreePool(FCB->TdiDeviceName.Buffer);
+
+    ExFreePool(FCB);
+
+    Irp->IoStatus.Status = STATUS_SUCCESS;
+    Irp->IoStatus.Information = 0;
+    IoCompleteRequest(Irp, IO_NETWORK_INCREMENT);
+
     AFD_DbgPrint(MID_TRACE, ("Returning success.\n"));
 
-    return Irp->IoStatus.Status;
+    return STATUS_SUCCESS;
 }
 
-static NTSTATUS STDCALL
+static NTSTATUS NTAPI
 AfdDisconnect(PDEVICE_OBJECT DeviceObject, PIRP Irp,
              PIO_STACK_LOCATION IrpSp) {
     PFILE_OBJECT FileObject = IrpSp->FileObject;
@@ -268,7 +311,7 @@ AfdDisconnect(PDEVICE_OBJECT DeviceObject, PIRP Irp,
 
     if( !(DisReq = LockRequest( Irp, IrpSp )) )
        return UnlockAndMaybeComplete( FCB, STATUS_NO_MEMORY,
-                                      Irp, 0, NULL );
+                                      Irp, 0 );
 
     if (NULL == FCB->RemoteAddress)
       {
@@ -281,7 +324,7 @@ AfdDisconnect(PDEVICE_OBJECT DeviceObject, PIRP Irp,
 
        if( !NT_SUCCESS(Status) || !ConnInfo )
            return UnlockAndMaybeComplete( FCB, STATUS_NO_MEMORY,
-                                          Irp, 0, NULL );
+                                          Irp, 0 );
       }
 
     if( DisReq->DisconnectType & AFD_DISCONNECT_SEND )
@@ -301,15 +344,18 @@ AfdDisconnect(PDEVICE_OBJECT DeviceObject, PIRP Irp,
 
     if (ConnInfo) ExFreePool( ConnInfo );
 
-    return UnlockAndMaybeComplete( FCB, Status, Irp, 0, NULL );
+    FCB->PollState |= AFD_EVENT_DISCONNECT;
+    PollReeval( FCB->DeviceExt, FCB->FileObject );
+
+    return UnlockAndMaybeComplete( FCB, Status, Irp, 0 );
 }
 
-static NTSTATUS STDCALL
+static NTSTATUS NTAPI
 AfdDispatch(PDEVICE_OBJECT DeviceObject, PIRP Irp)
 {
     PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
-    NTSTATUS Status = STATUS_SUCCESS;
-#ifdef DBG
+    NTSTATUS Status = STATUS_NOT_IMPLEMENTED;
+#if DBG
     PFILE_OBJECT FileObject = IrpSp->FileObject;
 #endif
 
@@ -333,6 +379,9 @@ AfdDispatch(PDEVICE_OBJECT DeviceObject, PIRP Irp)
        /* Ditto the borrowing */
        return AfdCloseSocket(DeviceObject, Irp, IrpSp);
 
+    case IRP_MJ_CLEANUP:
+        return AfdCleanupSocket(DeviceObject, Irp, IrpSp);
+
     /* write data */
     case IRP_MJ_WRITE:
        return AfdConnectedSocketWriteData( DeviceObject, Irp, IrpSp, TRUE );
@@ -379,6 +428,12 @@ AfdDispatch(PDEVICE_OBJECT DeviceObject, PIRP Irp)
        case IOCTL_AFD_GET_INFO:
            return AfdGetInfo( DeviceObject, Irp, IrpSp );
 
+       case IOCTL_AFD_SET_INFO:
+           return AfdSetInfo( DeviceObject, Irp, IrpSp );
+
+       case IOCTL_AFD_GET_CONTEXT_SIZE:
+           return AfdGetContextSize( DeviceObject, Irp, IrpSp );
+
        case IOCTL_AFD_GET_CONTEXT:
            return AfdGetContext( DeviceObject, Irp, IrpSp );
 
@@ -395,80 +450,79 @@ AfdDispatch(PDEVICE_OBJECT DeviceObject, PIRP Irp)
            return AfdDisconnect( DeviceObject, Irp, IrpSp );
 
        case IOCTL_AFD_GET_SOCK_NAME:
-           return AfdGetSockOrPeerName( DeviceObject, Irp, IrpSp, TRUE );
+           return AfdGetSockName( DeviceObject, Irp, IrpSp );
 
         case IOCTL_AFD_GET_PEER_NAME:
-            return AfdGetSockOrPeerName( DeviceObject, Irp, IrpSp, FALSE );
+            return AfdGetPeerName( DeviceObject, Irp, IrpSp );
 
        case IOCTL_AFD_GET_TDI_HANDLES:
-           AFD_DbgPrint(MIN_TRACE, ("IOCTL_AFD_GET_TDI_HANDLES\n"));
-           break;
-
-       case IOCTL_AFD_SET_INFO:
-           AFD_DbgPrint(MIN_TRACE, ("IOCTL_AFD_SET_INFO\n"));
+           DbgPrint("IOCTL_AFD_GET_TDI_HANDLES is UNIMPLEMENTED!\n");
            break;
 
        case IOCTL_AFD_SET_CONNECT_DATA:
-           AFD_DbgPrint(MIN_TRACE, ("IOCTL_AFD_SET_CONNECT_DATA\n"));
+           DbgPrint("IOCTL_AFD_SET_CONNECT_DATA is UNIMPLEMENTED!\n");
            break;
 
        case IOCTL_AFD_SET_CONNECT_OPTIONS:
-           AFD_DbgPrint(MIN_TRACE, ("IOCTL_AFD_SET_CONNECT_OPTIONS\n"));
+           DbgPrint("IOCTL_AFD_SET_CONNECT_OPTIONS is UNIMPLEMENTED!\n");
            break;
 
        case IOCTL_AFD_SET_DISCONNECT_DATA:
-           AFD_DbgPrint(MIN_TRACE, ("IOCTL_AFD_SET_DISCONNECT_DATA\n"));
+           DbgPrint("IOCTL_AFD_SET_DISCONNECT_DATA is UNIMPLEMENTED!\n");
            break;
 
        case IOCTL_AFD_SET_DISCONNECT_OPTIONS:
-           AFD_DbgPrint(MIN_TRACE, ("IOCTL_AFD_SET_DISCONNECT_OPTIONS\n"));
+           DbgPrint("IOCTL_AFD_SET_DISCONNECT_OPTIONS is UNIMPLEMENTED!\n");
            break;
 
        case IOCTL_AFD_GET_CONNECT_DATA:
-           AFD_DbgPrint(MIN_TRACE, ("IOCTL_AFD_GET_CONNECT_DATA\n"));
+           DbgPrint("IOCTL_AFD_GET_CONNECT_DATA is UNIMPLEMENTED!\n");
            break;
 
        case IOCTL_AFD_GET_CONNECT_OPTIONS:
-           AFD_DbgPrint(MIN_TRACE, ("IOCTL_AFD_GET_CONNECT_OPTIONS\n"));
+           DbgPrint("IOCTL_AFD_GET_CONNECT_OPTIONS is UNIMPLEMENTED!\n");
            break;
 
        case IOCTL_AFD_GET_DISCONNECT_DATA:
-           AFD_DbgPrint(MIN_TRACE, ("IOCTL_AFD_GET_DISCONNECT_DATA\n"));
+           DbgPrint("IOCTL_AFD_GET_DISCONNECT_DATA is UNIMPLEMENTED!\n");
            break;
 
        case IOCTL_AFD_GET_DISCONNECT_OPTIONS:
-           AFD_DbgPrint(MIN_TRACE, ("IOCTL_AFD_GET_DISCONNECT_OPTIONS\n"));
+           DbgPrint("IOCTL_AFD_GET_DISCONNECT_OPTIONS is UNIMPLEMENTED!\n");
            break;
 
        case IOCTL_AFD_SET_CONNECT_DATA_SIZE:
-           AFD_DbgPrint(MIN_TRACE, ("IOCTL_AFD_SET_CONNECT_DATA_SIZE\n"));
+           DbgPrint("IOCTL_AFD_SET_CONNECT_DATA_SIZE is UNIMPLEMENTED!\n");
            break;
 
        case IOCTL_AFD_SET_CONNECT_OPTIONS_SIZE:
-           AFD_DbgPrint(MIN_TRACE, ("IOCTL_AFD_SET_CONNECT_OPTIONS_SIZE\n"));
+           DbgPrint("IOCTL_AFD_SET_CONNECT_OPTIONS_SIZE is UNIMPLEMENTED!\n");
            break;
 
        case IOCTL_AFD_SET_DISCONNECT_DATA_SIZE:
-           AFD_DbgPrint(MIN_TRACE, ("IOCTL_AFD_SET_DISCONNECT_DATA_SIZE\n"));
+           DbgPrint("IOCTL_AFD_SET_DISCONNECT_DATA_SIZE is UNIMPLEMENTED!\n");
            break;
 
        case IOCTL_AFD_SET_DISCONNECT_OPTIONS_SIZE:
-           AFD_DbgPrint(MIN_TRACE, ("IOCTL_AFD_SET_DISCONNECT_OPTIONS_SIZE\n"));
+           DbgPrint("IOCTL_AFD_SET_DISCONNECT_OPTIONS_SIZE is UNIMPLEMENTED!\n");
            break;
 
        case IOCTL_AFD_DEFER_ACCEPT:
-           AFD_DbgPrint(MIN_TRACE, ("IOCTL_AFD_DEFER_ACCEPT\n"));
+           DbgPrint("IOCTL_AFD_DEFER_ACCEPT is UNIMPLEMENTED!\n");
            break;
 
        case IOCTL_AFD_GET_PENDING_CONNECT_DATA:
-           AFD_DbgPrint(MIN_TRACE, ("IOCTL_AFD_GET_PENDING_CONNECT_DATA\n"));
+           DbgPrint("IOCTL_AFD_GET_PENDING_CONNECT_DATA is UNIMPLEMENTED!\n");
+           break;
+
+       case IOCTL_AFD_VALIDATE_GROUP:
+           DbgPrint("IOCTL_AFD_VALIDATE_GROUP is UNIMPLEMENTED!\n");
            break;
 
        default:
-           Status = STATUS_NOT_IMPLEMENTED;
-           AFD_DbgPrint(MIN_TRACE, ("Unknown IOCTL (0x%x)\n",
-                                    IrpSp->Parameters.DeviceIoControl.
-                                    IoControlCode));
+           Status = STATUS_NOT_SUPPORTED;
+           DbgPrint("Unknown IOCTL (0x%x)\n",
+                    IrpSp->Parameters.DeviceIoControl.IoControlCode);
            break;
        }
        break;
@@ -492,12 +546,117 @@ AfdDispatch(PDEVICE_OBJECT DeviceObject, PIRP Irp)
     return (Status);
 }
 
-static VOID STDCALL
+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)
 {
 }
 
-NTSTATUS STDCALL
+NTSTATUS NTAPI
 DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
 {
     PDEVICE_OBJECT DeviceObject;
@@ -508,6 +667,7 @@ DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
     /* register driver routines */
     DriverObject->MajorFunction[IRP_MJ_CLOSE] = AfdDispatch;
     DriverObject->MajorFunction[IRP_MJ_CREATE] = AfdDispatch;
+    DriverObject->MajorFunction[IRP_MJ_CLEANUP] = AfdDispatch;
     DriverObject->MajorFunction[IRP_MJ_WRITE] = AfdDispatch;
     DriverObject->MajorFunction[IRP_MJ_READ] = AfdDispatch;
     DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = AfdDispatch;