Fix IO completion APIs/Structures.
authorAlex Ionescu <aionescu@gmail.com>
Thu, 25 Nov 2004 22:18:17 +0000 (22:18 +0000)
committerAlex Ionescu <aionescu@gmail.com>
Thu, 25 Nov 2004 22:18:17 +0000 (22:18 +0000)
Implement WSPASyncSelect and friends. Event re-enabling functionality missing and will be added tonight.

svn path=/trunk/; revision=11807

13 files changed:
reactos/include/afd/shared.h
reactos/include/ddk/iotypes.h
reactos/include/ntos/zw.h
reactos/include/ntos/zwtypes.h
reactos/lib/kernel32/file/iocompl.c
reactos/lib/msafd/include/msafd.h
reactos/lib/msafd/misc/dllmain.c
reactos/lib/msafd/misc/event.c
reactos/lib/msafd/misc/sndrcv.c
reactos/ntoskrnl/include/internal/io.h
reactos/ntoskrnl/io/iocomp.c
reactos/ntoskrnl/kd/gdbstub.c
reactos/w32api/include/ddk/ntifs.h

index 4fdef6c..248a756 100644 (file)
@@ -52,10 +52,10 @@ typedef struct _AFD_HANDLE_ {
 } AFD_HANDLE, *PAFD_HANDLE;
 
 typedef struct _AFD_POLL_INFO {
-    LARGE_INTEGER                      Timeout;
-    ULONG                              HandleCount;
-    PAFD_HANDLE                         InternalUse;
-    AFD_HANDLE                         Handles[1];
+       LARGE_INTEGER Timeout;
+       ULONG HandleCount;
+       BOOLEAN Exclusive;
+       AFD_HANDLE Handles[1];
 } AFD_POLL_INFO, *PAFD_POLL_INFO;
 
 typedef struct _AFD_ACCEPT_DATA {
index a6f4698..f043993 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: iotypes.h,v 1.69 2004/11/06 04:12:59 ion Exp $
+/* $Id: iotypes.h,v 1.70 2004/11/25 22:18:15 ion Exp $
  *
  */
 
@@ -752,7 +752,7 @@ typedef struct _SECTION_OBJECT_POINTERS
 typedef struct _IO_COMPLETION_CONTEXT
 {
    PVOID Port;
-   ULONG Key;
+   PVOID Key;
 } IO_COMPLETION_CONTEXT, *PIO_COMPLETION_CONTEXT;
 
 #define FO_FILE_OPEN                    0x00000001
index 8149579..7bd4599 100755 (executable)
@@ -1,5 +1,5 @@
 
-/* $Id: zw.h,v 1.35 2004/11/12 12:06:17 ekohl Exp $
+/* $Id: zw.h,v 1.36 2004/11/25 22:18:15 ion Exp $
  *
  * COPYRIGHT:        See COPYING in the top level directory
  * PROJECT:          ReactOS kernel
@@ -3567,8 +3567,8 @@ NTSTATUS
 STDCALL
 NtRemoveIoCompletion(
    IN  HANDLE           IoCompletionHandle,
-   OUT PULONG           CompletionKey,
-   OUT PULONG           CompletionValue,
+   OUT PVOID           *CompletionKey,
+   OUT PVOID           *CompletionContext,
    OUT PIO_STATUS_BLOCK IoStatusBlock,
    IN  PLARGE_INTEGER   Timeout OPTIONAL
    );
@@ -3577,8 +3577,8 @@ NTSTATUS
 STDCALL
 ZwRemoveIoCompletion(
    IN  HANDLE           IoCompletionHandle,
-   OUT PULONG           CompletionKey,
-   OUT PULONG           CompletionValue,
+   OUT PVOID           *CompletionKey,
+   OUT PVOID           *CompletionValue,
    OUT PIO_STATUS_BLOCK IoStatusBlock,
    IN  PLARGE_INTEGER   Timeout OPTIONAL
    );
@@ -4094,8 +4094,8 @@ NTSTATUS
 STDCALL
 NtSetIoCompletion(
    IN HANDLE   IoCompletionPortHandle,
-   IN ULONG    CompletionKey,
-   IN ULONG    CompletionValue,
+   IN PVOID    CompletionKey,
+   IN PVOID    CompletionContext,
    IN NTSTATUS CompletionStatus,
    IN ULONG    CompletionInformation
    );
@@ -4104,8 +4104,8 @@ NTSTATUS
 STDCALL
 ZwSetIoCompletion(
    IN HANDLE   IoCompletionPortHandle,
-   IN ULONG    CompletionKey,
-   IN ULONG    CompletionValue,
+   IN PVOID    CompletionKey,
+   IN PVOID    CompletionContext,
    IN NTSTATUS CompletionStatus,
    IN ULONG    CompletionInformation
    );
index 613d92c..1d5ca09 100755 (executable)
@@ -971,7 +971,7 @@ typedef struct _FILE_COMPRESSION_INFORMATION {
 
 typedef struct _FILE_COMPLETION_INFORMATION { // Information Class 30
    HANDLE IoCompletionHandle;
-   ULONG CompletionKey;
+   PVOID CompletionKey;
 } FILE_COMPLETION_INFORMATION, *PFILE_COMPLETION_INFORMATION;
 
 typedef struct _FILE_ALL_INFORMATION {
index e0beced..8b6ec7b 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: iocompl.c,v 1.15 2004/10/30 22:18:17 weiden Exp $
+/* $Id: iocompl.c,v 1.16 2004/11/25 22:18:16 ion Exp $
  *
  * COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         ReactOS system libraries
@@ -23,7 +23,7 @@ STDCALL
 CreateIoCompletionPort(
     HANDLE FileHandle,
     HANDLE ExistingCompletionPort,
-    DWORD CompletionKey,
+    ULONG_PTR CompletionKey,
     DWORD NumberOfConcurrentThreads
     )
 {
@@ -62,7 +62,7 @@ CreateIoCompletionPort(
    {
 #ifdef __USE_W32API
       CompletionInformation.Port = CompletionPort;
-      CompletionInformation.Key  = CompletionKey;
+      CompletionInformation.Key  = (PVOID)CompletionKey;
 #else
       CompletionInformation.IoCompletionHandle = CompletionPort;
       CompletionInformation.CompletionKey  = CompletionKey;
@@ -98,7 +98,7 @@ STDCALL
 GetQueuedCompletionStatus(
    HANDLE CompletionHandle,
    LPDWORD lpNumberOfBytesTransferred,
-   LPDWORD lpCompletionKey,
+   PULONG_PTR lpCompletionKey,
    LPOVERLAPPED *lpOverlapped,
    DWORD dwMilliseconds
    )
@@ -127,8 +127,8 @@ GetQueuedCompletionStatus(
    }
 
    errCode = NtRemoveIoCompletion(CompletionHandle,
-                                  lpCompletionKey,
-                                  lpNumberOfBytesTransferred,
+                                  (PVOID*)lpCompletionKey,
+                                  (PVOID*)lpNumberOfBytesTransferred,
                                   &IoStatus,
                                   &Interval);
 
@@ -166,10 +166,10 @@ PostQueuedCompletionStatus(
    NTSTATUS errCode;
 
    errCode = NtSetIoCompletion(CompletionHandle,  
-                               dwCompletionKey, 
-                               dwNumberOfBytesTransferred,//CompletionValue 
-                               0,                         //IoStatusBlock->Status
-                               (ULONG)lpOverlapped );     //IoStatusBlock->Information
+                               (PVOID)dwCompletionKey, 
+                               (PVOID)lpOverlapped,//CompletionValue 
+                               STATUS_SUCCESS,                         //IoStatusBlock->Status
+                               dwNumberOfBytesTransferred);     //IoStatusBlock->Information
 
    if ( !NT_SUCCESS(errCode) ) 
    {
index 09194da..3235244 100644 (file)
 #include <helpers.h>
 #include <debug.h>
 
+/* Because our headers are f*cked up */
+typedef LARGE_INTEGER TIME;
+#include <ntos/zw.h>
+
 extern HANDLE GlobalHeap;
 extern WSPUPCALLTABLE Upcalls;
 extern LPWPUCOMPLETEOVERLAPPEDREQUEST lpWPUCompleteOverlappedRequest;
 extern LIST_ENTRY SockHelpersListHead;
 extern HANDLE SockEvent;
+extern HANDLE SockAsyncCompletionPort;
+extern BOOLEAN SockAsyncSelectCalled;
 
 typedef enum _SOCKET_STATE {
     SocketOpen,
@@ -74,41 +80,48 @@ typedef struct _SOCK_SHARED_INFO {
     LONG                                               Unknown;
     DWORD                                              SequenceNumber;
     UINT                                               wMsg;
-    LONG                                               Event;
-    LONG                                               DisabledEvents;
+    LONG                                               AsyncEvents;
+    LONG                                               AsyncDisabledEvents;
 } SOCK_SHARED_INFO, *PSOCK_SHARED_INFO;
 
 typedef struct _SOCKET_INFORMATION {
-    ULONG                                              RefCount;
-    SOCKET                                             Handle;
-       SOCK_SHARED_INFO                        SharedData;
-    DWORD                                              HelperEvents;
-    PHELPER_DATA                               HelperData;
-    PVOID                                              HelperContext;
-    PSOCKADDR                                  LocalAddress;
-    PSOCKADDR                                  RemoteAddress;
-    HANDLE                                             TdiAddressHandle;
-    HANDLE                                             TdiConnectionHandle;
-    PVOID                                              AsyncData;
-    HANDLE                                             EventObject;
-    LONG                                               NetworkEvents;
-    CRITICAL_SECTION                   Lock;
-    PVOID                                              SanData;
-       BOOL                                            TrySAN;
-       SOCKADDR                                        WSLocalAddress;
-       SOCKADDR                                        WSRemoteAddress;
+       ULONG RefCount;
+       SOCKET Handle;
+       SOCK_SHARED_INFO SharedData;
+       DWORD HelperEvents;
+       PHELPER_DATA HelperData;
+       PVOID HelperContext;
+       PSOCKADDR LocalAddress;
+       PSOCKADDR RemoteAddress;
+       HANDLE TdiAddressHandle;
+       HANDLE TdiConnectionHandle;
+       PVOID AsyncData;
+       HANDLE EventObject;
+       LONG NetworkEvents;
+       CRITICAL_SECTION Lock;
+       PVOID SanData;
+       BOOL TrySAN;
+       SOCKADDR WSLocalAddress;
+       SOCKADDR WSRemoteAddress;
 } SOCKET_INFORMATION, *PSOCKET_INFORMATION;
 
 
 typedef struct _SOCKET_CONTEXT {
-       SOCK_SHARED_INFO                        SharedData;
-       ULONG                                           SizeOfHelperData;
-       ULONG                                           Padding;
-       SOCKADDR                                        LocalAddress;
-       SOCKADDR                                        RemoteAddress;
+       SOCK_SHARED_INFO SharedData;
+       ULONG SizeOfHelperData;
+       ULONG Padding;
+       SOCKADDR LocalAddress;
+       SOCKADDR RemoteAddress;
        /* Plus Helper Data */
 } SOCKET_CONTEXT, *PSOCKET_CONTEXT;
 
+typedef struct _ASYNC_DATA {
+       PSOCKET_INFORMATION ParentSocket;
+       DWORD SequenceNumber;
+       IO_STATUS_BLOCK IoStatusBlock;
+       AFD_POLL_INFO AsyncSelectInfo;
+} ASYNC_DATA, *PASYNC_DATA;
+
 SOCKET
 WSPAPI
 WSPAccept(
@@ -416,6 +429,39 @@ int SetSocketInformation(
 int CreateContext(
        PSOCKET_INFORMATION Socket
 );
+
+int SockAsyncThread(
+       PVOID ThreadParam
+);
+
+VOID 
+SockProcessAsyncSelect(
+       PSOCKET_INFORMATION Socket,
+       PASYNC_DATA AsyncData
+);
+
+VOID
+SockAsyncSelectCompletionRoutine(
+       PVOID Context,
+       PIO_STATUS_BLOCK IoStatusBlock
+);
+
+BOOLEAN
+SockCreateOrReferenceAsyncThread(
+       VOID
+);
+
+BOOLEAN SockGetAsyncSelectHelperAfdHandle(
+       VOID
+);
+
+VOID SockProcessQueuedAsyncSelect(
+       PVOID Context,
+       PIO_STATUS_BLOCK IoStatusBlock
+);
+
+typedef VOID (*PASYNC_COMPLETION_ROUTINE)(PVOID Context, PIO_STATUS_BLOCK IoStatusBlock);
+
 #endif /* __MSAFD_H */
 
 /* EOF */
index 0f57188..63e1e6d 100644 (file)
 DWORD DebugTraceLevel = 0;
 #endif /* DBG */
 
-HANDLE                                                 GlobalHeap;
-WSPUPCALLTABLE                                 Upcalls;
-LPWPUCOMPLETEOVERLAPPEDREQUEST lpWPUCompleteOverlappedRequest;
-ULONG                                                  SocketCount;
-PSOCKET_INFORMATION                    *Sockets = NULL;
-LIST_ENTRY                                             SockHelpersListHead = {NULL};
+HANDLE GlobalHeap;
+WSPUPCALLTABLE Upcalls;
+LPWPUCOMPLETEOVERLAPPEDREQUEST lpWPUCompleteOverlappedRequest;
+ULONG SocketCount;
+PSOCKET_INFORMATION *Sockets = NULL;
+LIST_ENTRY SockHelpersListHead = {NULL};
+ULONG SockAsyncThreadRefCount;
+HANDLE SockAsyncHelperAfdHandle;
+HANDLE SockAsyncCompletionPort;
+BOOLEAN SockAsyncSelectCalled;
 
 SOCKET 
 WSPAPI 
@@ -456,7 +460,7 @@ WSPSelect(
     
     /* Number of handles for AFD to Check */
     PollInfo->HandleCount = HandleCount;
-    PollInfo->InternalUse = 0;
+    PollInfo->Exclusive = FALSE;
     
     if (readfds != NULL) {
        for (i = 0; i < readfds->fd_count; i++, j++) {
@@ -1291,6 +1295,342 @@ int CreateContext(PSOCKET_INFORMATION Socket)
        return 0;
 }
 
+BOOLEAN SockCreateOrReferenceAsyncThread(VOID)
+{
+       HANDLE hAsyncThread;
+       DWORD AsyncThreadId;
+       HANDLE AsyncEvent;
+       OBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleFlags;
+       NTSTATUS Status;
+
+       /* Check if the Thread Already Exists */
+       if (SockAsyncThreadRefCount) {
+               return TRUE;
+       }
+       
+       /* Create the Completion Port */
+       if (!SockAsyncCompletionPort) {
+               Status = NtCreateIoCompletion(&SockAsyncCompletionPort,
+                                             IO_COMPLETION_ALL_ACCESS,
+                                             NULL,
+                                             2); // Allow 2 threads only
+       
+               /* Protect Handle */    
+               HandleFlags.ProtectFromClose = TRUE;
+               HandleFlags.Inherit = FALSE;
+               Status = NtSetInformationObject(SockAsyncCompletionPort,
+                                               ObjectHandleInformation,
+                                               &HandleFlags,
+                                               sizeof(HandleFlags));
+       }
+    
+       /* Create the Async Event */
+       Status = NtCreateEvent(&AsyncEvent,
+                              EVENT_ALL_ACCESS,
+                              NULL,
+                              NotificationEvent,
+                              FALSE);
+    
+       /* Create the Async Thread */
+       hAsyncThread = CreateThread(NULL,
+                                   0,
+                                   (LPTHREAD_START_ROUTINE)SockAsyncThread,
+                                   NULL,
+                                   0,
+                                   &AsyncThreadId);
+
+       /* Close the Handle */
+       NtClose(hAsyncThread);
+
+       /* Increase the Reference Count */
+       SockAsyncThreadRefCount++;
+       return TRUE;
+}
+
+int SockAsyncThread(PVOID ThreadParam)
+{
+       PVOID AsyncContext;
+       PASYNC_COMPLETION_ROUTINE AsyncCompletionRoutine;
+       IO_STATUS_BLOCK IOSB;
+       NTSTATUS Status;
+       LARGE_INTEGER Timeout;
+                          
+       /* Make the Thread Higher Priority */
+       SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL);
+       
+       /* Do a KQUEUE/WorkItem Style Loop, thanks to IoCompletion Ports */
+       do {
+               Status =  NtRemoveIoCompletion (SockAsyncCompletionPort,
+                                               (PVOID*)&AsyncCompletionRoutine,
+                                               &AsyncContext,
+                                               &IOSB,
+                                               &Timeout);
+                                               
+               /* Call the Async Function */
+               if (NT_SUCCESS(Status)) {
+                       //(*AsyncCompletionRoutine)(AsyncContext, IOSB);
+               } else {
+                       /* It Failed, sleep for a second */
+                       Sleep(1000);
+               }
+       } while ((Status != STATUS_TIMEOUT));
+
+    /* The Thread has Ended */
+    return 0;
+}
+
+BOOLEAN SockGetAsyncSelectHelperAfdHandle(VOID)
+{
+       UNICODE_STRING AfdHelper;
+       OBJECT_ATTRIBUTES ObjectAttributes;
+       IO_STATUS_BLOCK IoSb;
+       NTSTATUS Status;
+       FILE_COMPLETION_INFORMATION CompletionInfo;
+       OBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleFlags;
+
+       /* First, make sure we're not already intialized */
+       if (SockAsyncHelperAfdHandle) {
+               return TRUE;
+       }
+
+       /* Set up Handle Name and Object */
+       RtlInitUnicodeString(&AfdHelper, L"\\Device\\Afd\\AsyncSelectHlp" );
+       InitializeObjectAttributes(&ObjectAttributes,
+                                  &AfdHelper,
+                                  OBJ_INHERIT | OBJ_CASE_INSENSITIVE,
+                                  NULL,
+                                  NULL);
+
+       /* Open the Handle to AFD */
+       Status = NtCreateFile(&SockAsyncHelperAfdHandle,
+                             GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE,
+                             &ObjectAttributes,
+                             &IoSb,
+                             NULL,
+                             0,
+                             FILE_SHARE_READ | FILE_SHARE_WRITE,
+                             FILE_OPEN_IF,
+                             0,
+                             NULL,
+                             0);
+
+       /* 
+        * Now Set up the Completion Port Information 
+        * This means that whenever a Poll is finished, the routine will be executed
+        */
+       CompletionInfo.Port = SockAsyncCompletionPort;
+       CompletionInfo.Key = SockAsyncSelectCompletionRoutine;
+       Status = NtSetInformationFile(SockAsyncHelperAfdHandle,
+                                     &IoSb,
+                                     &CompletionInfo,
+                                     sizeof(CompletionInfo),
+                                     FileCompletionInformation);
+                                     
+                                     
+       /* Protect the Handle */
+       HandleFlags.ProtectFromClose = TRUE;
+       HandleFlags.Inherit = FALSE;
+       Status = NtSetInformationObject(SockAsyncCompletionPort,
+                                       ObjectHandleInformation,
+                                       &HandleFlags,
+                                       sizeof(HandleFlags));
+
+
+       /* Set this variable to true so that Send/Recv/Accept will know wether to renable disabled events */
+       SockAsyncSelectCalled = TRUE;
+       return TRUE;
+}
+
+VOID SockAsyncSelectCompletionRoutine(PVOID Context, PIO_STATUS_BLOCK IoStatusBlock)
+{
+
+       PASYNC_DATA AsyncData = Context;
+       PSOCKET_INFORMATION Socket;
+       ULONG x;
+    
+       /* Get the Socket */
+       Socket = AsyncData->ParentSocket;
+       
+       /* Check if the Sequence  Number Changed behind our back */
+       if (AsyncData->SequenceNumber != Socket->SharedData.SequenceNumber ){
+               return;
+       }
+
+       /* Check we were manually called b/c of a failure */
+       if (!NT_SUCCESS(IoStatusBlock->Status)) {
+               /* FIXME: Perform Upcall */
+               return;
+       }
+
+
+       for (x = 1; x; x<<=1) {
+               switch (AsyncData->AsyncSelectInfo.Handles[0].Events & x) {
+                       case AFD_EVENT_RECEIVE:
+                               if ((Socket->SharedData.AsyncEvents & FD_READ) && (!Socket->SharedData.AsyncDisabledEvents & FD_READ)) {
+                                       /* Make the Notifcation */
+                                       (Upcalls.lpWPUPostMessage)(Socket->SharedData.hWnd,
+                                                                  Socket->SharedData.wMsg,
+                                                                  Socket->Handle,
+                                                                  WSAMAKESELECTREPLY(FD_READ, 0));
+                                       /* Disable this event until the next read(); */
+                                       Socket->SharedData.AsyncDisabledEvents |= FD_READ;
+                               }
+                       
+                       case AFD_EVENT_OOB_RECEIVE:
+                               if ((Socket->SharedData.AsyncEvents & FD_OOB) && (!Socket->SharedData.AsyncDisabledEvents & FD_OOB)) {
+                                       /* Make the Notifcation */
+                                       (Upcalls.lpWPUPostMessage)(Socket->SharedData.hWnd,
+                                                                  Socket->SharedData.wMsg,
+                                                                  Socket->Handle,
+                                                                  WSAMAKESELECTREPLY(FD_OOB, 0));
+                                       /* Disable this event until the next read(); */
+                                       Socket->SharedData.AsyncDisabledEvents |= FD_OOB;
+                               }
+               
+                       case AFD_EVENT_SEND:
+                               if ((Socket->SharedData.AsyncEvents & FD_WRITE) && (!Socket->SharedData.AsyncDisabledEvents & FD_WRITE)) {
+                                       /* Make the Notifcation */
+                                       (Upcalls.lpWPUPostMessage)(Socket->SharedData.hWnd,
+                                                                  Socket->SharedData.wMsg,
+                                                                  Socket->Handle,
+                                                                  WSAMAKESELECTREPLY(FD_WRITE, 0));
+                                       /* Disable this event until the next write(); */
+                                       Socket->SharedData.AsyncDisabledEvents |= FD_WRITE;
+                               }
+                               
+                       case AFD_EVENT_ACCEPT:
+                               if ((Socket->SharedData.AsyncEvents & FD_ACCEPT) && (!Socket->SharedData.AsyncDisabledEvents & FD_ACCEPT)) {
+                                       /* Make the Notifcation */
+                                       (Upcalls.lpWPUPostMessage)(Socket->SharedData.hWnd,
+                                                                  Socket->SharedData.wMsg,
+                                                                  Socket->Handle,
+                                                                  WSAMAKESELECTREPLY(FD_ACCEPT, 0));
+                                       /* Disable this event until the next accept(); */
+                                       Socket->SharedData.AsyncDisabledEvents |= FD_ACCEPT;
+                               }
+
+                       case AFD_EVENT_DISCONNECT:
+                       case AFD_EVENT_ABORT:
+                       case AFD_EVENT_CLOSE:
+                               if ((Socket->SharedData.AsyncEvents & FD_CLOSE) && (!Socket->SharedData.AsyncDisabledEvents & FD_CLOSE)) {
+                                       /* Make the Notifcation */
+                                       (Upcalls.lpWPUPostMessage)(Socket->SharedData.hWnd,
+                                                                  Socket->SharedData.wMsg,
+                                                                  Socket->Handle,
+                                                                  WSAMAKESELECTREPLY(FD_CLOSE, 0));
+                                       /* Disable this event forever; */
+                                       Socket->SharedData.AsyncDisabledEvents |= FD_CLOSE;
+                               }
+
+                       /* FIXME: Support QOS */
+               }
+       }
+       
+       /* Check if there are any events left for us to check */
+       if ((Socket->SharedData.AsyncEvents & (~Socket->SharedData.AsyncDisabledEvents)) == 0 ) {
+               return;
+       }
+
+       /* Keep Polling */
+       SockProcessAsyncSelect(Socket, AsyncData);
+       return;
+}
+
+VOID SockProcessAsyncSelect(PSOCKET_INFORMATION Socket, PASYNC_DATA AsyncData)
+{
+
+       ULONG lNetworkEvents;
+       NTSTATUS Status;
+
+       /* Set up the Async Data Event Info */
+       AsyncData->AsyncSelectInfo.Timeout.HighPart = 0x7FFFFFFF;
+       AsyncData->AsyncSelectInfo.Timeout.LowPart = 0xFFFFFFFF;
+       AsyncData->AsyncSelectInfo.HandleCount = 1;
+       AsyncData->AsyncSelectInfo.Exclusive = TRUE;
+       AsyncData->AsyncSelectInfo.Handles[0].Handle = Socket->Handle;
+       AsyncData->AsyncSelectInfo.Handles[0].Events = 0;
+
+       /* Remove unwanted events */
+       lNetworkEvents = Socket->SharedData.AsyncEvents & (~Socket->SharedData.AsyncDisabledEvents);
+
+       /* Set Events to wait for */
+       if (lNetworkEvents & FD_READ) {
+               AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_RECEIVE;
+       }
+
+       if (lNetworkEvents & FD_WRITE) {
+               AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_SEND;
+       }
+
+       if (lNetworkEvents & FD_OOB) {
+               AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_OOB_RECEIVE;
+       }
+
+       if (lNetworkEvents & FD_ACCEPT) {
+               AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_ACCEPT;
+       }
+
+       if (lNetworkEvents & FD_CONNECT) {
+               AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_CONNECT | AFD_EVENT_CONNECT_FAIL;
+       }
+
+       if (lNetworkEvents & FD_CLOSE) {
+               AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_DISCONNECT | AFD_EVENT_ABORT;
+       }
+
+       if (lNetworkEvents & FD_QOS) {
+               AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_QOS;
+       }
+
+       if (lNetworkEvents & FD_GROUP_QOS) {
+               AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_GROUP_QOS;
+       }
+       
+       /* Send IOCTL */
+       Status = NtDeviceIoControlFile (SockAsyncHelperAfdHandle,
+                                       NULL,
+                                       NULL,
+                                       AsyncData,
+                                       &AsyncData->IoStatusBlock,
+                                       IOCTL_AFD_SELECT,
+                                       &AsyncData->AsyncSelectInfo,
+                                       sizeof(AsyncData->AsyncSelectInfo),
+                                       &AsyncData->AsyncSelectInfo,
+                                       sizeof(AsyncData->AsyncSelectInfo));
+
+       /* I/O Manager Won't call the completion routine, let's do it manually */
+       if (NT_SUCCESS(Status)) {
+               return;
+       } else {
+               AsyncData->IoStatusBlock.Status = Status;
+               SockAsyncSelectCompletionRoutine(AsyncData, &AsyncData->IoStatusBlock);
+       }
+}
+
+VOID SockProcessQueuedAsyncSelect(PVOID Context, PIO_STATUS_BLOCK IoStatusBlock)
+{
+       PASYNC_DATA AsyncData = Context;
+       PSOCKET_INFORMATION Socket;
+
+       /* Get the Socket */    
+       Socket = AsyncData->ParentSocket;
+
+       /* If someone closed it, stop the function */
+       if (Socket->SharedData.State != SocketClosed) {
+               /* Check if the Sequence Number changed by now, in which case quit */
+               if (AsyncData->SequenceNumber == Socket->SharedData.SequenceNumber) {
+                       /* Do the actuall select, if needed */
+                       if ((Socket->SharedData.AsyncEvents & (~Socket->SharedData.AsyncDisabledEvents))) {
+                               SockProcessAsyncSelect(Socket, AsyncData);
+                       }
+               }
+       }
+       
+       /* Free the Context */
+       HeapFree(GetProcessHeap(), 0, AsyncData);
+       return;
+}
+
 BOOL
 STDCALL
 DllMain(HANDLE hInstDll,
index 8c23e60..4de981e 100644 (file)
@@ -42,7 +42,10 @@ WSPEventSelect(
 
        /* Deactivate Async Select if there is one */
        if (Socket->EventObject) {
-               //SockAsyncSelect(Socket, NULL, 0, 0);
+               Socket->SharedData.hWnd = NULL;
+               Socket->SharedData.wMsg = 0;
+               Socket->SharedData.AsyncEvents = 0;
+               Socket->SharedData.SequenceNumber++; // This will kill Async Select after the next completion
        }
 
        /* Set Structure Info */
index d92a882..85c1440 100644 (file)
 INT
 WSPAPI
 WSPAsyncSelect(
-    IN  SOCKET s
+    IN  SOCKET Handle
     IN  HWND hWnd, 
     IN  UINT wMsg, 
     IN  LONG lEvent, 
     OUT LPINT lpErrno)
 {
-  UNIMPLEMENTED
+       PSOCKET_INFORMATION Socket = NULL;
+       PASYNC_DATA AsyncData;
+       NTSTATUS Status;
+       ULONG BlockMode;
 
-  return 0;
+       /* Get the Socket Structure associated to this Socket */
+       Socket = GetSocketStructure(Handle);
+
+       /* Allocate the Async Data Structure to pass on to the Thread later */
+       HeapAlloc(GetProcessHeap(), 0, sizeof(*AsyncData));
+
+       /* Change the Socket to Non Blocking */
+       BlockMode = 1;
+       SetSocketInformation(Socket, AFD_INFO_BLOCKING_MODE, &BlockMode, NULL);
+       Socket->SharedData.NonBlocking = TRUE;
+
+       /* Deactive WSPEventSelect */
+       if (Socket->SharedData.AsyncEvents) {
+               WSPEventSelect(Handle, NULL, 0, NULL);
+       }
+
+       /* Create the Asynch Thread if Needed */  
+       SockCreateOrReferenceAsyncThread();
+       
+       /* Open a Handle to AFD's Async Helper */
+       SockGetAsyncSelectHelperAfdHandle();
+
+       /* Store Socket Data */
+       Socket->SharedData.hWnd = hWnd;
+       Socket->SharedData.wMsg = wMsg;
+       Socket->SharedData.AsyncEvents = lEvent;
+       Socket->SharedData.AsyncDisabledEvents = 0;
+       Socket->SharedData.SequenceNumber++;
+
+        /* Return if there are no more Events */
+       if ((Socket->SharedData.AsyncEvents & (~Socket->SharedData.AsyncDisabledEvents)) == 0) {
+               HeapFree(GetProcessHeap(), 0, AsyncData);
+               return 0;
+       }
+
+       /* Set up the Async Data */
+       AsyncData->ParentSocket = Socket;
+       AsyncData->SequenceNumber = Socket->SharedData.SequenceNumber;
+
+       /* Begin Async Select by using I/O Completion */
+       Status = NtSetIoCompletion(SockAsyncCompletionPort,
+                                 (PVOID)&SockProcessQueuedAsyncSelect,
+                                 AsyncData,
+                                 0,
+                                 0);
+
+       /* Return */
+       return 0;
 }
 
 
index 4e369d9..f19dbed 100644 (file)
@@ -16,7 +16,7 @@
  *  along with this program; if not, write to the Free Software
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
-/* $Id: io.h,v 1.49 2004/11/19 21:31:02 navaraf Exp $
+/* $Id: io.h,v 1.50 2004/11/25 22:18:16 ion Exp $
  *
  * COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         ReactOS kernel
@@ -43,8 +43,8 @@
 
 
 typedef struct _IO_COMPLETION_PACKET{
-   ULONG             Key;
-   ULONG             Overlapped;
+   PVOID             Key;
+   PVOID             Context;
    IO_STATUS_BLOCK   IoStatus;
    LIST_ENTRY        ListEntry;
 } IO_COMPLETION_PACKET, *PIO_COMPLETION_PACKET;
index 7a1369b..4bf5ade 100644 (file)
@@ -271,8 +271,8 @@ NTSTATUS
 STDCALL
 NtRemoveIoCompletion(
    IN  HANDLE           IoCompletionHandle,
-   OUT PULONG           CompletionKey,
-   OUT PULONG           CompletionValue,
+   OUT PVOID            *CompletionKey,
+   OUT PVOID            *CompletionContext,
    OUT PIO_STATUS_BLOCK IoStatusBlock,
    IN  PLARGE_INTEGER   Timeout OPTIONAL
    )
@@ -302,7 +302,7 @@ NtRemoveIoCompletion(
       Packet = CONTAINING_RECORD(ListEntry, IO_COMPLETION_PACKET, ListEntry);
 
       if (CompletionKey) *CompletionKey = Packet->Key;
-      if (CompletionValue) *CompletionValue = Packet->Overlapped;
+      if (CompletionContext) *CompletionContext = Packet->Context;
       if (IoStatusBlock) *IoStatusBlock = Packet->IoStatus;
 
       ExFreeToNPagedLookasideList(&IoCompletionPacketLookaside, Packet);
@@ -330,8 +330,8 @@ NTSTATUS
 STDCALL
 NtSetIoCompletion(
    IN HANDLE   IoCompletionPortHandle,
-   IN ULONG    CompletionKey,
-   IN ULONG    CompletionValue,
+   IN PVOID    CompletionKey,
+   IN PVOID    CompletionContext,
    IN NTSTATUS CompletionStatus,
    IN ULONG    CompletionInformation
    )
@@ -352,7 +352,7 @@ NtSetIoCompletion(
       Packet = ExAllocateFromNPagedLookasideList(&IoCompletionPacketLookaside);
 
       Packet->Key = CompletionKey;
-      Packet->Overlapped = CompletionValue;
+      Packet->Context = CompletionContext;
       Packet->IoStatus.Status = CompletionStatus;
       Packet->IoStatus.Information = CompletionInformation;
    
index 4d34c30..4d80878 100644 (file)
@@ -86,7 +86,7 @@
 #include <ntoskrnl.h>
 #define NDEBUG
 #include <internal/debug.h>
-
+#include <internal/ps.h>
 
 /************************************************************************/
 /* BUFMAX defines the maximum number of characters in inbound/outbound buffers*/
index 669ccbf..d171d8f 100644 (file)
@@ -873,7 +873,7 @@ typedef struct _FILE_BOTH_DIR_INFORMATION {
 
 typedef struct _FILE_COMPLETION_INFORMATION {
     HANDLE  Port;
-    ULONG   Key;
+    PVOID   Key;
 } FILE_COMPLETION_INFORMATION, *PFILE_COMPLETION_INFORMATION;
 
 typedef struct _FILE_COMPRESSION_INFORMATION {