INT WSPAPI WSPAsyncSelect(IN SOCKET Handle, IN HWND hWnd, IN UINT wMsg, IN LONG lEvent, OUT LPINT lpErrno) { PSOCKET_INFORMATION Socket = NULL; PASYNC_DATA AsyncData; BOOLEAN BlockMode; /* Get the Socket Structure associated to this Socket */ Socket = GetSocketStructure(Handle); if (!Socket) { *lpErrno = WSAENOTSOCK; return SOCKET_ERROR; } /* Allocate the Async Data Structure to pass on to the Thread later */ AsyncData = HeapAlloc(GetProcessHeap(), 0, sizeof(*AsyncData)); if (!AsyncData) { MsafdReturnWithErrno( STATUS_INSUFFICIENT_RESOURCES, lpErrno, 0, NULL ); return INVALID_SOCKET; } /* Change the Socket to Non Blocking */ BlockMode = TRUE; SetSocketInformation(Socket, AFD_INFO_BLOCKING_MODE, &BlockMode, NULL, NULL); Socket->SharedData.NonBlocking = TRUE; /* Deactive WSPEventSelect */ if (Socket->SharedData.AsyncEvents) { if (WSPEventSelect(Handle, NULL, 0, lpErrno) == SOCKET_ERROR) { HeapFree(GetProcessHeap(), 0, AsyncData); return SOCKET_ERROR; } } /* 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 */ NtSetIoCompletion(SockAsyncCompletionPort, (PVOID)&SockProcessQueuedAsyncSelect, AsyncData, 0, 0); /* Return */ return ERROR_SUCCESS; }
int WSPAPI WSPEventSelect( SOCKET Handle, WSAEVENT hEventObject, long lNetworkEvents, LPINT lpErrno) { IO_STATUS_BLOCK IOSB; AFD_EVENT_SELECT_INFO EventSelectInfo; PSOCKET_INFORMATION Socket = NULL; NTSTATUS Status; BOOLEAN BlockMode; HANDLE SockEvent; Status = NtCreateEvent( &SockEvent, EVENT_ALL_ACCESS, NULL, 1, FALSE ); if( !NT_SUCCESS(Status) ) return -1; /* Get the Socket Structure associate to this Socket*/ Socket = GetSocketStructure(Handle); if (!Socket) { NtClose(SockEvent); *lpErrno = WSAENOTSOCK; return SOCKET_ERROR; } /* Set Socket to Non-Blocking */ BlockMode = TRUE; SetSocketInformation(Socket, AFD_INFO_BLOCKING_MODE, &BlockMode, NULL, NULL); Socket->SharedData.NonBlocking = TRUE; /* Deactivate Async Select if there is one */ if (Socket->EventObject) { 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 */ EventSelectInfo.EventObject = hEventObject; EventSelectInfo.Events = 0; /* Set Events to wait for */ if (lNetworkEvents & FD_READ) { EventSelectInfo.Events |= AFD_EVENT_RECEIVE; } if (lNetworkEvents & FD_WRITE) { EventSelectInfo.Events |= AFD_EVENT_SEND; } if (lNetworkEvents & FD_OOB) { EventSelectInfo.Events |= AFD_EVENT_OOB_RECEIVE; } if (lNetworkEvents & FD_ACCEPT) { EventSelectInfo.Events |= AFD_EVENT_ACCEPT; } if (lNetworkEvents & FD_CONNECT) { EventSelectInfo.Events |= AFD_EVENT_CONNECT | AFD_EVENT_CONNECT_FAIL; } if (lNetworkEvents & FD_CLOSE) { EventSelectInfo.Events |= AFD_EVENT_DISCONNECT | AFD_EVENT_ABORT | AFD_EVENT_CLOSE; } if (lNetworkEvents & FD_QOS) { EventSelectInfo.Events |= AFD_EVENT_QOS; } if (lNetworkEvents & FD_GROUP_QOS) { EventSelectInfo.Events |= AFD_EVENT_GROUP_QOS; } /* Send IOCTL */ Status = NtDeviceIoControlFile((HANDLE)Handle, SockEvent, NULL, NULL, &IOSB, IOCTL_AFD_EVENT_SELECT, &EventSelectInfo, sizeof(EventSelectInfo), NULL, 0); TRACE("AFD: %x\n", Status); /* Wait for return */ if (Status == STATUS_PENDING) { WaitForSingleObject(SockEvent, INFINITE); Status = IOSB.Status; } TRACE("Waited\n"); NtClose( SockEvent ); if (Status != STATUS_SUCCESS) { ERR("Got status 0x%08x.\n", Status); return MsafdReturnWithErrno(Status, lpErrno, 0, NULL); } TRACE("Closed event\n"); /* Set Socket Data*/ Socket->EventObject = hEventObject; Socket->NetworkEvents = lNetworkEvents; TRACE("Leaving\n"); return 0; }