The LSP Helper Winsock Layered Service Provider (LSP)

Other versions of this page are also available for the following:

Windows Mobile SupportedWindows Embedded CE Supported

8/28/2008

The LSP Helper simplifies the creation of Winsock Layered Service Providers (LSP) by providing two pass-through classes and a LSP module class from which developers only have to override the SPI interfaces needed for a new LSP. The LSP helper abstracts the installation algorithm and the algorithms necessary to determine the next provider to call in the Winsock provider chain.

The ILSPModule class defines the interface used by the LSP helper to define the installation details for an LSP. This includes the GUIDs and name of the of the LSP.

The ILSPProvider class defines the interface used by the CLSPProviderPassthrough class which provides a “pass through” implementation of all the non-socket related SPI interfaces.

The ILSPSocket class defines the interface used by the CLSPSocketPasstrhough class which provides a “pass through” implementation of all the socket related SPI interfaces.

ILSPModule

The developer must create a derived class of ILSPModule and implement the interfaces described in the following table.

ILSPModule* CreateLSPModule()

This function, which is not part of the ILSPModule interface, must be implemented by the developer to return a user defined derived object of the ILSPModule class.

GUID* ILSPModule::getGUIDForLSP()

This function must return the GUID for the LSP. This GUID uniquely identifies the specific provider.

GUID* getGUIDForChain()

This function must return the GUID to identify the provider chains over which this LSP is installed. A single GUID is used to identify all the protocol chains.

The protocols the helper installs over include the UDP, TCP, IPv4, and IPv6.

LPCWSTR getModuleName()

This function returns the text description of the provider.

INT getOptionalProtocolToInstallOver()

This function allows the developer to provide an optional protocol to install over. It is used by the Helper’s installation code. Implementation of this interfaces is optional.

ILSPModule Example Code

The following code is an example implementation of an ILSPModule derived class.

// TODO: Replace these GUIDs with your own. 
static GUID v_sampelsp_guid = 
{ 0x1546b33b, 0xa4c3, 0x4978, { 0xa3, 0x52, 0x97, 0xad, 0xd2, 0xc1, 0xd5, 0xf } };

// TODO: Replace these GUIDs with your own. 
static GUID v_samplelsp_chain_guid = 
{ 0xb26a9109, 0xabc9, 0x4bf4, { 0xb1, 0xbe, 0x78, 0x84, 0x5d, 0xac, 0xde, 0x9e } };

class CLSPModuleSampleLsp :public ILSPModule
{
    public:
        virtual GUID* getGUIDForLSP()
        { 
           return &v_sampelsp_guid;
        }
        virtual GUID* getGUIDForChain()
        {
           return &v_samplelsp_chain_guid;
        }
        virtual LPCWSTR getModuleName() 
        {
           return L"SampleLSP";
        }
};

ILSPModule*  CreateLSPModule()
{ 
return new CLSPModuleSampleLsp();
}

CLSProviderPassthrough Interfaces

The developer must create a derived class of CProviderPassthrough to use the LSP Helper. The following table outlines the required implementations necessary to instantiate a basic LSP using the LSP Helper classes.

ILSPProvider* CreateLSPProvider()

This function, which is not part of the ILSPProvider interface, must be implemented by the developer to return a user defined derivative of the CLSPProviderPassthrougth class.

ILSPSocket* ILSPProvider::CreateSocket()

This function must be implemented in a derived CLSPProviderPassthrough class to return a derived class of the CLSPSocketPassthrough. This is only required if the developer plans to override any socket related interfaces which is true almost all the time.

void ILSPProvider::Cleanup(bool)

This function must be implemented in a derived CLSPProviderPasstrhough class to do any conditional cleanup that would normally be done in a destructor. The Boolean input is true if the process is exiting, otherwise it is false.

The interfaces in the next table describe interfaces that should not be overridden by the developer.

ILSPProvider::CreateLSPSocket

This interface depends on the CreateSocket interface described below. It is called during the creation of a new socket.

ILSPProvider::CreateLSPSocketForAccept

This interface depends on the CreateSocket interface described below. It is called during the creation of a new socket during an accept.

ILSPProvider::_Initialize

This interfaces does private initialization required for the LSP helper. Developers must not override this interface.

The interfaces in the next table describe the SPI interfaces that the developer can optionally override in their class derived from CLSPProviderPassThrough.

ILSPProvider::WSPStringToAddress

See the Winsock SPI documentation for details

ILSPProvider::WSPAddressToString

See the Winsock SPI documentation for details

ILSPProvider::WSPSelect

See the Winsock SPI documentation for details

CLSProviderPassthrough Example

The following code is an example implementation of a CLSProviderPassthrough derived class.

class  CProviderSampleLsp : public CLSPProviderPassthrough
{
    public: 
        CProviderSampleLsp() 
        {
        }

        DWORD  Initialize()
        {
            return NO_ERROR;
        }

        void Cleanup( bool bInProcessExit)
        {
            // 'this'  is only deleted if not in PROCESS_EXIT;
            CLSPProviderPassthrough::Cleanup(bInProcessExit);
            return;
        }

        ~CProviderSampleLsp()
        {
            // Destructor should not be called during PROCESS_EXIT.
            // Thus it's ok to make a blocking call.
        }

        ILSPSocket* CreateSocket()
        {
            // Must return an object of a class 
            // derived from CLSPSocketPassthrough
            return new CSocketSampleLsp(); 
        }
};


ILSPProvider* CreateLSPProvider()
{
    CProviderSampleLsp* pLSP =  new CProviderSampleLsp();

    if (pLSP) 
    {
        DWORD ret = pLSP->Initialize();

        if (NO_ERROR != ret)
        {
            // unable to initialize
            delete pLSP;
            pLSP = NULL;
        }
    }
    return  (ILSPProvider*) pLSP;
}

CLSSocketPassthrough Interfaces

The developer must create a class derived from CLSPSocketPassthrough class in order to override any socket related SPI interfaces. Objects of the derived class must be returned from the ILSPProvider::CreateSocket() interface described in the CLPProviderPassthrough section.

CLSSocketPassthrough Socket Creation and Initialization

In order to control the creation of and initialization of new sockets, the developer must implement the interfaces described in the following table.

bool WSPSocket(

int af,

int type,

int protocol,

LPWSAPROTOCOL_INFOW lpProtocolInfo,

GROUP g,

DWORD dwFlags,

INT FAR *lpErrno)

This function is called during the creation of a new socket. The LSP helper calls ILSPProvider::CreateSocket() to create a new socket object (user defined class derived from CLSPSocketPassthrough) and then calls this interface of the new object to allow for socket specific initialization. Return false to prevent the creation of a new socket.

SOCKET WSPAPI WSPAccept(

struct sockaddr FAR *addr,

INT FAR *addrlen,

LPCONDITIONPROC lpfnCondition,

DWORD dwCallbackData,

INT FAR *lpErrno,

PVOID *ppClientData)

This function is called during the creation of a new socket as a result of WSPAccept(). If this function returns a valid socket then a new socket object will be created and the ILSPSocket::InitLSPSocketForAccept() interface of this new object will be called. The developer can provide user defined data using the ppClientData pointer from the accepting socket object to the new socket object.

bool InitLSPSocketForAccept(

CLSPSocketPassthrough*,

struct sockaddr FAR *addr,

INT FAR *addrlen,

LPCONDITIONPROC lpfnCondition,

DWORD dwCallbackData,

INT FAR *lpErrno,

PVOID pClientData);

This function is called on new socket object creates as a result of WSPAccept(). Return false to prevent the creation of the socket. The developer can provide user defined data using the ppClientData pointer from the accepting socket obect to the new socket object.

CLSSocketPassthrough Example

The following is a simple example of overriding an SPI interfaces in a class derived from CLSPSocketPassthrough.

class CSocketSampleLsp : public CLSPSocketPassthrough
{
public:
    virtual INT WSPRecv(
        IN LPWSABUF lpBuffers,
        IN DWORD dwBufferCount,
        IN LPDWORD lpNumberOfBytesRecvd,
        IN OUT LPDWORD lpFlags,
        IN LPWSAOVERLAPPED lpOverlapped,
        IN LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine,
        IN LPWSATHREADID lpThreadId,
        OUT INT FAR *lpErrno)
    {       
        INT ret = CLSPSocketPassthrough::WSPRecv(
                        lpBuffers, 
                        dwBufferCount, 
                        lpNumberOfBytesRecvd, 
                        lpFlags, 
                        lpOverlapped, 
                        lpCompletionRoutine, 
                        lpThreadId, 
                        lpErrno);

        DEBUGMSG(1, (L"WSPRecv() override received %d bytes.\n",           
                        *lpNumberOfBytesRecvd));

        return ret;
    }
};

See Also

Tasks

Using the LSP Installer

Concepts

Layered Protocols and Provider Chains
Installing an LSP
AutoBind LSP
Desktop Passthrough LSP