Esempio n. 1
0
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;
}
Esempio n. 2
0
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;
}