mirror of
https://github.com/reactos/reactos.git
synced 2025-02-22 16:36:33 +00:00
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:
parent
3379855217
commit
1623a0079f
13 changed files with 512 additions and 73 deletions
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
);
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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) )
|
||||
{
|
||||
|
|
|
@ -22,11 +22,17 @@
|
|||
#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 */
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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*/
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Reference in a new issue