818 lines
28 KiB
C++
818 lines
28 KiB
C++
//
|
|
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
|
|
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
|
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|
|
// PARTICULAR PURPOSE.
|
|
//
|
|
// Copyright (C) 2004 Microsoft Corporation. All Rights Reserved.
|
|
//
|
|
// Module Name: lspdel.cpp
|
|
//
|
|
// Description:
|
|
//
|
|
// This file contains the routines used to remove provider entries from the
|
|
// Winsock catalog. See instlsp.cpp for more information on running this code.
|
|
//
|
|
#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;
|
|
}
|