SOCKET WSPAPI WSPAccept( IN SOCKET s, OUT struct sockaddr FAR * addr, IN OUT LPINT addrlen, IN LPCONDITIONPROC lpfnCondition, IN DWORD dwCallbackData, OUT LPINT lpErrno ) /*++ Routine Description: This routine extracts the first connection on the queue of pending connections on s, and checks it against the condition function, provided the condition function is specified (i.e., not NULL). The condition function must be executed in the same thread as this routine is. If the condition function returns CF_ACCEPT, this routine creates a new socket and performs any socket grouping as indicated by the result parameter g in the condition function . Newly created sockets have the same properties as s including network events registered with WSPAsyncSelect() or with WSPEventSelect(), but not including the listening socket's group ID, if any. If the condition function returns CF_REJECT, this routine rejects the connection request. If the client's accept/reject decision cannot be made immediately, the condition function will return CF_DEFER to indicate that no decision has been made, and no action about this connection request is to be taken by the service provider. When the client is ready to take action on the connection request, it will invoke WSPAccept() again and return either CF_ACCEPT or CF_REJECT as a return value from the condition function. For sockets which are in the (default) blocking mode, if no pending connections are present on the queue, WSPAccept() blocks the caller until a connection is present. For sockets in a non-blocking mode, if this function is called when no pending connections are present on the queue, WSPAccept() returns the error code WSAEWOULDBLOCK as described below. The accepted socket may not be used to accept more connections. The original socket remains open. The argument addr is a result parameter that is filled in with the address of the connecting entity, as known to the service provider. The exact format of the addr parameter is determined by the address family in which the communication is occurring. The addrlen is a value-result parameter; it will initially contain the amount of space pointed to by addr. On return, it must contain the actual length (in bytes) of the address returned by the service provider. This call is used with connection- oriented socket types such as SOCK_STREAM. If addr and/or addrlen are equal to NULL, then no information about the remote address of the accepted socket is returned. Otherwise, these two parameters shall be filled in regardless of whether the condition function is specified or what it returns. The prototype of the condition function is as follows: int CALLBACK ConditionFunc( IN LPWSABUF lpCallerId, IN LPWSABUF lpCallerData, IN OUT LPQOS lpSQOS, IN OUT LPQOS lpGQOS, IN LPWSABUF lpCalleeId, IN LPWSABUF lpCalleeData, OUT GROUP FAR * g, IN DWORD dwCallbackData ); The lpCallerId and lpCallerData are value parameters which must contain the address of the connecting entity and any user data that was sent along with the connection request, respectively. If no caller ID or caller data is available, the corresponding parameter will be NULL. lpSQOS references the flow specs for socket s specified by the caller, one for each direction, followed by any additional provider-specific parameters. The sending or receiving flow spec values will be ignored as appropriate for any unidirectional sockets. A NULL value for lpSQOS indicates no caller supplied QOS. QOS information may be returned if a QOS negotiation is to occur. lpGQOS references the flow specs for the socket group the caller is to create, one for each direction, followed by any additional provider-specific parameters. A NULL value for lpGQOS indicates no caller-supplied group QOS. QOS information may be returned if a QOS negotiation is to occur. The lpCalleeId is a value parameter which contains the local address of the connected entity. The lpCalleeData is a result parameter used by the condition function to supply user data back to the connecting entity. The storage for this data must be provided by the service provider. lpCalleeData->len initially contains the length of the buffer allocated by the service provider and pointed to by lpCalleeData->buf. A value of zero means passing user data back to the caller is not supported. The condition function will copy up to lpCalleeData->len bytes of data into lpCalleeData->buf , and then update lpCalleeData->len to indicate the actual number of bytes transferred. If no user data is to be passed back to the caller, the condition function will set lpCalleeData->len to zero. The format of all address and user data is specific to the address family to which the socket belongs. The result parameter g is assigned within the condition function to indicate the following actions: if &g is an existing socket group ID, add s to this group, provided all the requirements set by this group are met; or if &g = SG_UNCONSTRAINED_GROUP, create an unconstrained socket group and have s as the first member; or if &g = SG_CONSTRAINED_GROUP, create a constrained socket group and have s as the first member; or if &g = zero, no group operation is performed. Any set of sockets grouped together must be implemented by a single service provider. For unconstrained groups, any set of sockets may be grouped together. A constrained socket group may consist only of connection-oriented sockets, and requires that connections on all grouped sockets be to the same address on the same host. For newly created socket groups, the new group ID must be available for the WinSock SPI client to retrieve by calling WSPGetSockOpt() with option SO_GROUP_ID. A socket group and its associated ID remain valid until the last socket belonging to this socket group is closed. Socket group IDs are unique across all processes for a given service provider. dwCallbackData is supplied to the condition function exactly as supplied by the caller of WSPAccept(). Arguments: s - A descriptor identifying a socket which is listening for connections after a WSPListen(). addr - An optional pointer to a buffer which receives the address of the connecting entity, as known to the service provider. The exact format of the addr argument is determined by the address family established when the socket was created. addrlen - An optional pointer to an integer which contains the length of the address addr. lpfnCondition - The procedure instance address of an optional, WinSock 2 client- supplied condition function which will make an accept/reject decision based on the caller information passed in as parameters, and optionally create and/or join a socket group by assigning an appropriate value to the result parameter, g, of this routine. dwCallbackData - Callback data to be passed back to the WinSock 2 client as a condition function parameter. This parameter is not interpreted by the service provider. lpErrno - A pointer to the error code. Return Value: If no error occurs, WSPAccept() returns a value of type SOCKET which is a descriptor for the accepted socket. Otherwise, a value of INVALID_SOCKET is returned, and a specific error code is available in lpErrno. --*/ { } // WSPAccept INT WSPAPI WSPAddressToString( IN LPSOCKADDR lpsaAddress, IN DWORD dwAddressLength, IN LPWSAPROTOCOL_INFOW lpProtocolInfo, OUT LPWSTR lpszAddressString, IN OUT LPDWORD lpdwAddressStringLength, OUT LPINT lpErrno ) /*++ Routine Description: This routine converts all components of a SOCKADDR structure into a human- readable string representation of the address. This is used mainly for display purposes. Arguments: lpsaAddress - Points to a SOCKADDR structure to translate into a string. dwAddressLength - The length of the Address SOCKADDR. lpProtocolInfo - The WSAPROTOCOL_INFOW struct for a particular provider. lpszAddressString - A buffer which receives the human-readable address string. lpdwAddressStringLength - The length of the AddressString buffer. Returns the length of the string actually copied into the buffer. lpErrno - A pointer to the error code. Return Value: If no error occurs, WSPAddressToString() returns 0. Otherwise, it returns SOCKET_ERROR, and a specific error code is available in lpErrno. --*/ { } // WSPAddressToString INT WSPAPI WSPAsyncSelect( IN SOCKET s, IN HWND hWnd, IN unsigned int wMsg, IN long lEvent, OUT LPINT lpErrno ) /*++ Routine Description: This routine is used to request that the service provider send a Window message to the client's window hWnd whenever it detects any of the network events specified by the lEvent parameter. The service provider should use the WPUPostMessage() function to post the message. The message to be sent is specified by the wMsg parameter. The socket for which notification is required is identified by s. This routine automatically sets socket s to non-blocking mode, regardless of the value of lEvent. See WSPIoctl() about how to set the socket back to blocking mode. The lEvent parameter is constructed by or'ing any of the values specified in the following list. Value Meaning ~~~~~ ~~~~~~~ FD_READ Issue notification of readiness for reading. FD_WRITE Issue notification of readiness for writing. FD_OOB Issue notification of the arrival of out-of-band data. FD_ACCEPT Issue notification of incoming connections. FD_CONNECT Issue notification of completed connection. FD_CLOSE Issue notification of socket closure. FD_QOS Issue notification of socket Quality of Service (QOS) changes. FD_GROUP_QOS Issue notification of socket group Quality of Service (QOS) changes. Invoking WSPAsyncSelect() for a socket cancels any previous WSPAsyncSelect() or WSPEventSelect() for the same socket. For example, to receive notification for both reading and writing, the WinSock SPI client must call WSPAsyncSelect() with both FD_READ and FD_WRITE, as follows: rc = WSPAsyncSelect(s, hWnd, wMsg, FD_READ | FD_WRITE, &error); It is not possible to specify different messages for different events. The following code will not work; the second call will cancel the effects of the first, and only FD_WRITE events will be reported with message wMsg2: rc = WSPAsyncSelect(s, hWnd, wMsg1, FD_READ, &error); rc = WSPAsyncSelect(s, hWnd, wMsg2, FD_WRITE, &error); // bad To cancel all notification - i.e., to indicate that the service provider should send no further messages related to network events on the socket - lEvent will be set to zero. rc = WSPAsyncSelect(s, hWnd, 0, 0, &error); Since a WSPAccept()'ed socket has the same properties as the listening socket used to accept it, any WSPAsyncSelect() events set for the listening socket apply to the accepted socket. For example, if a listening socket has WSPAsyncSelect() events FD_ACCEPT, FD_READ, and FD_WRITE, then any socket accepted on that listening socket will also have FD_ACCEPT, FD_READ, and FD_WRITE events with the same wMsg value used for messages. If a different wMsg or events are desired, the WinSock SPI client must call WSPAsyncSelect(), passing the accepted socket and the desired new information. When one of the nominated network events occurs on the specified socket s, the service provider uses WPUPostMessage() to send message wMsg to the WinSock SPI client's window hWnd. The wParam argument identifies the socket on which a network event has occurred. The low word of lParam specifies the network event that has occurred. The high word of lParam contains any error code. The error code be any error as defined in ws2spi.h. The possible network event codes which may be indicated are as follows: Value Meaning ~~~~~ ~~~~~~~ FD_READ Socket s ready for reading. FD_WRITE Socket s ready for writing. FD_OOB Out-of-band data ready for reading on socket s. FD_ACCEPT Socket s ready for accepting a new incoming connection. FD_CONNECT Connection initiated on socket s completed. FD_CLOSE Connection identified by socket s has been closed. FD_QOS Quality of Service associated with socket s has changed. FD_GROUP_QOS Quality of Service associated with the socket group to which s belongs has changed. Although WSPAsyncSelect() can be called with interest in multiple events, the service provider issues the same Windows message for each event. A WinSock 2 provider shall not continually flood a WinSock SPI client with messages for a particular network event. Having successfully posted notification of a particular event to a WinSock SPI client window, no further message(s) for that network event will be posted to the WinSock SPI client window until the WinSock SPI client makes the function call which implicitly reenables notification of that network event. Event Re-enabling functions ~~~~~ ~~~~~~~~~~~~~~~~~~~~~ FD_READ WSPRecv() or WSPRecvFrom(). FD_WRITE WSPSend() or WSPSendTo(). FD_OOB WSPRecv() or WSPRecvFrom(). FD_ACCEPT WSPAccept() unless the error code returned is WSATRY_AGAIN indicating that the condition function returned CF_DEFER. FD_CONNECT NONE FD_CLOSE NONE FD_QOS WSPIoctl() with SIO_GET_QOS FD_GROUP_QOS WSPIoctl() with SIO_GET_GROUP_QOS Any call to the reenabling routine, even one which fails, results in reenabling of message posting for the relevant event. For FD_READ, FD_OOB, and FD_ACCEPT events, message posting is "level- triggered." This means that if the reenabling routine is called and the relevant condition is still met after the call, a WSPAsyncSelect() message is posted to the WinSock SPI client. The FD_QOS and FD_GROUP_QOS events are considered edge triggered. A message will be posted exactly once when a QOS change occurs. Further messages will not be forthcoming until either the provider detects a further change in QOS or the WinSock SPI client renegotiates the QOS for the socket. If any event has already happened when the WinSock SPI client calls WSPAsyncSelect() or when the reenabling function is called, then a message is posted as appropriate. For example, consider the following sequence: 1. A WinSock SPI client calls WSPListen(). 2. A connect request is received but not yet accepted. 3. The WinSock SPI client calls WSPAsyncSelect() specifying that it wants to receive FD_ACCEPT messages for the socket. Due to the persistence of events, the WinSock service provider posts an FD_ACCEPT message immediately. The FD_WRITE event is handled slightly differently. An FD_WRITE message is posted when a socket is first connected with WSPConnect() (after FD_CONNECT, if also registered) or accepted with WSPAccept(), and then after a WSPSend() or WSPSendTo() fails with WSAEWOULDBLOCK and buffer space becomes available. Therefore, a WinSock SPI client can assume that sends are possible starting from the first FD_WRITE message and lasting until a send returns WSAEWOULDBLOCK. After such a failure the WinSock SPI client will be notified that sends are again possible with an FD_WRITE message. The FD_OOB event is used only when a socket is configured to receive out-of-band data separately. If the socket is configured to receive out-of-band data in-line, the out-of-band (expedited) data is treated as normal data and the WinSock SPI client must register an interest in FD_READ events, not FD_OOB events. The error code in an FD_CLOSE message indicates whether the socket close was graceful or abortive. If the error code is 0, then the close was graceful; if the error code is WSAECONNRESET, then the socket's virtual circuit was reset. This only applies to connection-oriented sockets such as SOCK_STREAM. The FD_CLOSE message is posted when a close indication is received for the virtual circuit corresponding to the socket. In TCP terms, this means that the FD_CLOSE is posted when the connection goes into the TIME WAIT or CLOSE WAIT states. This results from the remote end performing a WSPShutdown() on the send side or a WSPCloseSocket(). FD_CLOSE shall only be posted after all data is read from a socket. In the case of a graceful close, the service provider shall only send an FD_CLOSE message to indicate virtual circuit closure after all the received data has been read. It shall NOT send an FD_READ message to indicate this condition. The FD_QOS or FD_GROUP_QOS message is posted when any field in the flow spec associated with socket s or the socket group that s belongs to has changed, respectively. The service provider must update the QOS information available to the client via WSPIoctl() with SIO_GET_QOS and/or SIO_GET_GROUP_QOS. Here is a summary of events and conditions for each asynchronous notification message: FD_READ ~~~~~~~ 1. When WSPAsyncSelect() called, if there is data currently available to receive. 2. When data arrives, if FD_READ not already posted. 3. after WSPRecv() or WSPRecvfrom() called (with or without MSG_PEEK), if data is still available to receive. N.B. When WSPSetSockOpt() SO_OOBINLINE is enabled "data" includes both normal data and out-of-band (OOB) data in the instances noted above. FD_WRITE ~~~~~~~~ 1. When WSPAsyncSelect() called, if a WSPSend() or WSPSendTo() is possible. 2. After WSPConnect() or WSPAccept() called, when connection established. 3. After WSPSend() or WSPSendTo() fail with WSAEWOULDBLOCK, when WSPSend() or WSPSendTo() are likely to succeed. 4. After WSPBind() on a datagram socket. FD_OOB ~~~~~~ Only valid when WSPSetSockOpt() SO_OOBINLINE is disabled (default). 1. When WSPAsyncSelect() called, if there is OOB data currently available to receive with the MSG_OOB flag. 2. When OOB data arrives, if FD_OOB not already posted. 3. After WSPRecv() or WSPRecvfrom() called with or without MSG_OOB flag, if OOB data is still available to receive. FD_ACCEPT ~~~~~~~~~ 1. When WSPAsyncSelect() called, if there is currently a connection request available to accept. 2. When a connection request arrives, if FD_ACCEPT not already posted. 3. After WSPAccept() called, if there is another connection request available to accept. FD_CONNECT ~~~~~~~~~~ 1. When WSPAsyncSelect() called, if there is currently a connection established. 2. After WSPConnect() called, when connection is established (even when WSPConnect() succeeds immediately, as is typical with a datagram socket) FD_CLOSE ~~~~~~~~ Only valid on connection-oriented sockets (e.g. SOCK_STREAM) 1. When WSPAsyncSelect() called, if socket connection has been closed. 2. After remote system initiated graceful close, when no data currently available to receive (note: if data has been received and is waiting to be read when the remote system initiates a graceful close, the FD_CLOSE is not delivered until all pending data has been read). 3. After local system initiates graceful close with WSPShutdown() and remote system has responded with "End of Data" notification (e.g. TCP FIN), when no data currently available to receive. 4. When remote system aborts connection (e.g. sent TCP RST), and lParam will contain WSAECONNRESET error value. N.B. FD_CLOSE is not posted after WSPClosesocket() is called. FD_QOS ~~~~~~ 1. When WSPAsyncSelect() called, if the QOS associated with the socket has been changed. 2. After WSPIoctl() with SIO_GET_QOS called, when the QOS is changed. FD_GROUP_QOS ~~~~~~~~~~~~ 1. When WSPAsyncSelect() called, if the group QOS associated with the socket has been changed. 2. After WSPIoctl() with SIO_GET_GROUP_QOS called, when the group QOS is changed. Arguments: s - A descriptor identifying the socket for which event notification is required. hWnd - A handle identifying the window which should receive a message when a network event occurs. wMsg - The message to be sent when a network event occurs. lEvent - A bitmask which specifies a combination of network events in which the WinSock SPI client is interested. lpErrno - A pointer to the error code. Return Value: The return value is 0 if the WinSock SPI client's declaration of interest in the network event set was successful. Otherwise the value SOCKET_ERROR is returned, and a specific error code is available in lpErrno. --*/ { } // WSPAsyncSelect INT WSPAPI WSPBind( IN SOCKET s, IN const struct sockaddr FAR * name, IN int namelen, OUT LPINT lpErrno ) /*++ Routine Description: This routine is used on an unconnected connectionless or connection- oriented socket, before subsequent WSPConnect()s or WSPListen()s. When a socket is created with WSPSocket(), it exists in a name space (address family), but it has no name or local address assigned. WSPBind() establishes the local association of the socket by assigning a local name to an unnamed socket. As an example, in the Internet address family, a name consists of three parts: the address family, a host address, and a port number which identifies the WinSock SPI client. In WinSock 2, the name parameter is not strictly interpreted as a pointer to a "sockaddr" struct. Service providers are free to regard it as a pointer to a block of memory of size namelen. The first two bytes in this block (corresponding to "sa_family" in the "sockaddr" declaration) must contain the address family that was used to create the socket. Otherwise the error WSAEFAULT shall be indicated. If a WinSock 2 SPI client does not care what local address is assigned to it, it will specify the manifest constant value ADDR_ANY for the sa_data field of the name parameter. This instructs the service provider to use any appropriate network address. For TCP/IP, if the port is specified as 0, the service provider will assign a unique port to the WinSock SPI client with a value between 1024 and 5000. The SPI client may use WSPGetSockName() after WSPBind() to learn the address and the port that has been assigned to it, but note that if the Internet address is equal to INADDR_ANY, WSPGetSockOpt() will not necessarily be able to supply the address until the socket is connected, since several addresses may be valid if the host is multi-homed. Arguments: s - A descriptor identifying an unbound socket. name - The address to assign to the socket. The sockaddr structure is defined as follows: struct sockaddr { u_short sa_family; char sa_data[14]; }; Except for the sa_family field, sockaddr contents are expressed in network byte order. namelen - The length of the name. lpErrno - A pointer to the error code. Return Value: If no error occurs, WSPBind() returns 0. Otherwise, it returns SOCKET_ERROR, and a specific error code is available in lpErrno. --*/ { } // WSPBind INT WSPAPI WSPCancelBlockingCall( OUT LPINT lpErrno ) /*++ Routine Description: This routine cancels any outstanding blocking operation for this thread. It is normally used in two situations: 1. A WinSock SPI client is processing a message which has been received while a service provider is implementing pseudo blocking. In this case, WSAIsBlocking() will be true. 2. A blocking call is in progress, and the WinSock service provider has called back to the WinSock SPI client's "blocking hook" function (via the callback function retrieved from WPUQueryBlockingCallback()), which in turn is invoking this function. Such a situation might arise, for instance, in implementing a Cancel option for an operation which require an extended time to complete. In each case, the original blocking call will terminate as soon as possible with the error WSAEINTR. (In (1), the termination will not take place until Windows message scheduling has caused control to revert back to the pseudo blocking routine in WinSock. In (2), the blocking call will be terminated as soon as the blocking hook function completes.) In the case of a blocking WSPConnect() operation, WinSock will terminate the blocking call as soon as possible, but it may not be possible for the socket resources to be released until the connection has completed (and then been reset) or timed out. This is likely to be noticeable only if the WinSock SPI client immediately tries to open a new socket (if no sockets are available), or to WSPConnect() to the same peer. Canceling an WSPAccept() or a WSPSelect() call does not adversely impact the sockets passed to these calls. Only the particular call fails; any operation that was legal before the cancel is legal after the cancel, and the state of the socket is not affected in any way. Canceling any operation other than WSPAccept() and WSPSelect() can leave the socket in an indeterminate state. If a WinSock SPI client cancels a blocking operation on a socket, the only operation that the WinSock SPI client can depend on being able to perform on the socket is a call to WSPCloseSocket(), although other operations may work on some WinSock service providers. If a WinSock SPI client desires maximum portability, it must be careful not to depend on performing operations after a cancel. A WinSock SPI client may reset the connection by setting the timeout on SO_LINGER to 0 and calling WSPCloseSocket(). If a cancel operation compromised the integrity of a SOCK_STREAM's data stream in any way, the WinSock provider will reset the connection and fail all future operations other than WSPCloseSocket() with WSAECONNABORTED. Note it is acceptable for WSPCancelBlockingCall() to return successfully if the blocking network operation completes prior to being canceled. In this case, the blocking operation will return successfully as if WSPCancelBlockingCall() had never been called. The only way for the WinSock SPI client to know with certainty that an operation was actually canceled is to check for a return code of WSAEINTR from the blocking call. Arguments: lpErrno - A pointer to the error code. Return Value: The value returned by WSPCancelBlockingCall() is 0 if the operation was successfully canceled. Otherwise the value SOCKET_ERROR is returned, and a specific error code is available in lpErrno. --*/ { } // WSPCancelBlockingCall INT WSPAPI WSPCleanup( OUT LPINT lpErrno ) /*++ Routine Description: The WinSock 2 SPI client is required to perform a successful WSPStartup() call before it can use WinSock service providers. When it has completed the use of WinSock service providers, the SPI client will call WSPCleanup() to deregister itself from a WinSock service provider and allow the service provider to free any resources allocated on behalf of the WinSock 2 client. It is permissible for SPI clients to make more than one WSPStartup() call. For each WSPStartup() call a corresponding WSPCleanup() call will also be issued. Only the final WSPCleanup() for the service provider does the actual cleanup; the preceding calls simply decrement an internal reference count in the WinSock service provider. When the internal reference count reaches zero and actual cleanup operations commence, any pending blocking or asynchronous calls issued by any thread in this process are canceled without posting any notification messages or signaling any event objects. Any pending overlapped send and receive operations (WSPSend()/WSPSendTo()/WSPRecv()/WSPRecvFrom() with an overlapped socket) issued by any thread in this process are also canceled without setting the event object or invoking the completion routine, if specified. In this case, the pending overlapped operations fail with the error status WSA_OPERATION_ABORTED. Any sockets open when WSPCleanup() is called are reset and automatically deallocated as if WSPClosesocket() was called; sockets which have been closed with WSPCloseSocket() but which still have pending data to be sent are not affected--the pending data is still sent. This routine should not return until the service provider DLL is prepared to be unloaded from memory. In particular, any data remaining to be transmitted must either already have been sent or be queued for transmission by portions of the transport stack that will not be unloaded from memory along with the service provider's DLL. A WinSock service provider must be prepared to deal with a process which terminates without invoking WSPCleanup() - for example, as a result of an error. A WinSock service provider must ensure that WSPCleanup() leaves things in a state in which the WinSock 2 DLL can immediately invoke WSPStartup() to re-establish WinSock usage. Arguments: lpErrno - A pointer to the error code. Return Value: The return value is 0 if the operation has been successfully initiated. Otherwise the value SOCKET_ERROR is returned, and a specific error number is available in lpErrno. --*/ { } // WSPCleanup INT WSPAPI WSPCloseSocket( IN SOCKET s, OUT LPINT lpErrno ) /*++ Routine Description: This routine closes a socket. More precisely, it releases the socket descriptor s, so that further references to s should fail with the error WSAENOTSOCK. If this is the last reference to an underlying socket, the associated naming information and queued data are discarded. Any blocking, asynchronous or overlapped calls pending on the socket (issued by any thread in this process) are canceled without posting any notification messages, signaling any event objects or invoking any completion routines. In this case, the pending overlapped operations fail with the error status WSA_OPERATION_ABORTED. FD_CLOSE will not be posted after WSPCloseSocket() is called. WSPClosesocket() behavior is summarized as follows: If SO_DONTLINGER enabled (the default setting) WSPCloseSocket() returns immediately - connection is gracefully closed "in the background". If SO_LINGER enabled with a zero timeout, WSPCloseSocket() returns immediately - connection is reset/aborted. If SO_LINGER enabled with non-zero timeout: - With a blocking socket, WSPCloseSocket() blocks until all data sent or timeout expires. - With a non-blocking socket, WSPCloseSocket() returns immediately indicating failure. The semantics of WSPCloseSocket() are affected by the socket options SO_LINGER and SO_DONTLINGER as follows: Option Interval Type of close Wait for close? ~~~~~~ ~~~~~~~~ ~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~ SO_DONTLINGER Don't care Graceful No SO_LINGER Zero Hard No SO_LINGER Non-zero Graceful Yes If SO_LINGER is set (i.e. the l_onoff field of the linger structure is non-zero) and the timeout interval, l_linger, is zero, WSPClosesocket() is not blocked even if queued data has not yet been sent or acknowledged. This is called a "hard" or "abortive" close, because the socket's virtual circuit is reset immediately, and any unsent data is lost. Any WSPRecv() call on the remote side of the circuit will fail with WSAECONNRESET. If SO_LINGER is set with a non-zero timeout interval on a blocking socket, the WSPClosesocket() call blocks on a blocking socket until the remaining data has been sent or until the timeout expires. This is called a graceful disconnect. If the timeout expires before all data has been sent, the service provider should abort the connection before WSPClosesocket() returns. Enabling SO_LINGER with a non-zero timeout interval on a non-blocking socket is not recommended. In this case, the call to WSPClosesocket() will fail with an error of WSAEWOULDBLOCK if the close operation cannot be completed immediately. If WSPClosesocket() fails with WSAEWOULDBLOCK the socket handle is still valid, and a disconnect is not initiated. The WinSock SPI client must call WSPClosesocket() again to close the socket, although WSPClosesocket() may continue to fail unless the WinSock SPI client disables SO_DONTLINGER, enables SO_LINGER with a zero timeout, or calls WSPShutdown() to initiate closure. If SO_DONTLINGER is set on a stream socket (i.e. the l_onoff field of the linger structure is zero), the WSPClosesocket() call will return immediately. However, any data queued for transmission will be sent if possible before the underlying socket is closed. This is called a graceful disconnect and is the default behavior. Note that in this case the WinSock provider is allowed to retain any resources associated with the socket until such time as the graceful disconnect has completed or the provider aborts the connection due to an inability to complete the operation in a provider-determined amount of time. This may affect Winsock clients which expect to use all available sockets. Arguments: s - A descriptor identifying a socket. lpErrno - A pointer to the error code. Return Value: If no error occurs, WSPCloseSocket() returns 0. Otherwise, a value of SOCKET_ERROR is returned, and a specific error code is available in lpErrno. --*/ { } // WSPCloseSocket INT WSPAPI WSPConnect( IN SOCKET s, IN const struct sockaddr FAR * name, IN int namelen, IN LPWSABUF lpCallerData, OUT LPWSABUF lpCalleeData, IN LPQOS lpSQOS, IN LPQOS lpGQOS, OUT LPINT lpErrno ) /*++ Routine Description: This routine is used to create a connection to the specified destination, and to perform a number of other ancillary operations that occur at connect time as well. If the socket, s, is unbound, unique values are assigned to the local association by the system, and the socket is marked as bound. For connection-oriented sockets (e.g., type SOCK_STREAM), an active connection is initiated to the specified host using name (an address in the name space of the socket; for a detailed description, please see WSPBind()). When this call completes successfully, the socket is ready to send/receive data. If the address field of the name structure is all zeroes, WSPConnect() will return the error WSAEADDRNOTAVAIL. Any attempt to re-connect an active connection will fail with the error code WSAEISCONN. For a connectionless socket (e.g., type SOCK_DGRAM), the operation performed by WSPConnect() is to establish a default destination address so that the socket may be used with subsequent connection-oriented send and receive operations (WSPSend(),WSPRecv()). Any datagrams received from an address other than the destination address specified will be discarded. If the address field of the name structure is all zeroes, the socket will be "dis-connected" - the default remote address will be indeterminate, so WSPSend() and WSPRecv() calls will return the error code WSAENOTCONN, although WSPSendTo() and WSPRecvFrom() may still be used. The default destination may be changed by simply calling WSPConnect() again, even if the socket is already "connected". Any datagrams queued for receipt are discarded if name is different from the previous WSPConnect(). For connectionless sockets, name may indicate any valid address, including a broadcast address. However, to connect to a broadcast address, a socket must have WSPSetSockOpt() SO_BROADCAST enabled, otherwise WSPConnect() will fail with the error code WSAEACCES. On connectionless sockets, exchange of user to user data is not possible and the corresponding parameters will be silently ignored. The WinSock SPI client is responsible for allocating any memory space pointed to directly or indirectly by any of the parameters it specifies. The lpCallerData is a value parameter which contains any user data that is to be sent along with the connection request. If lpCallerData is NULL, no user data will be passed to the peer. The lpCalleeData is a result parameter which will reference any user data passed back from the peer as part of the connection establishment. lpCalleeData->len initially contains the length of the buffer allocated by the WinSock SPI client and pointed to by lpCalleeData->buf. lpCalleeData->len will be set to 0 if no user data has been passed back. The lpCalleeData information will be valid when the connection operation is complete. For blocking sockets, this will be when the WSPConnect() function returns. For non-blocking sockets, this will be after the FD_CONNECT notification has occurred. If lpCalleeData is NULL, no user data will be passed back. The exact format of the user data is specific to the address family to which the socket belongs and/or the applications involved. At connect time, a WinSock SPI client may use the lpSQOS and/or lpGQOS parameters to override any previous QOS specification made for the socket via WSPIoctl() with either the SIO_SET_QOS or SIO_SET_GROUP_QOS opcodes. lpSQOS specifies the flow specs for socket s, one for each direction, followed by any additional provider-specific parameters. If either the associated transport provider in general or the specific type of socket in particular cannot honor the QOS request, an error will be returned as indicated below. The sending or receiving flow spec values will be ignored, respectively, for any unidirectional sockets. If no provider-specific parameters are supplied, the buf and len fields of lpSQOS->ProviderSpecific should be set to NULL and 0, respectively. A NULL value for lpSQOS indicates no application supplied QOS. lpGQOS specifies the flow specs for the socket group (if applicable), one for each direction, followed by any additional provider-specific parameters. If no provider- specific parameters are supplied, the buf and len fields of lpSQOS->ProviderSpecific should be set to NULL and 0, respectively. A NULL value for lpGQOS indicates no application-supplied group QOS. This parameter will be ignored if s is not the creator of the socket group. When connected sockets break (i.e. become closed for whatever reason), they should be discarded and recreated. It is safest to assume that when things go awry for any reason on a connected socket, the WinSock SPI client must discard and recreate the needed sockets in order to return to a stable point. Arguments: s - A descriptor identifying an unconnected socket. name- The name of the peer to which the socket is to be connected. namelen - The length of the name. lpCallerData - A pointer to the user data that is to be transferred to the peer during connection establishment. lpCalleeData - A pointer to a buffer into which may be copied any user data received from the peer during connection establishment. lpSQOS - A pointer to the flow specs for socket s, one for each direction. lpGQOS - A pointer to the flow specs for the socket group (if applicable). lpErrno - A pointer to the error code. Return Value: If no error occurs, WSPConnect() returns 0. Otherwise, it returns SOCKET_ERROR, and a specific error code is available in lpErrno. --*/ { } // WSPConnect INT WSPAPI WSPDuplicateSocket( IN SOCKET s, IN DWORD dwProcessId, OUT LPWSAPROTOCOL_INFOW lpProtocolInfo, OUT LPINT lpErrno ) /*++ Routine Description: A source process calls WSPDuplicateSocket() to obtain a special WSAPROTOCOL_INFOW structure. It uses some interprocess communications (IPC) mechanism to pass the contents of this structure to a target process, which in turn uses it in a call to WSPSocket() to obtain a descriptor for the duplicated socket. Note that the special WSAPROTOCOL_INFOW structure may only be used once by the target process. It is the service provider's responsibility to perform whatever operations are needed in the source process context and to create a WSAPROTOCOL_INFOW structure that will be recognized when it subsequently appears as a parameter to WSPSocket() in the target processes' context. The provider must then return a socket descriptor that references a common underlying socket. The dwProviderReserved field of the WSAPROTOCOL_INFOW struct is available for the service provider's use, and may be used to store any useful context information, including a duplicated handle. When new socket descriptors are allocated IFS providers must call WPUModifyIFSHandle() and non-IFS providers must call WPUCreateSocketHandle(). The descriptors that reference a shared socket may be used independently as far as I/O is concerned. However, the WinSock interface does not implement any type of access control, so it is up to the processes involved to coordinate their operations on a shared socket. A typical use for shared sockets is to have one process that is responsible for creating sockets and establishing connections, hand off sockets to other processes which are responsible for information exchange. Since what is duplicated are the socket descriptors and not the underlying socket, all of the state associated with a socket is held in common across all the descriptors. For example a WSPSetSockOpt() operation performed using one descriptor is subsequently visible using a WSPGetSockOpt() from any or all descriptors. A process may call WSPClosesocket() on a duplicated socket and the descriptor will become deallocated. The underlying socket, however, will remain open until WSPClosesocket() is called by the last remaining descriptor. Notification on shared sockets is subject to the usual constraints of WSPAsyncSelect() and WSPEventSelect(). Issuing either of these calls using any of the shared descriptors cancels any previous event registration for the socket, regardless of which descriptor was used to make that registration. Thus, for example, a shared socket cannot deliver FD_READ events to process A and FD_WRITE events to process B. For situations when such tight coordination is required, it is suggested that developers use threads instead of separate processes. Arguments: s - Specifies the local socket descriptor. dwProcessId - Specifies the ID of the target process for which the shared socket will be used. lpProtocolInfo - A pointer to a buffer allocated by the client that is large enough to contain a WSAPROTOCOL_INFOW struct. The service provider copies the protocol info struct contents to this buffer. lpErrno - A pointer to the error code. Return Value: If no error occurs, WSPDuplicateSocket() returns zero. Otherwise, the value of SOCKET_ERROR is returned, and a specific error number is available in lpErrno. --*/ { } // WSPDuplicateSocket INT WSPAPI WSPEnumNetworkEvents( IN SOCKET s, IN WSAEVENT hEventObject, OUT LPWSANETWORKEVENTS lpNetworkEvents, OUT LPINT lpErrno ) /*++ Routine Description: This routine is used to report which network events have occurred for the indicated socket since the last invocation of this routine. It is intended for use in conjunction with WSPEventSelect(), which associates an event object with one or more network events. Recording of network events commences when WSPEventSelect() is called with a non-zero lNetworkEvents parameter and remains in effect until another call is made to WSPEventSelect() with the lNetworkEvents parameter set to zero, or until a call is made to WSPAsyncSelect(). The socket's internal record of network events is copied to the structure referenced by lpNetworkEvents, whereafter the internal network events record is cleared. If hEventObject is non-null, the indicated event object is also reset. The WinSock provider guarantees that the operations of copying the network event record, clearing it and resetting any associated event object are atomic, such that the next occurrence of a nominated network event will cause the event object to become set. In the case of this function returning SOCKET_ERROR, the associated event object is not reset and the record of network events is not cleared. The WSANETWORKEVENTS structure is defined as follows: typedef struct _WSANETWORKEVENTS { long lNetworkEvents; int iErrorCodes[FD_MAX_EVENTS]; } WSANETWORKEVENTS, FAR * LPWSANETWORKEVENTS; The lNetworkEvent field of the structure indicates which of the FD_XXX network events have occurred. The iErrorCodes array is used to contain any associated error codes, with array index corresponding to the position of event bits in lNetworkEvents. The identifiers FD_READ_BIT, FD_WRITE_BIT, etc. may be used to index the iErrorCodes array. Arguments: s - A descriptor identifying the socket. hEventObject - An optional handle identifying an associated event object to be reset. lpNetworkEvents - A pointer to a WSANETWORKEVENTS struct which is filled with a record of occurred network events and any associated error codes. lpErrno - A pointer to the error code. Return Value: The return value is 0 if the operation was successful. Otherwise the value SOCKET_ERROR is returned, and a specific error number is available in lpErrno. --*/ { } // WSPEnumNetworkEvents INT WSPAPI WSPEventSelect( IN SOCKET s, IN WSAEVENT hEventObject, IN long lNetworkEvents, OUT LPINT lpErrno ) /*++ Routine Description: This routine is used to specify an event object, hEventObject, to be associated with the selected network events, lNetworkEvents. The socket for which an event object is specified is identified by s. The event object is set when any of the nominated network events occur. WSPEventSelect() operates very similarly to WSPAsyncSelect(), the difference being in the actions taken when a nominated network event occurs. Whereas WSPAsyncSelect() causes a WinSock SPI client-specified Windows message to be posted, WSPEventSelect() sets the associated event object and records the occurrence of this event in an internal network event record. A WinSock SPI client can use WSPEnumNetworkEvents() to retrieve the contents of the internal network event record and thus determine which of the nominated network events have occurred. This routine automatically sets socket s to non-blocking mode, regardless of the value of lNetworkEvents. The lNetworkEvents parameter is constructed by OR'ing any of the values specified in the following list. Value Meaning ~~~~~ ~~~~~~~ FD_READ Issue notification of readiness for reading. FD_WRITE Issue notification of readiness for writing. FD_OOB Issue notification of the arrival of out-of-band data. FD_ACCEPT Issue notification of incoming connections. FD_CONNECT Issue notification of completed connection. FD_CLOSE Issue notification of socket closure. FD_QOS Issue notification of socket Quality of Service (QOS) changes. FD_GROUP_QOS Issue notification of socket group Quality of Service (QOS) changes. Issuing a WSPEventSelect() for a socket cancels any previous WSPAsyncSelect() or WSPEventSelect() for the same socket and clears the internal network event record. For example, to associate an event object with both reading and writing network events, the WinSock SPI client must call WSPEventSelect() with both FD_READ and FD_WRITE, as follows: rc = WSPEventSelect(s, hEventObject, FD_READ | FD_WRITE); It is not possible to specify different event objects for different network events. The following code will not work; the second call will cancel the effects of the first, and only FD_WRITE network event will be associated with hEventObject2: rc = WSPEventSelect(s, hEventObject1, FD_READ); rc = WSPEventSelect(s, hEventObject2, FD_WRITE); //bad To cancel the association and selection of network events on a socket, lNetworkEvents should be set to zero, in which case the hEventObject parameter will be ignored. rc = WSPEventSelect(s, hEventObject, 0); Closing a socket with WSPCloseSocket() also cancels the association and selection of network events specified in WSPEventSelect() for the socket. The WinSock SPI client, however, still must call WSACloseEvent() to explicitly close the event object and free any resources. Since a WSPAccept()'ed socket has the same properties as the listening socket used to accept it, any WSPEventSelect() association and network events selection set for the listening socket apply to the accepted socket. For example, if a listening socket has WSPEventSelect() association of hEventOject with FD_ACCEPT, FD_READ, and FD_WRITE, then any socket accepted on that listening socket will also have FD_ACCEPT, FD_READ, and FD_WRITE network events associated with the same hEventObject. If a different hEventObject or network events are desired, the WinSock SPI client should call WSPEventSelect(), passing the accepted socket and the desired new information. Having successfully recorded the occurrence of the network event and signaled the associated event object, no further actions are taken for that network event until the WinSock SPI client makes the function call which implicitly reenables the setting of that network event and signaling of the associated event object. Event Re-enabling functions ~~~~~ ~~~~~~~~~~~~~~~~~~~~~ FD_READ WSPRecv() or WSPRecvFrom(). FD_WRITE WSPSend() or WSPSendTo(). FD_OOB WSPRecv() or WSPRecvFrom(). FD_ACCEPT WSPAccept() unless the error code returned is WSATRY_AGAIN indicating that the condition function returned CF_DEFER. FD_CONNECT NONE FD_CLOSE NONE FD_QOS WSPIoctl() with SIO_GET_QOS FD_GROUP_QOS WSPIoctl() with SIO_GET_GROUP_QOS Any call to the reenabling routine, even one which fails, results in reenabling of recording and signaling for the relevant network event and event object, respectively. For FD_READ, FD_OOB, and FD_ACCEPT network events, network event recording and event object signaling are "level-triggered." This means that if the reenabling routine is called and the relevant network condition is still valid after the call, the network event is recorded and the associated event object is signaled . This allows a WinSock SPI client to be event- driven and not be concerned with the amount of data that arrives at any one time. Consider the following sequence: 1. The service provider receives 100 bytes of data on socket s, records the FD_READ network event and signals the associated event object. 2. The WinSock SPI client issues WSPRecv( s, buffptr, 50, 0) to read 50 bytes. 3. The service provider records the FD_READ network event and signals the associated event object again since there is still data to be read. With these semantics, a WinSock SPI client need not read all available data in response to an FD_READ network event --a single WSPRecv() in response to each FD_READ network event is appropriate. The FD_QOS and FD_GROUP_QOS events are considered edge triggered. A message will be posted exactly once when a QOS change occurs. Further indications will not be issued until either the service provider detects a further change in QOS or the WinSock SPI client renegotiates the QOS for the socket. If a network event has already happened when the WinSock SPI client calls WSPEventSelect() or when the reenabling function is called, then a network event is recorded and the associated event object is signaled as appropriate. For example, consider the following sequence: 1. A WinSock SPI client calls WSPListen(). 2. A connect request is received but not yet accepted. 3. The WinSock SPI client calls WSPEventSelect() specifying that it is interested in the FD_ACCEPT network event for the socket. The service provider records the FD_ACCEPT network event and signals the associated event object immediately. The FD_WRITE network event is handled slightly differently. An FD_WRITE network event is recorded when a socket is first connected with WSPConnect() or accepted with WSPAccept(), and then after a WSPSend() or WSPSendTo() fails with WSAEWOULDBLOCK and buffer space becomes available. Therefore, a WinSock SPI client can assume that sends are possible starting from the first FD_WRITE network event setting and lasting until a send returns WSAEWOULDBLOCK. After such a failure the WinSock SPI client will find out that sends are again possible when an FD_WRITE network event is recorded and the associated event object is signaled. The FD_OOB network event is used only when a socket is configured to receive out-of-band data separately. If the socket is configured to receive out-of-band data in-line, the out-of-band (expedited) data is treated as normal data and the WinSock SPI client should register an interest in, and will get, FD_READ network event, not FD_OOB network event. A WinSock SPI client may set or inspect the way in which out-of-band data is to be handled by using WSPSetSockOpt() or WSPGetSockOpt() for the SO_OOBINLINE option. The error code in an FD_CLOSE network event indicates whether the socket close was graceful or abortive. If the error code is 0, then the close was graceful; if the error code is WSAECONNRESET, then the socket's virtual circuit was reset. This only applies to connection-oriented sockets such as SOCK_STREAM. The FD_CLOSE network event is recorded when a close indication is received for the virtual circuit corresponding to the socket. In TCP terms, this means that the FD_CLOSE is recorded when the connection goes into the FIN WAIT or CLOSE WAIT states. This results from the remote end performing a WSPShutdown() on the send side or a WSPCloseSocket(). Service providers shall record ONLY an FD_CLOSE network event to indicate closure of a virtual circuit, they shall NOT record an FD_READ network event to indicate this condition. The FD_QOS or FD_GROUP_QOS network event is recorded when any field in the flow spec associated with socket s or the socket group that s belongs to has changed, respectively. This change must be made available to WinSock SPI clients via the WSPIoctl() function with SIO_GET_QOS and/or SIO_GET_GROUP_QOS to retrieve the current QOS for socket s or for the socket group s belongs to, respectively. Arguments: s - A descriptor identifying the socket. hEventObject - A handle identifying the event object to be associated with the supplied set of network events. lNetworkEvents - A bitmask which specifies the combination of network events in which the WinSock SPI client has interest. lpErrno - A pointer to the error code. Return Value: The return value is 0 if the WinSock SPI client's specification of the network events and the associated event object was successful. Otherwise the value SOCKET_ERROR is returned, and a specific error number is available in lpErrno. --*/ { } // WSPEventSelect BOOL WSPAPI WSPGetOverlappedResult( IN SOCKET s, IN LPWSAOVERLAPPED lpOverlapped, OUT LPDWORD lpcbTransfer, IN BOOL fWait, OUT LPDWORD lpdwFlags, OUT LPINT lpErrno ) /*++ Routine Description: The results reported by the WSPGetOverlappedResult() function are those of the specified socket's last overlapped operation to which the specified WSAOVERLAPPED structure was provided, and for which the operation's results were pending. A pending operation is indicated when the function that started the operation returns FALSE, and the lpErrno is WSA_IO_PENDING. When an I/O operation is pending, the function that started the operation resets the hEvent member of the WSAOVERLAPPED structure to the nonsignaled state. Then when the pending operation has been completed, the system sets the event object to the signaled state. If the fWait parameter is TRUE, WSPGetOverlappedResult() determines whether the pending operation has been completed by blocking and waiting for the event object to be in the signaled state. Arguments: s - Identifies the socket. This is the same socket that was specified when the overlapped operation was started by a call to WSPRecv(), WSPRecvFrom(), WSPSend(), WSPSendTo(), or WSPIoctl(). lpOverlapped - Points to a WSAOVERLAPPED structure that was specified when the overlapped operation was started. lpcbTransfer - Points to a 32-bit variable that receives the number of bytes that were actually transferred by a send or receive operation, or by WSPIoctl(). fWait - Specifies whether the function should wait for the pending overlapped operation to complete. If TRUE, the function does not return until the operation has been completed. If FALSE and the operation is still pending, the function returns FALSE and lpErrno is WSA_IO_INCOMPLETE. lpdwFlags - Points to a 32-bit variable that will receive one or more flags that supplement the completion status. If the overlapped operation was initiated via WSPRecv() or WSPRecvFrom(), this parameter will contain the results value for lpFlags parameter. lpErrno - A pointer to the error code. Return Value: If WSPGetOverlappedResult() succeeds, the return value is TRUE. This means that the overlapped operation has completed successfully and that the value pointed to by lpcbTransfer has been updated. If WSPGetOverlappedResult() returns FALSE, this means that either the overlapped operation has not completed or the overlapped operation completed but with errors, or that completion status could not be determined due to errors in one or more parameters to WSPGetOverlappedResult(). On failure, the value pointed to by lpcbTransfer will not be updated. lpErrno indicates the cause of the failure (either of WSPGetOverlappedResult() or of the associated overlapped operation). --*/ { } // WSPGetOverlappedResult INT WSPAPI WSPGetPeerName( IN SOCKET s, OUT struct sockaddr FAR * name, IN OUT LPINT namelen, OUT LPINT lpErrno ) /*++ Routine Description: This routine supplies the name of the peer connected to the socket s and stores it in the struct sockaddr referenced by name. It may be used only on a connected socket. For datagram sockets, only the name of a peer specified in a previous WSPConnect() call will be returned - any name specified by a previous WSPSendTo() call will not be returned by WSPGetPeerName(). On return, the namelen argument contains the actual size of the name returned in bytes. Arguments: s - A descriptor identifying a connected socket. name - A pointer to the structure which is to receive the name of the peer. namelen - A pointer to an integer which, on input, indicates the size of the structure pointed to by name, and on output indicates the size of the returned name. lpErrno - A pointer to the error code. Return Value: If no error occurs, WSPGetPeerName() returns 0. Otherwise, a value of SOCKET_ERROR is returned, and a specific error code is available in lpErrno. --*/ { } // WSPGetPeerName BOOL WSPAPI WSPGetQOSByName( IN SOCKET s, IN LPWSABUF lpQOSName, OUT LPQOS lpQOS, OUT LPINT lpErrno ) /*++ Routine Description: Clients may use this routine to initialize a QOS structure to a set of known values appropriate for a particular service class or media type. These values are stored in a template which is referenced by a well-known name Arguments: s - A descriptor identifying a socket. lpQOSName - Specifies the QOS template name. lpQOS - A pointer to the QOS structure to be filled. lpErrno - A pointer to the error code. Return Value: If no error occurs, WSPGetQOSByName() returns TRUE. Otherwise, a value of FALSE is returned, and a specific error code is available in lpErrno. --*/ { } // WSPGetQOSByName INT WSPAPI WSPGetSockName( IN SOCKET s, OUT struct sockaddr FAR * name, IN OUT LPINT namelen, OUT LPINT lpErrno ) /*++ Routine Description: This routine retrieves the current name for the specified socket descriptor in name. It is used on a bound and/or connected socket specified by the s parameter. The local association is returned. This call is especially useful when a WSPConnect() call has been made without doing a WSPBind() first; as this call provides the only means by which the local association that has been set by the service provider can be determined. If a socket was bound to an unspecified address (e.g., ADDR_ANY), indicating that any of the host's addresses within the specified address family should be used for the socket, WSPGetSockName() will not necessarily return information about the host address, unless the socket has been connected with WSPConnect() or WSPAccept. The WinSock SPI client must not assume that an address will be specified unless the socket is connected. This is because for a multi-homed host the address that will be used for the socket is unknown until the socket is connected. Arguments: s - A descriptor identifying a bound socket. name - A pointer to a structure used to supply the address (name) of the socket. namelen - A pointer to an integer which, on input, indicates the size of the structure pointed to by name, and on output indicates the size of the returned name. lpErrno - A pointer to the error code. Return Value: If no error occurs, WSPGetSockName() returns 0. Otherwise, a value of SOCKET_ERROR is returned, and a specific error code is available in lpErrno. --*/ { } // WSPGetSockName INT WSPAPI WSPGetSockOpt( IN SOCKET s, IN int level, IN int optname, OUT char FAR * optval, IN OUT LPINT optlen, OUT LPINT lpErrno ) /*++ Routine Description: This routine retrieves the current value for a socket option associated with a socket of any type, in any state, and stores the result in optval. Options may exist at multiple protocol levels, but they are always present at the uppermost "socket" level. Options affect socket operations, such as the routing of packets, out-of-band data transfer, etc. The value associated with the selected option is returned in the buffer optval. The integer pointed to by optlen should originally contain the size of this buffer; on return, it will be set to the size of the value returned. For SO_LINGER, this will be the size of a struct linger; for most other options it will be the size of an integer. The WinSock SPI client is responsible for allocating any memory space pointed to directly or indirectly by any of the parameters it specifies. If the option was never set with WSPSetSockOpt(), then WSPGetSockOpt() returns the default value for the option. Value Type Meaning ~~~~~ ~~~~ ~~~~~~~ SO_ACCEPTCONN BOOL Socket is WSPListen()ing. SO_BROADCAST BOOL Socket is configured for the transmission of broadcast messages on the socket. SO_DEBUG BOOL Debugging is enabled. SO_DONTROUTE BOOL Routing is disabled. SO_GROUP_ID GROUP The identifier of the group to which the socket belongs. SO_GROUP_PRIORITY int The relative priority for sockets that are part of a socket group. SO_KEEPALIVE BOOL Keepalives are being sent. SO_LINGER struct linger Returns the current linger options. SO_MAX_MSG_SIZE unsigned int Maximum size of a message for message-oriented socket types (e.g. SOCK_DGRAM). Has no meaning for stream-oriented sockets. SO_OOBINLINE BOOL Out-of-band data is being received in the normal data stream. SO_PROTOCOL_INFOW WSAPROTOCOL_INFOW Description of the protocol info for the protocol that is bound to this socket. SO_RCVBUF int Buffer size for receives. SO_REUSEADDR BOOL The socket may be bound to an address which is already in use. SO_SNDBUF int Buffer size for sends. SO_TYPE int The type of the socket (e.g. SOCK_STREAM). PVD_CONFIG Service An "opaque" data structure object Provider from the service provider Dependent associated with socket s. This object stores the current configuration information of the service provider. The exact format of this data structure is service provider specific. Calling WSPGetSockOpt() with an unsupported option will result in an error code of WSAENOPROTOOPT being returned in lpErrno. SO_DEBUG - WinSock service providers are encouraged (but not required) to supply output debug information if the SO_DEBUG option is set by a WinSock SPI client. The mechanism for generating the debug information and the form it takes are beyond the scope of this specification. SO_ERROR - The SO_ERROR option returns and resets the per-socket based error code (which is not necessarily the same as the per-thread error code that is maintained by the WinSock 2 DLL). A successful WinSock call on the socket does not reset the socket-based error code returned by the SO_ERROR option. SO_GROUP_ID - This is a get-only socket option which supplies the identifier of the group this socket belongs to. Note that socket group IDs are unique across all processes for a give service provider. If this socket is not a group socket, the value is NULL. SO_GROUP_PRIORITY - Group priority indicates the priority of the specified socket relative to other sockets within the socket group. Values are non- negative integers, with zero corresponding to the highest priority. Priority values represent a hint to the service provider about how potentially scarce resources should be allocated. For example, whenever two or more sockets are both ready to transmit data, the highest priority socket (lowest value for SO_GROUP_PRIORITY) should be serviced first, with the remainder serviced in turn according to their relative priorities. The WSAENOPROTOOPT error is indicated for non group sockets or for service providers which do not support group sockets. SO_KEEPALIVE - An WinSock SPI client may request that a TCP/IP provider enable the use of "keep-alive" packets on TCP connections by turning on the SO_KEEPALIVE socket option. A WinSock provider need not support the use of keep-alives: if it does, the precise semantics are implementation-specific but should conform to section 4.2.3.6 of RFC 1122: Requirements for Internet Hosts -- Communication Layers. If a connection is dropped as the result of "keep-alives" the error code WSAENETRESET is returned to any calls in progress on the socket, and any subsequent calls will fail with WSAENOTCONN. SO_LINGER - SO_LINGER controls the action taken when unsent data is queued on a socket and a WSPCloseSocket() is performed. See WSPCloseSocket() for a description of the way in which the SO_LINGER settings affect the semantics of WSPCloseSocket(). The WinSock SPI client sets the desired behavior by creating a struct linger (pointed to by the optval argument) with the following elements: struct linger { u_short l_onoff; u_short l_linger; }; To enable SO_LINGER, a WinSock SPI client should set l_onoff to a non-zero value, set l_linger to 0 or the desired timeout (in seconds), and call WSPSetSockOpt(). To enable SO_DONTLINGER (i.e. disable SO_LINGER) l_onoff should be set to zero and WSPSetSockOpt() should be called. Note that enabling SO_LINGER with a non-zero timeout on a non-blocking socket is not recommended (see WSPCloseSocket() for details). Enabling SO_LINGER also disables SO_DONTLINGER, and vice versa. Note that if SO_DONTLINGER is DISABLED (i.e. SO_LINGER is ENABLED) then no timeout value is specified. In this case the timeout used is implementation dependent. If a previous timeout has been established for a socket (by enabling SO_LINGER), then this timeout value should be reinstated by the service provider. SO_MAX_MSG_SIZE - This is a get-only socket option which indicates the maximum size of a message for message-oriented socket types (e.g. SOCK_DGRAM) as implemented by the service provider. It has no meaning for byte stream oriented sockets. SO_PROTOCOL_INFO - This is a get-only option which supplies the WSAPROTOCOL_INFOW structure associated with this socket. SO_RCVBUF & SO_SNDBUF - When a Windows Sockets implementation supports the SO_RCVBUF and SO_SNDBUF options, a WinSock SPI client may request different buffer sizes (larger or smaller). The call may succeed even though the service provider did not make available the entire amount requested. A WinSock SPI client must call WSPGetSockOpt() with the same option to check the buffer size actually provided. SO_REUSEADDR - By default, a socket may not be bound (see WSPBind()) to a local address which is already in use. On occasions, however, it may be desirable to "re-use" an address in this way. Since every connection is uniquely identified by the combination of local and remote addresses, there is no problem with having two sockets bound to the same local address as long as the remote addresses are different. To inform the WinSock provider that a WSPBind() on a socket should be allowed to bind to a local address that is already in use by another socket, the WinSock SPI client should set the SO_REUSEADDR socket option for the socket before issuing the WSPBind(). Note that the option is interpreted only at the time of the WSPBind(): it is therefore unnecessary (but harmless) to set the option on a socket which is not to be bound to an existing address, and setting or resetting the option after the WSPBind() has no effect on this or any other socket. PVD_CONFIG - This object stores the configuration information for the service provider associated with socket s. The exact format of this data structure is service provider specific. Arguments: s - A descriptor identifying a socket. level - The level at which the option is defined; the supported levels include SOL_SOCKET. optname - The socket option for which the value is to be retrieved. optval - A pointer to the buffer in which the value for the requested option is to be returned. optlen - A pointer to the size of the optval buffer. lpErrno - A pointer to the error code. Return Value: If no error occurs, WSPGetSockOpt() returns 0. Otherwise, a value of SOCKET_ERROR is returned, and a specific error code is available in lpErrno. --*/ { } // WSPGetSockOpt INT WSPAPI WSPIoctl( IN SOCKET s, IN DWORD dwIoControlCode, IN LPVOID lpvInBuffer, IN DWORD cbInBuffer, OUT LPVOID lpvOutBuffer, IN DWORD cbOutBuffer, OUT LPDWORD lpcbBytesReturned, IN LPWSAOVERLAPPED lpOverlapped, IN LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine, IN LPWSATHREADID lpThreadId, OUT LPINT lpErrno ) /*++ Routine Description: This routine is used to set or retrieve operating parameters associated with the socket, the transport protocol, or the communications subsystem. For non-overlapped sockets, lpOverlapped and lpCompletionRoutine parameters are ignored, and this routine may block if socket s is in the blocking mode. Note that if socket s is in the non-blocking mode, this routine may return WSAEWOULDBLOCK if the specified operation cannot be finished immediately. In this case, the WinSock SPI client should change the socket to the blocking mode and reissue the request. For overlapped sockets, operations that cannot be completed immediately will be initiated, and completion will be indicated at a later time. The final completion status is retrieved via the WSPGetOverlappedResult(). In as much as the dwIoControlCode parameter is now a 32 bit entity, it is possible to adopt an encoding scheme that provides a convenient way to partition the opcode identifier space. The dwIoControlCode parameter is architected to allow for protocol and vendor independence when adding new control codes, while retaining backward compatibility with Windows Sockets 1.1 and Unix control codes. The dwIoControlCode parameter has the following form: +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |3|3|2|2|2|2|2|2|2|2|2|2|1|1|1|1|1|1|1|1|1|1| | | | | | | | | | | |1|0|9|8|7|6|5|4|3|2|1|0|9|8|7|6|5|4|3|2|1|0|9|8|7|6|5|4|3|2|1|0| +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |I|O|V| T |Vendor/Address Family| Code | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ I - Set if the input buffer is valid for the code, as with IOC_IN. O - Set if the output buffer is valid for the code, as with IOC_OUT. Note that for codes with both input and output parameters, both I and O will be set. V - Set if there are no parameters for the code, as with IOC_VOID. T - A two-bit quantity which defines the type of ioctl. The following values are defined: 0 - The ioctl is a standard Unix ioctl code, as with FIONREAD, FIONBIO, etc. 1 - The ioctl is a generic Windows Sockets 2 ioctl code. New ioctl codes defined for Windows Sockets 2 will have T == 1. 2 - The ioctl applies only to a specific address family. 3 - The ioctl applies only to a specific vendor's provider. This type allows companies to be assigned a vendor number which appears in the Vendor/Address Family field, and then the vendor can define new ioctls specific to that vendor without having to register the ioctl with a clearinghouse, thereby providing vendor flexibility and privacy. Vendor/Address Family - An 11-bit quantity which defines the vendor who owns the code (if T == 3) or which contains the address family to which the code applies (if T == 2). If this is a Unix ioctl code (T == 0) then this field has the same value as the code on Unix. If this is a generic Windows Sockets 2 ioctl (T == 1) then this field can be used as an extension of the "code" field to provide additional code values. Code - The specific ioctl code for the operation. The following Unix commands are supported: FIONBIO - Enable or disable non-blocking mode on socket s. lpvInBuffer points at an unsigned long, which is non-zero if non-blocking mode is to be enabled and zero if it is to be disabled. When a socket is created, it operates in blocking mode (i.e. non-blocking mode is disabled). This is consistent with BSD sockets. The WSPAsyncSelect() or WSPEventSelect() routine automatically sets a socket to nonblocking mode. If WSPAsyncSelect() or WSPEventSelect() has been issued on a socket, then any attempt to use WSPIoctl() to set the socket back to blocking mode will fail with WSAEINVAL. To set the socket back to blocking mode, a WinSock SPI client must first disable WSPAsyncSelect() by calling WSPAsyncSelect() with the lEvent parameter equal to 0, or disable WSPEventSelect() by calling WSPEventSelect() with the lNetworkEvents parameter equal to 0. FIONREAD - Determine the amount of data which can be read atomically from socket s. lpvOutBuffer points at an unsigned long in which WSPIoctl() stores the result. If s is stream-oriented (e.g., type SOCK_STREAM), FIONREAD returns the total amount of data which may be read in a single receive operation; this is normally the same as the total amount of data queued on the socket. If s is message-oriented (e.g., type SOCK_DGRAM), FIONREAD returns the size of the first datagram (message) queued on the socket. SIOCATMARK - Determine whether or not all out-of-band data has been read. This applies only to a socket of stream style (e.g., type SOCK_STREAM) which has been configured for in-line reception of any out-of-band data (SO_OOBINLINE). If no out-of-band data is waiting to be read, the operation returns TRUE. Otherwise it returns FALSE, and the next receive operation performed on the socket will retrieve some or all of the data preceding the " mark"; the WinSock SPI client should use the SIOCATMARK operation to determine whether any remains. If there is any normal data preceding the "urgent" (out of band) data, it will be received in order. (Note that receive operations will never mix out-of-band and normal data in the same call.) lpvOutBuffer points at a BOOL in which WSPIoctl() stores the result. The following WinSock 2 commands are supported: SIO_ASSOCIATE_HANDLE (opcode setting: I, T==1) - Associate this socket with the specified handle of a companion interface. The input buffer contains the integer value corresponding to the manifest constant for the companion interface (e.g., TH_NETDEV, TH_TAPI, etc.), followed by a value which is a handle of the specified companion interface, along with any other required information. Refer to the appropriate section in the Windows Sockets 2 Protocol-Specific Annex and/or documentation for the particular companion interface for additional details. The total size is reflected in the input buffer length. No output buffer is required. The WSAENOPROTOOPT error code is indicated for service providers which do not support this ioctl. SIO_ENABLE_CIRCULAR_QUEUEING (opcode setting: V, T==1) - Indicates to a message-oriented service provider that a newly arrived message should never be dropped because of a buffer queue overflow. Instead, the oldest message in the queue should be eliminated in order to accommodate the newly arrived message. No input and output buffers are required. Note that this ioctl is only valid for sockets associated with unreliable, message- oriented protocols. The WSAENOPROTOOPT error code is indicated for service providers which do not support this ioctl. SIO_FIND_ROUTE (opcode setting: O, T==1) - When issued, this ioctl requests that the route to the remote address specified as a sockaddr in the input buffer be discovered. If the address already exists in the local cache, its entry is invalidated. In the case of Novell's IPX, this call initiates an IPX GetLocalTarget (GLT), which queries the network for the given remote address. SIO_FLUSH (opcode setting: V, T==1) - Discards current contents of the sending queue associated with this socket. No input and output buffers are required. The WSAENOPROTOOPT error code is indicated for service providers which do not support this ioctl. SIO_GET_BROADCAST_ADDRESS (opcode setting: O, T==1) - This ioctl fills the output buffer with a sockaddr struct containing a suitable broadcast address for use with WSPIoctl(). SIO_GET_EXTENSION_FUNCTION_POINTER (opcode setting: O, I, T==1) - Retrieve a pointer to the specified extension function supported by the associated service provider. The input buffer contains a GUID whose value identifies the extension function in question. The pointer to the desired function is returned in the output buffer. Extension function identifiers are established by service provider vendors and should be included in vendor documentation that describes extension function capabilities and semantics. SIO_GET_QOS (opcode setting: O,I, T==1) - Retrieve the QOS structure associated with the socket. The input buffer is optional. Some protocols (e.g. RSVP) allow the input buffer to be used to qualify a QOS request. The QOS structure will be copied into the output buffer. The output buffer must be sized large enough to be able to contain the full QOS struct. The WSAENOPROTOOPT error code is indicated for service providers which do not support QOS. SIO_GET_GROUP_QOS (opcode setting: O,I, T==1) - Retrieve the QOS structure associated with the socket group to which this socket belongs. The input buffer is optional. Some protocols (e.g. RSVP) allow the input buffer to be used to qualify a QOS request. The QOS structure will be copied into the output buffer. If this socket does not belong to an appropriate socket group, the SendingFlowspec and ReceivingFlowspec fields of the returned QOS struct are set to NULL. The WSAENOPROTOOPT error code is indicated for service providers which do not support QOS. SIO_MULTIPOINT_LOOPBACK (opcode setting: I, T==1) - Controls whether data sent in a multipoint session will also be received by the same socket on the local host. A value of TRUE causes loopback reception to occur while a value of FALSE prohibits this. SIO_MULTICAST_SCOPE (opcode setting: I, T==1) - Specifies the scope over which multicast transmissions will occur. Scope is defined as the number of routed network segments to be covered. A scope of zero would indicate that the multicast transmission would not be placed "on the wire" but could be disseminated across sockets within the local host. A scope value of one (the default) indicates that the transmission will be placed on the wire, but will not cross any routers. Higher scope values determine the number of routers that may be crossed. Note that this corresponds to the time-to-live (TTL) parameter in IP multicasting. SIO_SET_QOS (opcode setting: I, T==1) - Associate the supplied QOS structure with the socket. No output buffer is required, the QOS structure will be obtained from the input buffer. The WSAENOPROTOOPT error code is indicated for service providers which do not support QOS. SIO_SET_GROUP_QOS (opcode setting: I, T==1) - Establish the supplied QOS structure with the socket group to which this socket belongs. No output buffer is required, the QOS structure will be obtained from the input buffer. The WSAENOPROTOOPT error code is indicated for service providers which do not support QOS, or if the socket descriptor specified is not the creator of the associated socket group. SIO_TRANSLATE_HANDLE (opcode setting: I, O, T==1) - To obtain a corresponding handle for socket s that is valid in the context of a companion interface (e.g., TH_NETDEV, TH_TAPI, etc.). A manifest constant identifying the companion interface along with any other needed parameters are specified in the input buffer. The corresponding handle will be available in the output buffer upon completion of this routine. Refer to the appropriate section in the Windows Sockets 2 Protocol-Specific Annex and/or documentation for the particular companion interface for additional details. The WSAENOPROTOOPT error code is indicated for service providers which do not support this ioctl for the specified companion interface. If an overlapped operation completes immediately, WSPIoctl() returns a value of zero and the lpNumberOfBytesReturned parameter is updated with the number of bytes returned. If the overlapped operation is successfully initiated and will complete later, WSPIoctl() returns SOCKET_ERROR and indicates error code WSA_IO_PENDING. In this case, lpNumberOfBytesReturned is not updated. When the overlapped operation completes the amount of data transferred is indicated either via the cbTransferred parameter in the completion routine (if specified), or via the lpcbTransfer parameter in WSPGetOverlappedResult(). Providers must allow this routine to be called from within the completion routine of a previous WSPRecv(), WSPRecvFrom(), WSPSend() or WSPSendTo() function. However, for a given socket, I/O completion routines may not be nested. This permits time-sensitive data transmissions to occur entirely within a preemptive context. The lpOverlapped parameter must be valid for the duration of the overlapped operation. If multiple I/O operations are simultaneously outstanding, each must reference a separate overlapped structure. The WSAOVERLAPPED structure has the following form: typedef struct _WSAOVERLAPPED { DWORD Internal; // reserved DWORD InternalHigh; // reserved DWORD Offset; // reserved DWORD OffsetHigh; // reserved WSAEVENT hEvent; } WSAOVERLAPPED, FAR * LPWSAOVERLAPPED; If the lpCompletionRoutine parameter is NULL, the service provider signals the hEvent field of lpOverlapped when the overlapped operation completes if it contains a valid event object handle. The WinSock SPI client can use WSPGetOverlappedResult() to wait or poll on the event object. If lpCompletionRoutine is not NULL, the hEvent field is ignored and can be used by the WinSock SPI client to pass context information to the completion routine. It is the service provider's responsibility to arrange for invocation of the client-specified completion routine when the overlapped operation completes. Since the completion routine must be executed in the context of the same thread that initiated the overlapped operation, it cannot be invoked directly from the service provider. The WinSock DLL offers an asynchronous procedure call (APC) mechanism to facilitate invocation of completion routines. A service provider arranges for a function to be executed in the proper thread by calling WPUQueueApc(). Note that this routine must be invoked while in the context of the same process (but not necessarily the same thread) that was used to initiate the overlapped operation. It is the service provider's responsibility to arrange for this process context to be active prior to calling WPUQueueApc(). WPUQueueApc() takes as input parameters a pointer to a WSATHREADID structure (supplied to the provider via the lpThreadId input parameter), a pointer to an APC function to be invoked, and a 32 bit context value that is subsequently passed to the APC function. Because only a single 32-bit context value is available, the APC function cannot itself be the client-specified completion routine. The service provider must instead supply a pointer to its own APC function which uses the supplied context value to access the needed result information for the overlapped operation, and then invokes the client-specified completion routine. The prototype for the client-supplied completion routine is as follows: void CALLBACK CompletionRoutine( IN DWORD dwError, IN DWORD cbTransferred, IN LPWSAOVERLAPPED lpOverlapped, IN DWORD dwFlags ); CompletionRoutine is a placeholder for a client supplied function name. dwError specifies the completion status for the overlapped operation as indicated by lpOverlapped. cbTransferred specifies the number of bytes sent. No flag values are currently defined and the dwFlags value will be zero. This routine does not return a value. The completion routines may be called in any order, not necessarily in the same order the overlapped operations are completed. However, the service provider guarantees to the client that posted buffers are sent in the same order they are supplied. The ioctl codes with T == 0 are a subset of the ioctl codes used in Berkeley sockets. In particular, there is no command which is equivalent to FIOASYNC. Arguments: s - Handle to a socket dwIoControlCode - Control code of operation to perform lpvInBuffer - Address of input buffer cbInBuffer - Size of input buffer lpvOutBuffer - Address of output buffer cbOutBuffer - Size of output buffer lpcbBytesReturned - A pointer to the size of output buffer's contents. lpOverlapped - Address of WSAOVERLAPPED structure lpCompletionRoutine - A pointer to the completion routine called when the operation has been completed. lpThreadId - A pointer to a thread ID structure to be used by the provider in a subsequent call to WPUQueueApc(). The provider should store the referenced WSATHREADID structure (not the pointer to same) until after the WPUQueueApc() function returns. lpErrno - A pointer to the error code. Return Value: If no error occurs and the operation has completed immediately, WSPIoctl() returns 0. Note that in this case the completion routine, if specified, will have already been queued. Otherwise, a value of SOCKET_ERROR is returned, and a specific error code is available in lpErrno. The error code WSA_IO_PENDING indicates that an overlapped operation has been successfully initiated and that completion will be indicated at a later time. Any other error code indicates that no overlapped operation was initiated and no completion indication will occur. --*/ { } // WSPIoctl SOCKET WSPAPI WSPJoinLeaf( IN SOCKET s, IN const struct sockaddr FAR * name, IN int namelen, IN LPWSABUF lpCallerData, OUT LPWSABUF lpCalleeData, IN LPQOS lpSQOS, IN LPQOS lpGQOS, IN DWORD dwFlags, OUT LPINT lpErrno ) /*++ Routine Description: This routine is used to join a leaf node to a multipoint session, and to perform a number of other ancillary operations that occur at session join time as well. If the socket, s, is unbound, unique values are assigned to the local association by the system, and the socket is marked as bound. WSPJoinLeaf() has the same parameters and semantics as WSPConnect() except that it returns a socket descriptor (as in WSPAccept()), and it has an additional dwFlags parameter. Only multipoint sockets created using WSPSocket() with appropriate multipoint flags set may be used for input parameter s in this routine. If the socket is in the non-blocking mode, the returned socket descriptor will not be useable until after a corresponding FD_CONNECT indication has been received, except that closesocket() may be invoked on this socket descriptor to cancel a pending join operation. A root node in a multipoint session may call WSPJoinLeaf() one or more times in order to add a number of leaf nodes, however at most one multipoint connection request may be outstanding at a time. Refer to section 3.14. Protocol-Independent Multicast and Multipoint for additional information. The socket descriptor returned by WSPJoinLeaf() is different depending on whether the input socket descriptor, s, is a c_root or a c_leaf. When used with a c_root socket, the name parameter designates a particular leaf node to be added and the returned socket descriptor is a c_leaf socket corresponding to the newly added leaf node. The newly created socket has the same properties as s including asynchronous events registered with WSPAsyncSelect() or with WSPEventSelect(), but not including the c_root socket's group ID, if any. It is not intended to be used for exchange of multipoint data, but rather is used to receive network event indications (e.g. FD_CLOSE) for the connection that exists to the particular c_leaf. Some multipoint implementations may also allow this socket to be used for "side chats" between the root and an individual leaf node. An FD_CLOSE indication will be received for this socket if the corresponding leaf node calls WSPCloseSocket() to drop out of the multipoint session. Symmetrically, invoking WSPCloseSocket() on the c_leaf socket returned from WSPJoinLeaf() will cause the socket in the corresponding leaf node to get FD_CLOSE notification. When WSPJoinLeaf() is invoked with a c_leaf socket, the name parameter contains the address of the root node (for a rooted control scheme) or an existing multipoint session (non-rooted control scheme), and the returned socket descriptor is the same as the input socket descriptor. In other words, a new socket descriptor is not allocated. In a rooted control scheme, the root application would put its c_root socket in the listening mode by calling WSPListen(). The standard FD_ACCEPT notification will be delivered when the leaf node requests to join itself to the multipoint session. The root application uses the usual WSPAccept() functions to admit the new leaf node. The value returned from WSPAccept() is also a c_leaf socket descriptor just like those returned from WSPJoinLeaf(). To accommodate multipoint schemes that allow both root-initiated and leaf- initiated joins, it is acceptable for a c_root socket that is already in listening mode to be used as an input to WSPJoinLeaf(). The WinSock SPI client is responsible for allocating any memory space pointed to directly or indirectly by any of the parameters it specifies. The lpCallerData is a value parameter which contains any user data that is to be sent along with the multipoint session join request. If lpCallerData is NULL, no user data will be passed to the peer. The lpCalleeData is a result parameter which will contain any user data passed back from the peer as part of the multipoint session establishment. lpCalleeData->len initially contains the length of the buffer allocated by the WinSock SPI client and pointed to by lpCalleeData->buf. lpCalleeData->len will be set to 0 if no user data has been passed back. The lpCalleeData information will be valid when the multipoint join operation is complete. For blocking sockets, this will be when the WSPJoinLeaf() function returns. For non- blocking sockets, this will be after the FD_CONNECT notification has occurred. If lpCalleeData is NULL, no user data will be passed back. The exact format of the user data is specific to the address family to which the socket belongs and/or the applications involved. At multipoint session establishment time, a WinSock SPI client may use the lpSQOS and/or lpGQOS parameters to override any previous QOS specification made for the socket via WSPIoctl() with either the SIO_SET_QOS or SIO_SET_GROUP_QOS opcodes. lpSQOS specifies the flow specs for socket s, one for each direction, followed by any additional provider-specific parameters. If either the associated transport provider in general or the specific type of socket in particular cannot honor the QOS request, an error will be returned as indicated below. The sending or receiving flow spec values will be ignored, respectively, for any unidirectional sockets. If no provider-specific parameters are supplied, the buf and len fields of lpSQOS->ProviderSpecific should be set to NULL and 0, respectively. A NULL value for lpSQOS indicates no application supplied QOS. lpGQOS specifies the flow specs for the socket group (if applicable), one for each direction, followed by any additional provider-specific parameters. If no provider- specific parameters are supplied, the buf and len fields of lpSQOS->ProviderSpecific should be set to NULL and 0, respectively. A NULL value for lpGQOS indicates no application-supplied group QOS. This parameter will be ignored if s is not the creator of the socket group. The dwFlags parameter is used to indicate whether the socket will be acting only as a sender (JL_SENDER_ONLY), only as a receiver (JL_RECEIVER_ONLY), or both (JL_BOTH). When connected sockets break (i.e. become closed for whatever reason), they should be discarded and recreated. It is safest to assume that when things go awry for any reason on a connected socket, the WinSock SPI client must discard and recreate the needed sockets in order to return to a stable point. Arguments: s - A descriptor identifying a multipoint socket. name - The name of the peer to which the socket is to be joined. namelen - The length of the name. lpCallerData - A pointer to the user data that is to be transferred to the peer during multipoint session establishment. lpCalleeData - A pointer to the user data that is to be transferred back from the peer during multipoint session establishment. lpSQOS - A pointer to the flow specs for socket s, one for each direction. lpGQOS - A pointer to the flow specs for the socket group (if applicable). dwFlags - Flags to indicate that the socket is acting as a sender, receiver, or both. lpErrno - A pointer to the error code. Return Value: If no error occurs, WSPJoinLeaf() returns a value of type SOCKET which is a descriptor for the newly created multipoint socket. Otherwise, a value of INVALID_SOCKET is returned, and a specific error code is available in lpErrno. On a blocking socket, the return value indicates success or failure of the join operation. With a non-blocking socket, successful initiation of a join operation is indicated by a return value of a valid socket descriptor. Subsequently, an FD_CONNECT indication is given when the join operation completes, either successfully or otherwise. Also, until the multipoint session join attempt completes all subsequent calls to WSPJoinLeaf() on the same socket will fail with the error code WSAEALREADY. If the return error code indicates the multipoint session join attempt failed (i.e. WSAECONNREFUSED, WSAENETUNREACH, WSAETIMEDOUT) the WinSock SPI client may call WSPJoinLeaf() again for the same socket. --*/ { } // WSPJoinLeaf INT WSPAPI WSPListen( IN SOCKET s, IN int backlog, OUT LPINT lpErrno ) /*++ Routine Description: To accept connections, a socket is first created with WSPSocket(), a backlog for incoming connections is specified with WSPListen(), and then the connections are accepted with WSPAccept. WSPListen() applies only to sockets that are connection-oriented (e.g., SOCK_STREAM). The socket s is put into "passive'' mode where incoming connection requests are acknowledged and queued pending acceptance by the WinSock SPI client. This routine is typically used by servers that could have more than one connection request at a time: if a connection request arrives with the queue full, the client will receive an error with an indication of WSAECONNREFUSED. WSPListen() should continue to function rationally when there are no available descriptors. It should accept connections until the queue is emptied. If descriptors become available, a later call to WSPListen() or WSPAccept() will re-fill the queue to the current or most recent "backlog", if possible, and resume listening for incoming connections. A WinSock SPI client may call WSPListen() more than once on the same socket. This has the effect of updating the current backlog for the listening socket. Should there be more pending connections than the new backlog value, the excess pending connections will be reset and dropped. Backlog is limited (silently) to a reasonable value as determined by the service provider. Illegal values are replaced by the nearest legal value. Arguments: s - A descriptor identifying a bound, unconnected socket. backlog - The maximum length to which the queue of pending connections may grow. If this value is SOMAXCONN, then the service provider should set the backlog to a maximum "reasonable" value. lpErrno - A pointer to the error code. Return Value: If no error occurs, WSPListen() returns 0. Otherwise, a value of SOCKET_ERROR is returned, and a specific error code is available in lpErrno. --*/ { } // WSPListen INT WSPAPI WSPRecv( IN SOCKET s, IN OUT LPWSABUF lpBuffers, IN DWORD dwBufferCount, OUT LPDWORD lpNumberOfBytesRecvd, IN OUT LPDWORD lpFlags, IN LPWSAOVERLAPPED lpOverlapped, IN LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine, IN LPWSATHREADID lpThreadId, OUT LPINT lpErrno ) /*++ Routine Description: This routine is used on connected sockets or bound connectionless sockets specified by the s parameter and is used to read incoming data. For overlapped sockets WSPRecv() is used to post one or more buffers into which incoming data will be placed as it becomes available, after which the WinSock SPI client-specified completion indication (invocation of the completion routine or setting of an event object) occurs. If the operation does not complete immediately, the final completion status is retrieved via the completion routine or WSPGetOverlappedResult(). If both lpOverlapped and lpCompletionRoutine are NULL, the socket in this routine will be treated as a non-overlapped socket. For non-overlapped sockets, the lpOverlapped, lpCompletionRoutine, and lpThreadId parameters are ignored. Any data which has already been received and buffered by the transport will be copied into the supplied user buffers. For the case of a blocking socket with no data currently having been received and buffered by the transport, the call will block until data is received. The supplied buffers are filled in the order in which they appear in the array pointed to by lpBuffers, and the buffers are packed so that no holes are created. The array of WSABUF structures pointed to by the lpBuffers parameter is transient. If this operation completes in an overlapped manner, it is the service provider's responsibility to capture this array of pointers to WSABUF structures before returning from this call. This enables WinSock SPI clients to build stack-based WSABUF arrays. For byte stream style sockets (e.g., type SOCK_STREAM), incoming data is placed into the buffers until the buffers are filled, the connection is closed, or internally buffered data is exhausted. Regardless of whether or not the incoming data fills all the buffers, the completion indication occurs for overlapped sockets. For message-oriented sockets (e.g., type SOCK_DGRAM), an incoming message is placed into the supplied buffers, up to the total size of the buffers supplied, and the completion indication occurs for overlapped sockets. If the message is larger than the buffers supplied, the buffers are filled with the first part of the message. If the MSG_PARTIAL feature is supported by the service provider, the MSG_PARTIAL flag is set in lpFlags and subsequent receive operation(s) may be used to retrieve the rest of the message. If MSG_PARTIAL is not supported but the protocol is reliable, WSPRecv() generates the error WSAEMSGSIZE and a subsequent receive operation with a larger buffer can be used to retrieve the entire message. Otherwise (i.e. the protocol is unreliable and does not support MSG_PARTIAL), the excess data is lost, and WSPRecv() generates the error WSAEMSGSIZE. For connection-oriented sockets, WSPRecv() can indicate the graceful termination of the virtual circuit in one of two ways, depending on whether the socket is a byte stream or message-oriented. For byte streams, zero bytes having been read indicates graceful closure and that no more bytes will ever be read. For message-oriented sockets, where a zero byte message is often allowable, a return error code of WSAEDISCON is used to indicate graceful closure. In any case a return error code of WSAECONNRESET indicates an abortive close has occurred. lpFlags may be used to influence the behavior of the function invocation beyond the options specified for the associated socket. That is, the semantics of this routine are determined by the socket options and the lpFlags parameter. The latter is constructed by or-ing any of the following values: MSG_PEEK - Peek at the incoming data. The data is copied into the buffer but is not removed from the input queue. This flag is valid only for non-overlapped sockets. MSG_OOB - Process out-of-band data. MSG_PARTIAL - This flag is for message-oriented sockets only. On output, indicates that the data supplied is a portion of the message transmitted by the sender. Remaining portions of the message will be supplied in subsequent receive operations. A subsequent receive operation with MSG_PARTIAL flag cleared indicates end of sender's message. As an input parameter, MSG_PARTIAL indicates that the receive operation should complete even if only part of a message has been received by the service provider. If an overlapped operation completes immediately, WSPRecv() returns a value of zero and the lpNumberOfBytesRecvd parameter is updated with the number of bytes received. If the overlapped operation is successfully initiated and will complete later, WSPRecv() returns SOCKET_ERROR and indicates error code WSA_IO_PENDING. In this case, lpNumberOfBytesRecvd is not updated. When the overlapped operation completes the amount of data transferred is indicated either via the cbTransferred parameter in the completion routine (if specified), or via the lpcbTransfer parameter in WSPGetOverlappedResult(). Providers must allow this routine to be called from within the completion routine of a previous WSPRecv(), WSPRecvFrom(), WSPSend() or WSPSendTo() function. However, for a given socket, I/O completion routines may not be nested. This permits time-sensitive data transmissions to occur entirely within a preemptive context. The lpOverlapped parameter must be valid for the duration of the overlapped operation. If multiple I/O operations are simultaneously outstanding, each must reference a separate overlapped structure. The WSAOVERLAPPED structure has the following form: typedef struct _WSAOVERLAPPED { DWORD Internal; // reserved DWORD InternalHigh; // reserved DWORD Offset; // reserved DWORD OffsetHigh; // reserved WSAEVENT hEvent; } WSAOVERLAPPED, FAR * LPWSAOVERLAPPED; If the lpCompletionRoutine parameter is NULL, the service provider signals the hEvent field of lpOverlapped when the overlapped operation completes if it contains a valid event object handle. The WinSock SPI client can use WSPGetOverlappedResult() to wait or poll on the event object. If lpCompletionRoutine is not NULL, the hEvent field is ignored and can be used by the WinSock SPI client to pass context information to the completion routine. It is the service provider's responsibility to arrange for invocation of the client-specified completion routine when the overlapped operation completes. Since the completion routine must be executed in the context of the same thread that initiated the overlapped operation, it cannot be invoked directly from the service provider. The WinSock DLL offers an asynchronous procedure call (APC) mechanism to facilitate invocation of completion routines. A service provider arranges for a function to be executed in the proper thread by calling WPUQueueApc(). Note that this routine must be invoked while in the context of the same process (but not necessarily the same thread) that was used to initiate the overlapped operation. It is the service provider's responsibility to arrange for this process context to be active prior to calling WPUQueueApc(). WPUQueueApc() takes as input parameters a pointer to a WSATHREADID structure (supplied to the provider via the lpThreadId input parameter), a pointer to an APC function to be invoked, and a 32 bit context value that is subsequently passed to the APC function. Because only a single 32-bit context value is available, the APC function cannot itself be the client-specified completion routine. The service provider must instead supply a pointer to its own APC function which uses the supplied context value to access the needed result information for the overlapped operation, and then invokes the client-specified completion routine. The prototype for the client-supplied completion routine is as follows: void CALLBACK CompletionRoutine( IN DWORD dwError, IN DWORD cbTransferred, IN LPWSAOVERLAPPED lpOverlapped, IN DWORD dwFlags ); CompletionRoutine is a placeholder for a client supplied function name. dwError specifies the completion status for the overlapped operation as indicated by lpOverlapped. cbTransferred specifies the number of bytes sent. No flag values are currently defined and the dwFlags value will be zero. This routine does not return a value. The completion routines may be called in any order, not necessarily in the same order the overlapped operations are completed. However, the posted buffers are guaranteed to be filled in the same order they are supplied. Arguments: s - A descriptor identifying a connected socket. lpBuffers - A pointer to an array of WSABUF structures. Each WSABUF structure contains a pointer to a buffer and the length of the buffer. dwBufferCount - The number of WSABUF structures in the lpBuffers array. lpNumberOfBytesRecvd - A pointer to the number of bytes received by this call. lpFlags - A pointer to flags. lpOverlapped - A pointer to a WSAOVERLAPPED structure. lpCompletionRoutine - A pointer to the completion routine called when the receive operation has been completed. lpThreadId - A pointer to a thread ID structure to be used by the provider in a subsequent call to WPUQueueApc(). The provider should store the referenced WSATHREADID structure (not the pointer to same) until after the WPUQueueApc() function returns. lpErrno - A pointer to the error code. Return Value: If no error occurs and the receive operation has completed immediately, WSPRecv() returns 0. Note that in this case the completion routine, if specified, will have already been queued. Otherwise, a value of SOCKET_ERROR is returned, and a specific error code is available in lpErrno. The error code WSA_IO_PENDING indicates that the overlapped operation has been successfully initiated and that completion will be indicated at a later time. Any other error code indicates that no overlapped operations was initiated and no completion indication will occur. --*/ { } // WSPRecv INT WSPAPI WSPRecvDisconnect( IN SOCKET s, OUT LPWSABUF lpInboundDisconnectData, OUT LPINT lpErrno ) /*++ Routine Description: This routine is used on connection-oriented sockets to disable reception, and retrieve any incoming disconnect data from the remote party. After this routine has been successfully issued, subsequent receives on the socket will be disallowed. This has no effect on the lower protocol layers. For TCP, the TCP window is not changed and incoming data will be accepted (but not acknowledged) until the window is exhausted. For UDP, incoming datagrams are accepted and queued. In no case will an ICMP error packet be generated. To successfully receive incoming disconnect data, a WinSock SPI client must use other mechanisms to determine that the circuit has been closed. For example, a client needs to receive an FD_CLOSE notification, or get a 0 return value, or a WSAEDISCON error code from WSPRecv(). Note that WSPRecvDisconnect() does not close the socket, and resources attached to the socket will not be freed until WSPCloseSocket() is invoked. WSPRecvDisconnect() does not block regardless of the SO_LINGER setting on the socket. A WinSock SPI client should not rely on being able to re-use a socket after it has been WSPRecvDisconnect()ed. In particular, a WinSock provider is not required to support the use of WSPConnect() on such a socket. Arguments: s - A descriptor identifying a socket. lpInboundDisconnectData - A pointer to a buffer into which disconnect data is to be copied. lpErrno - A pointer to the error code. Return Value: If no error occurs, WSPRecvDisconnect() returns 0. Otherwise, a value of SOCKET_ERROR is returned, and a specific error code is available in lpErrno. --*/ { } // WSPRecvDisconnect INT WSPAPI WSPRecvFrom( IN SOCKET s, IN OUT LPWSABUF lpBuffers, IN DWORD dwBufferCount, OUT LPDWORD lpNumberOfBytesRecvd, IN OUT LPDWORD lpFlags, OUT struct sockaddr FAR * lpFrom, IN OUT LPINT lpFromlen, IN LPWSAOVERLAPPED lpOverlapped, IN LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine, IN LPWSATHREADID lpThreadId, OUT LPINT lpErrno ) /*++ Routine Description: This routine is used primarily on a connectionless socket specified by s. For overlapped sockets WSPRecv() is used to post one or more buffers into which incoming data will be placed as it becomes available, after which the WinSock SPI client-specified completion indication (invocation of the completion routine or setting of an event object) occurs. If the operation does not complete immediately, the final completion status is retrieved via the completion routine or WSPGetOverlappedResult(). Also note that the values pointed to by lpFrom and lpFromlen are not updated until completion is indicated. Applications must not use or disturb these values until they have been updated, therefore the client must not use automatic (i.e stack- based) variables for these parameters. If both lpOverlapped and lpCompletionRoutine are NULL, the socket in this routine will be treated as a non-overlapped socket. For non-overlapped sockets, the lpOverlapped, lpCompletionRoutine, and lpThreadId parameters are ignored. Any data which has already been received and buffered by the transport will be copied into the supplied user buffers. For the case of a blocking socket with no data currently having been received and buffered by the transport, the call will block until data is received. The supplied buffers are filled in the order in which they appear in the array pointed to by lpBuffers, and the buffers are packed so that no holes are created. The array of WSABUF structures pointed to by the lpBuffers parameter is transient. If this operation completes in an overlapped manner, it is the service provider's responsibility to capture this array of pointers to WSABUF structures before returning from this call. This enables WinSock SPI clients to build stack-based WSABUF arrays. For connectionless socket types, the address from which the data originated is copied to the buffer pointed by lpFrom. On input, the value pointed to by lpFromlen is initialized to the size of this buffer, and is modified on completion to indicate the actual size of the address stored there. As noted previously for overlapped sockets, the lpFrom and lpFromlen parameters are not updated until after the overlapped I/O has completed. The memory pointed to by these parameters must, therefore, remain available to the service provider and cannot be allocated on the WinSock SPI client's stack frame. The lpFrom and lpFromlen parameters are ignored for connection-oriented sockets. For byte stream style sockets (e.g., type SOCK_STREAM), incoming data is placed into the buffers until the buffers are filled, the connection is closed, or internally buffered data is exhausted. Regardless of whether or not the incoming data fills all the buffers, the completion indication occurs for overlapped sockets. For message-oriented sockets (e.g., type SOCK_DGRAM), an incoming message is placed into the supplied buffers, up to the total size of the buffers supplied, and the completion indication occurs for overlapped sockets. If the message is larger than the buffers supplied, the buffers are filled with the first part of the message. If the MSG_PARTIAL feature is supported by the service provider, the MSG_PARTIAL flag is set in lpFlags and subsequent receive operation(s) may be used to retrieve the rest of the message. If MSG_PARTIAL is not supported but the protocol is reliable, WSPRecvFrom() generates the error WSAEMSGSIZE and a subsequent receive operation with a larger buffer can be used to retrieve the entire message. Otherwise (i.e. the protocol is unreliable and does not support MSG_PARTIAL), the excess data is lost, and WSPRecvFrom() generates the error WSAEMSGSIZE. For connection-oriented sockets, WSPRecvFrom() can indicate the graceful termination of the virtual circuit in one of two ways, depending on whether the socket is a byte stream or message-oriented. For byte streams, zero bytes having been read indicates graceful closure and that no more bytes will ever be read. For message-oriented sockets, where a zero byte message is often allowable, a return error code of WSAEDISCON is used to indicate graceful closure. In any case a return error code of WSAECONNRESET indicates an abortive close has occurred. lpFlags may be used to influence the behavior of the function invocation beyond the options specified for the associated socket. That is, the semantics of this routine are determined by the socket options and the lpFlags parameter. The latter is constructed by or-ing any of the following values: MSG_PEEK - Peek at the incoming data. The data is copied into the buffer but is not removed from the input queue. This flag is valid only for non-overlapped sockets. MSG_OOB - Process out-of-band data. MSG_PARTIAL - This flag is for message-oriented sockets only. On output, indicates that the data supplied is a portion of the message transmitted by the sender. Remaining portions of the message will be supplied in subsequent receive operations. A subsequent receive operation with MSG_PARTIAL flag cleared indicates end of sender's message. As an input parameter, MSG_PARTIAL indicates that the receive operation should complete even if only part of a message has been received by the service provider. For message-oriented sockets, the MSG_PARTIAL bit is set in the lpFlags parameter if a partial message is received. If a complete message is received, MSG_PARTIAL is cleared in lpFlags. In the case of delayed completion, the value pointed to by lpFlags is not updated. When completion has been indicated the WinSock SPI client should call WSPGetOverlappedResult() and examine the flags pointed to by the lpdwFlags parameter. If an overlapped operation completes immediately, WSPRecvFrom() returns a value of zero and the lpNumberOfBytesRecvd parameter is updated with the number of bytes received. If the overlapped operation is successfully initiated and will complete later, WSPRecvFrom() returns SOCKET_ERROR and indicates error code WSA_IO_PENDING. In this case, lpNumberOfBytesRecvd is not updated. When the overlapped operation completes the amount of data transferred is indicated either via the cbTransferred parameter in the completion routine (if specified), or via the lpcbTransfer parameter in WSPGetOverlappedResult(). Providers must allow this routine to be called from within the completion routine of a previous WSPRecv(), WSPRecvFrom(), WSPSend() or WSPSendTo() function. However, for a given socket, I/O completion routines may not be nested. This permits time-sensitive data transmissions to occur entirely within a preemptive context. The lpOverlapped parameter must be valid for the duration of the overlapped operation. If multiple I/O operations are simultaneously outstanding, each must reference a separate overlapped structure. The WSAOVERLAPPED structure has the following form: typedef struct _WSAOVERLAPPED { DWORD Internal; // reserved DWORD InternalHigh; // reserved DWORD Offset; // reserved DWORD OffsetHigh; // reserved WSAEVENT hEvent; } WSAOVERLAPPED, FAR * LPWSAOVERLAPPED; If the lpCompletionRoutine parameter is NULL, the service provider signals the hEvent field of lpOverlapped when the overlapped operation completes if it contains a valid event object handle. The WinSock SPI client can use WSPGetOverlappedResult() to wait or poll on the event object. If lpCompletionRoutine is not NULL, the hEvent field is ignored and can be used by the WinSock SPI client to pass context information to the completion routine. It is the service provider's responsibility to arrange for invocation of the client-specified completion routine when the overlapped operation completes. Since the completion routine must be executed in the context of the same thread that initiated the overlapped operation, it cannot be invoked directly from the service provider. The WinSock DLL offers an asynchronous procedure call (APC) mechanism to facilitate invocation of completion routines. A service provider arranges for a function to be executed in the proper thread by calling WPUQueueApc(). Note that this routine must be invoked while in the context of the same process (but not necessarily the same thread) that was used to initiate the overlapped operation. It is the service provider's responsibility to arrange for this process context to be active prior to calling WPUQueueApc(). WPUQueueApc() takes as input parameters a pointer to a WSATHREADID structure (supplied to the provider via the lpThreadId input parameter), a pointer to an APC function to be invoked, and a 32 bit context value that is subsequently passed to the APC function. Because only a single 32-bit context value is available, the APC function cannot itself be the client-specified completion routine. The service provider must instead supply a pointer to its own APC function which uses the supplied context value to access the needed result information for the overlapped operation, and then invokes the client-specified completion routine. The prototype for the client-supplied completion routine is as follows: void CALLBACK CompletionRoutine( IN DWORD dwError, IN DWORD cbTransferred, IN LPWSAOVERLAPPED lpOverlapped, IN DWORD dwFlags ); CompletionRoutine is a placeholder for a client supplied function name. dwError specifies the completion status for the overlapped operation as indicated by lpOverlapped. cbTransferred specifies the number of bytes sent. No flag values are currently defined and the dwFlags value will be zero. This routine does not return a value. The completion routines may be called in any order, not necessarily in the same order the overlapped operations are completed. However, the posted buffers are guaranteed to be filled in the same order they are supplied. Arguments: s - A descriptor identifying a socket. lpBuffers - A pointer to an array of WSABUF structures. Each WSABUF structure contains a pointer to a buffer and the length of the buffer. dwBufferCount - The number of WSABUF structures in the lpBuffers array. lpNumberOfBytesRecvd - A pointer to the number of bytes received by this call. lpFlags - A pointer to flags. lpFrom - An optional pointer to a buffer which will hold the source address upon the completion of the overlapped operation. lpFromlen - A pointer to the size of the from buffer, required only if lpFrom is specified. lpOverlapped - A pointer to a WSAOVERLAPPED structure. lpCompletionRoutine - A pointer to the completion routine called when the receive operation has been completed. lpThreadId - A pointer to a thread ID structure to be used by the provider in a subsequent call to WPUQueueApc().The provider should store the referenced WSATHREADID structure (not the pointer to same) until after the WPUQueueApc() function returns. lpErrno - A pointer to the error code. Return Value: If no error occurs and the receive operation has completed immediately, WSPRecvFrom() returns 0. Note that in this case the completion routine, if specified will have already been queued. Otherwise, a value of SOCKET_ERROR is returned, and a specific error code is available in lpErrno. The error code WSA_IO_PENDING indicates that the overlapped operation has been successfully initiated and that completion will be indicated at a later time. Any other error code indicates that no overlapped operations was initiated and no completion indication will occur. --*/ { } // WSPRecvFrom INT WSPAPI WSPSelect( IN int nfds, IN OUT fd_set FAR * readfds, IN OUT fd_set FAR * writefds, IN OUT fd_set FAR * exceptfds, IN const struct timeval FAR * timeout, OUT LPINT lpErrno ) /*++ Routine Description: This routine is used to determine the status of one or more sockets. For each socket, the caller may request information on read, write or error status. The set of sockets for which a given status is requested is indicated by an fd_set structure. All entries in an fd_set correspond to sockets created by the service provider. Upon return, the structures are updated to reflect the subset of these sockets which meet the specified condition, and WSPSelect() returns the total number of sockets meeting the conditions. A set of macros is provided for manipulating an fd_set. These macros are compatible with those used in the Berkeley software, but the underlying representation is completely different. The parameter readfds identifies those sockets which are to be checked for readability. If the socket is currently WSPListen()ing, it will be marked as readable if an incoming connection request has been received, so that a WSPAccept() is guaranteed to complete without blocking. For other sockets, readability means that queued data is available for reading so that a WSPRecv() or WSPRecvfrom() is guaranteed not to block. For connection-oriented sockets, readability may also indicate that a close request has been received from the peer. If the virtual circuit was closed gracefully, then a WSPRecv() will return immediately with 0 bytes read. If the virtual circuit was reset, then a WSPRecv() will complete immediately with an error code, such as WSAECONNRESET. The presence of out-of-band data will be checked if the socket option SO_OOBINLINE has been enabled (see WSPSetSockOpt()). The parameter writefds identifies those sockets which are to be checked for writability. If a socket is WSPConnect()ing, writability means that the connection establishment successfully completed. If the socket is not in the process of WSPConnect()ing, writability means that a WSPSend() or WSPSendTo() are guaranteed to succeed. However, they may block on a blocking socket if the len exceeds the amount of outgoing system buffer space available.. (It is not specified how long these guarantees can be assumed to be valid, particularly in a multithreaded environment.) The parameter exceptfds identifies those sockets which are to be checked for the presence of out-of-band data or any exceptional error conditions. Note that out-of-band data will only be reported in this way if the option SO_OOBINLINE is FALSE. If a socket is WSPConnect()ing (non-blocking), failure of the connect attempt is indicated in exceptfds. Any two of readfds, writefds, or exceptfds may be given as NULL if no descriptors are to be checked for the condition of interest. At least one must be non-NULL, and any non- NULL descriptor set must contain at least one socket descriptor. A socket will be identified in a particular set when WSPSelect() returns if: readfds ~~~~~~~ If WSPListen()ing, a connection is pending, WSPAccept() will succeed. Data is available for reading (includes OOB data if SO_OOBINLINE is enabled). Connection has been closed/reset/aborted. writefds ~~~~~~~~ If WSPConnect()ing (non-blocking), connection has succeeded. Data may be sent. exceptfds ~~~~~~~~~ If WSPConnect()ing (non-blocking), connection attempt failed. OOB data is available for reading (only if SO_OOBINLINE is disabled). Three macros and one upcall function are defined in the header file ws2spi.h for manipulating and checking the descriptor sets. The variable FD_SETSIZE determines the maximum number of descriptors in a set. (The default value of FD_SETSIZE is 64, which may be modified by #defining FD_SETSIZE to another value before #including ws2spi.h.) Internally, socket handles in a fd_set are not represented as bit flags as in Berkeley Unix. Their data representation is opaque. Use of these macros will maintain software portability between different socket environments. The macros to manipulate and check fd_set contents are: FD_CLR(s, *set) Removes the descriptor s from set. FD_SET(s, *set) Adds descriptor s to set. FD_ZERO(*set) Initializes the set to the NULL set. The upcall function used to check the membership is: int WPUFDIsSet ( SOCKET s, FD_SET FAR * set ); which will return nonzero if s is a member of the set, or zero otherwise. The parameter timeout controls how long the WSPSelect() may take to complete. If timeout is a null pointer, WSPSelect() will block indefinitely until at least one descriptor meets the specified criteria. Otherwise, timeout points to a struct timeval which specifies the maximum time that WSPSelect() should wait before returning. When WSPSelect() returns, the contents of the struct timeval are not altered. If the timeval is initialized to {0, 0}, WSPSelect() will return immediately; this is used to "poll" the state of the selected sockets. If this is the case, then the WSPSelect() call is considered nonblocking and the standard assumptions for nonblocking calls apply. For example, the blocking hook will not be called, and the WinSock provider will not yield. WSPSelect() has no effect on the persistence of socket events registered with WSPAsyncSelect() or WSPEventSelect(). Arguments: nfds - This argument is ignored and included only for the sake of compatibility. readfds - An optional pointer to a set of sockets to be checked for readability. writefds - An optional pointer to a set of sockets to be checked for writability exceptfds - An optional pointer to a set of sockets to be checked for errors. timeout - The maximum time for WSPSelect() to wait, or NULL for a blocking operation. lpErrno - A pointer to the error code. Return Value: WSPSelect() returns the total number of descriptors which are ready and contained in the fd_set structures, or SOCKET_ERROR if an error occurred. If the return value is SOCKET_ERROR, a specific error code is available in lpErrno. --*/ { } // WSPSelect INT WSPAPI WSPSend( IN SOCKET s, IN LPWSABUF lpBuffers, IN DWORD dwBufferCount, OUT LPDWORD lpNumberOfBytesSent, IN DWORD dwFlags, IN LPWSAOVERLAPPED lpOverlapped, IN LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine, IN LPWSATHREADID lpThreadId, OUT LPINT lpErrno ) /*++ Routine Description: This routine is used to write outgoing data from one or more buffers on a connection-oriented socket specified by s. It may also be used, however, on connectionless sockets which have a stipulated default peer address established via the WSPConnect() function. For overlapped sockets (created using WSPSocket() with flag WSA_FLAG_OVERLAPPED) this will occur using overlapped I/O, unless both lpOverlapped and lpCompletionRoutine are NULL in which case the socket is treated as a non-overlapped socket. A completion indication will occur (invocation of the completion routine or setting of an event object) when the supplied buffer(s) have been consumed by the transport. If the operation does not complete immediately, the final completion status is retrieved via the completion routine or WSPGetOverlappedResult(). For non-overlapped sockets, the parameters lpOverlapped, lpCompletionRoutine, and lpThreadId are ignored and WSPSend() adopts the regular synchronous semantics. Data is copied from the supplied buffer(s) into the transport's buffer. If the socket is non-blocking and stream- oriented, and there is not sufficient space in the transport's buffer, WSPSend() will return with only part of the supplied buffers having been consumed. Given the same buffer situation and a blocking socket, WSPSend() will block until all of the supplied buffer contents have been consumed. The array of WSABUF structures pointed to by the lpBuffers parameter is transient. If this operation completes in an overlapped manner, it is the service provider's responsibility to capture these WSABUF structures before returning from this call. This enables applications to build stack- based WSABUF arrays. For message-oriented sockets, care must be taken not to exceed the maximum message size of the underlying provider, which can be obtained by getting the value of socket option SO_MAX_MSG_SIZE. If the data is too long to pass atomically through the underlying protocol the error WSAEMSGSIZE is returned, and no data is transmitted. Note that the successful completion of a WSPSend() does not indicate that the data was successfully delivered. dwFlags may be used to influence the behavior of the function invocation beyond the options specified for the associated socket. That is, the semantics of this routine are determined by the socket options and the dwFlags parameter. The latter is constructed by or-ing any of the following values: MSG_DONTROUTE - Specifies that the data should not be subject to routing. A WinSock service provider may choose to ignore this flag. MSG_OOB - Send out-of-band data (stream style socket such as SOCK_STREAM only). MSG_PARTIAL - Specifies that lpBuffers only contains a partial message. Note that the error code WSAEOPNOTSUPP will be returned which do not support partial message transmissions. If an overlapped operation completes immediately, WSPSend() returns a value of zero and the lpNumberOfBytesSent parameter is updated with the number of bytes sent. If the overlapped operation is successfully initiated and will complete later, WSPSend() returns SOCKET_ERROR and indicates error code WSA_IO_PENDING. In this case, lpNumberOfBytesSent is not updated. When the overlapped operation completes the amount of data transferred is indicated either via the cbTransferred parameter in the completion routine (if specified), or via the lpcbTransfer parameter in WSPGetOverlappedResult(). Providers must allow this routine to be called from within the completion routine of a previous WSPRecv(), WSPRecvFrom(), WSPSend() or WSPSendTo() function. However, for a given socket, I/O completion routines may not be nested. This permits time-sensitive data transmissions to occur entirely within a preemptive context. The lpOverlapped parameter must be valid for the duration of the overlapped operation. If multiple I/O operations are simultaneously outstanding, each must reference a separate overlapped structure. The WSAOVERLAPPED structure has the following form: typedef struct _WSAOVERLAPPED { DWORD Internal; // reserved DWORD InternalHigh; // reserved DWORD Offset; // reserved DWORD OffsetHigh; // reserved WSAEVENT hEvent; } WSAOVERLAPPED, FAR * LPWSAOVERLAPPED; If the lpCompletionRoutine parameter is NULL, the service provider signals the hEvent field of lpOverlapped when the overlapped operation completes if it contains a valid event object handle. The WinSock SPI client can use WSPGetOverlappedResult() to wait or poll on the event object. If lpCompletionRoutine is not NULL, the hEvent field is ignored and can be used by the WinSock SPI client to pass context information to the completion routine. It is the service provider's responsibility to arrange for invocation of the client-specified completion routine when the overlapped operation completes. Since the completion routine must be executed in the context of the same thread that initiated the overlapped operation, it cannot be invoked directly from the service provider. The WinSock DLL offers an asynchronous procedure call (APC) mechanism to facilitate invocation of completion routines. A service provider arranges for a function to be executed in the proper thread by calling WPUQueueApc(). Note that this routine must be invoked while in the context of the same process (but not necessarily the same thread) that was used to initiate the overlapped operation. It is the service provider's responsibility to arrange for this process context to be active prior to calling WPUQueueApc(). WPUQueueApc() takes as input parameters a pointer to a WSATHREADID structure (supplied to the provider via the lpThreadId input parameter), a pointer to an APC function to be invoked, and a 32 bit context value that is subsequently passed to the APC function. Because only a single 32-bit context value is available, the APC function cannot itself be the client-specified completion routine. The service provider must instead supply a pointer to its own APC function which uses the supplied context value to access the needed result information for the overlapped operation, and then invokes the client-specified completion routine. The prototype for the client-supplied completion routine is as follows: void CALLBACK CompletionRoutine( IN DWORD dwError, IN DWORD cbTransferred, IN LPWSAOVERLAPPED lpOverlapped, IN DWORD dwFlags ); CompletionRoutine is a placeholder for a client supplied function name. dwError specifies the completion status for the overlapped operation as indicated by lpOverlapped. cbTransferred specifies the number of bytes sent. No flag values are currently defined and the dwFlags value will be zero. This routine does not return a value. The completion routines may be called in any order, not necessarily in the same order the overlapped operations are completed. However, the service provider guarantees to the client that posted buffers are sent in the same order they are supplied. Arguments: s - A descriptor identifying a connected socket. lpBuffers - A pointer to an array of WSABUF structures. Each WSABUF structure contains a pointer to a buffer and the length of the buffer. This array must remain valid for the duration of the send operation. dwBufferCount - The number of WSABUF structures in the lpBuffers array. lpNumberOfBytesSent - A pointer to the number of bytes sent by this call. dwFlags - Specifies the way in which the call is made. lpOverlapped - A pointer to a WSAOVERLAPPED structure. lpCompletionRoutine - A pointer to the completion routine called when the send operation has been completed. lpThreadId - A pointer to a thread ID structure to be used by the provider in a subsequent call to WPUQueueApc(). The provider should store the referenced WSATHREADID structure (not the pointer to same) until after the WPUQueueApc() function returns. lpErrno - A pointer to the error code. Return Value: If no error occurs and the send operation has completed immediately, WSPSend() returns 0. Note that in this case the completion routine, if specified, will have already been queued. Otherwise, a value of SOCKET_ERROR is returned, and a specific error code is available in lpErrno. The error code WSA_IO_PENDING indicates that the overlapped operation has been successfully initiated and that completion will be indicated at a later time. Any other error code indicates that no overlapped operation was initiated and no completion indication will occur. --*/ { } // WSPSend INT WSPAPI WSPSendDisconnect( IN SOCKET s, IN LPWSABUF lpOutboundDisconnectData, OUT LPINT lpErrno ) /*++ Routine Description: This routine is used on connection-oriented sockets to disable transmission, and to initiate termination of the connection along with the transmission of disconnect data, if any. After this routine has been successfully issued, subsequent sends are disallowed. lpOutboundDisconnectData, if not NULL, points to a buffer containing the outgoing disconnect data to be sent to the remote party. Note that WSPSendDisconnect() does not close the socket, and resources attached to the socket will not be freed until WSPCloseSocket() is invoked. WSPSendDisconnect() does not block regardless of the SO_LINGER setting on the socket. A WinSock SPI client should not rely on being able to re-use a socket after it has been WSPSendDisconnect()ed. In particular, a WinSock provider is not required to support the use of WSPConnect() on such a socket. Arguments: s - A descriptor identifying a socket. lpOutboundDisconnectData - A pointer to the outgoing disconnect data. lpErrno - A pointer to the error code. Return Value: If no error occurs, WSPSendDisconnect() returns 0. Otherwise, a value of SOCKET_ERROR is returned, and a specific error code is available in lpErrno. --*/ { } // WSPSendDisconnect INT WSPAPI WSPSendTo( IN SOCKET s, IN LPWSABUF lpBuffers, IN DWORD dwBufferCount, OUT LPDWORD lpNumberOfBytesSent, IN DWORD dwFlags, IN const struct sockaddr FAR * lpTo, IN int iTolen, IN LPWSAOVERLAPPED lpOverlapped, IN LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine, IN LPWSATHREADID lpThreadId, OUT LPINT lpErrno ) /*++ Routine Description: This routine is normally used on a connectionless socket specified by s to send a datagram contained in one or more buffers to a specific peer socket identified by the lpTo parameter. On a connection-oriented socket, the lpTo and iToLen parameters are ignored; in this case the WSPSendTo() is equivalent to WSPSend(). For overlapped sockets (created using WSPSocket() with flag WSA_FLAG_OVERLAPPED) this will occur using overlapped I/O, unless both lpOverlapped and lpCompletionRoutine are NULL in which case the socket is treated as a non-overlapped socket. A completion indication will occur (invocation of the completion routine or setting of an event object) when the supplied buffer(s) have been consumed by the transport. If the operation does not complete immediately, the final completion status is retrieved via the completion routine or WSPGetOverlappedResult(). For non-overlapped sockets, the parameters lpOverlapped, lpCompletionRoutine, and lpThreadId are ignored and WSPSend() adopts the regular synchronous semantics. Data is copied from the supplied buffer(s) into the transport's buffer. If the socket is non-blocking and stream- oriented, and there is not sufficient space in the transport's buffer, WSPSend() will return with only part of the supplied buffers having been consumed. Given the same buffer situation and a blocking socket, WSPSend() will block until all of the supplied buffer contents have been consumed. The array of WSABUF structures pointed to by the lpBuffers parameter is transient. If this operation completes in an overlapped manner, it is the service provider's responsibility to capture these WSABUF structures before returning from this call. This enables applications to build stack- based WSABUF arrays. For message-oriented sockets, care must be taken not to exceed the maximum message size of the underlying provider, which can be obtained by getting the value of socket option SO_MAX_MSG_SIZE. If the data is too long to pass atomically through the underlying protocol the error WSAEMSGSIZE is returned, and no data is transmitted. Note that the successful completion of a WSPSendTo() does not indicate that the data was successfully delivered. dwFlags may be used to influence the behavior of the function invocation beyond the options specified for the associated socket. That is, the semantics of this routine are determined by the socket options and the dwFlags parameter. The latter is constructed by or-ing any of the following values: MSG_DONTROUTE - Specifies that the data should not be subject to routing. A WinSock service provider may choose to ignore this flag. MSG_OOB - Send out-of-band data (stream style socket such as SOCK_STREAM only). MSG_PARTIAL - Specifies that lpBuffers only contains a partial message. Note that the error code WSAEOPNOTSUPP will be returned which do not support partial message transmissions. If an overlapped operation completes immediately, WSPSendTo() returns a value of zero and the lpNumberOfBytesSent parameter is updated with the number of bytes sent. If the overlapped operation is successfully initiated and will complete later, WSPSendTo() returns SOCKET_ERROR and indicates error code WSA_IO_PENDING. In this case, lpNumberOfBytesSent is not updated. When the overlapped operation completes the amount of data transferred is indicated either via the cbTransferred parameter in the completion routine (if specified), or via the lpcbTransfer parameter in WSPGetOverlappedResult(). Providers must allow this routine to be called from within the completion routine of a previous WSPRecv(), WSPRecvFrom(), WSPSend() or WSPSendTo() function. However, for a given socket, I/O completion routines may not be nested. This permits time-sensitive data transmissions to occur entirely within a preemptive context. The lpOverlapped parameter must be valid for the duration of the overlapped operation. If multiple I/O operations are simultaneously outstanding, each must reference a separate overlapped structure. The WSAOVERLAPPED structure has the following form: typedef struct _WSAOVERLAPPED { DWORD Internal; // reserved DWORD InternalHigh; // reserved DWORD Offset; // reserved DWORD OffsetHigh; // reserved WSAEVENT hEvent; } WSAOVERLAPPED, FAR * LPWSAOVERLAPPED; If the lpCompletionRoutine parameter is NULL, the service provider signals the hEvent field of lpOverlapped when the overlapped operation completes if it contains a valid event object handle. The WinSock SPI client can use WSPGetOverlappedResult() to wait or poll on the event object. If lpCompletionRoutine is not NULL, the hEvent field is ignored and can be used by the WinSock SPI client to pass context information to the completion routine. It is the service provider's responsibility to arrange for invocation of the client-specified completion routine when the overlapped operation completes. Since the completion routine must be executed in the context of the same thread that initiated the overlapped operation, it cannot be invoked directly from the service provider. The WinSock DLL offers an asynchronous procedure call (APC) mechanism to facilitate invocation of completion routines. A service provider arranges for a function to be executed in the proper thread by calling WPUQueueApc(). Note that this routine must be invoked while in the context of the same process (but not necessarily the same thread) that was used to initiate the overlapped operation. It is the service provider's responsibility to arrange for this process context to be active prior to calling WPUQueueApc(). WPUQueueApc() takes as input parameters a pointer to a WSATHREADID structure (supplied to the provider via the lpThreadId input parameter), a pointer to an APC function to be invoked, and a 32 bit context value that is subsequently passed to the APC function. Because only a single 32-bit context value is available, the APC function cannot itself be the client-specified completion routine. The service provider must instead supply a pointer to its own APC function which uses the supplied context value to access the needed result information for the overlapped operation, and then invokes the client-specified completion routine. The prototype for the client-supplied completion routine is as follows: void CALLBACK CompletionRoutine( IN DWORD dwError, IN DWORD cbTransferred, IN LPWSAOVERLAPPED lpOverlapped, IN DWORD dwFlags ); CompletionRoutine is a placeholder for a client supplied function name. dwError specifies the completion status for the overlapped operation as indicated by lpOverlapped. cbTransferred specifies the number of bytes sent. No flag values are currently defined and the dwFlags value will be zero. This routine does not return a value. The completion routines may be called in any order, not necessarily in the same order the overlapped operations are completed. However, the service provider guarantees to the client that posted buffers are sent in the same order they are supplied. Arguments: s - A descriptor identifying a socket. lpBuffers - A pointer to an array of WSABUF structures. Each WSABUF structure contains a pointer to a buffer and the length of the buffer. This array must remain valid for the duration of the send operation. dwBufferCount - The number of WSABUF structures in the lpBuffers array. lpNumberOfBytesSent - A pointer to the number of bytes sent by this call. dwFlags - Specifies the way in which the call is made. lpTo - An optional pointer to the address of the target socket. iTolen - The size of the address in lpTo. lpOverlapped - A pointer to a WSAOVERLAPPED structure. lpCompletionRoutine - A pointer to the completion routine called when the send operation has been completed. lpThreadId - A pointer to a thread ID structure to be used by the provider in a subsequent call to WPUQueueApc(). The provider should store the referenced WSATHREADID structure (not the pointer to same) until after the WPUQueueApc() function returns. lpErrno - A pointer to the error code. Return Value: If no error occurs and the send operation has completed immediately, WSPSendTo() returns 0. Note that in this case the completion routine, if specified, will have already been queued. Otherwise, a value of SOCKET_ERROR is returned, and a specific error code is available in lpErrno. The error code WSA_IO_PENDING indicates that the overlapped operation has been successfully initiated and that completion will be indicated at a later time. Any other error code indicates that no overlapped operation was initiated and no completion indication will occur. --*/ { } // WSPSendTo INT WSPAPI WSPSetSockOpt( IN SOCKET s, IN int level, IN int optname, IN const char FAR * optval, IN int optlen, OUT LPINT lpErrno ) /*++ Routine Description: This routine sets the current value for a socket option associated with a socket of any type, in any state. Although options may exist at multiple protocol levels, they are always present at the uppermost "socket' level. Options affect socket operations, such as whether broadcast messages may be sent on the socket, etc. There are two types of socket options: Boolean options that enable or disable a feature or behavior, and options which require an integer value or structure. To enable a Boolean option, optval points to a nonzero integer. To disable the option optval points to an integer equal to zero. optlen should be equal to sizeof(int) for Boolean options. For other options, optval points to the an integer or structure that contains the desired value for the option, and optlen is the length of the integer or structure. Value Type Meaning ~~~~~ ~~~~ ~~~~~~~ SO_BROADCAST BOOL Allow transmission of broadcast messages on the socket. SO_DEBUG BOOL Record debugging information. SO_DONTLINGER BOOL Don't block close waiting for unsent data to be sent. Setting this option is equivalent to setting SO_LINGER with l_onoff set to zero. SO_DONTROUTE BOOL Don't route: send directly to interface. SO_GROUP_PRIORITY int Specify the relative priority to be established for sockets that are part of a socket group. SO_KEEPALIVE BOOL Send keepalives. SO_LINGER struct linger Linger on close if unsent data is present. SO_OOBINLINE BOOL Receive out-of-band data in the normal data stream. SO_RCVBUF int Specify buffer size for receives. SO_REUSEADDR BOOL Allow the socket to be bound to an address which is already in use. (See WSPBind().) SO_SNDBUF int Specify buffer size for sends. PVD_CONFIG Service This object stores the Provider configuration information for the Dependent service provider associated with socket s. The exact format of this data structure is service provider specific. Calling WSPSetSockOpt() with an unsupported option will result in an error code of WSAENOPROTOOPT being returned in lpErrno. SO_DEBUG - WinSock service providers are encouraged (but not required) to supply output debug information if the SO_DEBUG option is set by a WinSock SPI client. The mechanism for generating the debug information and the form it takes are beyond the scope of this specification. SO_GROUP_PRIORITY - Group priority indicates the priority of the specified socket relative to other sockets within the socket group. Values are non- negative integers, with zero corresponding to the highest priority. Priority values represent a hint to the service provider about how potentially scarce resources should be allocated. For example, whenever two or more sockets are both ready to transmit data, the highest priority socket (lowest value for SO_GROUP_PRIORITY) should be serviced first, with the remainder serviced in turn according to their relative priorities. The WSAENOPROTOOPT error is indicated for non group sockets or for service providers which do not support group sockets. SO_KEEPALIVE - An WinSock SPI client may request that a TCP/IP provider enable the use of "keep-alive" packets on TCP connections by turning on the SO_KEEPALIVE socket option. A WinSock provider need not support the use of keep-alives: if it does, the precise semantics are implementation-specific but should conform to section 4.2.3.6 of RFC 1122: Requirements for Internet Hosts -- Communication Layers. If a connection is dropped as the result of "keep-alives" the error code WSAENETRESET is returned to any calls in progress on the socket, and any subsequent calls will fail with WSAENOTCONN. SO_LINGER - SO_LINGER controls the action taken when unsent data is queued on a socket and a WSPCloseSocket() is performed. See WSPCloseSocket() for a description of the way in which the SO_LINGER settings affect the semantics of WSPCloseSocket(). The WinSock SPI client sets the desired behavior by creating a struct linger (pointed to by the optval argument) with the following elements: struct linger { u_short l_onoff; u_short l_linger; }; To enable SO_LINGER, a WinSock SPI client should set l_onoff to a non-zero value, set l_linger to 0 or the desired timeout (in seconds), and call WSPSetSockOpt(). To enable SO_DONTLINGER (i.e. disable SO_LINGER) l_onoff should be set to zero and WSPSetSockOpt() should be called. Note that enabling SO_LINGER with a non-zero timeout on a non-blocking socket is not recommended (see WSPCloseSocket() for details). Enabling SO_LINGER also disables SO_DONTLINGER, and vice versa. Note that if SO_DONTLINGER is DISABLED (i.e. SO_LINGER is ENABLED) then no timeout value is specified. In this case the timeout used is implementation dependent. If a previous timeout has been established for a socket (by enabling SO_LINGER), then this timeout value should be reinstated by the service provider. SO_REUSEADDR - By default, a socket may not be bound (see WSPBind()) to a local address which is already in use. On occasions, however, it may be desirable to "re-use" an address in this way. Since every connection is uniquely identified by the combination of local and remote addresses, there is no problem with having two sockets bound to the same local address as long as the remote addresses are different. To inform the WinSock provider that a WSPBind() on a socket should be allowed to bind to a local address that is already in use by another socket, the WinSock SPI client should set the SO_REUSEADDR socket option for the socket before issuing the WSPBind(). Note that the option is interpreted only at the time of the WSPBind(): it is therefore unnecessary (but harmless) to set the option on a socket which is not to be bound to an existing address, and setting or resetting the option after the WSPBind() has no effect on this or any other socket. SO_RCVBUF & SO_SNDBUF - When a Windows Sockets implementation supports the SO_RCVBUF and SO_SNDBUF options, a WinSock SPI client may request different buffer sizes (larger or smaller). The call may succeed even though the service provider did not make available the entire amount requested. A WinSock SPI client must call WSPGetSockOpt() with the same option to check the buffer size actually provided. PVD_CONFIG - This object stores the configuration information for the service provider associated with socket s. The exact format of this data structure is service provider specific. Arguments: s - A descriptor identifying a socket. level - The level at which the option is defined; the supported levels include SOL_SOCKET. optname - The socket option for which the value is to be set. optval - A pointer to the buffer in which the value for the requested option is supplied. optlen - The size of the optval buffer. lpErrno - A pointer to the error code. Return Value: If no error occurs, WSPSetSockOpt() returns 0. Otherwise, a value of SOCKET_ERROR is returned, and a specific error code is available in lpErrno. --*/ { } // WSPSetSockOpt INT WSPAPI WSPShutdown( IN SOCKET s, IN int how, OUT LPINT lpErrno ) /*++ Routine Description: This routine is used on all types of sockets to disable reception, transmission, or both. If how is SD_RECEIVE, subsequent receives on the socket will be disallowed. This has no effect on the lower protocol layers. For TCP sockets, if there is still data queued on the socket waiting to be received, or data arrives subsequently, the connection is reset, since the data cannot be delivered to the user. For UDP sockets, incoming datagrams are accepted and queued. In no case will an ICMP error packet be generated. If how is SD_SEND, subsequent sends on the socket are disallowed. For TCP sockets, a FIN will be sent. Setting how to SD_BOTH disables both sends and receives as described above. Note that WSPShutdown() does not close the socket, and resources attached to the socket will not be freed until WSPCloseSocket() is invoked. WSPShutdown() does not block regardless of the SO_LINGER setting on the socket. A WinSock SPI client should not rely on being able to re-use a socket after it has been shut down. In particular, a WinSock service provider is not required to support the use of WSPConnect() on such a socket. Arguments: s - A descriptor identifying a socket. how - A flag that describes what types of operation will no longer be allowed. lpErrno - A pointer to the error code. Return Value: If no error occurs, WSPShutdown() returns 0. Otherwise, a value of SOCKET_ERROR is returned, and a specific error code is available in lpErrno. --*/ { } // WSPShutdown SOCKET WSPAPI WSPSocket( IN int af, IN int type, IN int protocol, IN LPWSAPROTOCOL_INFOW lpProtocolInfo, IN GROUP g, IN DWORD dwFlags, OUT LPINT lpErrno ) /*++ Routine Description: WSPSocket() causes a socket descriptor and any related resources to be allocated. By default, the created socket will not have the overlapped attribute. WinSock providers are encouraged to be realized as Windows installable file systems, and supply system file handles as socket descriptors. These providers must call WPUModifyIFSHandle() prior to returning from this routine For non-file-system WinSock providers, WPUCreateSocketHandle() must be used to acquire a unique socket descriptor from the WinSock 2 DLL prior to returning from this routine. The values for af, type and protocol are those supplied by the application in the corresponding API functions socket() or WSASocket(). A service provider is free to ignore or pay attention to any or all of these values as is appropriate for the particular protocol. However, the provider must be willing to accept the value of zero for af and type, since the WinSock 2 DLL considers these to be wild card values. Also the value of manifest constant FROM_PROTOCOL_INFOW must be accepted for any of af, type and protocol. This value indicates that the WinSock 2 application wishes to use the corresponding values from the indicated WSAPROTOCOL_INFOW struct: iAddressFamily iSocketType iProtocol Parameter g is used to indicate the appropriate actions on socket groups: If g is an existing socket group ID, join the new socket to this group, provided all the requirements set by this group are met. If g = SG_UNCONSTRAINED_GROUP, create an unconstrained socket group and have the new socket be the first member. If g = SG_CONSTRAINED_GROUP, create a constrained socket group and have the new socket be the first member. If g = zero, no group operation is performed. Any set of sockets grouped together must be implemented by a single service provider. For unconstrained groups, any set of sockets may be grouped together. A constrained socket group may consist only of connection-oriented sockets, and requires that connections on all grouped sockets be to the same address on the same host. For newly created socket groups, the new group ID must be available for the WinSock SPI client to retrieve by calling WSPGetSockOpt() with option SO_GROUP_ID. A socket group and its associated ID remain valid until the last socket belonging to this socket group is closed. Socket group IDs are unique across all processes for a given service provider. The dwFlags parameter may be used to specify the attributes of the socket by OR-ing any of the following Flags: WSA_FLAG_OVERLAPPED - This flag causes an overlapped socket to be created. Overlapped sockets may utilize WSPSend(), WSPSendTo(), WSPRecv(), WSPRecvFrom() and WSPIoctl() for overlapped I/O operations, which allows multiple operations to be initiated and in progress simultaneously. WSA_FLAG_MULTIPOINT_C_ROOT - Indicates that the socket created will be a c_root in a multipoint session. Only allowed if a rooted control plane is indicated in the protocol's WSAPROTOCOL_INFOW struct. WSA_FLAG_MULTIPOINT_C_LEAF - Indicates that the socket created will be a c_leaf in a multicast session. Only allowed if XP1_SUPPORT_MULTIPOINT is indicated in the protocol's WSAPROTOCOL_INFOW struct. WSA_FLAG_MULTIPOINT_D_ROOT - Indicates that the socket created will be a d_root in a multipoint session. Only allowed if a rooted data plane is indicated in the protocol's WSAPROTOCOL_INFOW struct. WSA_FLAG_MULTIPOINT_D_LEAF - Indicates that the socket created will be a d_leaf in a multipoint session. Only allowed if XP1_SUPPORT_MULTIPOINT is indicated in the protocol's WSAPROTOCOL_INFOW struct. N.B For multipoint sockets, exactly one of WSA_FLAG_MULTIPOINT_C_ROOT or WSA_FLAG_MULTIPOINT_C_LEAF must be specified, and exactly one of WSA_FLAG_MULTIPOINT_D_ROOT or WSA_FLAG_MULTIPOINT_D_LEAF must be specified. Connection-oriented sockets such as SOCK_STREAM provide full-duplex connections, and must be in a connected state before any data may be sent or received on them. A connection to another socket is created with a WSPConnect() call. Once connected, data may be transferred using WSPSend() and WSPRecv() calls. When a session has been completed, a WSPCloseSocket() must be performed. The communications protocols used to implement a reliable, connection- oriented socket ensure that data is not lost or duplicated. If data for which the peer protocol has buffer space cannot be successfully transmitted within a reasonable length of time, the connection is considered broken and subsequent calls will fail with the error code set to WSAETIMEDOUT. Connectionless, message-oriented sockets allow sending and receiving of datagrams to and from arbitrary peers using WSPSendTo() and WSPRecvFrom(). If such a socket is WSPConnect()ed to a specific peer, datagrams may be sent to that peer using WSPSend() and may be received from (only) this peer using WSPRecv(). Support for sockets with type SOCK_RAW is not required but service providers are encouraged to support raw sockets whenever it makes sense to do so. When a special WSAPROTOCOL_INFOW struct (obtained via the WSPDuplicateSocket() function and used to create additional descriptors for a shared socket) is passed as an input parameter to WSPSocket(), the g and dwFlags parameters are ignored. Arguments: af- An address family specification. type - A type specification for the new socket. protocol - A particular protocol to be used with the socket which is specific to the indicated address family. lpProtocolInfo - A pointer to a WSAPROTOCOL_INFOW struct that defines the characteristics of the socket to be created. g - The identifier of the socket group which the new socket is to join. dwFlags - The socket attribute specification. lpErrno - A pointer to the error code. Return Value: If no error occurs, WSPSocket() returns a descriptor referencing the new socket. Otherwise, a value of INVALID_SOCKET is returned, and a specific error code is available in lpErrno. --*/ { } // WSPSocket INT WSPAPI WSPStartup( IN WORD wVersionRequested, OUT LPWSPDATA lpWSPData, IN LPWSAPROTOCOL_INFOW lpProtocolInfo, IN WSPUPCALLTABLE UpcallTable, OUT LPWSPPROC_TABLE lpProcTable ) /*++ Routine Description: This routine MUST be the first WinSock SPI function called by a WinSock SPI client on a per-process basis. It allows the client to specify the version of WinSock SPI required and to provide its upcall dispatch table. All upcalls, i.e., functions prefixed with WPU, made by the WinSock service provider are invoked via the client's upcall dispatch table. This routine also allows the client to retrieve details of the specific WinSock service provider implementation. The WinSock SPI client may only issue further WinSock SPI functions after a successful WSPStartup() invocation. A table of pointers to the rest of the SPI functions is retrieved via the lpProcTable parameter. In order to support future versions of the WinSock SPI and the WinSock 2 DLL which may have functionality differences from the current WinSock SPI, a negotiation takes place in WSPStartup(). The caller of WSPStartup() (either the WinSock 2 DLL or a layered protocol) and the WinSock service provider indicate to each other the highest version that they can support, and each confirms that the other's highest version is acceptable. Upon entry to WSPStartup(), the WinSock service provider examines the version requested by the client. If this version is equal to or higher than the lowest version supported by the service provider, the call succeeds and the service provider returns in wHighVersion the highest version it supports and in wVersion the minimum of its high version and wVersionRequested. The WinSock service provider then assumes that the WinSock SPI client will use wVersion. If the wVersion field of the WSPDATA structure is unacceptable to the caller, it should call WSPCleanup() and either search for another WinSock service provider or fail to initialize. This negotiation allows both a WinSock service provider and a WinSock SPI client to support a range of WinSock versions. A client can successfully utilize a WinSock service provider if there is any overlap in the version ranges. The following chart gives examples of how WSPStartup() works in conjunction with different WinSock DLL and WinSock service provider (SP) versions: DLL SP wVersion- wVersion wHigh- End Version Version Requested Version Result ~~~~~~~ ~~~~~~~ ~~~~~~~~~ ~~~~~~~~ ~~~~~~~ ~~~~~~ 1.1 1.1 1.1 1.1 1.1 use 1.1 1.0 1.1 1.0 1.1 1.0 1.0 use 1.0 1.0 1.0 1.1 1.0 1.0 1.1 use 1.0 1.1 1.0 1.1 1.1 1.1 1.1 use 1.1 1.1 1.0 1.1 1.0 1.0 DLL fails 1.0 1.1 1.0 --- --- WSAVERNOTSUPPORTED 1.0 1.1 1.0 1.1 1.1 1.1 1.1 use 1.1 1.1 2.0 1.1 2.0 1.1 1.1 use 1.1 2.0 2.0 2.0 2.0 2.0 use 2.0 The following code fragment demonstrates how a WinSock SPI client which supports only version 2.0 of WinSock SPI makes a WSPStartup() call: WORD wVersionRequested; WSPDATA WSPData; int err; WSPUPCALLTABLE upcallTable = { // initialize upcallTable with function pointers }; LPWSPPROC_TABLE lpProcTable = { // allocate memory for the ProcTable }; wVersionRequested = MAKEWORD( 2, 0 ); err = WSPStartup( wVersionRequested, &WSPData, lpProtocolBuffer, upcallTable, lpProcTable ); if ( err != 0 ) { // Tell the user that we couldn't find a useable // WinSock service provider. return; } // Confirm that the WinSock service provider supports 2.0. // Note that if the service provider supports versions // greater than 2.0 in addition to 2.0, it will still // return 2.0 in wVersion since that is the version we // requested. if ( LOBYTE( WSPData.wVersion ) != 2 || HIBYTE( WSPData.wVersion ) != 0 ) { // Tell the user that we couldn't find a useable // WinSock service provider. WSPCleanup( ); return; } // The WinSock service provider is acceptable. Proceed. And this code fragment demonstrates how a WinSock service provider which supports only version 2.0 performs the WSPStartup() negotiation: // Make sure that the version requested is >= 2.0. // The low byte is the major version and the high // byte is the minor version. if ( LOBYTE( wVersionRequested ) < 2) { return WSAVERNOTSUPPORTED; } // Since we only support 2.0, set both wVersion and // wHighVersion to 2.0. lpWSPData->wVersion = MAKEWORD( 2, 0 ); lpWSPData->wHighVersion = MAKEWORD( 2, 0 ); Once the WinSock SPI client has made a successful WSPStartup() call, it may proceed to make other WinSock SPI calls as needed. When it has finished using the services of the WinSock service provider, the client must call WSPCleanup() in order to allow the WinSock service provider to free any resources allocated for the client. Details of how WinSock service provider information is encoded in the WSPData structure is as follows: typedef struct WSPData { WORD wVersion; WORD wHighVersion; char szDescription[WSPDESCRIPTION_LEN+1]; } WSPDATA, FAR * LPWSPDATA; The members of this structure are: wVersion- The version of the WinSock SPI specification that the WinSock service provider expects the caller to use. wHighVersion - The highest version of the WinSock SPI specification that this service provider can support (also encoded as above). Normally this will be the same as wVersion. szDescription - A null-terminated ASCII string into which the WinSock provider copies a description of itself. The text (up to 256 characters in length) may contain any characters except control and formatting characters: the most likely use that a SPI client will put this to is to display it (possibly truncated) in a status message. A WinSock SPI client may call WSPStartup() more than once if it needs to obtain the WSPData structure information more than once. On each such call the client may specify any version number supported by the provider. There must be one WSPCleanup() call corresponding to every successful WSPStartup() call to allow third-party DLLs to make use of a WinSock provider. This means, for example, that if WSPStartup() is called three times, the corresponding call to WSPCleanup() must occur three times. The first two calls to WSPCleanup() do nothing except decrement an internal counter; the final WSPCleanup() call does all necessary resource deallocation. Arguments: wVersionRequested - The highest version of WinSock SPI support that the caller can use. The high order byte specifies the minor version (revision) number; the low-order byte specifies the major version number. lpWSPData - A pointer to the WSPDATA data structure that is to receive details of the WinSock service provider. lpProtocolInfo - A pointer to a WSAPROTOCOL_INFOW struct that defines the characteristics of the desired protocol. This is especially useful when a single provider DLL is capable of instantiating multiple different service providers.. UpcallTable - The WinSock 2 DLL's upcall dispatch table. lpProcTable - A pointer to the table of SPI function pointers. Return Value: WSPStartup() returns zero if successful. Otherwise it returns an error code. --*/ { } // WSPStartup INT WSPAPI WSPStringToAddress( IN LPWSTR AddressString, IN INT AddressFamily, IN LPWSAPROTOCOL_INFOW lpProtocolInfo, OUT LPSOCKADDR lpAddress, IN OUT LPINT lpAddressLength, OUT LPINT lpErrno ) /*++ Routine Description: This routine converts a human-readable string to a socket address structure (SOCKADDR) suitable for pass to Windows Sockets routines which take such a structure. Any missing components of the address will be defaulted to a reasonable value if possible. For example, a missing port number will be defaulted to zero. Arguments: AddressString - Points to the zero-terminated human-readable string to convert. AddressFamily - The address family to which the string belongs, or AF_UNSPEC if it is unknown. lpProtocolInfo - The provider's WSAPROTOCOL_INFOW struct. lpAddress - A buffer which is filled with a single SOCKADDR structure. lpAddressLength - The length of the Address buffer. Returns the size of the resultant SOCKADDR structure. lpErrno - A pointer to the error code. Return Value: If no error occurs, WSPStringToAddress() returns 0. Otherwise, a value of SOCKET_ERROR is returned, and a specific error code is available in lpErrno. --*/ { } // WSPStringToAddress