Fix IO completion APIs/Structures.

Implement WSPASyncSelect and friends. Event re-enabling functionality missing and will be added tonight.

svn path=/trunk/; revision=11807
This commit is contained in:
Alex Ionescu 2004-11-25 22:18:17 +00:00
parent 3379855217
commit 1623a0079f
13 changed files with 512 additions and 73 deletions

View file

@ -52,10 +52,10 @@ typedef struct _AFD_HANDLE_ {
} AFD_HANDLE, *PAFD_HANDLE; } AFD_HANDLE, *PAFD_HANDLE;
typedef struct _AFD_POLL_INFO { typedef struct _AFD_POLL_INFO {
LARGE_INTEGER Timeout; LARGE_INTEGER Timeout;
ULONG HandleCount; ULONG HandleCount;
PAFD_HANDLE InternalUse; BOOLEAN Exclusive;
AFD_HANDLE Handles[1]; AFD_HANDLE Handles[1];
} AFD_POLL_INFO, *PAFD_POLL_INFO; } AFD_POLL_INFO, *PAFD_POLL_INFO;
typedef struct _AFD_ACCEPT_DATA { typedef struct _AFD_ACCEPT_DATA {

View 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 typedef struct _IO_COMPLETION_CONTEXT
{ {
PVOID Port; PVOID Port;
ULONG Key; PVOID Key;
} IO_COMPLETION_CONTEXT, *PIO_COMPLETION_CONTEXT; } IO_COMPLETION_CONTEXT, *PIO_COMPLETION_CONTEXT;
#define FO_FILE_OPEN 0x00000001 #define FO_FILE_OPEN 0x00000001

View file

@ -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 * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
@ -3567,8 +3567,8 @@ NTSTATUS
STDCALL STDCALL
NtRemoveIoCompletion( NtRemoveIoCompletion(
IN HANDLE IoCompletionHandle, IN HANDLE IoCompletionHandle,
OUT PULONG CompletionKey, OUT PVOID *CompletionKey,
OUT PULONG CompletionValue, OUT PVOID *CompletionContext,
OUT PIO_STATUS_BLOCK IoStatusBlock, OUT PIO_STATUS_BLOCK IoStatusBlock,
IN PLARGE_INTEGER Timeout OPTIONAL IN PLARGE_INTEGER Timeout OPTIONAL
); );
@ -3577,8 +3577,8 @@ NTSTATUS
STDCALL STDCALL
ZwRemoveIoCompletion( ZwRemoveIoCompletion(
IN HANDLE IoCompletionHandle, IN HANDLE IoCompletionHandle,
OUT PULONG CompletionKey, OUT PVOID *CompletionKey,
OUT PULONG CompletionValue, OUT PVOID *CompletionValue,
OUT PIO_STATUS_BLOCK IoStatusBlock, OUT PIO_STATUS_BLOCK IoStatusBlock,
IN PLARGE_INTEGER Timeout OPTIONAL IN PLARGE_INTEGER Timeout OPTIONAL
); );
@ -4094,8 +4094,8 @@ NTSTATUS
STDCALL STDCALL
NtSetIoCompletion( NtSetIoCompletion(
IN HANDLE IoCompletionPortHandle, IN HANDLE IoCompletionPortHandle,
IN ULONG CompletionKey, IN PVOID CompletionKey,
IN ULONG CompletionValue, IN PVOID CompletionContext,
IN NTSTATUS CompletionStatus, IN NTSTATUS CompletionStatus,
IN ULONG CompletionInformation IN ULONG CompletionInformation
); );
@ -4104,8 +4104,8 @@ NTSTATUS
STDCALL STDCALL
ZwSetIoCompletion( ZwSetIoCompletion(
IN HANDLE IoCompletionPortHandle, IN HANDLE IoCompletionPortHandle,
IN ULONG CompletionKey, IN PVOID CompletionKey,
IN ULONG CompletionValue, IN PVOID CompletionContext,
IN NTSTATUS CompletionStatus, IN NTSTATUS CompletionStatus,
IN ULONG CompletionInformation IN ULONG CompletionInformation
); );

View file

@ -971,7 +971,7 @@ typedef struct _FILE_COMPRESSION_INFORMATION {
typedef struct _FILE_COMPLETION_INFORMATION { // Information Class 30 typedef struct _FILE_COMPLETION_INFORMATION { // Information Class 30
HANDLE IoCompletionHandle; HANDLE IoCompletionHandle;
ULONG CompletionKey; PVOID CompletionKey;
} FILE_COMPLETION_INFORMATION, *PFILE_COMPLETION_INFORMATION; } FILE_COMPLETION_INFORMATION, *PFILE_COMPLETION_INFORMATION;
typedef struct _FILE_ALL_INFORMATION { typedef struct _FILE_ALL_INFORMATION {

View 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 * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS system libraries * PROJECT: ReactOS system libraries
@ -23,7 +23,7 @@ STDCALL
CreateIoCompletionPort( CreateIoCompletionPort(
HANDLE FileHandle, HANDLE FileHandle,
HANDLE ExistingCompletionPort, HANDLE ExistingCompletionPort,
DWORD CompletionKey, ULONG_PTR CompletionKey,
DWORD NumberOfConcurrentThreads DWORD NumberOfConcurrentThreads
) )
{ {
@ -62,7 +62,7 @@ CreateIoCompletionPort(
{ {
#ifdef __USE_W32API #ifdef __USE_W32API
CompletionInformation.Port = CompletionPort; CompletionInformation.Port = CompletionPort;
CompletionInformation.Key = CompletionKey; CompletionInformation.Key = (PVOID)CompletionKey;
#else #else
CompletionInformation.IoCompletionHandle = CompletionPort; CompletionInformation.IoCompletionHandle = CompletionPort;
CompletionInformation.CompletionKey = CompletionKey; CompletionInformation.CompletionKey = CompletionKey;
@ -98,7 +98,7 @@ STDCALL
GetQueuedCompletionStatus( GetQueuedCompletionStatus(
HANDLE CompletionHandle, HANDLE CompletionHandle,
LPDWORD lpNumberOfBytesTransferred, LPDWORD lpNumberOfBytesTransferred,
LPDWORD lpCompletionKey, PULONG_PTR lpCompletionKey,
LPOVERLAPPED *lpOverlapped, LPOVERLAPPED *lpOverlapped,
DWORD dwMilliseconds DWORD dwMilliseconds
) )
@ -127,8 +127,8 @@ GetQueuedCompletionStatus(
} }
errCode = NtRemoveIoCompletion(CompletionHandle, errCode = NtRemoveIoCompletion(CompletionHandle,
lpCompletionKey, (PVOID*)lpCompletionKey,
lpNumberOfBytesTransferred, (PVOID*)lpNumberOfBytesTransferred,
&IoStatus, &IoStatus,
&Interval); &Interval);
@ -166,10 +166,10 @@ PostQueuedCompletionStatus(
NTSTATUS errCode; NTSTATUS errCode;
errCode = NtSetIoCompletion(CompletionHandle, errCode = NtSetIoCompletion(CompletionHandle,
dwCompletionKey, (PVOID)dwCompletionKey,
dwNumberOfBytesTransferred,//CompletionValue (PVOID)lpOverlapped,//CompletionValue
0, //IoStatusBlock->Status STATUS_SUCCESS, //IoStatusBlock->Status
(ULONG)lpOverlapped ); //IoStatusBlock->Information dwNumberOfBytesTransferred); //IoStatusBlock->Information
if ( !NT_SUCCESS(errCode) ) if ( !NT_SUCCESS(errCode) )
{ {

View file

@ -22,11 +22,17 @@
#include <helpers.h> #include <helpers.h>
#include <debug.h> #include <debug.h>
/* Because our headers are f*cked up */
typedef LARGE_INTEGER TIME;
#include <ntos/zw.h>
extern HANDLE GlobalHeap; extern HANDLE GlobalHeap;
extern WSPUPCALLTABLE Upcalls; extern WSPUPCALLTABLE Upcalls;
extern LPWPUCOMPLETEOVERLAPPEDREQUEST lpWPUCompleteOverlappedRequest; extern LPWPUCOMPLETEOVERLAPPEDREQUEST lpWPUCompleteOverlappedRequest;
extern LIST_ENTRY SockHelpersListHead; extern LIST_ENTRY SockHelpersListHead;
extern HANDLE SockEvent; extern HANDLE SockEvent;
extern HANDLE SockAsyncCompletionPort;
extern BOOLEAN SockAsyncSelectCalled;
typedef enum _SOCKET_STATE { typedef enum _SOCKET_STATE {
SocketOpen, SocketOpen,
@ -74,41 +80,48 @@ typedef struct _SOCK_SHARED_INFO {
LONG Unknown; LONG Unknown;
DWORD SequenceNumber; DWORD SequenceNumber;
UINT wMsg; UINT wMsg;
LONG Event; LONG AsyncEvents;
LONG DisabledEvents; LONG AsyncDisabledEvents;
} SOCK_SHARED_INFO, *PSOCK_SHARED_INFO; } SOCK_SHARED_INFO, *PSOCK_SHARED_INFO;
typedef struct _SOCKET_INFORMATION { typedef struct _SOCKET_INFORMATION {
ULONG RefCount; ULONG RefCount;
SOCKET Handle; SOCKET Handle;
SOCK_SHARED_INFO SharedData; SOCK_SHARED_INFO SharedData;
DWORD HelperEvents; DWORD HelperEvents;
PHELPER_DATA HelperData; PHELPER_DATA HelperData;
PVOID HelperContext; PVOID HelperContext;
PSOCKADDR LocalAddress; PSOCKADDR LocalAddress;
PSOCKADDR RemoteAddress; PSOCKADDR RemoteAddress;
HANDLE TdiAddressHandle; HANDLE TdiAddressHandle;
HANDLE TdiConnectionHandle; HANDLE TdiConnectionHandle;
PVOID AsyncData; PVOID AsyncData;
HANDLE EventObject; HANDLE EventObject;
LONG NetworkEvents; LONG NetworkEvents;
CRITICAL_SECTION Lock; CRITICAL_SECTION Lock;
PVOID SanData; PVOID SanData;
BOOL TrySAN; BOOL TrySAN;
SOCKADDR WSLocalAddress; SOCKADDR WSLocalAddress;
SOCKADDR WSRemoteAddress; SOCKADDR WSRemoteAddress;
} SOCKET_INFORMATION, *PSOCKET_INFORMATION; } SOCKET_INFORMATION, *PSOCKET_INFORMATION;
typedef struct _SOCKET_CONTEXT { typedef struct _SOCKET_CONTEXT {
SOCK_SHARED_INFO SharedData; SOCK_SHARED_INFO SharedData;
ULONG SizeOfHelperData; ULONG SizeOfHelperData;
ULONG Padding; ULONG Padding;
SOCKADDR LocalAddress; SOCKADDR LocalAddress;
SOCKADDR RemoteAddress; SOCKADDR RemoteAddress;
/* Plus Helper Data */ /* Plus Helper Data */
} SOCKET_CONTEXT, *PSOCKET_CONTEXT; } 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 SOCKET
WSPAPI WSPAPI
WSPAccept( WSPAccept(
@ -416,6 +429,39 @@ int SetSocketInformation(
int CreateContext( int CreateContext(
PSOCKET_INFORMATION Socket 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 */ #endif /* __MSAFD_H */
/* EOF */ /* EOF */

View file

@ -20,12 +20,16 @@
DWORD DebugTraceLevel = 0; DWORD DebugTraceLevel = 0;
#endif /* DBG */ #endif /* DBG */
HANDLE GlobalHeap; HANDLE GlobalHeap;
WSPUPCALLTABLE Upcalls; WSPUPCALLTABLE Upcalls;
LPWPUCOMPLETEOVERLAPPEDREQUEST lpWPUCompleteOverlappedRequest; LPWPUCOMPLETEOVERLAPPEDREQUEST lpWPUCompleteOverlappedRequest;
ULONG SocketCount; ULONG SocketCount;
PSOCKET_INFORMATION *Sockets = NULL; PSOCKET_INFORMATION *Sockets = NULL;
LIST_ENTRY SockHelpersListHead = {NULL}; LIST_ENTRY SockHelpersListHead = {NULL};
ULONG SockAsyncThreadRefCount;
HANDLE SockAsyncHelperAfdHandle;
HANDLE SockAsyncCompletionPort;
BOOLEAN SockAsyncSelectCalled;
SOCKET SOCKET
WSPAPI WSPAPI
@ -456,7 +460,7 @@ WSPSelect(
/* Number of handles for AFD to Check */ /* Number of handles for AFD to Check */
PollInfo->HandleCount = HandleCount; PollInfo->HandleCount = HandleCount;
PollInfo->InternalUse = 0; PollInfo->Exclusive = FALSE;
if (readfds != NULL) { if (readfds != NULL) {
for (i = 0; i < readfds->fd_count; i++, j++) { for (i = 0; i < readfds->fd_count; i++, j++) {
@ -1291,6 +1295,342 @@ int CreateContext(PSOCKET_INFORMATION Socket)
return 0; 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 BOOL
STDCALL STDCALL
DllMain(HANDLE hInstDll, DllMain(HANDLE hInstDll,

View file

@ -42,7 +42,10 @@ WSPEventSelect(
/* Deactivate Async Select if there is one */ /* Deactivate Async Select if there is one */
if (Socket->EventObject) { 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 */ /* Set Structure Info */

View file

@ -15,15 +15,65 @@
INT INT
WSPAPI WSPAPI
WSPAsyncSelect( WSPAsyncSelect(
IN SOCKET s, IN SOCKET Handle,
IN HWND hWnd, IN HWND hWnd,
IN UINT wMsg, IN UINT wMsg,
IN LONG lEvent, IN LONG lEvent,
OUT LPINT lpErrno) 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;
} }

View file

@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * 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 * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
@ -43,8 +43,8 @@
typedef struct _IO_COMPLETION_PACKET{ typedef struct _IO_COMPLETION_PACKET{
ULONG Key; PVOID Key;
ULONG Overlapped; PVOID Context;
IO_STATUS_BLOCK IoStatus; IO_STATUS_BLOCK IoStatus;
LIST_ENTRY ListEntry; LIST_ENTRY ListEntry;
} IO_COMPLETION_PACKET, *PIO_COMPLETION_PACKET; } IO_COMPLETION_PACKET, *PIO_COMPLETION_PACKET;

View file

@ -271,8 +271,8 @@ NTSTATUS
STDCALL STDCALL
NtRemoveIoCompletion( NtRemoveIoCompletion(
IN HANDLE IoCompletionHandle, IN HANDLE IoCompletionHandle,
OUT PULONG CompletionKey, OUT PVOID *CompletionKey,
OUT PULONG CompletionValue, OUT PVOID *CompletionContext,
OUT PIO_STATUS_BLOCK IoStatusBlock, OUT PIO_STATUS_BLOCK IoStatusBlock,
IN PLARGE_INTEGER Timeout OPTIONAL IN PLARGE_INTEGER Timeout OPTIONAL
) )
@ -302,7 +302,7 @@ NtRemoveIoCompletion(
Packet = CONTAINING_RECORD(ListEntry, IO_COMPLETION_PACKET, ListEntry); Packet = CONTAINING_RECORD(ListEntry, IO_COMPLETION_PACKET, ListEntry);
if (CompletionKey) *CompletionKey = Packet->Key; if (CompletionKey) *CompletionKey = Packet->Key;
if (CompletionValue) *CompletionValue = Packet->Overlapped; if (CompletionContext) *CompletionContext = Packet->Context;
if (IoStatusBlock) *IoStatusBlock = Packet->IoStatus; if (IoStatusBlock) *IoStatusBlock = Packet->IoStatus;
ExFreeToNPagedLookasideList(&IoCompletionPacketLookaside, Packet); ExFreeToNPagedLookasideList(&IoCompletionPacketLookaside, Packet);
@ -330,8 +330,8 @@ NTSTATUS
STDCALL STDCALL
NtSetIoCompletion( NtSetIoCompletion(
IN HANDLE IoCompletionPortHandle, IN HANDLE IoCompletionPortHandle,
IN ULONG CompletionKey, IN PVOID CompletionKey,
IN ULONG CompletionValue, IN PVOID CompletionContext,
IN NTSTATUS CompletionStatus, IN NTSTATUS CompletionStatus,
IN ULONG CompletionInformation IN ULONG CompletionInformation
) )
@ -352,7 +352,7 @@ NtSetIoCompletion(
Packet = ExAllocateFromNPagedLookasideList(&IoCompletionPacketLookaside); Packet = ExAllocateFromNPagedLookasideList(&IoCompletionPacketLookaside);
Packet->Key = CompletionKey; Packet->Key = CompletionKey;
Packet->Overlapped = CompletionValue; Packet->Context = CompletionContext;
Packet->IoStatus.Status = CompletionStatus; Packet->IoStatus.Status = CompletionStatus;
Packet->IoStatus.Information = CompletionInformation; Packet->IoStatus.Information = CompletionInformation;

View file

@ -86,7 +86,7 @@
#include <ntoskrnl.h> #include <ntoskrnl.h>
#define NDEBUG #define NDEBUG
#include <internal/debug.h> #include <internal/debug.h>
#include <internal/ps.h>
/************************************************************************/ /************************************************************************/
/* BUFMAX defines the maximum number of characters in inbound/outbound buffers*/ /* BUFMAX defines the maximum number of characters in inbound/outbound buffers*/

View file

@ -873,7 +873,7 @@ typedef struct _FILE_BOTH_DIR_INFORMATION {
typedef struct _FILE_COMPLETION_INFORMATION { typedef struct _FILE_COMPLETION_INFORMATION {
HANDLE Port; HANDLE Port;
ULONG Key; PVOID Key;
} FILE_COMPLETION_INFORMATION, *PFILE_COMPLETION_INFORMATION; } FILE_COMPLETION_INFORMATION, *PFILE_COMPLETION_INFORMATION;
typedef struct _FILE_COMPRESSION_INFORMATION { typedef struct _FILE_COMPRESSION_INFORMATION {