WSPStartup (Windows Embedded CE 6.0)
1/6/2010
This function initiates use of a Windows Sockets service provider by a client.
Syntax
int WSPStartup(
WORD wVersionRequested,
LPWSPDATAW lpWSPData,
LPWSAPROTOCOL_INFOW lpProtocolInfo,
WSPUPCALLTABLE UpcallTable,
LPWSPPROC_TABLE lpProcTable
);
Parameters
- wVersionRequested
[in] 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] Pointer to the data structure that is to receive details of the Windows Sockets service provider.
- lpProtocolInfo
[in] 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] Upcall dispatch table for ws2.dll.
- lpProcTable
[out] Pointer to the table of SPI function pointers.
Return Value
This function returns zero if successful. Otherwise, it returns an error code.
The following table shows the possible error codes.
Error value | Description |
---|---|
WSASYSNOTREADY |
Indicates that the underlying network subsystem is not ready for network communication. |
WSAVERNOTSUPPORTED |
Version of Windows Sockets SPI support requested is not provided by this particular Windows Sockets service provider. |
WSAEINPROGRESS |
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. |
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.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.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. On entering WSPStartup, the Windows Sockets service provider examines the version requested by the client. If this version is equal to or later 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 member 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 table gives examples of how WSPStartup works in conjunction with different ws2.dll and Windows Sockets service provider versions.
DLL versions | Service provider 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 sample shows how a Windows Sockets SPI client 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 */
/* later 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. */
The following code sample shows how a Windows Sockets service provider 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.
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, like 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.
The following list shows the strong conditions for a service thread:
- In the implementation of overlapped I/O completion.
- 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.
The following list shows the design rules that, if carefully followed, allow a service thread to be safely used:
- Use a service thread only for functionality that is unavailable to 16-bit Windows Sockets 1.1 clients.
- 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 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 provider 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 provider 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 (that is, 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 provider 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.
Requirements
Header | ws2spi.h |
Library | Ws2.lib |
Windows Embedded CE | Windows CE .NET 4.0 and later |