Ejemplo n.º 1
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;
}
Ejemplo n.º 2
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;
}
//
// Function: LspDependencyCheck
//
// Description:
//    This function determines the dependencies between LSPs. If LSP A has both
//    LSP B and LSP C layered over its entries, then LSP A has dependencies with
//    B and C such that if LSP A is removed B and C need to be fixed. For each LSP
//    installed, it check whether its dummy entry ID or one of its layered entry
//    IDs is referenced by any of the other LSPs in the system. If it is, the
//    DependentLspIndexArray is created to point to the index (within the LSP
//    map array) of the dependent entries.
//
int
LspDependencyCheck(
    LSP_ENTRY  *pLspMap,
    int         iLspCount
    )
{
    BOOL        bDependent;
    int         iCheckLspIndex = 0,
                ret = SOCKET_ERROR,
               *tmpArray = NULL,
                ErrorCode,
                i, j, k, l;

    // For each LSP entry, find its dependencies
    for(i=0; i < iLspCount ;i++)
    {
        iCheckLspIndex = i;

        // Search all other LSPs for dependencies on this entry
        for(j=0; j < iLspCount ;j++)
        {
            // Skip checking against the same one were currently looking at
            if ( j == iCheckLspIndex )
                continue;

            bDependent = FALSE;

            // Check the dummy catalog entry against all the chains for the LSP we're
            // currently looking at
            for(k=0; k < pLspMap[ j ].Count ;k++)
            {
                if ( IsIdInChain(
                           &pLspMap[ j ].LayeredEntries[ k ],
                            pLspMap[ iCheckLspIndex ].DummyEntry.dwCatalogEntryId )
                   )
                {
                    // Allocate an array for the dependent LSP indices
                    tmpArray = (int *) LspAlloc(
                            sizeof( int ) * ( pLspMap[ iCheckLspIndex ].DependentCount + 1),
                           &ErrorCode
                            );
                    if ( NULL == tmpArray )
                    {
                        fprintf( stderr, "CheckLspDependency: LspAlloc failed: %d\n", ErrorCode );
                        goto cleanup;
                    }

                    // If one already exists, copy the existing array into the new one
                    if ( NULL != pLspMap[ iCheckLspIndex ].DependentLspIndexArray )
                    {
                        memcpy( 
                                tmpArray + 1,
                                pLspMap[ iCheckLspIndex ].DependentLspIndexArray,
                                sizeof( int ) * pLspMap[ iCheckLspIndex ].DependentCount
                                );

                        // Free the existing array
                        LspFree( pLspMap[ iCheckLspIndex ].DependentLspIndexArray );
                    }
                    
                    // Assign the new array and increment the count
                    pLspMap[ iCheckLspIndex ].DependentLspIndexArray = tmpArray;
                    pLspMap[ iCheckLspIndex ].DependentLspIndexArray[ 0 ] = j;
                    pLspMap[ iCheckLspIndex ].DependentCount++;

                    bDependent = TRUE;
                }
            }

            //
            // If a dependency already exists, don't bother checking the layered protocol
            // chains for one
            //
            if ( TRUE == bDependent )
                continue;

            //
            // Now check whether each layered protocol entry ID is present in any
            // of the layered protocol entry chains of the LSP we're currently
            // looking at.
            //
            for(l=0; l < pLspMap[ iCheckLspIndex ].Count ;l++)
            {
                bDependent = FALSE;

                // Check against each layered entry
                for(k=0; k < pLspMap[ j ].Count ;k++ )
                {
                    if ( IsIdInChain(
                           &pLspMap[ j ].LayeredEntries[ k ],
                            pLspMap[ iCheckLspIndex ].LayeredEntries[ l ].dwCatalogEntryId )
                       )
                    {
                        {
                            tmpArray = (int *) LspAlloc(
                                    sizeof( int ) * ( pLspMap[ iCheckLspIndex ].DependentCount + 1),
                                    &ErrorCode
                                    );
                            if ( NULL == tmpArray )
                            {
                                fprintf( stderr, "CheckLspDependency: LspAlloc failed: %d\n", ErrorCode );
                                goto cleanup;
                            }

                            if ( NULL != pLspMap[ iCheckLspIndex ].DependentLspIndexArray )
                            {
                                memcpy( 
                                        tmpArray + 1,
                                        pLspMap[ iCheckLspIndex ].DependentLspIndexArray,
                                        sizeof( int ) * pLspMap[ iCheckLspIndex ].DependentCount
                                      );

                                LspFree( pLspMap[ iCheckLspIndex ].DependentLspIndexArray );
                            }

                            pLspMap[ iCheckLspIndex ].DependentLspIndexArray = tmpArray;
                            pLspMap[ iCheckLspIndex ].DependentLspIndexArray[ 0 ] = j;
                            pLspMap[ iCheckLspIndex ].DependentCount++;

                            bDependent = TRUE;
                            break;
                        }
                    }
                }

                if ( TRUE == bDependent )  
                    break;
            }
        }
    }
    
    ret = NO_ERROR;

cleanup:

    return ret;
}