示例#1
0
int
WSPAPI
WSPRecv(SOCKET Handle,
        LPWSABUF lpBuffers,
        DWORD dwBufferCount,
        LPDWORD lpNumberOfBytesRead,
        LPDWORD ReceiveFlags,
        LPWSAOVERLAPPED lpOverlapped,
        LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine,
        LPWSATHREADID lpThreadId,
        LPINT lpErrno)
{
    PIO_STATUS_BLOCK        IOSB;
    IO_STATUS_BLOCK         DummyIOSB;
    AFD_RECV_INFO           RecvInfo;
    NTSTATUS                Status;
    PVOID                   APCContext;
    PVOID                   APCFunction;
    HANDLE                  Event = NULL;
    HANDLE                  SockEvent;
    PSOCKET_INFORMATION     Socket;

    AFD_DbgPrint(MID_TRACE,("Called (%x)\n", Handle));

    /* Get the Socket Structure associate to this Socket*/
    Socket = GetSocketStructure(Handle);
    if (!Socket)
    {
        *lpErrno = WSAENOTSOCK;
        return SOCKET_ERROR;
    }

    Status = NtCreateEvent( &SockEvent, EVENT_ALL_ACCESS,
                            NULL, 1, FALSE );

    if( !NT_SUCCESS(Status) )
        return -1;

    /* Set up the Receive Structure */
    RecvInfo.BufferArray = (PAFD_WSABUF)lpBuffers;
    RecvInfo.BufferCount = dwBufferCount;
    RecvInfo.TdiFlags = 0;
    RecvInfo.AfdFlags = Socket->SharedData.NonBlocking ? AFD_IMMEDIATE : 0;

    /* Set the TDI Flags */
    if (*ReceiveFlags == 0)
    {
        RecvInfo.TdiFlags |= TDI_RECEIVE_NORMAL;
    }
    else
    {
        if (*ReceiveFlags & MSG_OOB)
        {
            RecvInfo.TdiFlags |= TDI_RECEIVE_EXPEDITED;
        }

        if (*ReceiveFlags & MSG_PEEK)
        {
            RecvInfo.TdiFlags |= TDI_RECEIVE_PEEK;
        }

        if (*ReceiveFlags & MSG_PARTIAL)
        {
            RecvInfo.TdiFlags |= TDI_RECEIVE_PARTIAL;
        }
    }

    /* Verifiy if we should use APC */

    if (lpOverlapped == NULL)
    {
        /* Not using Overlapped structure, so use normal blocking on event */
        APCContext = NULL;
        APCFunction = NULL;
        Event = SockEvent;
        IOSB = &DummyIOSB;
    }
    else
    {
        if (lpCompletionRoutine == NULL)
        {
            /* Using Overlapped Structure, but no Completition Routine, so no need for APC */
            APCContext = lpOverlapped;
            APCFunction = NULL;
            Event = lpOverlapped->hEvent;
        }
        else
        {
            /* Using Overlapped Structure and a Completition Routine, so use an APC */
            APCFunction = NULL; // should be a private io completition function inside us
            APCContext = lpCompletionRoutine;
            RecvInfo.AfdFlags |= AFD_SKIP_FIO;
        }

        IOSB = (PIO_STATUS_BLOCK)&lpOverlapped->Internal;
        RecvInfo.AfdFlags |= AFD_OVERLAPPED;
    }

    IOSB->Status = STATUS_PENDING;

    /* Send IOCTL */
    Status = NtDeviceIoControlFile((HANDLE)Handle,
                                   Event,
                                   APCFunction,
                                   APCContext,
                                   IOSB,
                                   IOCTL_AFD_RECV,
                                   &RecvInfo,
                                   sizeof(RecvInfo),
                                   NULL,
                                   0);

    /* Wait for completition of not overlapped */
    if (Status == STATUS_PENDING && lpOverlapped == NULL)
    {
        /* It's up to the protocol to time out recv.  We must wait
         * until the protocol decides it's had enough.
         */
        WaitForSingleObject(SockEvent, INFINITE);
        Status = IOSB->Status;
    }

    NtClose( SockEvent );

    AFD_DbgPrint(MID_TRACE,("Status %x Information %d\n", Status, IOSB->Information));

    /* Return the Flags */
    *ReceiveFlags = 0;

    switch (Status)
    {
    case STATUS_RECEIVE_EXPEDITED:
        *ReceiveFlags = MSG_OOB;
        break;
    case STATUS_RECEIVE_PARTIAL_EXPEDITED:
        *ReceiveFlags = MSG_PARTIAL | MSG_OOB;
        break;
    case STATUS_RECEIVE_PARTIAL:
        *ReceiveFlags = MSG_PARTIAL;
        break;
    }

    /* Re-enable Async Event */
    if (*ReceiveFlags & MSG_OOB)
    {
        SockReenableAsyncSelectEvent(Socket, FD_OOB);
    }
    else
    {
        SockReenableAsyncSelectEvent(Socket, FD_READ);
    }

    return MsafdReturnWithErrno ( Status, lpErrno, IOSB->Information, lpNumberOfBytesRead );
}
示例#2
0
int
WSPAPI
WSPSendTo(SOCKET Handle,
          LPWSABUF lpBuffers,
          DWORD dwBufferCount,
          LPDWORD lpNumberOfBytesSent,
          DWORD iFlags,
          const struct sockaddr *SocketAddress,
          int SocketAddressLength,
          LPWSAOVERLAPPED lpOverlapped,
          LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine,
          LPWSATHREADID lpThreadId,
          LPINT lpErrno)
{
    PIO_STATUS_BLOCK        IOSB;
    IO_STATUS_BLOCK         DummyIOSB;
    AFD_SEND_INFO_UDP       SendInfo;
    NTSTATUS                Status;
    PVOID                   APCContext;
    PVOID                   APCFunction;
    HANDLE                  Event = NULL;
    PTRANSPORT_ADDRESS      RemoteAddress;
    PSOCKADDR               BindAddress = NULL;
    INT                     BindAddressLength;
    HANDLE                  SockEvent;
    PSOCKET_INFORMATION     Socket;

    /* Get the Socket Structure associate to this Socket */
    Socket = GetSocketStructure(Handle);
    if (!Socket)
    {
        *lpErrno = WSAENOTSOCK;
        return SOCKET_ERROR;
    }

    if (!(Socket->SharedData.ServiceFlags1 & XP1_CONNECTIONLESS))
    {
        /* Use WSPSend for connection-oriented sockets */
        return WSPSend(Handle,
                       lpBuffers,
                       dwBufferCount,
                       lpNumberOfBytesSent,
                       iFlags,
                       lpOverlapped,
                       lpCompletionRoutine,
                       lpThreadId,
                       lpErrno);
    }

    /* Bind us First */
    if (Socket->SharedData.State == SocketOpen)
    {
        /* Get the Wildcard Address */
        BindAddressLength = Socket->HelperData->MaxWSAddressLength;
        BindAddress = HeapAlloc(GlobalHeap, 0, BindAddressLength);
        if (!BindAddress)
        {
            MsafdReturnWithErrno(STATUS_INSUFFICIENT_RESOURCES, lpErrno, 0, NULL);
            return INVALID_SOCKET;
        }

        Socket->HelperData->WSHGetWildcardSockaddr(Socket->HelperContext,
                BindAddress,
                &BindAddressLength);
        /* Bind it */
        if (WSPBind(Handle, BindAddress, BindAddressLength, lpErrno) == SOCKET_ERROR)
            return SOCKET_ERROR;
    }

    RemoteAddress = HeapAlloc(GlobalHeap, 0, 0x6 + SocketAddressLength);
    if (!RemoteAddress)
    {
        if (BindAddress != NULL)
        {
            HeapFree(GlobalHeap, 0, BindAddress);
        }
        return MsafdReturnWithErrno(STATUS_INSUFFICIENT_RESOURCES, lpErrno, 0, NULL);
    }

    Status = NtCreateEvent(&SockEvent,
                           EVENT_ALL_ACCESS,
                           NULL, 1, FALSE);

    if (!NT_SUCCESS(Status))
    {
        HeapFree(GlobalHeap, 0, RemoteAddress);
        if (BindAddress != NULL)
        {
            HeapFree(GlobalHeap, 0, BindAddress);
        }
        return SOCKET_ERROR;
    }

    /* Set up Address in TDI Format */
    RemoteAddress->TAAddressCount = 1;
    RemoteAddress->Address[0].AddressLength = SocketAddressLength - sizeof(SocketAddress->sa_family);
    RtlCopyMemory(&RemoteAddress->Address[0].AddressType, SocketAddress, SocketAddressLength);

    /* Set up Structure */
    SendInfo.BufferArray = (PAFD_WSABUF)lpBuffers;
    SendInfo.AfdFlags = Socket->SharedData.NonBlocking ? AFD_IMMEDIATE : 0;
    SendInfo.BufferCount = dwBufferCount;
    SendInfo.TdiConnection.RemoteAddress = RemoteAddress;
    SendInfo.TdiConnection.RemoteAddressLength = Socket->HelperData->MaxTDIAddressLength;

    /* Verifiy if we should use APC */
    if (lpOverlapped == NULL)
    {
        /* Not using Overlapped structure, so use normal blocking on event */
        APCContext = NULL;
        APCFunction = NULL;
        Event = SockEvent;
        IOSB = &DummyIOSB;
    }
    else
    {
        if (lpCompletionRoutine == NULL)
        {
            /* Using Overlapped Structure, but no Completition Routine, so no need for APC */
            APCContext = lpOverlapped;
            APCFunction = NULL;
            Event = lpOverlapped->hEvent;
        }
        else
        {
            /* Using Overlapped Structure and a Completition Routine, so use an APC */
            /* Should be a private io completition function inside us */
            APCFunction = NULL;
            APCContext = lpCompletionRoutine;
            SendInfo.AfdFlags |= AFD_SKIP_FIO;
        }

        IOSB = (PIO_STATUS_BLOCK)&lpOverlapped->Internal;
        SendInfo.AfdFlags |= AFD_OVERLAPPED;
    }

    /* Send IOCTL */
    Status = NtDeviceIoControlFile((HANDLE)Handle,
                                   Event,
                                   APCFunction,
                                   APCContext,
                                   IOSB,
                                   IOCTL_AFD_SEND_DATAGRAM,
                                   &SendInfo,
                                   sizeof(SendInfo),
                                   NULL,
                                   0);

    /* Wait for completition of not overlapped */
    if (Status == STATUS_PENDING && lpOverlapped == NULL)
    {
        /* BUGBUG, shouldn't wait infintely for send... */
        WaitForSingleObject(SockEvent, INFINITE);
        Status = IOSB->Status;
    }

    NtClose(SockEvent);
    HeapFree(GlobalHeap, 0, RemoteAddress);
    if (BindAddress != NULL)
    {
        HeapFree(GlobalHeap, 0, BindAddress);
    }

    SockReenableAsyncSelectEvent(Socket, FD_WRITE);

    return MsafdReturnWithErrno(Status, lpErrno, IOSB->Information, lpNumberOfBytesSent);
}
示例#3
0
int
WSPAPI
WSPSend(SOCKET Handle,
        LPWSABUF lpBuffers,
        DWORD dwBufferCount,
        LPDWORD lpNumberOfBytesSent,
        DWORD iFlags,
        LPWSAOVERLAPPED lpOverlapped,
        LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine,
        LPWSATHREADID lpThreadId,
        LPINT lpErrno)
{
    PIO_STATUS_BLOCK        IOSB;
    IO_STATUS_BLOCK         DummyIOSB;
    AFD_SEND_INFO           SendInfo;
    NTSTATUS                Status;
    PVOID                   APCContext;
    PVOID                   APCFunction;
    HANDLE                  Event = NULL;
    HANDLE                  SockEvent;
    PSOCKET_INFORMATION     Socket;

    /* Get the Socket Structure associate to this Socket*/
    Socket = GetSocketStructure(Handle);
    if (!Socket)
    {
        *lpErrno = WSAENOTSOCK;
        return SOCKET_ERROR;
    }

    Status = NtCreateEvent( &SockEvent, EVENT_ALL_ACCESS,
                            NULL, 1, FALSE );

    if( !NT_SUCCESS(Status) )
        return -1;

    AFD_DbgPrint(MID_TRACE,("Called\n"));

    /* Set up the Send Structure */
    SendInfo.BufferArray = (PAFD_WSABUF)lpBuffers;
    SendInfo.BufferCount = dwBufferCount;
    SendInfo.TdiFlags = 0;
    SendInfo.AfdFlags = Socket->SharedData.NonBlocking ? AFD_IMMEDIATE : 0;

    /* Set the TDI Flags */
    if (iFlags)
    {
        if (iFlags & MSG_OOB)
        {
            SendInfo.TdiFlags |= TDI_SEND_EXPEDITED;
        }
        if (iFlags & MSG_PARTIAL)
        {
            SendInfo.TdiFlags |= TDI_SEND_PARTIAL;
        }
    }

    /* Verifiy if we should use APC */
    if (lpOverlapped == NULL)
    {
        /* Not using Overlapped structure, so use normal blocking on event */
        APCContext = NULL;
        APCFunction = NULL;
        Event = SockEvent;
        IOSB = &DummyIOSB;
    }
    else
    {
        if (lpCompletionRoutine == NULL)
        {
            /* Using Overlapped Structure, but no Completition Routine, so no need for APC */
            APCContext = lpOverlapped;
            APCFunction = NULL;
            Event = lpOverlapped->hEvent;
        }
        else
        {
            /* Using Overlapped Structure and a Completition Routine, so use an APC */
            APCFunction = NULL; // should be a private io completition function inside us
            APCContext = lpCompletionRoutine;
            SendInfo.AfdFlags |= AFD_SKIP_FIO;
        }

        IOSB = (PIO_STATUS_BLOCK)&lpOverlapped->Internal;
        SendInfo.AfdFlags |= AFD_OVERLAPPED;
    }

    IOSB->Status = STATUS_PENDING;

    /* Send IOCTL */
    Status = NtDeviceIoControlFile((HANDLE)Handle,
                                   Event,
                                   APCFunction,
                                   APCContext,
                                   IOSB,
                                   IOCTL_AFD_SEND,
                                   &SendInfo,
                                   sizeof(SendInfo),
                                   NULL,
                                   0);

    /* Wait for completition of not overlapped */
    if (Status == STATUS_PENDING && lpOverlapped == NULL)
    {
        WaitForSingleObject(SockEvent, INFINITE); // BUGBUG, shouldn wait infintely for send...
        Status = IOSB->Status;
    }

    NtClose( SockEvent );

    if (Status == STATUS_PENDING)
    {
        AFD_DbgPrint(MID_TRACE,("Leaving (Pending)\n"));
        return MsafdReturnWithErrno(Status, lpErrno, IOSB->Information, lpNumberOfBytesSent);
    }

    /* Re-enable Async Event */
    SockReenableAsyncSelectEvent(Socket, FD_WRITE);

    AFD_DbgPrint(MID_TRACE,("Leaving (Success, %d)\n", IOSB->Information));

    return MsafdReturnWithErrno( Status, lpErrno, IOSB->Information, lpNumberOfBytesSent );
}
示例#4
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;
}
示例#5
0
文件: event.c 项目: RPG-7/reactos
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;
}
示例#6
0
文件: event.c 项目: RPG-7/reactos
INT
WSPAPI
WSPEnumNetworkEvents(
  IN  SOCKET Handle,
  IN  WSAEVENT hEventObject,
  OUT LPWSANETWORKEVENTS lpNetworkEvents,
  OUT LPINT lpErrno)
{
    AFD_ENUM_NETWORK_EVENTS_INFO EnumReq;
    IO_STATUS_BLOCK				IOSB;
    PSOCKET_INFORMATION			Socket = NULL;
    NTSTATUS					Status;
    HANDLE                                  SockEvent;

    TRACE("Called (lpNetworkEvents %x)\n", lpNetworkEvents);

    Status = NtCreateEvent( &SockEvent, EVENT_ALL_ACCESS,
			    NULL, 1, FALSE );

    if( !NT_SUCCESS(Status) ) {
        ERR("Could not make an event %x\n", Status);
        return -1;
    }

    /* Get the Socket Structure associate to this Socket*/
    Socket = GetSocketStructure(Handle);
    if (!Socket)
    {
       NtClose(SockEvent);
       *lpErrno = WSAENOTSOCK;
       return SOCKET_ERROR;
    }

    EnumReq.Event = hEventObject;

    /* Send IOCTL */
    Status = NtDeviceIoControlFile((HANDLE)Handle,
				   SockEvent,
				   NULL,
				   NULL,
				   &IOSB,
				   IOCTL_AFD_ENUM_NETWORK_EVENTS,
				   &EnumReq,
				   sizeof(EnumReq),
				   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("Status 0x%08x", Status);
        return MsafdReturnWithErrno(Status, lpErrno, 0, NULL);
    }

    TRACE("Closed event\n");
    TRACE("About to touch struct at %x (%d)\n", lpNetworkEvents, sizeof(*lpNetworkEvents));

    lpNetworkEvents->lNetworkEvents = 0;

    /* Set Events to wait for */
    if (EnumReq.PollEvents & AFD_EVENT_RECEIVE) {
        lpNetworkEvents->lNetworkEvents |= FD_READ;
        lpNetworkEvents->iErrorCode[FD_READ_BIT] = TranslateNtStatusError(EnumReq.EventStatus[FD_READ_BIT]);
    }

    if (EnumReq.PollEvents & AFD_EVENT_SEND) {
        lpNetworkEvents->lNetworkEvents |= FD_WRITE;
        lpNetworkEvents->iErrorCode[FD_WRITE_BIT] = TranslateNtStatusError(EnumReq.EventStatus[FD_WRITE_BIT]);
    }

    if (EnumReq.PollEvents & AFD_EVENT_OOB_RECEIVE) {
        lpNetworkEvents->lNetworkEvents |= FD_OOB;
        lpNetworkEvents->iErrorCode[FD_OOB_BIT] = TranslateNtStatusError(EnumReq.EventStatus[FD_OOB_BIT]);
    }

    if (EnumReq.PollEvents & AFD_EVENT_ACCEPT) {
        lpNetworkEvents->lNetworkEvents |= FD_ACCEPT;
        lpNetworkEvents->iErrorCode[FD_ACCEPT_BIT] = TranslateNtStatusError(EnumReq.EventStatus[FD_ACCEPT_BIT]);
    }

    if (EnumReq.PollEvents &
            (AFD_EVENT_CONNECT | AFD_EVENT_CONNECT_FAIL)) {
        lpNetworkEvents->lNetworkEvents |= FD_CONNECT;
        lpNetworkEvents->iErrorCode[FD_CONNECT_BIT] = TranslateNtStatusError(EnumReq.EventStatus[FD_CONNECT_BIT]);
    }

    if (EnumReq.PollEvents &
	(AFD_EVENT_DISCONNECT | AFD_EVENT_ABORT | AFD_EVENT_CLOSE)) {
        lpNetworkEvents->lNetworkEvents |= FD_CLOSE;
        lpNetworkEvents->iErrorCode[FD_CLOSE_BIT] = TranslateNtStatusError(EnumReq.EventStatus[FD_CLOSE_BIT]);
    }

    if (EnumReq.PollEvents & AFD_EVENT_QOS) {
	lpNetworkEvents->lNetworkEvents |= FD_QOS;
	lpNetworkEvents->iErrorCode[FD_QOS_BIT] = TranslateNtStatusError(EnumReq.EventStatus[FD_QOS_BIT]);
    }

    if (EnumReq.PollEvents & AFD_EVENT_GROUP_QOS) {
        lpNetworkEvents->lNetworkEvents |= FD_GROUP_QOS;
        lpNetworkEvents->iErrorCode[FD_GROUP_QOS_BIT] = TranslateNtStatusError(EnumReq.EventStatus[FD_GROUP_QOS_BIT]);
    }

    TRACE("Leaving\n");

    return MsafdReturnWithErrno(STATUS_SUCCESS, lpErrno, 0, NULL);
}