From: Alex Ionescu Date: Thu, 25 Nov 2004 22:18:17 +0000 (+0000) Subject: Fix IO completion APIs/Structures. X-Git-Tag: backups/ELF_support@12700~11^2~172 X-Git-Url: https://git.reactos.org/?p=reactos.git;a=commitdiff_plain;h=1623a0079f0c018da8385c24b6eb25ee2999a20e;hp=3379855217e8168cd3a6977234a6ff54f1789335 Fix IO completion APIs/Structures. Implement WSPASyncSelect and friends. Event re-enabling functionality missing and will be added tonight. svn path=/trunk/; revision=11807 --- diff --git a/reactos/include/afd/shared.h b/reactos/include/afd/shared.h index 4fdef6ce377..248a756b948 100644 --- a/reactos/include/afd/shared.h +++ b/reactos/include/afd/shared.h @@ -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 { diff --git a/reactos/include/ddk/iotypes.h b/reactos/include/ddk/iotypes.h index a6f4698540e..f04399375c9 100644 --- a/reactos/include/ddk/iotypes.h +++ b/reactos/include/ddk/iotypes.h @@ -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 diff --git a/reactos/include/ntos/zw.h b/reactos/include/ntos/zw.h index 81495797148..7bd45996930 100755 --- a/reactos/include/ntos/zw.h +++ b/reactos/include/ntos/zw.h @@ -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 ); diff --git a/reactos/include/ntos/zwtypes.h b/reactos/include/ntos/zwtypes.h index 613d92c3dca..1d5ca09b6bb 100755 --- a/reactos/include/ntos/zwtypes.h +++ b/reactos/include/ntos/zwtypes.h @@ -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 { diff --git a/reactos/lib/kernel32/file/iocompl.c b/reactos/lib/kernel32/file/iocompl.c index e0beced14b7..8b6ec7bc17e 100644 --- a/reactos/lib/kernel32/file/iocompl.c +++ b/reactos/lib/kernel32/file/iocompl.c @@ -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) ) { diff --git a/reactos/lib/msafd/include/msafd.h b/reactos/lib/msafd/include/msafd.h index 09194dab008..3235244cda2 100644 --- a/reactos/lib/msafd/include/msafd.h +++ b/reactos/lib/msafd/include/msafd.h @@ -22,11 +22,17 @@ #include #include +/* Because our headers are f*cked up */ +typedef LARGE_INTEGER TIME; +#include + 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 */ diff --git a/reactos/lib/msafd/misc/dllmain.c b/reactos/lib/msafd/misc/dllmain.c index 0f571883bd2..63e1e6d5df8 100644 --- a/reactos/lib/msafd/misc/dllmain.c +++ b/reactos/lib/msafd/misc/dllmain.c @@ -20,12 +20,16 @@ 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, diff --git a/reactos/lib/msafd/misc/event.c b/reactos/lib/msafd/misc/event.c index 8c23e605a17..4de981e9370 100644 --- a/reactos/lib/msafd/misc/event.c +++ b/reactos/lib/msafd/misc/event.c @@ -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 */ diff --git a/reactos/lib/msafd/misc/sndrcv.c b/reactos/lib/msafd/misc/sndrcv.c index d92a882f312..85c14408e95 100644 --- a/reactos/lib/msafd/misc/sndrcv.c +++ b/reactos/lib/msafd/misc/sndrcv.c @@ -15,15 +15,65 @@ 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; } diff --git a/reactos/ntoskrnl/include/internal/io.h b/reactos/ntoskrnl/include/internal/io.h index 4e369d99ab2..f19dbedf65d 100644 --- a/reactos/ntoskrnl/include/internal/io.h +++ b/reactos/ntoskrnl/include/internal/io.h @@ -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; diff --git a/reactos/ntoskrnl/io/iocomp.c b/reactos/ntoskrnl/io/iocomp.c index 7a1369b4522..4bf5adeb1fc 100644 --- a/reactos/ntoskrnl/io/iocomp.c +++ b/reactos/ntoskrnl/io/iocomp.c @@ -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; diff --git a/reactos/ntoskrnl/kd/gdbstub.c b/reactos/ntoskrnl/kd/gdbstub.c index 4d34c30c3f8..4d808784d16 100644 --- a/reactos/ntoskrnl/kd/gdbstub.c +++ b/reactos/ntoskrnl/kd/gdbstub.c @@ -86,7 +86,7 @@ #include #define NDEBUG #include - +#include /************************************************************************/ /* BUFMAX defines the maximum number of characters in inbound/outbound buffers*/ diff --git a/reactos/w32api/include/ddk/ntifs.h b/reactos/w32api/include/ddk/ntifs.h index 669ccbfd64f..d171d8f610d 100644 --- a/reactos/w32api/include/ddk/ntifs.h +++ b/reactos/w32api/include/ddk/ntifs.h @@ -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 {