Patch by hardon. Properly handle 0 timeouts. Fixes bug 857.
[reactos.git] / reactos / drivers / net / afd / afd / select.c
index b714c35..212afc3 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: select.c,v 1.5 2004/11/15 18:24:57 arty Exp $
+/* $Id$
  * COPYRIGHT:        See COPYING in the top level directory
  * PROJECT:          ReactOS kernel
  * FILE:             drivers/net/afd/afd/select.c
 #include "tdiconn.h"
 #include "debug.h"
 
-VOID CopyBackStatus( PAFD_HANDLE HandleArray,
+static VOID PrintEvents( ULONG Events ) {
+#if DBG
+    char *events_list[] = { "AFD_EVENT_RECEIVE",
+                            "AFD_EVENT_OOB_RECEIVE",
+                            "AFD_EVENT_SEND",
+                            "AFD_EVENT_DISCONNECT",
+                            "AFD_EVENT_ABORT",
+                            "AFD_EVENT_CLOSE",
+                            "AFD_EVENT_CONNECT",
+                            "AFD_EVENT_ACCEPT",
+                            "AFD_EVENT_CONNECT_FAIL",
+                            "AFD_EVENT_QOS",
+                            "AFD_EVENT_GROUP_QOS",
+                            NULL };
+    int i;
+
+    for( i = 0; events_list[i]; i++ )
+        if( Events & (1 << i) ) AFD_DbgPrint(MID_TRACE,("%s ", events_list[i] ));
+#endif
+}
+
+static VOID CopyBackStatus( PAFD_HANDLE HandleArray,
                     UINT HandleCount ) {
     UINT i;
-    
+
     for( i = 0; i < HandleCount; i++ ) {
        HandleArray[i].Events = HandleArray[i].Status;
        HandleArray[i].Status = 0;
     }
 }
 
-VOID ZeroEvents( PAFD_HANDLE HandleArray,
+static VOID ZeroEvents( PAFD_HANDLE HandleArray,
                 UINT HandleCount ) {
     UINT i;
-    
-    for( i = 0; i < HandleCount; i++ ) {
-       HandleArray[i].Events = 0;
+
+    for( i = 0; i < HandleCount; i++ )
        HandleArray[i].Status = 0;
-    }
 }
 
-NTSTATUS STDCALL
-ScanForImmediateTrigger( PAFD_HANDLE HandleArray,
-                        UINT HandleCount,
-                        PUINT HandlesSet ) {
-    NTSTATUS Status = STATUS_SUCCESS;
-    PFILE_OBJECT FileObject;
-    PAFD_FCB FCB;
-    UINT i;
-    BOOLEAN ShouldReturnNow = FALSE;
-
-    for( i = 0; i < HandleCount && NT_SUCCESS(Status); i++ ) {
-        HandleArray[i].Status = 0;
-       Status = 
-           ObReferenceObjectByHandle
-           ( (PVOID)HandleArray[i].Handle,
-             FILE_ALL_ACCESS,
-             NULL,
-             KernelMode,
-             (PVOID*)&FileObject,
-             NULL );
-
-       if( NT_SUCCESS(Status) ) {
-           FCB = FileObject->FsContext;
-           /* Check select bits */
-           
-           AFD_DbgPrint(MID_TRACE,("Locking socket state\n"));
 
-           if( !SocketAcquireStateLock( FCB ) ) {
-               AFD_DbgPrint(MID_TRACE,("Failed to get a socket state\n"));
-               Status = STATUS_UNSUCCESSFUL;
-           } else {
-               AFD_DbgPrint(MID_TRACE,("Got a socket state\n"));
-               Status = STATUS_SUCCESS;
-               HandleArray[i].Status = 
-                   FCB->PollState & HandleArray[i].Events;
-               if( HandleArray[i].Status ) ShouldReturnNow = TRUE;
-               ObDereferenceObject( (PVOID)HandleArray[i].Handle );
-               AFD_DbgPrint(MID_TRACE,("Unlocking\n"));
-               SocketStateUnlock( FCB );
-               AFD_DbgPrint(MID_TRACE,("Unlocked\n"));
-           }
-       }
+/* you must pass either Poll OR Irp */
+static VOID SignalSocket( 
+   PAFD_ACTIVE_POLL Poll OPTIONAL, 
+   PIRP _Irp OPTIONAL, 
+   PAFD_POLL_INFO PollReq,
+       NTSTATUS Status 
+   ) 
+{
+    UINT i;
+    PIRP Irp = _Irp ? _Irp : Poll->Irp;
+    AFD_DbgPrint(MID_TRACE,("Called (Status %x)\n", Status));
+    
+    if (Poll)
+    {
+       KeCancelTimer( &Poll->Timer );
+      RemoveEntryList( &Poll->ListEntry );
+      ExFreePool( Poll );
+   }
+    
+    Irp->IoStatus.Status = Status;
+    Irp->IoStatus.Information =
+        FIELD_OFFSET(AFD_POLL_INFO, Handles) + sizeof(AFD_HANDLE) * PollReq->HandleCount;
+    CopyBackStatus( PollReq->Handles,
+                   PollReq->HandleCount );
+    for( i = 0; i < PollReq->HandleCount; i++ ) {
+        AFD_DbgPrint
+            (MAX_TRACE,
+             ("Handle(%x): Got %x,%x\n",
+              PollReq->Handles[i].Handle,
+              PollReq->Handles[i].Events,
+              PollReq->Handles[i].Status));
     }
-
-    if( !NT_SUCCESS(Status) || ShouldReturnNow ) return Status; 
-    else return STATUS_PENDING;
+    UnlockHandles( AFD_HANDLES(PollReq), PollReq->HandleCount );
+    AFD_DbgPrint(MID_TRACE,("Completing\n"));
+    IoCompleteRequest( Irp, IO_NETWORK_INCREMENT );
+    AFD_DbgPrint(MID_TRACE,("Done\n"));
 }
 
-VOID SelectTimeout( PKDPC Dpc,
+static VOID SelectTimeout( PKDPC Dpc,
                    PVOID DeferredContext,
                    PVOID SystemArgument1,
                    PVOID SystemArgument2 ) {
     PAFD_ACTIVE_POLL Poll = DeferredContext;
     PAFD_POLL_INFO PollReq;
-    PAFD_DEVICE_EXTENSION DeviceExt;
     PIRP Irp;
     KIRQL OldIrql;
+    PAFD_DEVICE_EXTENSION DeviceExt;
+
+    AFD_DbgPrint(MID_TRACE,("Called\n"));
 
     Irp = Poll->Irp;
     DeviceExt = Poll->DeviceExt;
-
     PollReq = Irp->AssociatedIrp.SystemBuffer;
 
+    ZeroEvents( PollReq->Handles, PollReq->HandleCount );
+
     KeAcquireSpinLock( &DeviceExt->Lock, &OldIrql );
-    RemoveEntryList( &Poll->ListEntry );
+    SignalSocket( Poll, NULL, PollReq, STATUS_TIMEOUT );
     KeReleaseSpinLock( &DeviceExt->Lock, OldIrql );
 
-    ExFreePool( Poll );
+    AFD_DbgPrint(MID_TRACE,("Timeout\n"));
+}
 
-    ZeroEvents( PollReq->Handles, PollReq->HandleCount );
+VOID KillSelectsForFCB( PAFD_DEVICE_EXTENSION DeviceExt,
+                        PFILE_OBJECT FileObject,
+                        BOOLEAN OnlyExclusive ) {
+    KIRQL OldIrql;
+    PLIST_ENTRY ListEntry;
+    PAFD_ACTIVE_POLL Poll;
+    PIRP Irp;
+    PAFD_POLL_INFO PollReq;
+    PAFD_HANDLE HandleArray;
+    UINT i;
+
+    AFD_DbgPrint(MID_TRACE,("Killing selects that refer to %x\n", FileObject));
+
+    KeAcquireSpinLock( &DeviceExt->Lock, &OldIrql );
+
+    ListEntry = DeviceExt->Polls.Flink;
+    while ( ListEntry != &DeviceExt->Polls ) {
+       Poll = CONTAINING_RECORD(ListEntry, AFD_ACTIVE_POLL, ListEntry);
+       ListEntry = ListEntry->Flink;
+        Irp = Poll->Irp;
+        PollReq = Irp->AssociatedIrp.SystemBuffer;
+        HandleArray = AFD_HANDLES(PollReq);
+
+        for( i = 0; i < PollReq->HandleCount; i++ ) {
+            AFD_DbgPrint(MAX_TRACE,("Req: %x, This %x\n",
+                                    HandleArray[i].Handle, FileObject));
+            if( (PVOID)HandleArray[i].Handle == FileObject &&
+                (!OnlyExclusive || (OnlyExclusive && Poll->Exclusive)) ) {
+                ZeroEvents( PollReq->Handles, PollReq->HandleCount );
+                SignalSocket( Poll, NULL, PollReq, STATUS_SUCCESS );
+            }
+       }
+    }
 
-    Irp->IoStatus.Status = STATUS_TIMEOUT;
-    Irp->IoStatus.Information = -1;
+    KeReleaseSpinLock( &DeviceExt->Lock, OldIrql );
 
-    IoCompleteRequest( Irp, IO_NO_INCREMENT );
+    AFD_DbgPrint(MID_TRACE,("Done\n"));
 }
 
 NTSTATUS STDCALL
-AfdSelect( PDEVICE_OBJECT DeviceObject, PIRP Irp, 
+AfdSelect( PDEVICE_OBJECT DeviceObject, PIRP Irp,
           PIO_STACK_LOCATION IrpSp ) {
     NTSTATUS Status = STATUS_NO_MEMORY;
+    PAFD_FCB FCB;
+    PFILE_OBJECT FileObject;
     PAFD_POLL_INFO PollReq = Irp->AssociatedIrp.SystemBuffer;
     PAFD_DEVICE_EXTENSION DeviceExt = DeviceObject->DeviceExtension;
-    PAFD_ACTIVE_POLL Poll = NULL;
     UINT CopySize = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
-    UINT AllocSize = 
+    UINT AllocSize =
        CopySize + sizeof(AFD_ACTIVE_POLL) - sizeof(AFD_POLL_INFO);
     KIRQL OldIrql;
-    UINT HandlesSignalled; 
+    UINT i, Signalled = 0;
+    ULONG Exclusive = PollReq->Exclusive;
 
-    AFD_DbgPrint(MID_TRACE,("Called (HandleCount %d Timeout %d)\n", 
+    AFD_DbgPrint(MID_TRACE,("Called (HandleCount %d Timeout %d)\n",
                            PollReq->HandleCount,
-                           (INT)(PollReq->Timeout.QuadPart * -1)));
+                           (INT)(PollReq->Timeout.QuadPart)));
 
-    Status = ScanForImmediateTrigger( PollReq->Handles,
-                                     PollReq->HandleCount,
-                                     &HandlesSignalled );
-    
-    if( Status == STATUS_PENDING ) {
-       Poll = ExAllocatePool( NonPagedPool, AllocSize );
-       
-       if( Poll ) {
-           KeAcquireSpinLock( &DeviceExt->Lock, &OldIrql );
-           
-           KeInitializeDpc( (PRKDPC)&Poll->TimeoutDpc, 
-                            (PKDEFERRED_ROUTINE)SelectTimeout,
-                            Poll );
-           PollReq->Timeout.QuadPart *= -1;
-           /* Negative values are relative */
-           KeInitializeTimerEx( &Poll->Timer, NotificationTimer );
-           KeSetTimer( &Poll->Timer, PollReq->Timeout, &Poll->TimeoutDpc );
-           
-           Poll->Irp = Irp;
-           Poll->DeviceExt = DeviceExt;
-
-           InsertTailList( &DeviceExt->Polls, &Poll->ListEntry );
-           Status = STATUS_PENDING;
-
-           KeReleaseSpinLock( &DeviceExt->Lock, OldIrql );
-       } else Status = STATUS_NO_MEMORY;
-    } else if( Status == STATUS_SUCCESS ) {
-       CopyBackStatus( PollReq->Handles,
-                       PollReq->HandleCount );
-    } else {
-       ZeroEvents( PollReq->Handles,
-                   PollReq->HandleCount );
+    SET_AFD_HANDLES(PollReq,
+                   LockHandles( PollReq->Handles, PollReq->HandleCount ));
+
+    if( !AFD_HANDLES(PollReq) ) {
+       Irp->IoStatus.Status = STATUS_NO_MEMORY;
+       Irp->IoStatus.Information = 0;
+       IoCompleteRequest( Irp, IO_NETWORK_INCREMENT );
+       return Irp->IoStatus.Status;
     }
 
-    AFD_DbgPrint(MID_TRACE,("Returning %x\n", Status));
+    if( Exclusive ) {
+        for( i = 0; i < PollReq->HandleCount; i++ ) {
+            if( !AFD_HANDLES(PollReq)[i].Handle ) continue;
 
-    if( Status == STATUS_PENDING )
-       IoMarkIrpPending( Irp );
-    else {
-       Irp->IoStatus.Status = Status;
-       Irp->IoStatus.Information = HandlesSignalled;
-       IoCompleteRequest( Irp, IO_NETWORK_INCREMENT );
+            KillSelectsForFCB( DeviceExt,
+                               (PFILE_OBJECT)AFD_HANDLES(PollReq)[i].Handle,
+                               TRUE );
+        }
     }
 
+    ZeroEvents( PollReq->Handles,
+               PollReq->HandleCount );
+
+       KeAcquireSpinLock( &DeviceExt->Lock, &OldIrql );
+
+       for( i = 0; i < PollReq->HandleCount; i++ ) {
+           if( !AFD_HANDLES(PollReq)[i].Handle ) continue;
+
+           FileObject = (PFILE_OBJECT)AFD_HANDLES(PollReq)[i].Handle;
+           FCB = FileObject->FsContext;
+
+           if( (FCB->PollState & AFD_EVENT_CLOSE) ||
+               (PollReq->Handles[i].Status & AFD_EVENT_CLOSE) ) {
+               AFD_HANDLES(PollReq)[i].Handle = 0;
+               PollReq->Handles[i].Events = 0;
+               PollReq->Handles[i].Status = AFD_EVENT_CLOSE;
+               Signalled++;
+           } else {
+                AFD_DbgPrint(MID_TRACE, ("AFD: Select Events: "));
+                PrintEvents( PollReq->Handles[i].Events );
+                AFD_DbgPrint(MID_TRACE,("\n"));
+
+               PollReq->Handles[i].Status =
+                   PollReq->Handles[i].Events & FCB->PollState;
+               if( PollReq->Handles[i].Status ) {
+                   AFD_DbgPrint(MID_TRACE,("Signalling %x with %x\n",
+                                           FCB, FCB->PollState));
+                   Signalled++;
+               }
+           }
+       }
+
+       if( Signalled ) {
+           Status = STATUS_SUCCESS;
+           Irp->IoStatus.Status = Status;
+           SignalSocket( NULL, Irp, PollReq, Status );
+       } else {
+      
+       PAFD_ACTIVE_POLL Poll = NULL;
+       
+       Poll = ExAllocatePool( NonPagedPool, AllocSize );
+       if (Poll){
+          Poll->Irp = Irp;
+          Poll->DeviceExt = DeviceExt;
+          Poll->Exclusive = Exclusive;
+
+          KeInitializeTimerEx( &Poll->Timer, NotificationTimer );
+
+          KeInitializeDpc( (PRKDPC)&Poll->TimeoutDpc,
+             (PKDEFERRED_ROUTINE)SelectTimeout,
+             Poll );
+          
+          InsertTailList( &DeviceExt->Polls, &Poll->ListEntry );
+
+          KeSetTimer( &Poll->Timer, PollReq->Timeout, &Poll->TimeoutDpc );
+
+          Status = STATUS_PENDING;
+          IoMarkIrpPending( Irp );
+       } else {
+          AFD_DbgPrint(MAX_TRACE, ("FIXME: do something with the IRP!\n"));
+          Status = STATUS_NO_MEMORY;
+       }
+       }
+
+       KeReleaseSpinLock( &DeviceExt->Lock, OldIrql );
+
+    AFD_DbgPrint(MID_TRACE,("Returning %x\n", Status));
+
     return Status;
 }
 
-VOID SignalSocket( PAFD_ACTIVE_POLL Poll, PAFD_POLL_INFO PollReq, UINT i ) {
-    /* One of the files was destroyed.  We return now with error. */
-    Poll->Irp->IoStatus.Status = STATUS_SUCCESS; /* XXX REVISIT */
-    Poll->Irp->IoStatus.Information = 1;
-    CopyBackStatus( PollReq->Handles,
-                   PollReq->HandleCount );
-    IoCompleteRequest( Poll->Irp, IO_NETWORK_INCREMENT );
+NTSTATUS STDCALL
+AfdEventSelect( PDEVICE_OBJECT DeviceObject, PIRP Irp,
+               PIO_STACK_LOCATION IrpSp ) {
+    PFILE_OBJECT FileObject = IrpSp->FileObject;
+    NTSTATUS Status = STATUS_NO_MEMORY;
+    PAFD_EVENT_SELECT_INFO EventSelectInfo =
+       (PAFD_EVENT_SELECT_INFO)LockRequest( Irp, IrpSp );
+    PAFD_FCB FCB = FileObject->FsContext;
+
+    AFD_DbgPrint(MID_TRACE,("Called (Event %x Triggers %x)\n",
+                           EventSelectInfo->EventObject,
+                           EventSelectInfo->Events));
+
+    if( !SocketAcquireStateLock( FCB ) ) {
+       UnlockRequest( Irp, IrpSp );
+       return LostSocket( Irp, FALSE );
+    }
+
+    FCB->EventSelectTriggers = FCB->EventsFired = 0;
+    if( FCB->EventSelect ) ObDereferenceObject( FCB->EventSelect );
+    FCB->EventSelect = NULL;
+
+    if( EventSelectInfo->EventObject && EventSelectInfo->Events ) {
+       Status = ObReferenceObjectByHandle( (PVOID)EventSelectInfo->
+                                           EventObject,
+                                           FILE_ALL_ACCESS,
+                                           NULL,
+                                           KernelMode,
+                                           (PVOID *)&FCB->EventSelect,
+                                           NULL );
+
+       if( !NT_SUCCESS(Status) )
+           FCB->EventSelect = NULL;
+       else
+           FCB->EventSelectTriggers = EventSelectInfo->Events;
+    } else /* Work done, cancelling select */
+       Status = STATUS_SUCCESS;
+
+    AFD_DbgPrint(MID_TRACE,("Returning %x\n", Status));
+
+    return UnlockAndMaybeComplete( FCB, STATUS_SUCCESS, Irp,
+                                  0, NULL, TRUE );
 }
 
-BOOLEAN UpdatePollWithFCB( PAFD_ACTIVE_POLL Poll, PFILE_OBJECT FileObject ) {
+NTSTATUS STDCALL
+AfdEnumEvents( PDEVICE_OBJECT DeviceObject, PIRP Irp,
+              PIO_STACK_LOCATION IrpSp ) {
+    PFILE_OBJECT FileObject = IrpSp->FileObject;
+    PAFD_ENUM_NETWORK_EVENTS_INFO EnumReq =
+       (PAFD_ENUM_NETWORK_EVENTS_INFO)LockRequest( Irp, IrpSp );
+    PAFD_FCB FCB = FileObject->FsContext;
+
+    AFD_DbgPrint(MID_TRACE,("Called (FCB %x)\n", FCB));
+
+    if( !SocketAcquireStateLock( FCB ) ) {
+       UnlockRequest( Irp, IrpSp );
+       return LostSocket( Irp, FALSE );
+    }
+
+    EnumReq->PollEvents = FCB->PollState;
+    RtlZeroMemory( EnumReq->EventStatus, sizeof(EnumReq->EventStatus) );
+
+    return UnlockAndMaybeComplete( FCB, STATUS_SUCCESS, Irp,
+                                  0, NULL, TRUE );
+}
+
+/* * * NOTE ALWAYS CALLED AT DISPATCH_LEVEL * * */
+static BOOLEAN UpdatePollWithFCB( PAFD_ACTIVE_POLL Poll, PFILE_OBJECT FileObject ) {
     UINT i;
-    NTSTATUS Status;
-    PFILE_OBJECT TargetFile;
     PAFD_FCB FCB;
+    UINT Signalled = 0;
     PAFD_POLL_INFO PollReq = Poll->Irp->AssociatedIrp.SystemBuffer;
 
+    ASSERT( KeGetCurrentIrql() == DISPATCH_LEVEL );
+
     for( i = 0; i < PollReq->HandleCount; i++ ) {
-       Status = 
-           ObReferenceObjectByHandle
-           ( (PVOID)PollReq->Handles[i].Handle,
-             FILE_ALL_ACCESS,
-             NULL,
-             KernelMode,
-             (PVOID*)&TargetFile,
-             NULL );
-       
-       if( !NT_SUCCESS(Status) ) { 
-           PollReq->Handles[i].Status = AFD_EVENT_CLOSE;
-           SignalSocket( Poll, PollReq, i );
-           return TRUE;
-       } else {
-           FCB = FileObject->FsContext;
+       if( !AFD_HANDLES(PollReq)[i].Handle ) continue;
 
-           AFD_DbgPrint(MID_TRACE,("Locking socket state\n"));
+       FileObject = (PFILE_OBJECT)AFD_HANDLES(PollReq)[i].Handle;
+       FCB = FileObject->FsContext;
 
-           if( !SocketAcquireStateLock( FCB ) ) {
-               PollReq->Handles[i].Status = AFD_EVENT_CLOSE;
-               SignalSocket( Poll, PollReq, i );
-           } else {
-               PollReq->Handles[i].Status = 
-                   PollReq->Handles[i].Events & FCB->PollState;
-               if( PollReq->Handles[i].Status )
-                   SignalSocket( Poll, PollReq, i );
-               SocketStateUnlock( FCB );
+       if( (FCB->PollState & AFD_EVENT_CLOSE) ||
+           (PollReq->Handles[i].Status & AFD_EVENT_CLOSE) ) {
+           AFD_HANDLES(PollReq)[i].Handle = 0;
+           PollReq->Handles[i].Events = 0;
+           PollReq->Handles[i].Status = AFD_EVENT_CLOSE;
+           Signalled++;
+       } else {
+           PollReq->Handles[i].Status =
+               PollReq->Handles[i].Events & FCB->PollState;
+           if( PollReq->Handles[i].Status ) {
+               AFD_DbgPrint(MID_TRACE,("Signalling %x with %x\n",
+                                       FCB, FCB->PollState));
+               Signalled++;
            }
-           return TRUE;
        }
     }
 
-    return FALSE;
+    return Signalled ? 1 : 0;
 }
 
 VOID PollReeval( PAFD_DEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject ) {
     PAFD_ACTIVE_POLL Poll = NULL;
     PLIST_ENTRY ThePollEnt = NULL;
+    PAFD_FCB FCB;
     KIRQL OldIrql;
+    PAFD_POLL_INFO PollReq;
+    PKEVENT EventSelect = NULL;
 
-    AFD_DbgPrint(MID_TRACE,("Called: DeviceExt %x FileObject %x\n", 
+    AFD_DbgPrint(MID_TRACE,("Called: DeviceExt %x FileObject %x\n",
                            DeviceExt, FileObject));
 
     KeAcquireSpinLock( &DeviceExt->Lock, &OldIrql );
 
+    /* Take care of any event select signalling */
+    FCB = (PAFD_FCB)FileObject->FsContext;
+
+    /* Not sure if i can do this at DISPATCH_LEVEL ... try it at passive */
+    AFD_DbgPrint(MID_TRACE,("Current State: %x, Events Fired: %x, "
+                           "Select Triggers %x\n",
+                           FCB->PollState, FCB->EventsFired,
+                           FCB->EventSelectTriggers));
+    if( FCB->PollState & ~FCB->EventsFired & FCB->EventSelectTriggers ) {
+       FCB->EventsFired |= FCB->PollState;
+       EventSelect = FCB->EventSelect;
+    }
+
+    if( !FCB ) {
+       KeReleaseSpinLock( &DeviceExt->Lock, OldIrql );
+       return;
+    }
+
+    /* Now signal normal select irps */
     ThePollEnt = DeviceExt->Polls.Flink;
 
     while( ThePollEnt != &DeviceExt->Polls ) {
        Poll = CONTAINING_RECORD( ThePollEnt, AFD_ACTIVE_POLL, ListEntry );
+       PollReq = Poll->Irp->AssociatedIrp.SystemBuffer;
+       AFD_DbgPrint(MID_TRACE,("Checking poll %x\n", Poll));
+
        if( UpdatePollWithFCB( Poll, FileObject ) ) {
            ThePollEnt = ThePollEnt->Flink;
-           RemoveEntryList( &Poll->ListEntry );
-       } else 
+           AFD_DbgPrint(MID_TRACE,("Signalling socket\n"));
+           SignalSocket( Poll, NULL, PollReq, STATUS_SUCCESS );
+       } else
            ThePollEnt = ThePollEnt->Flink;
     }
 
     KeReleaseSpinLock( &DeviceExt->Lock, OldIrql );
 
+    AFD_DbgPrint(MID_TRACE,("Setting event %x\n", EventSelect));
+    if( EventSelect ) KeSetEvent( EventSelect, IO_NETWORK_INCREMENT, FALSE );
+
     AFD_DbgPrint(MID_TRACE,("Leaving\n"));
 }