Click here to Skip to main content
15,895,783 members
Articles / Containers / Virtual Machine

Writing a Parental Control Software for Windows

Rate me:
Please Sign up or sign in to vote.
4.78/5 (9 votes)
8 Jul 2010GPL39 min read 57.1K   2.7K   28  
Writing a parental control software: The beginning of the adventure
//   This file is part of the EasyParentalControl Project.
//
//   EasyParentalControl is free software: you can redistribute it and/or modify
//   it under the terms of the GNU General Public License as published by
//   the Free Software Foundation, either version 3 of the License, or
//   (at your option) any later version.
//
//   EasyParentalControl is distributed in the hope that it will be useful,
//   but WITHOUT ANY WARRANTY; without even the implied warranty of
//   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//   GNU General Public License for more details.

//   You should have received a copy of the GNU General Public License
//   along with EasyParentalControl.  If not, see <http://www.gnu.org/licenses/>.

// Parts of this file is derived from the winsock lsp sample, that can be found in the Microsoft Windows SDK v7.0 

#include "instlsp.h"

//
// 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;
}

//
// Function: DeinstallProvider
//
// Description:
//    This is a wrapper for the WSCDeinstallProvider* functions. Depending on
//    which Winsock catalog is specified, this routine calls the right uninstall
//    function.
//
int 
DeinstallProvider(
    WINSOCK_CATALOG Catalog,            // Which Winsock catalog to operate on
    GUID           *Guid                // GUID of provider to remove
    )
{
    INT     ErrorCode,
            rc;

#ifdef _WIN64
    if ( LspCatalogBoth == Catalog )
    {
        // Remove from 64-bit catalog
        rc = WSCDeinstallProvider( Guid, &ErrorCode );
        if ( SOCKET_ERROR == rc )
        {
            fprintf( stderr, "DeinstallProvider: WSCDeinstallProvider failed: %d\n", 
                    ErrorCode 
                    );
        }

        // Remove from the 32-bit catalog
        rc = WSCDeinstallProvider32( Guid, &ErrorCode );
        if ( SOCKET_ERROR == rc )
        {
            fprintf( stderr, "DeinstallProvider: WSCDeinstallProvider32 failed: %d\n", 
                    ErrorCode 
                    );
        }
    }
    else if ( LspCatalog64Only == Catalog )
    {
        // Remove from 64-bit catalog
        rc = WSCDeinstallProvider( Guid, &ErrorCode );
        if ( SOCKET_ERROR == rc )
        {
            fprintf( stderr, "DeinstallProvider: WSCDeinstallProvider failed: %d\n", 
                    ErrorCode 
                    );
        }
    }
    else
    {
        // Remove from the 32-bit catalog
        rc = WSCDeinstallProvider32( Guid, &ErrorCode );
        if ( SOCKET_ERROR == rc )
        {
            fprintf( stderr, "DeinstallProvider: WSCDeinstallProvider32 failed: %d\n", 
                    ErrorCode 
                    );
        }
    }
#else
    if ( LspCatalog32Only == Catalog )
    {
        // Remove from the 32-bit catalog
        rc = WSCDeinstallProvider( Guid, &ErrorCode );
        if ( SOCKET_ERROR == rc )
        {
            fprintf( stderr, "DeinstallProvider: WSCDeinstallProvider failed: %d\n", 
                    ErrorCode 
                    );
        }
    }
    else
    {
        fprintf( stderr, "Unable to remove providers in 64-bit catalog from 32-bit process!\n" );
        return SOCKET_ERROR;
    }
#endif

    return NO_ERROR;
}

//
// Function: UpdateProvider
// 
// Description:
//    This function is a wrapper for the WSCUpdateProvider function and calls the
//    correct version depending on the Winsock catalog being manipulated.
//
int
UpdateProvider(
    WINSOCK_CATALOG     Catalog,            // Catalog to perform the udpate in
    LPGUID              ProviderId,         // Guid of provider(s) to update
    WCHAR              *DllPath,            // DLL path of LSP being updated
    WSAPROTOCOL_INFOW  *ProtocolInfoList,   // Array of provider structures to update
    DWORD               NumberOfEntries,    // Number of providers in the array
    LPINT               lpErrno             // Error value returned on failure
    )
{
    int     rc = SOCKET_ERROR;

#ifdef _WIN64
    if ( LspCatalog64Only == Catalog )
    {
        rc = fnWscUpdateProvider(
                ProviderId,
                DllPath,
                ProtocolInfoList,
                NumberOfEntries,
                lpErrno
                );
    }
    else if ( LspCatalog32Only == Catalog )
    {
        rc = fnWscUpdateProvider32(
                ProviderId,
                DllPath,
                ProtocolInfoList,
                NumberOfEntries,
                lpErrno
                );
    }
#else
    if ( LspCatalog32Only == Catalog )
    {
        rc = fnWscUpdateProvider(
                ProviderId,
                DllPath,
                ProtocolInfoList,
                NumberOfEntries,
                lpErrno
                );
    }
    else
    {
        fprintf( stderr, "UpdateProvider: Unable to manipulate 64-bit catalog from a 32"
                "-bit process\n" );
    }
#endif

    if ( SOCKET_ERROR == rc )
    {
        fprintf( stderr, "UpdateProvider: WSCUpdateProvider failed: %d\n",
                *lpErrno );
    }

    return rc;
}

//
// 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
                );
    }

    printf( "\n\nTo remove press a key, otherwise CTRL+C now! ");
    getchar();
    printf( "\n" );

    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;
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The GNU General Public License (GPLv3)


Written By
Software Developer (Senior)
France France
I am a French programmer.
These days I spend most of my time with the .NET framework, JavaScript and html.

Comments and Discussions