//
// Function: PrintProviders
//
// Description: 
//    This function prints out each entry in the Winsock catalog and its
//    catalog ID if the parameter, bLayeredOnly, is FALSE. If TRUE then
//    print only those layered catalog entries.
//
void 
PrintProviders(
    WINSOCK_CATALOG Catalog, 
    BOOL            bLayeredOnly, 
    BOOL            bVerbose
    )
{
    WSAPROTOCOL_INFOW  *pProtocolInfo = NULL;
    INT                 iProtocolCount = 0,
                        i;

    // Enumerate catalog and print it
	pProtocolInfo = EnumerateProviders( Catalog, &iProtocolCount );
    if ( NULL == pProtocolInfo )
    {
        fprintf( stderr, "PrintProviders: Unable to enumerate catalog!\n" );
        goto cleanup;
    }

    for(i=0; i < iProtocolCount ;i++)
    {
        if ( FALSE == bLayeredOnly )
        {
            // Print all providers
            if ( TRUE == bVerbose )
                PrintProtocolInfo( &pProtocolInfo[ i ] );
            else
                printf("%04d - %S\n", 
                        pProtocolInfo[ i ].dwCatalogEntryId,
                        pProtocolInfo[ i ].szProtocol
                        );
        }
        else if ( LAYERED_PROTOCOL == pProtocolInfo[ i ].ProtocolChain.ChainLen )
        {
            // Print only layered providers
            if ( TRUE == bVerbose )
                PrintProtocolInfo( &pProtocolInfo[ i ] );
            else
                printf("%04d - %S\n", 
                        pProtocolInfo[ i ].dwCatalogEntryId,
                        pProtocolInfo[ i ].szProtocol
                        );
        }
    }
    
cleanup:

    if ( NULL != pProtocolInfo )
        FreeProviders( pProtocolInfo );

    return;
}
Beispiel #2
0
//
// Function: FindMatchingLspEntryForProtocolInfo
//
// Description:
//      This function searches for the appropriate LSP protocol chain entry which 
//      would handle a given WSAPROTOCOL_INFOW.
//
PROVIDER *
FindMatchingLspEntryForProtocolInfo(
        WSAPROTOCOL_INFOW *inInfo,
        PROVIDER          *lspProviders,
        int                lspCount,
        BOOL               fromStartup
        )
{
    WSAPROTOCOL_INFOW  *ProtocolInfo = NULL;
    DWORD               hiddenEntryId;
    int                 ProtocolCount,
                        i, j, k;

    // Two possibilites - this inInfo belongs to our LSP or its a layer over our LSP

    // First see if the inInfo is one of the LSPs entry
    for(i=0; i < lspCount ;i++)
    {
        if ( inInfo->dwCatalogEntryId == lspProviders[ i ].LayerProvider.dwCatalogEntryId )
        {
            return &lspProviders[ i ];
        }
    }

    ASSERT( inInfo->ProtocolChain.ChainLen > 1 );

    // Next check the inInfo's protocol chains for a reference to our LSP
    for(i=0; i < lspCount ;i++)
    {
        for(j=1; j < inInfo->ProtocolChain.ChainLen ;j++)
        {
            if ( ( inInfo->ProtocolChain.ChainEntries[ j ] == lspProviders[ i ].LayerProvider.dwCatalogEntryId ) &&
                 ( lspProviders[ i ].LayerProvider.ProtocolChain.ChainLen == LAYERED_PROTOCOL )
               )
            {
                // Bad news, the entry passed to us references our dummy entry so we
                //    need to do some heuristic work to find the "correct" LSP entry
                //    that corresponds to the input provider
                goto next_match;
            }
            else if ( inInfo->ProtocolChain.ChainEntries[ j ] == lspProviders[ i ].LayerProvider.dwCatalogEntryId )
            {
                return &lspProviders[ i ];
            }
        }
    }

next_match:

    // If we didn't find an explicit match we'll have to guess - first try to
    //    match address family, socket type, protocol and provider flags
    for(i=0; i < lspCount ;i++)
    {
        if ( ( inInfo->iAddressFamily == lspProviders[ i ].LayerProvider.iAddressFamily ) &&
             ( inInfo->iSocketType == lspProviders[ i ].LayerProvider.iSocketType ) &&
             ( inInfo->iProtocol == lspProviders[ i ].LayerProvider.iProtocol ) &&
             ( ( ( inInfo->dwServiceFlags1 & ~XP1_IFS_HANDLES ) ==
                 ( lspProviders[ i ].LayerProvider.dwServiceFlags1 & ~XP1_IFS_HANDLES ) 
               )
             )
           )
        {
            return &lspProviders[ i ];
        }
    }

    // If this routine was called from WSPSocket and we can't find a match yet, we're
    //    in bad shape since the protocol info passed in matches no entries of this 
    //    LSPs ...

    ASSERT( fromStartup );

#ifndef DBG
    UNREFERENCED_PARAMETER( fromStartup );
#endif

    //
    // Still no match. See if the protocol info passed in belongs to another LSP.
    // Enumerate all its protocol entries and see if we reside in any of those
    // chains. This typically will happen when an LSP is layered over us and it
    // bulk loads all of the providers beneath its entries upon its first WSPStartup
    // call.
    //
    // For example consider the following catalog (where this LSP is LSP1):
    //
    //  _____________ _____________
    //  | LSP 2 TCP | | LSP 2 UDP |
    //  _____________              
    //  | LSP 1 TCP |
    //  _____________ _____________
    //  | BASE TCP  | | BASE UDP  |
    //
    // When LSP 2 is started, its WSPStartup is invoked with its UDP entry (since
    // the application created a UDP socket). Because LSP2 initializes all its layers
    // upon first WSPStartup it will load all the layers beneath it. So LSP2 will
    // load LSP1 and invoke its WSPStartup but will pass the UDP protocol info which
    // it was passed. At this point LSP1 won't know what to do since it was passed a
    // UDP entry and its not layered over any UDP entry. LSP1 cannot return any
    // entry if its an IFS LSP which implements only a subset of the Winsock
    // functions (i.e. LSP1 will return a mix of function pointers from BASE TCP
    // and its own LSP DLL). Because of this, LSP1 will try to "match" which
    // chain from LSP2 it actually resides in such that when LSP2 creates a TCP
    // socket later, it will have the correct function pointers.
    //
    // The heuristic is:
    // 1. Find all layered protocol entries belonging to the WSAPROTOCOL_INFOW passed.
    //    In the above example it would find LSP2 TCP and LSP2 UDP.
    // 2. Iterate through each provider found and walk the protocol chain in each 
    //    provider, looking for a reference to LSP1's entry.
    // 3. If found check LSP1 entry to see if it has already been loaded. If not
    //    then this is the match, if so then LSP2 could be layered over another TCP
    //    entry which is also layered over LSP1 so keep looking.
    //

    // Should never receive a base or dummy entry
    ASSERT( inInfo->ProtocolChain.ChainLen > 1 );

    ProtocolInfo = EnumerateProviders( LspCatalogBoth, &ProtocolCount );
    if ( NULL == ProtocolInfo )
    {
        dbgprint("FindMatchingLspEntryForProtocolInfo: EnumerateProviders failed!\n");
        goto cleanup;
    }

    hiddenEntryId = 0;
    for(i=0; i < ProtocolCount ;i++)
    {
        if ( inInfo->ProtocolChain.ChainEntries[ 0 ] == ProtocolInfo[ i ].dwCatalogEntryId )
        {
            hiddenEntryId = ProtocolInfo[ i ].dwCatalogEntryId;
            break;
        }
    }

    ASSERT( hiddenEntryId );

    for(i=0; i < ProtocolCount ;i++)
    {
        if ( ProtocolInfo[ i ].ProtocolChain.ChainEntries[ 0 ] == hiddenEntryId )
        {
            // This entry belongs to the LSP layered over us - walk its chains to
            //    see if it references our LSP
            for(j=1; j < ProtocolInfo[ i ].ProtocolChain.ChainLen ;j++)
            {
                for(k=0; k < lspCount ;k++)
                {
                    if ( ProtocolInfo[ i ].ProtocolChain.ChainEntries[ j ] ==
                         lspProviders[ k ].LayerProvider.ProtocolChain.ChainEntries[ 0 ]
                       )
                    {
                        // Bad news again, the protocol chain of the LSP above us
                        //   references our dummy LSP entry so we'll have to try
                        //   to match according to the protocol triplet and provider
                        //   flags
                        if ( ( ProtocolInfo[ i ].iAddressFamily == 
                               lspProviders[ k ].LayerProvider.iAddressFamily ) &&
                             ( ProtocolInfo[ i ].iSocketType ==
                               lspProviders[ k ].LayerProvider.iSocketType ) &&
                             ( ProtocolInfo[ i ].iProtocol ==
                               lspProviders[ k ].LayerProvider.iProtocol ) &&
                             ( ( ProtocolInfo[ i ].dwServiceFlags1 & ~XP1_IFS_HANDLES ) ==
                               ( lspProviders[ k ].LayerProvider.dwServiceFlags1 & ~XP1_IFS_HANDLES ) )
                           )
                        {
                            return &lspProviders[ i ];
                        }
                    }

                    if ( ( ProtocolInfo[ i ].ProtocolChain.ChainEntries[ j ] ==
                            lspProviders[ k ].LayerProvider.dwCatalogEntryId ) &&
                         ( lspProviders[ k ].StartupCount == 0 ) 
                       )
                    {
                        return &lspProviders[ i ];
                    }
                }
            }
        }
    }
    
cleanup:

    ASSERT( FALSE ); 

    return NULL;
}
Beispiel #3
0
//
// Function: FindLspEntries
//
// Description:
//      This function searches the Winsock catalog and builds an array of the
//      WSAPROTOCOL_INFOW structures which belong to the LSP. This includes
//      all layered protocol chains as well as the LSP dummy (hidden) entry.
//      The function first finds the dummy entry using 'gProviderGuid' which
//      is the global GUID of the dummy entry. From there, the catalog is
//      searched for all entries whose first entry in the protocol chain
//      matches the dummy entry's catalog ID.
//
BOOL
FindLspEntries(
        PROVIDER  **lspProviders,
        int        *lspProviderCount,
        int        *lpErrno
        )
{
    PROVIDER           *Providers = NULL;
    LPWSAPROTOCOL_INFOW ProtocolInfo = NULL;
    DWORD               DummyLspId = 0;
    int                 ProtocolCount = 0,
                        LayerCount = 0,
                        idx,
                        i, j;

    *lspProviderCount = 0;
    *lspProviders = NULL;

    // Enumerate the catalog
    ProtocolInfo = EnumerateProviders( LspCatalogBoth, &ProtocolCount );
    if ( NULL == ProtocolInfo )
    {
        dbgprint("FindLspEntries; EnumerateProviders failed!");
        goto cleanup;
    }

    // Find our dummy LSP entry ID
    DummyLspId = 0;
    for(i=0; i < ProtocolCount ;i++)
    {
        if ( 0 == memcmp( &ProtocolInfo[ i ].ProviderId, &gProviderGuid, sizeof( gProviderGuid ) ) )
        {
            DummyLspId = ProtocolInfo[ i ].dwCatalogEntryId;
            break;
        }
    }

    ASSERT( 0 != DummyLspId );

    // Count how many LSP layered entries are present
    LayerCount = 0;
    for(i=0; i < ProtocolCount ;i++)
    {
        if ( ( ProtocolInfo[ i ].ProtocolChain.ChainLen > 1 ) &&
             ( DummyLspId == ProtocolInfo[ i ].ProtocolChain.ChainEntries[ 0 ] )
           )
        {
            LayerCount++;
        }
    }

    ASSERT( 0 != LayerCount );

    // Allocate space for the layered providers
    Providers = (PROVIDER *) LspAlloc( sizeof(PROVIDER) * LayerCount, lpErrno );
    if ( NULL == Providers )
    {
        dbgprint("FindLspEntries: LspAlloc failed: %d", *lpErrno );
        goto cleanup;
    }

    idx = 0;

    // Save the LSP layered entries
    for(i=0; i < ProtocolCount ;i++)
    {
        // The layered protocol entries for this LSP will always reference the
        //    dummy entry ID as its first entry in the chain array. Also make
        //    sure to check only LSP entries (since a base provider's chain length
        //    is 1 but the chain array entries can be garbage)
        if ( ( ProtocolInfo[ i ].ProtocolChain.ChainLen > 1 ) &&
             ( DummyLspId == ProtocolInfo[ i ].ProtocolChain.ChainEntries[ 0 ] )
           )
        {
            // Copy the new entry to the head
            memcpy( &Providers[ idx ].LayerProvider, &ProtocolInfo[ i ], sizeof(WSAPROTOCOL_INFOW) );
            Providers[ idx ].LayerProvider.szProtocol[ WSAPROTOCOL_LEN ] = '\0';

            // Copy the provider underneath this entry
            for(j=0; j < ProtocolCount ;j++)
            {
                // The next provider can either be a base, a dummy, or another layered
                //    protocol chain. If a dummy or layer then both providers will have
                //    the same DLL to load.
                if ( ProtocolInfo[ i ].ProtocolChain.ChainEntries[ 1 ] ==
                     ProtocolInfo[ j ].dwCatalogEntryId )
                {
                    memcpy( &Providers[ idx ].NextProvider, &ProtocolInfo[ j ],
                            sizeof( WSAPROTOCOL_INFOW ) );
                    Providers[ idx ].NextProvider.szProtocol[ WSAPROTOCOL_LEN ] = '\0';
                    break;
                }
            }

            // Verify we copied the lower layer
            ASSERT( j < ProtocolCount );

            InitializeCriticalSection( &Providers[ idx ].ProviderCritSec );
            InitializeListHead( &Providers[ idx ].SocketList );

            idx++;
        }
    }

    ASSERT( idx == LayerCount );

    if ( NULL != ProtocolInfo )
        FreeProviders( ProtocolInfo );

    *lspProviders = Providers;
    *lspProviderCount = LayerCount;

    return TRUE;

cleanup:

    if ( NULL != ProtocolInfo )
        FreeProviders( ProtocolInfo );

    if ( NULL != Providers )
        LspFree( Providers );

    return FALSE;
}
Beispiel #4
0
//
// Function: InstallNonIfsLspProtocolChains
//
// Description:
//      This function builds and install the protocol chain entries associated with
//      a non-IFS LSP. The caling routine installs the dummy, hidden entry in the
//      catalog and this routine enumerates the catalog, finds the dummy entry,
//      builds the layered chain entries, and installs them into the catalog.
//
int
InstallNonIfsLspProtocolChains(
    WINSOCK_CATALOG eCatalog,
    GUID           *Guid,
    WCHAR          *lpszLspName,
    WCHAR          *lpszLspFullPathAndFile,
    DWORD          *pdwCatalogIdArray,
    DWORD           dwCatalogIdArrayCount
    )
{
    WSAPROTOCOL_INFOW   *pProvider = NULL,
                        *pLayeredEntries = NULL;
    DWORD                dwDummyLspId = 0;
    INT                  iProviderCount = 0,
                         retval = SOCKET_ERROR,
                         idx,
                         err,
                         rc,
                         i, j;
    HRESULT              hr;

    // Enumerate the catalog
    pProvider = EnumerateProviders( eCatalog, &iProviderCount );
    if ( NULL == pProvider )
    {
        fprintf( stderr, "InstallNonIfsLspProtocolChain: Unable to enumerate catalog\n" );
        goto cleanup;
    }

    pLayeredEntries = (WSAPROTOCOL_INFOW *) LspAlloc( sizeof(WSAPROTOCOL_INFOW) *
            dwCatalogIdArrayCount, &err );
    if ( NULL == pLayeredEntries )
    {
        fprintf( stderr, "InstallNonIfsLspProtocolChain: LspAlloc failed: %d\n", err );
        goto cleanup;
    }

    // Find the dummy entry so we can extract its catalog ID
    dwDummyLspId = GetCatalogIdForProviderGuid( Guid, pProvider, iProviderCount );

    ASSERT( dwDummyLspId != 0 );

    // Go through the catalog and build the layered entries
    idx = 0;
    for(i=0; i < iProviderCount ;i++)
    {
        for(j=0; j < (int) dwCatalogIdArrayCount ;j++)
        {
            if ( pProvider[ i ].dwCatalogEntryId == pdwCatalogIdArray[ j ] )
            {
                if ( pProvider[ i ].ProtocolChain.ChainLen >= ( MAX_PROTOCOL_CHAIN - 1 ) )
                {
                    fprintf( stderr, "InstallNonIfsLspProtocolchain: Too many LSPs installed!\n");
                    goto cleanup;
                }

                memcpy( &pLayeredEntries[ idx ], &pProvider[ i ], sizeof( WSAPROTOCOL_INFOW ) );

                // Put our LSP name in the protocol field
                hr = StringCchPrintfW( pLayeredEntries[ idx ].szProtocol, WSAPROTOCOL_LEN,
                        L"%s over [%s]",
                        lpszLspName,
                        pProvider[ i ].szProtocol
                        );
                if ( FAILED( hr ) )
                {
                    fprintf( stderr, "InstallNonIfsLspProtocolChain: StringCchPrintfW failed: 0x%x\n", hr );
                    goto cleanup;
                }

                // Move all the protocol chain entries down by 1 position and insert 
                // the dummy entry id at the head
                InsertIdIntoProtocolChain( &pLayeredEntries[ idx ], 0, dwDummyLspId );

                // The second entry is always the ID of the current pProvider[i]
                //     In case of multiple LSPs then if we didn't do this the [1] index
                //     would contain the ID of that LSP's dummy entry and not the entry
                //     itself.
                pLayeredEntries[ idx ].ProtocolChain.ChainEntries[ 1 ] = 
                        pProvider[ i ].dwCatalogEntryId;

                // Remove the IFS flag 
                pLayeredEntries[ idx ].dwServiceFlags1 &= (~XP1_IFS_HANDLES);

                idx++;
            }
        }
    }

    for(i=0; i < (int)dwCatalogIdArrayCount ;i++)
    {
        // Create a GUID for the protocol chain entries
        if ( UuidCreate( &pLayeredEntries[ i ].ProviderId ) != RPC_S_OK )
        {
            fprintf(stderr, "InstallNonIfsLspProtocolChains: UuidCreate failed: %d\n", GetLastError());
            goto cleanup;
        }

        // Install the layered chain providers
        rc = InstallProvider(
                eCatalog, 
               &pLayeredEntries[ i ].ProviderId, 
                lpszLspFullPathAndFile,
               &pLayeredEntries[ i ], 
                1
                );
        if ( NO_ERROR != rc )
        {
            fprintf(stderr, "InstallNonIfsLspProtocolChains: Unable to install layered chain entries!\n");
            goto cleanup;
        }
    }

    // Reorder the winsock catalog so the layered chain entries appear first
    rc = ReorderCatalog( eCatalog, dwDummyLspId );
    if ( NO_ERROR != rc )
    {
        fprintf(stderr, "InstallNonIfsLspProtocolChains: Unable to reorder Winsock catalog!\n");
        goto cleanup;
    }

    retval = NO_ERROR;

cleanup:

    if ( NULL != pProvider )
        FreeProviders( pProvider );

    if ( NULL != pLayeredEntries )
        LspFree( pLayeredEntries );

    return retval;
}
Beispiel #5
0
//
// Function: InstallIfsLspProtocolChains
//
// Description:
//      This routine installs the layered protocol chains for an IFS based LSP. It
//      assumes the LSP dummy entry is already installed. This function first enumerates
//      the catalog to find the ID of the dummy entry. It then builds the protocol
//      entries for the IFS layered protocols. Note that an IFS entry must be installed
//      such that no non-IFS providers are layered beneath it. This means if the user
//      chooses to install the IFS LSP over a provider which includes non-IFS layers, it
//      must insert itself into the chain such that it is below all non-IFS providers.
//      This means that existing entries need to be modified in order to reflect this
//      ordering. Also in the event that the IFS LSP is inserted into an existing chain
//      this installer still builds a series of standalone entries (i.e. entries that
//      would have existed of the LSPs layered over the IFS LSP were installed after
//      the IFS LSP was).
//
int
InstallIfsLspProtocolChains(
    WINSOCK_CATALOG eCatalog,
    GUID           *Guid,
    WCHAR          *lpszLspName,
    WCHAR          *lpszLspFullPathAndFile,
    DWORD          *pdwCatalogIdArray,
    DWORD           dwCatalogIdArrayCount
    )
{
    WSAPROTOCOL_INFOW  *pProvider = NULL,
                       *pProviderNew = NULL,
                       *pLayeredEntries = NULL,
                       *pEntry = NULL,
                        TempEntry = {0};
    DWORD              *pProviderOrder = NULL,
                        dwDummyLspId;
    WCHAR               wszLspDll[ MAX_PATH ];
    BOOL                bLayeredOverNonIfs = FALSE,
                        bContainsNonIfs = FALSE;
    HRESULT             hr;
    int                 ProviderPathLen = MAX_PATH-1,
                        iProviderCount,
                        iProviderCountNew,
                        LayerIdx,
                        retval = SOCKET_ERROR,
                        err,
                        idx,
                        rc,
                        i, j, k;

    // Enumerate the catalog
    pProvider = EnumerateProviders( eCatalog, &iProviderCount );
    if ( NULL == pProvider )
    {
        fprintf( stderr, "InstallIfsLspProtocolChains: Unable to enumerate catalog\n" );
        goto cleanup;
    }

    // Find the dummy, hidden entry of our new LSP
    dwDummyLspId = GetCatalogIdForProviderGuid( Guid, pProvider, iProviderCount );

    ASSERT( dwDummyLspId != 0 );

    // Allocate space for the protocol chains of the new LSP
    pLayeredEntries = (WSAPROTOCOL_INFOW *) LspAlloc( sizeof(WSAPROTOCOL_INFOW) *
            dwCatalogIdArrayCount, &err );
    if ( NULL == pLayeredEntries )
    {
        fprintf( stderr, "InstallIfsLspProtocolChains: LspAlloc failed: %d\n", err );
        goto cleanup;
    }

    LayerIdx = 0;

    // Build the layered protocol entries as well as a list of those providers which
    // require modification. Whenever an LSP is installed, a number of protocol entries
    // are installed where the first entry in the chain array is the LSP's dummy entry.
    // Addtionally, if we're installing an IFS LSP over an provider whose protocol chain
    // includes non-IFS LSPs, the IFS LSP must be placed in the chain such that no
    // non-IFS LSPs are positioned after it in the chain.

    // Loop through each ID we're layering over
    for(i=0; i < (int)dwCatalogIdArrayCount ;i++)
    {
        for(j=0; j < iProviderCount ;j++)
        {
            printf("Matching selected ID %d to catalog %d\n",
                    pdwCatalogIdArray[ i ], pProvider[ j ].dwCatalogEntryId );

            if ( pdwCatalogIdArray[ i ] == pProvider[ j ].dwCatalogEntryId )
            {
                // Verify the entry has room enough to be layered over
                if ( pProvider[ j ].ProtocolChain.ChainLen >= ( MAX_PROTOCOL_CHAIN - 1 ) )
                {
                    fprintf( stderr, "InstallIfsLspProtocolChain: Too many LSPs installed!\n");
                    goto cleanup;
                }

                // Save off the entry which we're layering over
                memcpy( &pLayeredEntries[ LayerIdx ], &pProvider[ j ],
                        sizeof( pLayeredEntries[ 0  ] ) );

                memcpy( &TempEntry, &pProvider[ j ], sizeof( TempEntry ) );        

                // Fill in the new LSP entry's name
                hr = StringCchPrintfW( pLayeredEntries[ LayerIdx ].szProtocol, WSAPROTOCOL_LEN,
                        L"%s over [%s]",
                        lpszLspName,
                        pProvider[ j ].szProtocol 
                        );
                if ( FAILED( hr ) )
                {
                    fprintf( stderr, "InstallIfsLspProtocolChains: StringCchPrintfW failed: 0x%x\n", hr );
                    goto cleanup;
                }

                // Check whether the selected entry contains non IFS LSPs in its chain
                if ( pProvider[ j ].ProtocolChain.ChainLen >= 2 )
                {
                    for(k=pProvider[ j ].ProtocolChain.ChainLen-2 ; k >= 0 ;k--)
                    {
                        bContainsNonIfs = IsNonIfsProvider( pProvider, iProviderCount, 
                                pProvider[ j ].ProtocolChain.ChainEntries[ k ] );

                        if ( TRUE == bContainsNonIfs )
                        {
                            // Need to modify the pProvider entry to reference the
                            // added LSP entry within its chain

                            // In the 'modified' array make a space at location after 'k'
                            InsertIdIntoProtocolChain( &pProvider[ j ], k+1, UPDATE_LSP_ENTRY );

                            // Save the index to the layer which corresponds to this entry
                            pProvider[ j ].dwProviderReserved = LayerIdx + 1;

                            // Need to fix the 'pLayeredEntry' as well
                            BuildSubsetLspChain( &pLayeredEntries[ LayerIdx ], k+1, dwDummyLspId );

                            pLayeredEntries[ LayerIdx ].dwServiceFlags1 |= XP1_IFS_HANDLES;

                            bLayeredOverNonIfs = TRUE;

                            // Need to insert the IFS provider in all LSPs that  are layered
                            // above the location where the IFS provider was just inserted
                            InsertIfsLspIntoAllChains( &TempEntry, pProvider, iProviderCount, 
                                    LayerIdx + 1, k );

                            break;
                        }
                    }
                }

                // Need to setup the protocol chain in the pLayeredEntry if we haven't
                // already done so above
                if ( TRUE != bContainsNonIfs )
                {
                    InsertIdIntoProtocolChain( &pLayeredEntries[ LayerIdx ], 0, dwDummyLspId );

                    // The second entry is always the ID of the current pProvider[i]
                    //     In case of multiple LSPs then if we didn't do this the [1] index
                    //     would contain the ID of that LSP's dummy entry and not the entry
                    //     itself.
                    pLayeredEntries[ LayerIdx ].ProtocolChain.ChainEntries[ 1 ] = 
                            TempEntry.dwCatalogEntryId;

                    pLayeredEntries[ LayerIdx ].dwServiceFlags1 |= XP1_IFS_HANDLES;
                }

                LayerIdx++;
            }
        }
    }

    ASSERT( LayerIdx == (int)dwCatalogIdArrayCount );

    // Create a unique GUID for each provider to install and install it
    for(i=0;i < (int)dwCatalogIdArrayCount ;i++)
    {
        if ( RPC_S_OK != UuidCreate( &pLayeredEntries[ i ].ProviderId ) )
        {
            fprintf(stderr, "InstallIfsLspProtocolChains: UuidCreate failed: %d\n", GetLastError());
            goto cleanup;
        }

        rc = InstallProvider( eCatalog, &pLayeredEntries[ i ].ProviderId,
                lpszLspFullPathAndFile, &pLayeredEntries[ i ], 1 );
        if ( NO_ERROR != rc )
        {
            fprintf(stderr, "InstallIfsLspProtocolChains: Unable to install the dummy LSP entry!\n");
            goto cleanup;
        }
    }

    if ( TRUE == bLayeredOverNonIfs )
    {
        // Enumerate the catalog again so we can find the catalog IDs

        pProviderNew = EnumerateProviders( eCatalog, &iProviderCountNew );
        if ( NULL == pProvider )
        {
            fprintf( stderr, "InstallIfsLspProtocolChains: Unable to enumerate catalog\n" );
            goto cleanup;
        }

        for(i=0; i < (int)dwCatalogIdArrayCount ;i++)
        {
            pLayeredEntries[ i ].dwCatalogEntryId = GetCatalogIdForProviderGuid(
                   &pLayeredEntries[ i ].ProviderId,
                    pProviderNew,
                    iProviderCountNew
                    );

            ASSERT( pLayeredEntries[ i ].dwCatalogEntryId != 0 );
        }

        // Update the protocol chains of the modified entries to point to the just
        //    installed providers
        for(i=0; i < iProviderCount ;i++)
        {
            if ( pProvider[ i ].dwProviderReserved == 0 )
                continue;

            for(j=0; j < pProvider[ i ].ProtocolChain.ChainLen ;j++)
            {
                if ( UPDATE_LSP_ENTRY == pProvider[ i ].ProtocolChain.ChainEntries[ j ] )
                {
                    pProvider[ i ].ProtocolChain.ChainEntries[ j ] = 
                        pLayeredEntries[ pProvider[ i ].dwProviderReserved - 1 ].dwCatalogEntryId;

                    pProvider[ i ].dwProviderReserved = 0;
                }
            }

            // Get the DLL path
            ProviderPathLen = MAX_PATH-1;
            rc = WSCGetProviderPath(
                    &pProvider[ i ].ProviderId,
                     wszLspDll,
                    &ProviderPathLen,
                    &err
                     );
            if ( SOCKET_ERROR == rc )
            {
                fprintf( stderr, "InstallIfsLspProtocolChains: WSCGetProviderPath failed: %d\n", err );
                goto cleanup;
            }

            // Update the providers which were modified
            rc = UpdateProvider( eCatalog, &pProvider[ i ].ProviderId,
                    wszLspDll, &pProvider[ i ], 1, &err );
            if ( SOCKET_ERROR == rc )
            {
                fprintf( stderr, "InstallIfsLspProtocolChains: UpdateProvider failed: %d\n", err );
                goto cleanup;
            }

            printf("Updated entry ID: %d: %S (chain len = %d)\n",
                    pProvider[ i ].dwCatalogEntryId,
                    pProvider[ i ].szProtocol,
                    pProvider[ i ].ProtocolChain.ChainLen
                    );
        }

        FreeProviders( pProvider );
        pProvider = NULL;

        FreeProviders( pProviderNew );
        pProviderNew = NULL;

        /*
        {
            WSADATA wsd;

            WSACleanup();

            WSAStartup( MAKEWORD(2,2), &wsd );
        }
        */

        pProvider = EnumerateProviders( eCatalog, &iProviderCount );
        if ( NULL == pProvider )
        {
            fprintf( stderr, "InstallIfsLspProtocolChains: Unable to enumerate catalog\n" );
            goto cleanup;
        }

        // Allocate an array of DWORDs to contain the new catalog ordering
        pProviderOrder = (DWORD *)LspAlloc( iProviderCount * sizeof(DWORD), &err );
        if ( NULL == pProviderOrder )
        {
            fprintf( stderr, "InstallIfsLspProtocolChains: Unable to enumerate catalog\n" );
            goto cleanup;
        }

        // First add the entries we layered over first
        idx = 0;
        for(i=0; i < (int)dwCatalogIdArrayCount ;i++)
        {
            pEntry = FindProviderById( pdwCatalogIdArray[ i ], pProvider, iProviderCount );
            if ( NULL == pEntry )
            {
                fprintf(stderr, "InstallIfsLspProtocolChain: Unable to find entry to reorder catalog!\n");
                goto cleanup;
            }

            pEntry->dwProviderReserved = 1;

            pProviderOrder[ idx++ ] = pEntry->dwCatalogEntryId;
        }

        // Now go through the protocol chain of the entries we layered over and put those
        //    LSP entries next in the new order
        for(i=0; i < (int)dwCatalogIdArrayCount ;i++)
        {
            pEntry = FindProviderById( pdwCatalogIdArray[ i ], pProvider, iProviderCount );
            if ( NULL == pEntry )
            {
                fprintf(stderr, "InstallIfsLspProtocolChain: Unable to find entry to reorder catalog!\n");
                goto cleanup;
            }

            printf("Looping through: %d: %S (chain len = %d)\n", 
                    pEntry->dwCatalogEntryId,
                    pEntry->szProtocol,
                    pEntry->ProtocolChain.ChainLen );

            for(j=1; j < pEntry->ProtocolChain.ChainLen-1 ;j++)
            {
                dwDummyLspId = FindDummyIdFromProtocolChainId(
                        pEntry->ProtocolChain.ChainEntries[ j ],
                        pProvider,
                        iProviderCount
                        );

                printf("   Finding dummy ID for chain entry: %d is %d\n", 
                        pEntry->ProtocolChain.ChainEntries[ j ],
                        dwDummyLspId
                        );

                for(k=0; k < iProviderCount ;k++)
                {
                    if ( ( pProvider[ k ].ProtocolChain.ChainLen >= 2 ) &&
                         ( pProvider[ k ].ProtocolChain.ChainEntries[ 0 ] == dwDummyLspId ) &&
                         ( pProvider[ k ].dwProviderReserved == 0 )
                       )
                    {
                        pProviderOrder[ idx++ ] = pProvider[ k ].dwCatalogEntryId;
                        pProvider[ k ].dwProviderReserved = 1;

                        printf("      Adding: %d\n", pProvider[ k ].dwCatalogEntryId );
                    }
                }
            }
        }

        // Now any catalog entry that wasn't already copied, copy it
        for(i=0; i < iProviderCount ;i++)
        {
            if ( pProvider[ i ].dwProviderReserved == 0 )
                pProviderOrder[ idx++ ] = pProvider[ i ].dwCatalogEntryId;
        }

        ASSERT( idx == iProviderCount );

        // Write the new catalog order
        rc = WriteProviderOrder( eCatalog, pProviderOrder, iProviderCount, &err );
        if ( NO_ERROR != rc )
        {
            fprintf( stderr, "InstallIfsLspProtocolChains: WriteProviderOrder failed: %d\n",
                    err );
            goto cleanup;
        }
    }
    else
    {
        //
        // Reorder the winsock catalog so the layered chain entries appear first.
        // Since we didn't have to modify any existing entries, all we need to do is
        //    move the added entries to the head of the catalog
        // 
        rc = ReorderCatalog( eCatalog, dwDummyLspId );
        if ( NO_ERROR != rc )
        {
            fprintf(stderr, "InstallIfsLspProtocolChains: Unable to reorder Winsock catalog!\n");
            goto cleanup;
        }
    }

    retval = NO_ERROR;

cleanup:
    
    if ( NULL != pProvider )
    {
        FreeProviders( pProvider );
        pProvider = NULL;
    }

    if ( NULL != pProviderNew )
    {
        FreeProviders( pProviderNew );
        pProviderNew = NULL;
    }

    if ( NULL != pProviderOrder )
    {
        LspFree( pProviderOrder );
        pProviderOrder = NULL;
    }

    return retval;
}
Beispiel #6
0
//
// Function: CreateDummyEntry
//
// Description:
//    This creates a single WSAPROTOCOL_INFOW structure which describes the
//    hidden "dummy" entry for an LSP. This is required since the layered
//    chain entries must reference the catalog ID of the LSP and a catalog ID
//    cannot be obtained until an entry is installed.
//
WSAPROTOCOL_INFOW *
CreateDummyEntry(
    WINSOCK_CATALOG Catalog, 
    INT CatalogId, 
    WCHAR *lpwszLspName,
    BOOL IfsProvider
    )
{
    WSAPROTOCOL_INFOW *pProtocolInfo = NULL,
                      *pDummyEntry = NULL,
                      *pEntry = NULL;
    INT                iProtocolCount = 0;
    int                err;

    // Enumerate the catalog
    pProtocolInfo = EnumerateProviders( Catalog, &iProtocolCount );
    if ( NULL == pProtocolInfo )
    {
        fprintf(stderr, "CreateDummyEntry: EnumerateProviders failed!\n");
        goto cleanup;
    }

    // Find one of the providers we are layering over
    pEntry = FindProviderById( CatalogId, pProtocolInfo, iProtocolCount );
    if ( pEntry )
    {
        // Allocate space and copy the provider structure
        pDummyEntry = (WSAPROTOCOL_INFOW *) LspAlloc(
                sizeof( WSAPROTOCOL_INFOW ),
               &err
                );
        if ( NULL == pDummyEntry )
        {
            fprintf( stderr, "CreateDummyEntry: LspAlloc failed: %d\n", err );
            goto cleanup;
        }

        // Copy the entry as a basis for the dummy entry
        memcpy( pDummyEntry, pEntry, sizeof( WSAPROTOCOL_INFOW ) );
    }
    else
    {
        fprintf(stderr, "CreateDummyEntry: Error! Unable to find provider with ID of %d\n\n",
                CatalogId 
                );
        goto cleanup;
    }

    // Remove the IFS provider flag if the LSP doesn't support it
    if ( FALSE == IfsProvider )
        pDummyEntry->dwServiceFlags1 &= (~XP1_IFS_HANDLES);

    // Set the flags indicating this is a hidden ("dummy") entry
    pDummyEntry->iSocketType = 0;
    pDummyEntry->iProtocol   = 0;
    pDummyEntry->dwProviderFlags |= PFL_HIDDEN;
    pDummyEntry->dwProviderFlags &= (~PFL_MATCHES_PROTOCOL_ZERO);
    pDummyEntry->ProtocolChain.ChainLen = LAYERED_PROTOCOL;

    // Copy the LSP name
    wcsncpy( pDummyEntry->szProtocol, lpwszLspName, WSAPROTOCOL_LEN );

cleanup:

    if ( NULL != pProtocolInfo )
        FreeProviders( pProtocolInfo );

    return pDummyEntry;
}
Beispiel #7
0
//
// Function: InstallProvider
//
// Description:
//    This is a wrapper for the WSCInstallProvider function. Depending on
//    which catalog is specified, this routine calls the correct install
//    routine.
//
int 
InstallProvider(
    WINSOCK_CATALOG     Catalog,        // Which catalog are we operating on
    GUID               *Guid,           // GUID under which provider will be installed
    WCHAR              *lpwszLspPath,   // Path to LSP's DLL
    WSAPROTOCOL_INFOW  *pProvider,      // Array of provider structures to install
    INT                 iProviderCount  // Number of providers in array
    )
{
    WSAPROTOCOL_INFOW *pEnumProviders = NULL,
                      *pEntry = NULL;
    INT                iEnumProviderCount,
                       ErrorCode,
                       rc = SOCKET_ERROR;

#ifdef _WIN64
    if ( LspCatalog32Only == Catalog )
    {
        // Can't install only in 32-bit catalog from 64-bit
        fprintf( stderr, "InstallProvider: Error! It is not possible to install only "
                "in 32-bit catalog from 64-bit process!\n\n"
                );
        goto cleanup;
    }
    else if ( LspCatalog64Only == Catalog )
    {
        // Just need to call WSCInstallProvider
        rc = WSCInstallProvider( 
                Guid, 
                lpwszLspPath, 
                pProvider, 
                iProviderCount, 
               &ErrorCode 
                );
    }
    else
    {
        // To install in both we must call WSCInstallProviderPath64_32
        rc = WSCInstallProvider64_32(
                Guid, 
                lpwszLspPath, 
                pProvider, 
                iProviderCount, 
               &ErrorCode
                );
    }
#else
    if ( LspCatalog32Only == Catalog )
    {
        // From a 32-bit process we can only install into 32-bit catalog
        rc = WSCInstallProvider(
                Guid, 
                lpwszLspPath, 
                pProvider, 
                iProviderCount, 
               &ErrorCode
                );
    }
    else
    {
        // From a 32-bit process, we can't touch the 64-bit catalog at all
        fprintf( stderr, "InstallProvider: Error! It is not possible to install into "
                "the 64-bit catalog from a 32-bit process!\n\n"
                );
        goto cleanup;
    }
#endif
    if ( SOCKET_ERROR == rc )
    {
        fprintf( stderr, "InstallProvider: WSCInstallProvider* failed: %d\n", ErrorCode );
        goto cleanup;
    }

    // Go back and enumerate what we just installed
    pEnumProviders = EnumerateProviders( Catalog, &iEnumProviderCount );
    if ( NULL == pEnumProviders )
    {
        fprintf( stderr, "InstallProvider: EnumerateProviders failed!\n" );
        goto cleanup;
    }
    
    // Make sure our entry is in the catalog
    pEntry = FindProviderByGuid( Guid, pEnumProviders, iEnumProviderCount );
    if ( pEntry )
    {
        printf( "Installed: [%4d] %S\n", 
                pEntry->dwCatalogEntryId,
                pEntry->szProtocol
                );
    }

cleanup:

    if ( NULL != pEnumProviders )
        FreeProviders( pEnumProviders );

    return rc;
}
Beispiel #8
0
//
// Function: ReorderACatalog
//
// Description:
//    This routine enumerates a single catalog (32 or 64 bit) and reorders
//    the catalog according to the supplied catalog ID. That is, any provider
//    with that ID at the head of it's protocol chain is moved to the beginning
//    of the catalog.
//
DWORD *
ReorderACatalog(
    WINSOCK_CATALOG Catalog,
    DWORD           dwLayerId,
    INT            *dwEntryCount
    )
{
    WSAPROTOCOL_INFOW   *pProvider = NULL;
    DWORD               *pdwProtocolOrder = NULL;
    INT                  iProviderCount = 0,
                         idx,
                         err,
                         i;

    // Validate parameters
    if ( ( NULL == dwEntryCount ) || ( LspCatalogBoth == Catalog ) )
        return NULL;

    // Enumerate the catalog
    pProvider = EnumerateProviders( Catalog, &iProviderCount );
    if ( NULL == pProvider )
    {
        fprintf( stderr, "ReorderACatalog: Unable to enumerate Winsock catalog!\n" );
        goto cleanup;
    }

    // Allocate space for the array of catalog IDs (the catalog order)
    pdwProtocolOrder = (DWORD *) LspAlloc(
            sizeof( DWORD ) * iProviderCount,
           &err
            );
    if ( NULL == pdwProtocolOrder )
    {
        fprintf(stderr, "ReorderACatalog: LspAlloc failed: %d\n", GetLastError());
        goto cleanup;
    }

    idx = 0;

    // First put all the layered entries at the head of the catalog
    for(i=0; i < iProviderCount ;i++)
    {
        if ( TRUE == IsIdInChain( &pProvider[ i ], dwLayerId ) )
        {
            pdwProtocolOrder[ idx++ ] = pProvider[ i ].dwCatalogEntryId;
        }
    }

    // Put the remaining entries after the layered chain entries
    for(i=0; i < iProviderCount ;i++)
    {
        if ( FALSE == IsIdInChain( &pProvider[ i ], dwLayerId ) )
        {
            pdwProtocolOrder[ idx++ ] = pProvider[ i ].dwCatalogEntryId;
        }
    }

cleanup:

    if (pProvider)
        FreeProviders(pProvider);

    // Update the count
    *dwEntryCount = iProviderCount;


    return pdwProtocolOrder;
}
Beispiel #9
0
//
// Function: RemoveProvider
//
// Description:
//    This function removes a layered provider. Things can get tricky if
//    we're removing a layered provider which has been layered over by
//    another provider. This routine first creates the LSP map to determine
//    if other LSPs on the system reference the LSP we want to remove. If
//    there are we must fix those LSPs before deleting the target LSP.
//    If we're on a platform that supports WSCUpdateProvider its simply a
//    matter of removing any reference to the target LSP's layered protocol
//    chains and the dummy hidden entry.
//
//    If we're not on a WSCUpdateProvider enabled system, then its very tricky.
//    We must uninstall the dependent LSPs first followed by reinstalling them
//    in the same order they were originally installed. For example if LSP1,
//    LSP2, and LSP3 are installed (in that order) and this routine is invoked
//    to remove LSP1, we must uninstall LSP3 and LSP2 followed by re-installing
//    (LSP2 first then LSP3). For each LSP added back we must fix up the protocol
//    chains of the next higher LSP so the reference the new catalog IDs (since
//    the action of installing an LSP assigns a new catalog ID).
//
//    NOTE: If WSCUpdateProvider is not supported there is the possiblity of
//          another process changing the Winsock catalog at the same time we're
//          trying to fix it back up. If this occurs it is possible for the
//          corruption to occur.
//
int
RemoveProvider(
    WINSOCK_CATALOG Catalog,            // Catalog to remove an LSP from
    DWORD           dwProviderId        // Catalog ID of LSPs hidden entry
)
{
    WSAPROTOCOL_INFOW   *pProvider = NULL,
                         *pLayeredEntries = NULL;
    LSP_ENTRY           *pLspMap = NULL,
                         *pLspMapEntryDel = NULL;
    DWORD               *pdwCatalogOrder = NULL;
    INT                  iProviderCount = 0,
                         iLayerCount = 0,
                         iLspCount = 0,
                         ErrorCode,
                         Status,
                         rc,
                         i, j, k, l;

    Status = SOCKET_ERROR;

    // Enumerate the catalog
    pProvider = EnumerateProviders( Catalog, &iProviderCount );
    if ( pProvider == NULL )
    {
        fprintf( stderr, "RemoveProvider: Unable to enumerate catalog!\n" );
        goto cleanup;
    }

    // Allocate an array to save of the provider order in case we have to
    //    do uninstall and reinstall providers
    pdwCatalogOrder = (DWORD *) LspAlloc(
                          sizeof( DWORD ) * iProviderCount,
                          &ErrorCode
                      );
    if ( NULL == pdwCatalogOrder )
    {
        fprintf( stderr, "RemoveProvider: LspAlloc failed: %d\n", ErrorCode );
        goto cleanup;
    }

    for(i=0; i < iProviderCount ; i++)
    {
        pdwCatalogOrder[ i ] = pProvider[ i ].dwCatalogEntryId;
    }

    // Build a map of the LSPs installed on the system
    pLspMap = BuildLspMap( pProvider, iProviderCount, &iLspCount );
    if ( NULL == pLspMap )
    {
        fprintf( stderr, "RemoveProvider: Unable to build LSP map!\n" );
        goto cleanup;
    }

    // Validate the catalog entry ID to remove
    pLspMapEntryDel = NULL;

    for(i=0; ( i < iLspCount ) && ( NULL == pLspMapEntryDel ) ; i++)
    {
        if ( dwProviderId == pLspMap[ i ].DummyEntry.dwCatalogEntryId )
        {
            pLspMapEntryDel = &pLspMap[ i ];
        }
        else
        {
            for(j=0; j < pLspMap[ i ].Count ; j++)
            {
                if ( dwProviderId == pLspMap[ i ].LayeredEntries[ j ].dwCatalogEntryId )
                {
                    // In this case the user supplied the catalog ID of an LSP protocol
                    // chain entry -- not the hidden layered entry (dummy). Here we'll
                    // reset the dwProviderId to that of the dummy hidden entry.
                    //
                    if ( pLspMap[ i ].OrphanedEntries != TRUE )
                    {
                        printf( "Catalog ID %d is a layered protocol entry and not the hidden\n"
                                "provider representing the entire LSP. The LSP which owns this\n"
                                "provider is ID %d (%ws). This entire LSP will be removed!\n",
                                dwProviderId,
                                pLspMap[ i ].DummyEntry.dwCatalogEntryId,
                                pLspMap[ i ].DummyEntry.szProtocol
                              );
                        dwProviderId = pLspMap[ i ].DummyEntry.dwCatalogEntryId;
                        pLspMapEntryDel = &pLspMap[ i ];
                    }
                    else
                    {
                        printf( "Catalog ID %d is one of %d orphaned protocol entries.\n"
                                "These entries could be causing serious problems and\n"
                                "will be removed. The following providers are to be\n"
                                "deleted:\n",
                                pLspMap[ i ].LayeredEntries[ j ].dwCatalogEntryId,
                                pLspMap[ i ].Count
                              );
                        for(k=0; k < pLspMap[ i ].Count ; k++)
                        {
                            printf("   %d: %ws\n",
                                   pLspMap[ i ].LayeredEntries[ k ].dwCatalogEntryId,
                                   pLspMap[ i ].LayeredEntries[ k ].szProtocol
                                  );
                        }
                        pLspMapEntryDel = &pLspMap[ i ];
                    }
                    break;
                }
            }
        }
    }

    // Make sure we found a provider to remove
    if ( NULL == pLspMapEntryDel )
    {
        fprintf( stderr, "\n\nError! Invalid Winsock catalog ID supplied: %d\n",
                 dwProviderId
               );
        goto cleanup;
    }

    //
    // Print which entries are being removed
    //

    printf( "\nThe following LSP entries will be removed:\n" );
    if ( pLspMapEntryDel->OrphanedEntries != TRUE )
    {
        printf( "LSP Hidden ID: %6d Name %ws\n",
                pLspMapEntryDel->DummyEntry.dwCatalogEntryId,
                pLspMapEntryDel->DummyEntry.szProtocol
              );
    }
    else
    {
        printf( "Orphaned LSP protocol chain entries:\n");
    }
    for(i=0; i < pLspMapEntryDel->Count ; i++)
    {
        printf( "LSP Layer  ID: %6d Name %ws\n",
                pLspMapEntryDel->LayeredEntries[ i ].dwCatalogEntryId,
                pLspMapEntryDel->LayeredEntries[ i ].szProtocol
              );
    }

    ErrorCode = NO_ERROR;

    if ( 0 != pLspMapEntryDel->DependentCount )
    {
        int iLspIdx;

        printf( "\n\nOther LSPs are dependent on this one! "
                "Additional cleanup is required..\n\n" );

        for(i=0; i < pLspMapEntryDel->DependentCount ; i++)
        {
            iLspIdx =  pLspMapEntryDel->DependentLspIndexArray[ i ];

            printf( "Fixing LSP index %d: %ws\n",
                    pLspMap[ iLspIdx ].DummyEntry.dwCatalogEntryId,
                    pLspMap[ iLspIdx ].DummyEntry.szProtocol
                  );

            // Remove any reference to the deleted LSPs dummy catalog ID
            for(j=0; j < pLspMap[ iLspIdx ].Count ; j++)
            {
                if ( IsIdInChain( &pLspMap[ iLspIdx ].LayeredEntries[ j ],
                                  pLspMapEntryDel->DummyEntry.dwCatalogEntryId )
                   )
                {
                    printf( "Removing ID %d from layered chain %d: %ws\n",
                            pLspMapEntryDel->DummyEntry.dwCatalogEntryId,
                            pLspMap[ iLspIdx ].LayeredEntries[ j ].dwCatalogEntryId,
                            pLspMap[ iLspIdx ].LayeredEntries[ j ].szProtocol
                          );

                    // Remove the deleted LSPs ID from the chain
                    rc = RemoveIdFromChain(
                             &pLspMap[ iLspIdx ].LayeredEntries[ j ],
                             pLspMapEntryDel->DummyEntry.dwCatalogEntryId
                         );
                    if ( FALSE == rc )
                    {
                        fprintf( stderr, "RemoveProvider: ID not found in chain!\n" );
                        continue;
                    }

                    pLspMap[ iLspIdx ].LayerChanged[ j ] = TRUE;
                }
            }

            // Remove any reference to the deleted LSPs layered entries catalog
            // IDs from the layers of the dependent LSP
            for(l=0; l < pLspMapEntryDel->Count ; l++)
            {
                for(j=0; j < pLspMap[ iLspIdx ].Count ; j++)
                {
                    if ( IsIdInChain( &pLspMap[ iLspIdx ].LayeredEntries[ j ],
                                      pLspMapEntryDel->LayeredEntries[ l ].dwCatalogEntryId )
                       )
                    {
                        printf( "Removing ID %d from layered chain %d: %ws\n",
                                pLspMapEntryDel->DummyEntry.dwCatalogEntryId,
                                pLspMap[ iLspIdx ].LayeredEntries[ j ].dwCatalogEntryId,
                                pLspMap[ iLspIdx ].LayeredEntries[ j ].szProtocol
                              );

                        // Remove the deleted LSPs ID from the chain
                        rc = RemoveIdFromChain(
                                 &pLspMap[ iLspIdx ].LayeredEntries[ j ],
                                 pLspMapEntryDel->LayeredEntries[ l ].dwCatalogEntryId
                             );
                        if ( FALSE == rc )
                        {
                            fprintf( stderr, "RemoveProvider: ID not found in chain!\n" );
                            continue;
                        }

                        pLspMap[ iLspIdx ].LayerChanged[ j ] = TRUE;
                    }
                }
            }
        }

        //
        // All dependent LSPs should no longer reference any of the LSPs IDs which is
        //    to be removed. Now we must write our changes back to the catalog. Life
        //    is easy if we're on a system that supports WSCUpdateProvider.
        //

        if ( NULL != fnWscUpdateProvider )
        {
            //
            // Life is good, simply call UpdateProvider on each entry in the LSP map
            //    that was updated.
            //
            for(i=0; i < pLspMapEntryDel->DependentCount ; i++)
            {
                iLspIdx = pLspMapEntryDel->DependentLspIndexArray[ i ];

                for(j=0; j < pLspMap[ iLspIdx ].Count; j++)
                {
                    if ( TRUE == pLspMap[ iLspIdx ].LayerChanged[ j ] )
                    {
                        rc = UpdateProvider(
                                 Catalog,
                                 &pLspMap[ iLspIdx ].LayeredEntries[ j ].ProviderId,
                                 pLspMap[ iLspIdx ].wszLspDll,
                                 &pLspMap[ iLspIdx ].LayeredEntries[ j ],
                                 1,
                                 &ErrorCode
                             );
                    }
                }
            }
        }
        else        // fnWscUpdateProvider == NULL
        {
            int                 MaxLayers = 0;

            //
            // Life isn't so good. We need to remove all dependent LSPs first in the
            //    reverse order they were installed so that if something fails, we
            //    won't leave the catalog in a bad state. Then we need to reinstall
            //    them in the same order they were originally installed and fix any
            //    of the remaining dependent LSPs to reference the correct catalog IDs
            //    before they are also reinstalled.
            //

            // Find the maximum protocol chain length of all the LSPs since we need
            //    scratch space. We do the allocation first before making changes to
            //    the catalog.
            MaxLayers = MaxLayeredChainCount(
                            pLspMap,
                            iLspCount
                        );

            pLayeredEntries = (WSAPROTOCOL_INFOW *) LspAlloc(
                                  sizeof( WSAPROTOCOL_INFOW ) * MaxLayers,
                                  &ErrorCode
                              );
            if ( NULL == pLayeredEntries )
            {
                fprintf( stderr, "RemoveProvider: LspAlloc failed: %d\n",
                         ErrorCode );
                goto cleanup;
            }

            // Remove the dependent LSPs in reverse order. NOTE: We don't have to
            //    remove the dummy hidden entries since there is no information
            //    in those providers that need updating.
            for(i=0; i < pLspMapEntryDel->DependentCount ; i++)
            {
                iLspIdx = pLspMapEntryDel->DependentLspIndexArray[ i ];

                for(j=0; j < pLspMap[ iLspIdx ].LayeredGuidCount ; j++)
                {
                    rc = DeinstallProvider(
                             Catalog,
                             &pLspMap[ iLspIdx ].LayeredGuids[ j ]
                         );
                    if ( SOCKET_ERROR == rc )
                    {
                        fprintf( stderr,
                                 "RemoveProvider: An error occured trying to remove an LSP.\n"
                                 "\t\tThis may be due to another process changing the Catalog\n"
                                 "\t\tAborting...\n"
                               );
                        goto cleanup;
                    }
                }
            }

            // All the dependent LSP layers have been removed, now add them
            // back in reverse order
            for(i=pLspMapEntryDel->DependentCount-1; i >= 0 ; i--)
            {
                iLspIdx = pLspMapEntryDel->DependentLspIndexArray[ i ];

                // Install the layered entries
                for(j=0; j < pLspMap[ iLspIdx ].LayeredGuidCount ; j++)
                {
                    iLayerCount = MaxLayers;

                    rc = GetLayeredEntriesByGuid(
                             pLayeredEntries,
                             &iLayerCount,
                             pLspMap[ iLspIdx ].LayeredEntries,
                             pLspMap[ iLspIdx ].Count,
                             &pLspMap[ iLspIdx ].LayeredGuids[ j ]
                         );

                    rc = InstallProvider(
                             Catalog,
                             &pLspMap[ iLspIdx ].LayeredGuids[ j ],
                             pLspMap[ iLspIdx ].wszLspDll,
                             pLayeredEntries,
                             iLayerCount
                         );

                }

                // Enumerate catalog to find new IDs

                DWORD ProviderLen = iProviderCount * sizeof( WSAPROTOCOL_INFOW );

                int NewProviderCount = EnumerateProvidersExisting(
                                           Catalog,
                                           pProvider,
                                           &ProviderLen
                                       );
                if ( SOCKET_ERROR == NewProviderCount )
                {
                    fprintf( stderr, "RemoveProvider: EnumerateProvidersExisting failed: %d\n",
                             GetLastError() );
                }

                // Update the old references to the new
                MapNewEntriesToOld(
                    &pLspMap[ iLspIdx ],
                    pProvider,
                    NewProviderCount
                );

                // Update the provider order array with the new provider values
                UpdateProviderOrder(
                    &pLspMap[ iLspIdx ],
                    pdwCatalogOrder,
                    iProviderCount
                );

                // For the remaining LSPs which we still need to install, update any
                //    references to the removed LSPs with their new IDs
                for(k=i-1; k >= 0 ; k--)
                {
                    int iLspIdx2 = pLspMapEntryDel->DependentLspIndexArray[ k ];

                    printf( "Updating IDs for index %d\n", iLspIdx2 );

                    for(l=0; l < pLspMap[ iLspIdx ].Count ; l++)
                    {
                        UpdateLspMap(
                            &pLspMap[ iLspIdx2 ],
                            pLspMap[ iLspIdx ].LayeredEntries[ l ].dwCatalogEntryId,
                            pLspMap[ iLspIdx ].LayeredEntries[ l ].dwProviderReserved
                        );
                    }
                }
            }

            // Reorder the catalog back to what it was before. Since we've added
            //    back all the LSPs we removed earlier, the catalog should be the
            //    same size as when we started.
            rc = WriteProviderOrder(
                     Catalog,
                     pdwCatalogOrder,
                     iProviderCount,
                     &ErrorCode
                 );
            if ( SOCKET_ERROR == rc )
            {
                fprintf( stderr, "RemoveProvider: WriteProviderOrder failed: %d\n",
                         ErrorCode );
            }
        }
    }

    //
    // Now all dependencies have been fixed, remove the specified provider
    //

    // Remove the layered protocol entries
    for(i=0; i < pLspMapEntryDel->LayeredGuidCount ; i++)
    {
        rc = DeinstallProvider(
                 Catalog,
                 &pLspMapEntryDel->LayeredGuids[ i ]
             );
    }

    // Remove the dummy entry
    rc = DeinstallProvider(
             Catalog,
             &pLspMapEntryDel->DummyEntry.ProviderId
         );

    Status = NO_ERROR;

cleanup:

    //
    // Cleanup allocations
    //

    if ( NULL != pLayeredEntries )
        LspFree( pLayeredEntries );

    if ( NULL != pProvider )
        FreeProviders(pProvider);

    if ( NULL != pLspMap )
        FreeLspMap( pLspMap, iLspCount );

    if ( NULL != pdwCatalogOrder )
        LspFree( pdwCatalogOrder );

    return Status;
}
Beispiel #10
0
//
// Function: RemoveAllLayeredEntries
//
// Description:
//    In the event that the layered entries become totally hosed up. This
//    function will remove any non base provider.
//
int RemoveAllLayeredEntries(
    WINSOCK_CATALOG Catalog         // Catalog to remove all LSPs from
)
{
    WSAPROTOCOL_INFOW   *pProviders = NULL,
                         *pAssociated = NULL;
    WCHAR                szGuidString[ MAX_PATH ];
    LSP_ENTRY           *pLspMap = NULL;
    INT                  iProviderCount,
                         iAssociatedCount,
                         iMaxCount,
                         iLspCount = 0,
                         Status,
                         rc,
                         i, j, k;

    Status = SOCKET_ERROR;

    // First enumerate the catalog
    pProviders = EnumerateProviders( Catalog, &iProviderCount );
    if ( NULL == pProviders )
    {
        fprintf(stderr, "RemoveAllLayeredEntries: Unable to enumerate catalog!\n");
        goto cleanup;
    }

    // Build a mapping of the LSPs installed on the system
    pLspMap = BuildLspMap( pProviders, iProviderCount, &iLspCount );
    if ( NULL == pLspMap )
    {
        printf("\nNo LSPs to remove!\n");
        goto cleanup;
    }

    iMaxCount = MaxLayeredChainCount( pLspMap, iLspCount );

    pAssociated = (WSAPROTOCOL_INFOW *) LspAlloc(
                      sizeof( WSAPROTOCOL_INFOW ) * iMaxCount,
                      &rc
                  );
    if ( NULL == pAssociated )
    {
        fprintf( stderr, "RemoveAllLayeredEntries: LspAlloc failed: %d\n", rc );
        goto cleanup;
    }

    printf( "\n%d LSPs installed:\n", iLspCount );
    for(i=0; i < iLspCount ; i++)
    {
        if ( pLspMap[ i ].OrphanedEntries != TRUE )
        {
            printf("   %d: %ws with %d layered entries\n",
                   pLspMap[ i ].DummyEntry.dwCatalogEntryId,
                   pLspMap[ i ].DummyEntry.szProtocol,
                   pLspMap[ i ].Count
                  );
        }
        else
        {
            printf("   Orphaned LSP chain entries:\n");
            for(j=0; j < pLspMap[ i ].Count ; j++)
            {
                printf("\t   %d %ws\n",
                       pLspMap[ i ].LayeredEntries[ j ].dwCatalogEntryId,
                       pLspMap[ i ].LayeredEntries[ j ].szProtocol
                      );
            }
        }
    }

    printf("\nRemoving LSPs...\n\n");

    for(i=0; i < iLspCount ; i++)
    {
        if ( pLspMap[ i ].OrphanedEntries != TRUE )
        {
            // First remove the dummy entry
            printf( "Removing dummy entry for: %ws\n", pLspMap[ i ].DummyEntry.szProtocol );

            rc = DeinstallProvider( Catalog, &pLspMap[ i ].DummyEntry.ProviderId );

            if ( pLspMap[ i ].LayeredGuidCount > 0 )
                printf("Removing the associated layered entries with GUIDs:\n");

            for(j=0; j < pLspMap[ i ].LayeredGuidCount ; j++)
            {
                StringFromGUID2( pLspMap[ i ].LayeredGuids[ j ], szGuidString, MAX_PATH-1 );
                printf( "\tGUID: %ws\n", szGuidString );

                iAssociatedCount = iMaxCount;

                // Get a list of all providers under this GUID so we can print it out
                rc = GetLayeredEntriesByGuid(
                         pAssociated,
                         &iAssociatedCount,
                         pLspMap[ i ].LayeredEntries,
                         pLspMap[ i ].Count,
                         &pLspMap[ i ].LayeredGuids[ j ]
                     );
                if ( SOCKET_ERROR == rc )
                {
                    fprintf( stderr, "RemoveAllLayeredProviders: GetLayeredEntriesByGuid failed!\n" );
                    goto cleanup;
                }

                for(k=0; k < iAssociatedCount ; k++)
                {
                    printf("\t  %d: %ws\n",
                           pAssociated[ k ].dwCatalogEntryId,
                           pAssociated[ k ].szProtocol
                          );
                }

                rc = DeinstallProvider( Catalog, &pLspMap[ i ].LayeredGuids[ j ] );
                if ( SOCKET_ERROR == rc )
                {
                    fprintf( stderr, "RemoveAllLayeredProviders: DeinstallProvider failed!\n" );
                }
                else
                {
                    printf( "   Uninstalled providers for %ws\n", szGuidString );
                }
            }
        }
        else
        {
            printf("Removing the following orphaned entries:\n");
            for(j=0; j < pLspMap[ i ].Count ; j++)
            {
                printf("\t  %d: %ws\n",
                       pLspMap[ i ].LayeredEntries[ j ].dwCatalogEntryId,
                       pLspMap[ i ].LayeredEntries[ j ].szProtocol
                      );
            }

            for(j=0; j < pLspMap[ i ].LayeredGuidCount ; j++)
            {
                StringFromGUID2( pLspMap[ i ].LayeredGuids[ j ], szGuidString, MAX_PATH-1 );

                rc = DeinstallProvider( Catalog, &pLspMap[ i ].LayeredGuids[ j ] );
                if ( SOCKET_ERROR == rc )
                {
                    fprintf( stderr, "RemoveAllLayeredProviders: DeinstallProvider failed!\n");
                }
                else
                {
                    printf("\tUninstalled providers for %ws\n", szGuidString );
                }
            }
        }
    }

    Status = NO_ERROR;

cleanup:

    if ( NULL != pProviders )
        FreeProviders( pProviders );

    if ( NULL != pLspMap )
        FreeLspMap( pLspMap, iLspCount );

    if ( NULL != pAssociated )
        LspFree( pAssociated );

    return Status;
}
Beispiel #11
0
//
// Function: InstallProviderVista
//
// Description:
//    On Windows Vista and later there is a new LSP install function
//    (WSCInstallProviderAndChains) that performs all necessary installation
//    steps in a single call (instead of multiple WSCInstallProvider calls).
//    This function dynamically loads the function and invokes it to install
//    the LSP. The function either expects a NULL list of WSAPROTOCOL_INFOW
//    structures in which case it installs the LSP over each unique address
//    family, socket type, and protocol base provider on the system. Otherwise,
//    if the pdwCatalogIdArray specifies exact providers, this function builds
//    a list of those provider structures in which case the install API installs
//    the LSP over each instance of the address family, socket type and protocol
//    specified in the array.
//
int
InstallProviderVista(
        WINSOCK_CATALOG eCatalog,               // Which catalog to install LSP into
        __in_z WCHAR   *lpszLspName,            // String name of LSP
        __in_z WCHAR   *lpszLspPathAndFile,     // Location of LSP dll and dll name
        LPGUID          providerGuid,
        DWORD           dwCatalogIdArrayCount,  // Number of entries in pdwCatalogIdArray
        DWORD          *pdwCatalogIdArray,      // Array of IDs to install over
        BOOL            IfsProvider,
        BOOL            InstallOverAll
        )
{
    LPWSCINSTALLPROVIDERANDCHAINS lpInstallProviderAndChains;
    WSAPROTOCOL_INFOW *protocolList = NULL;
    WSAPROTOCOL_INFOW *pEnumProviders = NULL;
    HMODULE hMod = NULL;
    DWORD dwEntryCount;
    char *lpInstallFunction = NULL;
    INT iEnumProviderCount;
    int rc, i, j, error;
    

    rc = SOCKET_ERROR;

    //
    // Dynamically load the function in order for this installer to run properly
    // on downlevel OSes
    //
    hMod = LoadLibrary("ws2_32.dll");
    if ( NULL == hMod )
    {
        fprintf(stderr, "Unable to load ws2_32.dll!\n");
        goto cleanup;
    }

#ifdef _WIN64
    if ( ( eCatalog == LspCatalog32Only ) || ( eCatalog == LspCatalog64Only ) )
    {
        fprintf(stderr, "New install API always installs into both catalogs!\n");
        goto cleanup;
    }
    else 
    {
        lpInstallFunction = "WSCInstallProviderAndChains64_32";
    }
#else
    if ( ( eCatalog == LspCatalog64Only) || ( eCatalog == LspCatalogBoth ) )
    {
        fprintf(stderr, "Cannot install into 64-bit catalog from 32-bit process\n");
        goto cleanup;
    }
    else
    {
        lpInstallFunction = "WSCInstallProviderAndChains";
    }
#endif

    // Load the new install function
    lpInstallProviderAndChains = (LPWSCINSTALLPROVIDERANDCHAINS) GetProcAddress( 
            hMod,
            lpInstallFunction
            );
    if ( NULL == lpInstallProviderAndChains )
    {
        fprintf( stderr, "InstallLsp: Unable to load WSCInstallProviderAndChains function!\n");
        rc = SOCKET_ERROR;
        goto cleanup;
    }

    if ( InstallOverAll )
    {
        //
        // Install over all unique BSPs on the system so pass NULL for the provider list
        //

        rc = lpInstallProviderAndChains(
                providerGuid,
                lpszLspPathAndFile,
                lpszLspName,
                ( IfsProvider ? XP1_IFS_HANDLES : 0 ),
                NULL,
                NULL,
                NULL,
               &error
                );
        if ( SOCKET_ERROR == rc )
        {
            fprintf(stderr, "InstallProviderVista: %s failed: %d\n", 
                    lpInstallFunction, error );
            goto cleanup;
        }
    }
    else
    {
        //
        // User specified a subset of providers to install over so build a list of
        //    the corresponding WSAPROTOCOL_INFOW structures to pass to install call
        //

        protocolList = (WSAPROTOCOL_INFOW *) LspAlloc( sizeof(WSAPROTOCOL_INFOW) *
                dwCatalogIdArrayCount, &error);
        if ( NULL == protocolList )
        {
            fprintf(stderr, "InstallProviderVista: Out of memory!\n");
            rc = SOCKET_ERROR;
            goto cleanup;
        }

        pEnumProviders = EnumerateProviders( eCatalog, &iEnumProviderCount );
        if ( NULL == pEnumProviders )
        {
            fprintf(stderr, "InstallProviderVista: Unable to enumerate catalog!\n");
            rc = SOCKET_ERROR;
            goto cleanup;
        }

        // Build a list of protocol structures to layer over
        dwEntryCount = 0;
        for(i=0; i < (int)dwCatalogIdArrayCount ;i++)
        {
            for(j=0; j < iEnumProviderCount ;j++)
            {
                if ( pdwCatalogIdArray[i] == pEnumProviders[j].dwCatalogEntryId )
                {
                    memcpy( &protocolList[dwEntryCount++], &pEnumProviders[j], sizeof(WSAPROTOCOL_INFOW) );
                }
            }
        }

        rc = lpInstallProviderAndChains(
                providerGuid,
                lpszLspPathAndFile,
                lpszLspName,
                ( IfsProvider ? XP1_IFS_HANDLES : 0 ),
                protocolList,
                dwEntryCount,
                NULL,
               &error
                );
        if ( SOCKET_ERROR == rc )
        {
            fprintf(stderr, "InstallProviderVista: %s failed: %d\n", 
                    lpInstallFunction, error );
            goto cleanup;
        }
    }

    rc = NO_ERROR;

cleanup:

    if ( NULL != hMod )
        FreeLibrary( hMod );

    if ( NULL != pEnumProviders )
        FreeProviders( pEnumProviders );

    if ( NULL != protocolList )
        LspFree( protocolList );

    return rc;
}
//
// Function: main
//
// Description:
//    Parse the command line arguments and call either the install, remove, 
//    print, etc. routines.
//
int _cdecl main(int argc, char *argv[])
{
    WSADATA             wsd;
    LPWSAPROTOCOL_INFOW pProtocolInfo   = NULL;
    LSP_ENTRY          *pLspMap=NULL;
#ifdef _WIN64
    WINSOCK_CATALOG     eCatalog        = LspCatalog64Only;
#else
    WINSOCK_CATALOG     eCatalog        = LspCatalog32Only;
#endif
    INT                 iTotalProtocols = 0,
                        iLspCount       = 0,
                        i;
    DWORD              *pdwCatalogIdArray = NULL,
                        dwCatalogIdArrayCount = 0,       // How many to install over
                        dwRemoveCatalogId = 0;
    BOOL                bInstall                   = TRUE,
                        bInstallOverAll            = FALSE,
                        bRemoveAllLayeredEntries   = FALSE,
                        bPrintProviders            = FALSE,
                        bDisplayOnlyLayeredEntries = FALSE,
                        bVerbose                   = FALSE,
                        bMapLsp                    = FALSE,
                        bArgsOkay                  = FALSE,
                        bIFSProvider               = FALSE;
    char               *lpszLspName = NULL,
                       *lpszLspPathAndFile = NULL,
                       *lpszLspPathAndFile32 = NULL;
    int                 rc;

    ////////////////////////////////////////////////////////////////////////////
    //
    // Initialization and Command Line Parsing
    //
    ////////////////////////////////////////////////////////////////////////////

    // Load Winsock
    rc = WSAStartup( MAKEWORD(2,2), &wsd );
    if ( 0 != rc )
    {
        fprintf( stderr, "Unable to load Winsock: %d\n", rc );
        return -1;
    }

    // Initialize data structures
    LspCreateHeap( &rc );

    __try
    {
        InitializeCriticalSection( &gDebugCritSec );
    }
    __except( EXCEPTION_EXECUTE_HANDLER )
    {
        goto cleanup;
    }


    // First count how many catalog parameters are supplied so we can dynamically
    // allocate the right sized buffer
    for(i=1; i < argc ;i++)
    {
        if ( strncmp( argv[ i ], "-o", 2 ) == 0 )
            dwCatalogIdArrayCount++;
    }

    // Allocate space for the array of catalog IDs
    if ( 0 < dwCatalogIdArrayCount )
    {
        pdwCatalogIdArray = (DWORD *) LspAlloc(
                sizeof( DWORD ) * dwCatalogIdArrayCount,
                &rc
                );
        if ( NULL == pdwCatalogIdArray )
        {
            goto cleanup;
        }
    }

    // Set back to zero so we can use it as the index into our array
    dwCatalogIdArrayCount = 0;

    // Parse the command line
    for(i=1; i < argc ;i++)
    {
        if ( ( 2   != strlen( argv[i] ) ) && 
             ( '-' != argv[i][0] ) && 
             ( '/' != argv[i][0] )
           )
        {
            goto cleanup;
        }

        switch ( tolower( argv[i][1] ) )
        {
            case 'a':               // Install LSP over all currently installed providers
                bInstallOverAll = TRUE;
                break;

            case 'c':               // For 64-bit: which catalog to operate on?
                if (i+1 >= argc)
                    goto cleanup;

                switch (tolower(argv[i+1][0]))
                {
                    case 'b':       // Both Winsock catalogs
                        eCatalog = LspCatalogBoth;
                        break;
                    case '6':       // 64-bit Winsock catalog only
                        eCatalog = LspCatalog64Only;
                        break;
                    case '3':       // 32-bit Winsock catalog only
                        eCatalog = LspCatalog32Only;
                        break;
                    default:
                        goto cleanup;
                        break;
                }
                i++;
                break;

            case 'd':               // Full path and filename to LSP
                if ( i+1 >= argc )
                    goto cleanup;
                if (_strnicmp(argv[i], "-d32", 4))
                    lpszLspPathAndFile32 = argv[ ++i ];
                else
                    lpszLspPathAndFile = argv[ ++i ];

                break;

            case 'f':               // Uninstall all layered providers
                bRemoveAllLayeredEntries = TRUE;
                bInstall = FALSE;
                break;

            case 'h':               // Install as an IFS provider
                bIFSProvider = TRUE;
                break;

            case 'i':               // install
                bInstall = TRUE;
                break;

            case 'l':               // print the layered providers only
                bPrintProviders = TRUE;
                bDisplayOnlyLayeredEntries = TRUE;
                break;

            case 'm':               // Map and print the LSP structure
                bMapLsp = TRUE;
                bInstall = FALSE;
                break;

            case 'n':               // name of the LSP to install (not the DLL name)
                if (i+1 >= argc)
                    goto cleanup;

                lpszLspName = argv[++i];
                break;

            case 'o':               // catalog id (to install over)
                if (i+1 >= argc)
                    goto cleanup;

                pdwCatalogIdArray[dwCatalogIdArrayCount++] = atoi(argv[++i]);
                break;

            case 'p':               // print the catalog
                bPrintProviders = TRUE;
                bDisplayOnlyLayeredEntries = FALSE;
                break;

            case 'r':               // remove an LSP
                bInstall = FALSE;
                if (i+1 >= argc)
                    goto cleanup;
                dwRemoveCatalogId = atol(argv[++i]);
                break;

            case 'v':               // verbose mode (when printing with -p option)
                bVerbose = TRUE;
                break;

            default:
                goto cleanup;
                break;
        }
    }

#ifndef _WIN64
    if ( LspCatalog64Only == eCatalog )
    {
        fprintf(stderr, "\n\nUnable to manipulate 64-bit Winsock catalog from 32-bit process!\n\n");
        goto cleanup;
    }
#endif

    bArgsOkay = TRUE;

    gModule = LoadUpdateProviderFunction();

    if ( TRUE == bPrintProviders )
    {
        // Print the 32-bit catalog
        if ( ( LspCatalogBoth == eCatalog ) || ( LspCatalog32Only == eCatalog ) )
        {
            printf( "\n\nWinsock 32-bit Catalog:\n" );
            printf( "=======================\n" );
            PrintProviders( LspCatalog32Only, bDisplayOnlyLayeredEntries, bVerbose );
        }
        // Print the 64-bit catalog
        if ( ( LspCatalogBoth == eCatalog ) || ( LspCatalog64Only == eCatalog ) )
        {
            printf( "\n\nWinsock 64-bit Catalog:\n" );
            printf( "=======================\n" );
            PrintProviders( LspCatalog64Only, bDisplayOnlyLayeredEntries, bVerbose );
        }
    }
    else if ( TRUE == bInstall )
    {
        if ( NULL == lpszLspPathAndFile )
        {
            fprintf( stderr, "\n\nError! Please specify path and filename of LSP!\n\n");
            bArgsOkay = FALSE;
            goto cleanup;
        }

        if ( TRUE == bInstallOverAll )
        {
            // Make sure user didn't specify '-a' and '-o' flags
            if ( 0 != dwCatalogIdArrayCount )
            {
                fprintf( stderr, "\n\nError! Cannot specify both '-a' and '-o' flags!\n\n" );
                goto cleanup;
            }

            // Enumerate the appropriate catalog we will be working on
            pProtocolInfo = EnumerateProviders( eCatalog, &iTotalProtocols );
            if ( NULL == pProtocolInfo )
            {
                fprintf( stderr, "%s: EnumerateProviders: Unable to enumerate Winsock catalog\n",
                        argv[ 0 ]
                        );
                goto cleanup;
            }

            // Count how many non layered protocol entries there are
            for(i=0; i < iTotalProtocols ;i++)
            {
                if ( LAYERED_PROTOCOL != pProtocolInfo[ i ].ProtocolChain.ChainLen )
                    dwCatalogIdArrayCount++;
            }

            // Allocate space for all the entries
            pdwCatalogIdArray = (DWORD *) LspAlloc(
                    sizeof( DWORD ) * dwCatalogIdArrayCount,
                   &rc
                    );
            if ( NULL == pdwCatalogIdArray )
            {
                fprintf( stderr, "%s: LspAlloc failed: %d\n", argv[ 0 ], rc );
                goto cleanup;
            }

            // Get the catalog IDs for all existing providers
            dwCatalogIdArrayCount = 0 ;
            for(i=0; i < iTotalProtocols ;i++)
            {
                if ( LAYERED_PROTOCOL != pProtocolInfo[ i ].ProtocolChain.ChainLen )
                {
                    pdwCatalogIdArray[ dwCatalogIdArrayCount++ ] = pProtocolInfo[ i ].dwCatalogEntryId;
                }
            }

            FreeProviders( pProtocolInfo );
            pProtocolInfo = NULL;
        }

        // Install the LSP with the supplied parameters
        rc = InstallLsp(
                eCatalog,
                lpszLspName,
                lpszLspPathAndFile,
                lpszLspPathAndFile32,
                dwCatalogIdArrayCount,
                pdwCatalogIdArray,
                bIFSProvider,
                bInstallOverAll
                );
    }
    else if ( TRUE == bMapLsp )
    {
        // Display the 32-bit LSP catalog map
        if ( ( LspCatalogBoth == eCatalog ) || ( LspCatalog32Only == eCatalog ) )
        {
            printf("\n32-bit Winsock LSP Map:\n\n");

            pProtocolInfo = EnumerateProviders( LspCatalog32Only, &iTotalProtocols );
            if ( NULL == pProtocolInfo )
            {
                fprintf(stderr, "%s: EnumerateProviders: Unable to enumerate Winsock catalog\n",
                        argv[ 0 ] 
                        );
                goto cleanup;
            }

            pLspMap = BuildLspMap( pProtocolInfo, iTotalProtocols, &iLspCount );
            if ( NULL == pLspMap )
            {
                printf( "\nNo LSPs are installed\n\n" );
            }
            else
            {
                PrintLspMap( pLspMap, iLspCount );

                FreeLspMap( pLspMap, iLspCount );
                pLspMap = NULL;
            }
           
            FreeProviders( pProtocolInfo );
            pProtocolInfo = NULL;
        }

        // Display the 64-bit LSP catalog map
        if ( ( LspCatalogBoth == eCatalog ) || ( LspCatalog64Only == eCatalog ) )
        {
            printf("\n64-bit Winsock LSP Map:\n\n");

            pProtocolInfo = EnumerateProviders( LspCatalog64Only, &iTotalProtocols );
            if ( NULL == pProtocolInfo )
            {
                fprintf(stderr, "%s: EnumerateProviders: Unable to enumerate Winsock catalog\n",
                        argv[ 0 ]
                        );
                goto cleanup;
            }

            pLspMap = BuildLspMap( pProtocolInfo, iTotalProtocols, &iLspCount );
            if ( NULL == pLspMap )
            {
                printf( "\nNo LSPs are installed\n\n" );
            }
            else
            {
                PrintLspMap( pLspMap, iLspCount );

                FreeLspMap( pLspMap, iLspCount );
                pLspMap = NULL;
            }

            FreeProviders( pProtocolInfo );
            pProtocolInfo = NULL;
        }
    }
    else
    {
        // We must be removing an LSP

        if ( TRUE == bRemoveAllLayeredEntries )
        {
            if ( ( LspCatalogBoth == eCatalog ) || ( LspCatalog32Only == eCatalog ) )
                RemoveAllLayeredEntries( LspCatalog32Only );

            if ( ( LspCatalogBoth == eCatalog ) || ( LspCatalog64Only == eCatalog ) )
                RemoveAllLayeredEntries( LspCatalog64Only );
        }
        else
        {

            // Make sure a catalog entry to remove was supplied
            if ( dwRemoveCatalogId == 0 )
            {
                bArgsOkay = FALSE;
                goto cleanup;
            }

            if ( ( LspCatalogBoth == eCatalog ) || ( LspCatalog32Only == eCatalog ) )
                RemoveProvider( LspCatalog32Only, dwRemoveCatalogId );

            if ( ( LspCatalogBoth == eCatalog ) || ( LspCatalog64Only == eCatalog ) )
                RemoveProvider( LspCatalog64Only, dwRemoveCatalogId );

        }
    }

cleanup:

    if ( FALSE == bArgsOkay )
        usage( argv[ 0 ] );

    //
    // When invoked on Vista under non elevated permissions, the EXE is launched in
    // a new CMD window. The following getchar stops the window from exiting 
    // immediately so you can see what its output was.
    //
    printf("Press any key to continue...\n");
    getchar();

    //
    // Free any dynamic allocations and/or handles
    //

    if ( NULL != pdwCatalogIdArray )
        LspFree( pdwCatalogIdArray );

    if ( NULL != pProtocolInfo)
        FreeProviders( pProtocolInfo );

    if ( NULL != pLspMap )
        FreeLspMap( pLspMap, iLspCount );

    if ( NULL != gModule )
        FreeLibrary( gModule );

    LspDestroyHeap( );

    DeleteCriticalSection( &gDebugCritSec );

    WSACleanup();

    return 0;
}