eventsel.c
Upload User: caisha3
Upload Date: 2013-09-21
Package Size: 208739k
Code Size: 15k
Category:

Windows Develop

Development Platform:

Visual C++

  1. /*++
  2. Copyright (c) 1992 Microsoft Corporation
  3. Module Name:
  4.     eventsel.c
  5. Abstract:
  6.     This module contains support for the WSAEventSelect() and
  7.     WSAEnumNetworkEvents() WinSock APIs.
  8. Author:
  9.     Keith Moore (keithmo)        5-Aug-1995
  10. Revision History:
  11. --*/
  12. #include "winsockp.h"
  13. //
  14. // Data to make the mapping of poll events to FD_* events simpler
  15. // in WSAEnumNetworkEvents().  Note that FD_CONNECT and FD_CLOSE
  16. // are not in this list.  They must be handled specially.
  17. //
  18. typedef struct _POLL_MAPPING {
  19.     ULONG   PollEventBit;
  20.     LONG    NetworkEventBit;
  21. } POLL_MAPPING, *PPOLL_MAPPING;
  22. POLL_MAPPING PollEventMapping[] =
  23.     {
  24.         {   AFD_POLL_RECEIVE_BIT,           FD_READ_BIT      },
  25.         {   AFD_POLL_SEND_BIT,              FD_WRITE_BIT     },
  26.         {   AFD_POLL_RECEIVE_EXPEDITED_BIT, FD_OOB_BIT       },
  27.         {   AFD_POLL_ACCEPT_BIT,            FD_ACCEPT_BIT    },
  28.         {   AFD_POLL_QOS_BIT,               FD_QOS_BIT       },
  29.         {   AFD_POLL_GROUP_QOS_BIT,         FD_GROUP_QOS_BIT }
  30. #ifdef _PNP_POWER_
  31.         ,
  32.         {   AFD_POLL_ROUTING_IF_CHANGE_BIT, FD_ROUTING_INTERFACE_CHANGE_BIT },
  33.         {   AFD_POLL_ADDRESS_LIST_CHANGE_BIT, FD_ADDRESS_LIST_CHANGE_BIT }
  34. #endif // _PNP_POWER
  35.     };
  36. #define NUM_POLL_MAPPINGS (sizeof(PollEventMapping) / sizeof(PollEventMapping[0]))
  37. int
  38. WSPAPI
  39. WSPEventSelect (
  40.     SOCKET Handle,
  41.     WSAEVENT hEventObject,
  42.     long lNetworkEvents,
  43.     LPINT lpErrno
  44.     )
  45. /*++
  46. Routine Description:
  47.     Does that event select thang.   CKMBUGBUG
  48. Arguments:
  49.     Handle - A descriptor identifying the socket for which event
  50.         notification is required.
  51.     hEventObject - A handle identifying the event object which should
  52.         be signalled when a network event occurs.
  53.     lEvent - A bitmask which specifies a combination of network events
  54.         in which the application is interested.
  55. Return Value:
  56.     The return value is 0 if the application's declaration of interest
  57.     in the network event set was successful.  Otherwise the value
  58.     SOCKET_ERROR is returned, and a specific error number may be
  59.     retrieved by calling WSAGetLastError().
  60. --*/
  61. {
  62.     PSOCKET_INFORMATION socket;
  63. PWINSOCK_TLS_DATA tlsData;
  64.     int err;
  65.     BOOLEAN blocking;
  66.     WS_ENTER( "WSPEventSelect", (PVOID)Handle, (PVOID)hEventObject, (PVOID)lNetworkEvents, NULL );
  67.     WS_ASSERT( lpErrno != NULL );
  68.     err = SockEnterApi( &tlsData );
  69.     if( err != NO_ERROR ) {
  70.         WS_EXIT( "WSPEventSelect", SOCKET_ERROR, TRUE );
  71.         *lpErrno = err;
  72.         return SOCKET_ERROR;
  73.     }
  74.     //
  75.     // Initialize locals so that we know how to clean up on exit.
  76.     //
  77.     socket = NULL;
  78.     //
  79.     // Find a pointer to the socket structure corresponding to the
  80.     // passed-in handle.
  81.     //
  82.     socket = SockFindAndReferenceSocket( Handle, TRUE );
  83.     if ( socket == NULL ) {
  84.         err = WSAENOTSOCK;
  85.         goto exit;
  86.     }
  87.     //
  88.     // Set the socket to nonblocking.
  89.     //
  90.     blocking = TRUE;
  91.     err = SockSetInformation(
  92.                 socket,
  93.                 AFD_NONBLOCKING_MODE,
  94.                 &blocking,
  95.                 NULL,
  96.                 NULL
  97.                 );
  98.     if ( err != NO_ERROR ) {
  99.         goto exit;
  100.     }
  101.     socket->NonBlocking = TRUE;
  102.     //
  103.     // If there's a WSAAsyncSelect active on this socket, deactivate it.
  104.     //
  105.     if( socket->AsyncSelectlEvent ) {
  106.         SockAcquireSocketLockExclusive (socket);
  107.         socket->AsyncSelecthWnd = NULL;
  108.         socket->AsyncSelectwMsg = 0;
  109.         socket->AsyncSelectlEvent = 0;
  110.         //
  111.         // Bump serial number so that completing async select
  112.         // request goes on the floor.
  113.         //
  114.         socket->AsyncSelectSerialNumber += 1;
  115.         SockReleaseSocketLock (socket);
  116.     }
  117.     //
  118.     // Make sure that only valid bits are specified in lEvent.
  119.     //
  120.     // !!! should we also make sure that the bits make sense for the
  121.     //     state of the socket, i.e. don't allow FD_ACCEPT on a
  122.     //     connected socket?
  123.     //
  124.     if ( (lNetworkEvents & ~FD_ALL_EVENTS) != 0 ) {
  125.         err = WSAEINVAL;
  126.         goto exit;
  127.     }
  128.     //
  129.     // Let the helper do the dirty work.
  130.     //
  131.     err = SockEventSelectHelper(
  132.               socket,
  133.               hEventObject,
  134.               lNetworkEvents
  135.               );
  136. exit:
  137.     if ( socket != NULL ) {
  138.         SockDereferenceSocket( socket );
  139.     }
  140.     if ( err != NO_ERROR) {
  141.         IF_DEBUG(EVENT_SELECT) {
  142.             WS_PRINT(( "WSPEventSelect failed: %ldn", err ));
  143.         }
  144.         WS_EXIT( "WSPEventSelect", SOCKET_ERROR, TRUE );
  145.         *lpErrno = err;
  146.         return SOCKET_ERROR;
  147.     }
  148.     IF_DEBUG(EVENT_SELECT) {
  149.         WS_PRINT(( "WSPEventSelect successfully posted request, "
  150.                    "socket = %lxn", socket ));
  151.     }
  152.     WS_EXIT( "WSPEventSelect", NO_ERROR, FALSE );
  153.     return NO_ERROR;
  154. } // WSPEventSelect
  155. int
  156. SockEventSelectHelper(
  157.     PSOCKET_INFORMATION Socket,
  158.     WSAEVENT hEventObject,
  159.     long lNetworkEvents
  160.     )
  161. /*++
  162. Routine Description:
  163.     x
  164. Arguments:
  165.     x
  166. Return Value:
  167.     x
  168. --*/
  169. {
  170.     AFD_EVENT_SELECT_INFO eventInfo;
  171.     IO_STATUS_BLOCK ioStatusBlock;
  172.     NTSTATUS status;
  173. PWINSOCK_TLS_DATA tlsData;
  174. tlsData = GET_THREAD_DATA ();
  175.     //
  176.     // Acquire the lock that protects this socket.  We hold this lock
  177.     // throughout this routine to synchronize against other callers
  178.     // performing operations on the socket we're using.
  179.     //
  180.     SockAcquireSocketLockExclusive( Socket );
  181.     //
  182.     // Initialize the AFD_EVENT_SELECT_INFO structure.
  183.     //
  184.     eventInfo.Event = hEventObject;
  185.     eventInfo.PollEvents = 0;
  186.     if( lNetworkEvents & FD_READ ) {
  187.         eventInfo.PollEvents |= AFD_POLL_RECEIVE;
  188.     }
  189.     if( lNetworkEvents & FD_WRITE ) {
  190.         eventInfo.PollEvents |= AFD_POLL_SEND;
  191.     }
  192.     if( lNetworkEvents & FD_OOB ) {
  193.         eventInfo.PollEvents |= AFD_POLL_RECEIVE_EXPEDITED;
  194.     }
  195.     if( lNetworkEvents & FD_ACCEPT ) {
  196.         eventInfo.PollEvents |= AFD_POLL_ACCEPT;
  197.     }
  198.     if( lNetworkEvents & FD_CONNECT ) {
  199.         eventInfo.PollEvents |= AFD_POLL_CONNECT | AFD_POLL_CONNECT_FAIL;
  200.     }
  201.     if( lNetworkEvents & FD_CLOSE ) {
  202.         eventInfo.PollEvents |= AFD_POLL_DISCONNECT | AFD_POLL_ABORT;
  203.     }
  204.     if( lNetworkEvents & FD_QOS ) {
  205.         eventInfo.PollEvents |= AFD_POLL_QOS;
  206.     }
  207.     if( lNetworkEvents & FD_GROUP_QOS ) {
  208.         eventInfo.PollEvents |= AFD_POLL_GROUP_QOS;
  209.     }
  210. #ifdef _PNP_POWER_
  211.     if( lNetworkEvents & FD_ROUTING_INTERFACE_CHANGE ) {
  212.         eventInfo.PollEvents |= AFD_POLL_ROUTING_IF_CHANGE;
  213.     }
  214.     if( lNetworkEvents & FD_ADDRESS_LIST_CHANGE ) {
  215.         eventInfo.PollEvents |= AFD_POLL_ADDRESS_LIST_CHANGE;
  216.     }
  217. #endif // _PNP_POWER_
  218.     //
  219.     // Send the IOCTL to AFD.  AFD will reference the event object and
  220.     // store the poll events in its internal endpoint structure.
  221.     //
  222.     status = NtDeviceIoControlFile(
  223.                  Socket->HContext.Handle,
  224.                  tlsData->EventHandle,
  225.                  NULL,                      // APC Routine
  226.                  NULL,                      // APC Context
  227.                  &ioStatusBlock,
  228.                  IOCTL_AFD_EVENT_SELECT,
  229.                  &eventInfo,
  230.                  sizeof(eventInfo),
  231.                  NULL,
  232.                  0
  233.                  );
  234.     if( status == STATUS_PENDING ) {
  235.         SockWaitForSingleObject(
  236.             tlsData->EventHandle,
  237.             Socket->Handle,
  238.             SOCK_NEVER_CALL_BLOCKING_HOOK,
  239.             SOCK_NO_TIMEOUT
  240.             );
  241.         status = ioStatusBlock.Status;
  242.     }
  243.     if( !NT_SUCCESS(status) ) {
  244.         SockReleaseSocketLock( Socket );
  245.         return SockNtStatusToSocketError( status );
  246.     }
  247.     //
  248.     // Store the event object handle and network event mask in the socket.
  249.     //
  250.     Socket->EventSelectEventObject = hEventObject;
  251.     Socket->EventSelectlNetworkEvents = lNetworkEvents;
  252.     //
  253.     // Release the socket lock & return.
  254.     //
  255.     SockReleaseSocketLock( Socket );
  256.     return NO_ERROR;
  257. } // SockEventSelectHelper
  258. int
  259. WSPAPI
  260. WSPEnumNetworkEvents (
  261.     SOCKET Handle,
  262.     WSAEVENT hEventObject,
  263.     LPWSANETWORKEVENTS lpNetworkEvents,
  264.     LPINT lpErrno
  265.     )
  266. /*++
  267. Routine Description:
  268.     Does that enum network events thang.    CKMBUGBUG
  269. Arguments:
  270.     Handle - A descriptor identifying the socket.
  271.     hEventObject - An optional handle identifying an associated event
  272.         object to be reset.
  273.     lpNetworkEvents - Points to a WSANETWORKEVENTS structure which records
  274.         an occurred network event and the associated error code.
  275. Return Value:
  276.     The return value is 0 if the application's declaration of interest
  277.     in the network event set was successful.  Otherwise the value
  278.     SOCKET_ERROR is returned, and a specific error number may be
  279.     retrieved by calling WSAGetLastError().
  280. --*/
  281. {
  282. PWINSOCK_TLS_DATA tlsData;
  283.     PSOCKET_INFORMATION socket;
  284.     INT err;
  285.     AFD_ENUM_NETWORK_EVENTS_INFO eventInfo;
  286.     IO_STATUS_BLOCK ioStatusBlock;
  287.     NTSTATUS status;
  288.     NTSTATUS eventStatus;
  289.     INT i;
  290.     PPOLL_MAPPING pollMapping;
  291.     WS_ENTER( "WSPEnumNetworkEvents", (PVOID)Handle, (PVOID)hEventObject, (PVOID)lpNetworkEvents, NULL );
  292.     WS_ASSERT( lpErrno != NULL );
  293.     err = SockEnterApi( &tlsData );
  294.     if( err != NO_ERROR ) {
  295.         WS_EXIT( "WSPEnumNetworkEvents", SOCKET_ERROR, TRUE );
  296.         *lpErrno = err;
  297.         return SOCKET_ERROR;
  298.     }
  299.     //
  300.     // Initialize locals so that we know how to clean up on exit.
  301.     //
  302.     socket = NULL;
  303.     //
  304.     // Validate the parameters.
  305.     //
  306.     if( lpNetworkEvents == NULL ) {
  307.         err = WSAEINVAL;
  308.         goto exit;
  309.     }
  310.     //
  311.     // Find a pointer to the socket structure corresponding to the
  312.     // passed-in handle.
  313.     //
  314.     socket = SockFindAndReferenceSocket( Handle, TRUE );
  315.     if ( socket == NULL ) {
  316.         err = WSAENOTSOCK;
  317.         goto exit;
  318.     }
  319.     //
  320.     // Acquire the lock that protects this socket.  We hold this lock
  321.     // throughout this routine to synchronize against other callers
  322.     // performing operations on the socket we're using.
  323.     //
  324.     SockAcquireSocketLockExclusive( socket );
  325.     //
  326.     // Send the IOCTL to AFD.  AFD will update the structure with
  327.     // information on network events that have occurred.  AFD will
  328.     // then reset the event object (if specified).
  329.     //
  330.     status = NtDeviceIoControlFile(
  331.                  (HANDLE)Handle,
  332.                  tlsData->EventHandle,
  333.                  NULL,                      // APC Routine
  334.                  NULL,                      // APC Context
  335.                  &ioStatusBlock,
  336.                  IOCTL_AFD_ENUM_NETWORK_EVENTS,
  337.                  hEventObject,
  338.                  0,
  339.                  &eventInfo,
  340.                  sizeof(eventInfo)
  341.                  );
  342.     if( status == STATUS_PENDING ) {
  343.         SockWaitForSingleObject(
  344.             tlsData->EventHandle,
  345.             socket->Handle,
  346.             SOCK_NEVER_CALL_BLOCKING_HOOK,
  347.             SOCK_NO_TIMEOUT
  348.             );
  349.         status = ioStatusBlock.Status;
  350.     }
  351.     if( !NT_SUCCESS(status) ) {
  352.         err = SockNtStatusToSocketError( status );
  353.         goto exit;
  354.     }
  355.     __try {
  356.         //
  357.         // Zero the WSANETWORKEVENTS structure.
  358.         //
  359.         lpNetworkEvents->lNetworkEvents = 0;
  360.         //
  361.         // Interpret the results.
  362.         //
  363.         pollMapping = PollEventMapping;
  364.         for( i = 0 ; i < NUM_POLL_MAPPINGS ; i++ ) {
  365.             if( eventInfo.PollEvents & ( 1 << pollMapping->PollEventBit ) ) {
  366.                 lpNetworkEvents->lNetworkEvents |=
  367.                     ( 1 << pollMapping->NetworkEventBit );
  368.                 eventStatus = eventInfo.EventStatus[pollMapping->PollEventBit];
  369.                 if( !NT_SUCCESS(eventStatus) ) {
  370.                     lpNetworkEvents->iErrorCode[pollMapping->NetworkEventBit] =
  371.                         SockNtStatusToSocketError( eventStatus );
  372.                 }
  373.                 else {
  374.                     lpNetworkEvents->iErrorCode[pollMapping->NetworkEventBit] = 0;
  375.                 }
  376.             }
  377.             pollMapping++;
  378.         }
  379.         if( eventInfo.PollEvents & AFD_POLL_CONNECT ) {
  380.             lpNetworkEvents->lNetworkEvents |= FD_CONNECT;
  381.             eventStatus = eventInfo.EventStatus[AFD_POLL_CONNECT_BIT];
  382.             if( !NT_SUCCESS(eventStatus ) ) {
  383.                 lpNetworkEvents->iErrorCode[FD_CONNECT_BIT] =
  384.                     SockNtStatusToSocketError( eventStatus );
  385.             }
  386.             else {
  387.                 lpNetworkEvents->iErrorCode[FD_CONNECT_BIT] = 0;
  388.             }
  389.         } else if (eventInfo.PollEvents & AFD_POLL_CONNECT_FAIL ) {
  390.             lpNetworkEvents->lNetworkEvents |= FD_CONNECT;
  391.             eventStatus = eventInfo.EventStatus[AFD_POLL_CONNECT_FAIL_BIT];
  392.             if( !NT_SUCCESS(eventStatus ) ) {
  393.                 lpNetworkEvents->iErrorCode[FD_CONNECT_BIT] =
  394.                     SockNtStatusToSocketError( eventStatus );
  395.             }
  396.             else {
  397.                 lpNetworkEvents->iErrorCode[FD_CONNECT_BIT] = 0;
  398.             }
  399.         }
  400.         if( eventInfo.PollEvents & AFD_POLL_ABORT ) {
  401.             lpNetworkEvents->lNetworkEvents |= FD_CLOSE;
  402.             eventStatus = eventInfo.EventStatus[AFD_POLL_ABORT_BIT];
  403.             if( !NT_SUCCESS(eventStatus ) ) {
  404.                 lpNetworkEvents->iErrorCode[FD_CLOSE_BIT] =
  405.                     SockNtStatusToSocketError( eventStatus );
  406.             }
  407.             else {
  408.                 lpNetworkEvents->iErrorCode[FD_CLOSE_BIT] = 0;
  409.             }
  410.         } else if( eventInfo.PollEvents & AFD_POLL_DISCONNECT ) {
  411.             lpNetworkEvents->lNetworkEvents |= FD_CLOSE;
  412.             eventStatus = eventInfo.EventStatus[AFD_POLL_DISCONNECT_BIT];
  413.             if( !NT_SUCCESS(eventStatus ) ) {
  414.                 lpNetworkEvents->iErrorCode[FD_CLOSE_BIT] =
  415.                     SockNtStatusToSocketError( eventStatus );
  416.             }
  417.             else {
  418.                 lpNetworkEvents->iErrorCode[FD_CLOSE_BIT] = 0;
  419.             }
  420.         }
  421.     }
  422.     __except (SOCK_EXCEPTION_FILTER()) {
  423.         err = WSAEFAULT;
  424.         goto exit;
  425.     }
  426. exit:
  427.     if ( socket != NULL ) {
  428.         SockReleaseSocketLock( socket );
  429.         SockDereferenceSocket( socket );
  430.     }
  431.     if ( err != NO_ERROR) {
  432.         IF_DEBUG(EVENT_SELECT) {
  433.             WS_PRINT(( "WSPEnumNetworkEvents failed: %ldn", err ));
  434.         }
  435.         WS_EXIT( "WSPEnumNetworkEvents", SOCKET_ERROR, TRUE );
  436.         *lpErrno = err;
  437.         return SOCKET_ERROR;
  438.     }
  439.     IF_DEBUG(EVENT_SELECT) {
  440.         WS_PRINT(( "WSPEnumNetworkEvents successfully posted request, "
  441.                    "socket = %lxn", socket ));
  442.     }
  443.     WS_EXIT( "WSPEnumNetworkEvents", NO_ERROR, FALSE );
  444.     return NO_ERROR;
  445. } // WSPEnumNetworkEvents