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.
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.
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.
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.
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).
The WPUCompleteOverlappedRequest function completes an overlapped I/O request with a client-specified completion mechanism that is something other than user mode APC.
int WPUCompleteOverlappedRequest (
IN SOCKET s,
IN DWORD cbTransferred,
OUT LPINT lpErrno
s: service provider socket created by WPUCreateSocketHandle
lpOverlapped: a pointer to WSAOVERLAPPED structure associated with the function call to be completed.
dwError: completion status of the overlapped operation.
cbTransferred: number of bytes transferred to or from client buffers (depends on the nature of the send/receive request being completed).
lpErrno: a pointer to the error code.
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.
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.
WSAEINVAL socket s does not specify a socket created with WPUCreateSocketHandle call.