WSPStartup

The WSPStartup function initiates use of a Windows Sockets service provider by a client.

int WSPStartup (
  WORD wVersionRequested,               
  LPWSPDATAW lpWSPData,                 
  LPWSAPROTOCOL_INFOW lpProtocolInfo,   
  WSPUPCALLTABLE UpcallTable,           
  LPWSPPROC_TABLE lpProcTable           
);
 

Parameters

wVersionRequested
[in] The highest version of Windows Sockets 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
[out] A pointer to the WSPDATA data structure that is to receive details of the Windows Sockets service provider.
lpProtocolInfo
[in] A pointer to a WSAPROTOCOL_INFOW structure 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
[in] The WS2_32.DLL's upcall dispatch table.
lpProcTable
[out] A pointer to the table of SPI function pointers.

Remarks

This function must be the first Windows Sockets SPI function called by a Windows Sockets SPI client on a per-process basis. It allows the client to specify the version of Windows Sockets SPI required and to provide its upcall dispatch table. All upcalls (that is, functions prefixed with WPU) made by the Windows Sockets service provider are invoked through the client's upcall dispatch table. This function also allows the client to retrieve details of the specific Windows Sockets service provider implementation. The Windows Sockets SPI client can only issue further Windows Sockets SPI functions after a successful WSPStartup invocation. A table of pointers to the rest of the SPI functions is retrieved through the lpProcTable parameter.

In order to support future versions of the Windows Sockets SPI and the WS2_32.DLL which may have functionality differences from the current Windows Sockets SPI, a negotiation takes place in WSPStartup. The caller of WSPStartup (either the WS2_32.DLL or a layered protocol) and the Windows Sockets 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 Windows Sockets 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 Windows Sockets service provider then assumes that the Windows Sockets 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 Windows Sockets service provider or fail to initialize.

This negotiation allows both a Windows Sockets service provider and a Windows Sockets SPI client to support a range of Windows Sockets versions. A client can successfully utilize a Windows Sockets service provider if there is any overlap in the version ranges. The following chart gives examples of how WSPStartup works in conjunction with different WS2_32.DLL and Windows Sockets service provider (SP) versions:

DLL
Versions
SP
Versions
wVersion
Requested
wVersion wHigh
Version
End 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 Windows Sockets SPI client which supports only version 2 of Windows Sockets 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, 2 );
 
err = WSPStartup( wVersionRequested, &WSPData, lpProtocolBuffer, upcallTable, lpProcTable );
if ( err != 0 ) {
    /* Tell the user that we could not find a useable */
    /* Windows Sockets service provider.                     */
    return;
}
 
/* Confirm that the Windows Sockets service provider supports 2.2.*/
/* Note that if the service provider supports versions */
/* greater than 2.2 in addition to 2.2, it will still */
/* return 2.2 in wVersion since that is the version we  */
/* requested.                                           */
 
if ( LOBYTE( WSPData.wVersion ) != 2 ||
         HIBYTE( WSPData.wVersion ) != 2 ) {
    /* Tell the user that we could not find a useable */
    /* Windows Sockets service provider.                     */
    WSPCleanup( );
    return;   
}
 
/* The Windows Sockets service provider is acceptable. Proceed. */
 

And this code fragment demonstrates how a Windows Sockets service provider which supports only version 2 performs the WSPStartup negotiation:

/* Make sure that the version requested is >= 2.2.  */
/* The low byte is the major version and the high   */
/* byte is the minor version.                       */
 
if ( LOBYTE( wVersionRequested ) < 2) ||
    ((LOBYTE( wVersionRequested ) == 2) &&
     (HIBYTE( wVersionRequested ) < 2))) {
    return WSAVERNOTSUPPORTED;
}
 
/* Since we only support 2.2, set both wVersion and  */
/* wHighVersion to 2.2.                              */
 
lpWSPData->wVersion = MAKEWORD( 2, 2 );
lpWSPData->wHighVersion = MAKEWORD( 2, 2 );
 

Once the Windows Sockets SPI client has made a successful WSPStartup call, it can proceed to make other Windows Sockets SPI calls as needed. When it has finished using the services of the Windows Sockets service provider, the client must call WSPCleanup in order to allow the Windows Sockets service provider to free any resources allocated for the client.

Details of how Windows Sockets service provider information is encoded in the WSPData structure is as follows:

typedef struct WSPData {
    WORD        wVersion;
    WORD        wHighVersion;
    WCHAR       szDescription[WSPDESCRIPTION_LEN+1];
} WSPDATA, FAR * LPWSPDATA;
 

The members of this structure are:

Element Usage
wVersion The version of the Windows Sockets SPI specification that the Windows Sockets service provider expects the caller to use.
wHighVersion The highest version of the Windows Sockets SPI specification that this service provider can support (also encoded as above). Normally this will be the same as wVersion.
szDescription A null-terminated Unicode string into which the Windows Sockets provider copies a description of itself. The text (up to 256 characters in length) can 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 Windows Sockets SPI client can call WSPStartup more than once if it needs to obtain the WSPData structure information more than once. On each such call the client can 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 Windows Sockets 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.

This function (and most other service provider functions) can be invoked in a thread that started out as a 16-bit process if the client is a 16-bit Windows Sockets 1.1 client. One important limitation of 16-bit processes is that a 16-bit process cannot create threads. This is significant to service provider implementers that plan to use an internal service thread as part of the implementation.

Fortunately, there are usually only two areas where the desire for a service thread is strong: (1) in the implementation of overlapped I/O completion, and (2) in the implementation of WSPEventSelect. Both of these areas are only accessible through new Windows Sockets 2 functions, which can only be invoked by 32-bit processes. A service thread can be safely used if several design rules are carefully followed: (1) Use a service thread only for functionality that is unavailable to 16-bit Windows Sockets 1.1 clients, and (2) create the service thread only on demand.

Several other cautions apply to the use of internal service threads. First, threads generally carry some performance penalty. Use as few as possible, and avoid thread transitions wherever possible. Second, your code should always check for errors in creating threads and fail gracefully and informatively (for example, with WSAEOPNOTSUPP) in case some execution event you did not expect results in a 16-bit process executing a code path that needs threads.

Layered Service Provider Considerations

A layered service provider supplies an implementation of this function, but it is also a client of this function when it calls WSPStartup to initialize the next layer in the protocol chain. The call to the next layer's WSPStartup may happen during the execution of this layer's WSPStartup or it may be delayed and called on demand, such as when WSPSocket is called. In any case, some special considerations apply to this function's lpProtocolInfo parameter as it is propagated down through the layers of the protocol chain.

The layered provider searches the ProtocolChain of the structure referenced by lpProtocolInfo to determine its own location in the chain (by searching for the layer's own catalog entry Id) and the identity of the next element in the chain. If the next element is another layer then when the next layer's WSPStartup is called, this layer must pass to the next layer a lpProtocolInfo that references the same unmodified WSAPROTOCOL_INFOW structure with the same unmodified chain information. However, if the next layer is the base protocol (i.e., the last element in the chain), this layer performs a substitution when calling the base provider's WSPStartup. In this case, the base provider's WSAPROTOCOL_INFOW structure should be referenced by the lpProtocolInfo parameter.

One vital benefit of this policy is that base service providers do not have to be aware of protocol chains.

This same propagation policy applies when propagating a WSAPROTOCOL_INFOW structure through a layered sequence of other functions such as WSPAddressToString, WSPDuplicateSocket, WSPSocket, or WSPStringToAddress.

Return Values

WSPStartup returns zero if successful. Otherwise, it returns one of the error codes listed below.

Error Codes

WSASYSNOTREADY Indicates that the underlying network subsystem is not ready for network communication.
WSAVERNOTSUPPORTED The version of Windows Sockets SPI support requested is not provided by this particular Windows Sockets service provider.
WSAEINPROGRESS A blocking Windows Sockets operation is in progress.
WSAEPROCLIM Limit on the number of clients supported by the Windows Sockets implementation has been reached.
WSAEFAULT The lpWSPData or lpProcTable parameter is invalid.

QuickInfo

  Windows NT: Yes
  Windows: Yes
  Windows CE: Unsupported.
  Header: Declared in ws2spi.h.

See Also

WSPSend, WSPSendTo, WSPCleanup