Editor's Note: The contents of this document were integrated in revision 2.2.1 of the "Windows Sockets 2 Service Provider Interface" specification. It is presented here to provide an overview of the problem and the Layered Service Provider requirements for support of Installed File Systems (IFS) socket handles. Where differences exist between this document--which was a draft of revisions to the specification--and the updated 2.2.1 SPI specification, defer to the contents of the specification (specifically, see sections, 4.2.4, 4.2.6 and 4.2.9).

Specification Revision Request

Overview of Problem

Windows Sockets 2 layered service providers cannot create socket handles that are true file system handles. An application written to Windows Sockets 1.1 that uses file system I/O calls (e.g. ReadFile and WriteFile) on sockets handles fails when the application attempts to perform I/O on socket handles exported by a Windows Sockets 2 layered service provider. In addition, Winsock 1.1 and Windows Sockets 2 applications that associate socket handles with completion ports (available only on Windows NT) also fail. Some applications affected include: NT RPC service, MS Internet Server, Netscape Internet Server and others. In the case of NT RPC service, installing layered service provider as default Internet service provider in Windows Sockets 2 renders the whole system unusable after reboot.

Resolution 1

The first resolution requires the layered service provider to meet two conditions in order to work around this problem: a) the provider must be layered on the top of a base service provider that exposes IFS socket handles, which is almost always the case, and b) the layered provider cannot post-process overlapped IO using WSPSend (WriteFile), WSPSendTo, WSPRecv (ReadFile), WSPRecvFrom, or WSPIoctl. If both conditions are met, the layered service provider can expose base service provider socket handles as its own instead of creating them with the WPUCreateSocketHandle call.

In addition, the layered service provider should expose base provider entry points for WSPSend and WSPRecv in its dispatch table. This requirement is optional, however, as a layered service provider cannot rely on always being called whenever an application invokes through the IO system calls the send and receive functions mentioned above, even if it provides its own entry points in the dispatch table.

Required Spec change (clarification):

  • 1) In order to reuse the handles of a base service provider, a layered service provider must call WPUModifyIFSHandle with its own (layered service provider) catalog ID as the second parameter for the socket handle returned by the base service provider. Calling this function will inform WS_32.DLL that it should call the layered service provider and not the base service provider for any API request received on the socket handle. The current specification does not explicitly mention that the WPUModufyIFSHandle upcall can be used in this way and should be changed to do this.
  • 2) In the description of the initialization of protocol chains, the current specification states the following about base protocols:
  • A layered provider would then in turn load the next protocol provider in the chain and initialize it with a call to WSPStartup, and so forth. Whenever the next lower layer is another layered provider, the chain's WSAPROTOCOL_INFO struct must be referenced in the WSPStartup call. When the next lower layer is a base protocol (signifying the end of the chain), the chain's WSAPROTOCOL_INFO struct is no longer propagated downward. Instead, the current layer must reference a WSAPROTOCOL_INFO struct that corresponds to the protocol that the base provider should use. Thus, the base provider has no notion of being involved in a protocol chain.
  • However, the current specification does not explicitly require that the same policy (substitution of chain's WSAPROTOCOL_INFO struct to base provider's own) should be followed when processing other calls involving the passage of the WSAPROTOCOL_INFO structure down the protocol chain, i.e.: WSPSocket, WSPStringToAddress, and WSPAddressToString. The specification should be clarified to follow the same policy in all calls.

    Resolution 2

    The second resolution will assure that any socket handles created by a service provider with the existing function WPUCreateSocketHandle will in fact be file system handles (IFS) backed up by Windows Sockets 2 kernel mode component. This component will receive file system requests on behalf of the service provider in kernel mode, marshal the parameters, and call into the appropriate service provider entry point, WSPSend for WriteFile operation and WSPRecv for ReadFile operation, in the context of a dedicated user mode thread.

    Upon completion of the call, the results will be marshaled back to kernel mode and original file system request will be completed. The kernel/user mode interaction, the thread context switches, plus the parameter marshaling will result in significant performance penalty.

    The kernel mode component will also allow a layered service provider to properly deliver completion notifications to applications that associate their socket handles with completion ports

    Thus, the socket handles created with WPUCreateSocketHandle service will be indistinguishable from true file system handles. However, any layered service provider that uses this methodology should still identify itself as non-IFS provider by not setting XP1_IFS_HANDLES flag in provider information structure. An application can use this flag to identify whether it should avoid using file system calls and thus avoid the performance cost described above.

    Required Spec change:

    The Windows Sockets 2 specification should be modified to provide an additional "upcall" function for use by the service providers which will have to be imported directly from WS2_32.DLL (it is impossible to extend the "upcall" table to include this new function because it ("upcall" table) is passed by value in WSAStartup function).

    New Function Prototype


    The WPUCompleteOverlappedRequest function completes an overlapped I/O request with a client-specified completion mechanism that is something other than user mode APC.



    WPUCompleteOverlappedRequest is used by non-IFS service providers to complete an overlapped request for which the client did not request completion with APC (APC completion is handled by WPUQueueApc). WS2_32.DLL will use the appropriate notification mechanism defined by the operating system as requested by the client to complete the operation: notification by signaling the event provided in WSAOVERLAPPED structure, or notification with a completion port if a socket handle is associated with one.

    The service provider should expect that its WSPGetOverlappedResult will be called to retrieve Windows Sockets 2 error code and any additional information in the Flags parameter for the request. It thus should store this information in the WSAOVERLAPPED structure using Offset and OffsetHigh members. The Internal and InternalHigh members will be used by Windows Sockets to complete the request while the hEvent member is used by the client. Therefore, they should not be used by the service provider. However, the service provider can take advantage of the following documented behavior of Windows Sockets.

    The Internal member of WSAOVERLAPPED will be used to indicate whether operation is in progress. When a completion indication is delivered to the application, it will be set to system dependent error code which is something other than WSA_OPERATION_IN_PROGRESS (service provider can thus initialize the field to WSA_OPERATION_IN_PROGRESS as soon as it starts processing the request and then use this value to indicate to itself that request has not yet completed).

    The InternalHigh member of WSAOVERLAPPED will be used to report the number of bytes transferred. WPUCompleteOverlappedRequest will make sure that this member contains the number of bytes transferred when completion indication is delivered to the application.

    This new service will be available both on Win95 and NT and will work correctly (complete the request as requested by the user) whether or not the socket handle is associated with completion port.


    The WPUCompleteOverlappedRequest function is only supported for the socket handles created by WPUCreateSocketHandle and not for sockets created by the service provider itself.

    Return Values

    If no error occurs, WPUCompleteOverlappedRequest returns zero and completes the request with mechanism request by the client (signal an event in the WSAOVERLAPPED structure and/or deliver notification to the completion port if socket is associated with one). Otherwise, it returns SOCKET_ERROR, and a specific error code is available in lpErrno.

    Error Codes