2025-11-28 00:35:46 +09:00

986 lines
32 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: lspmap.cpp
//
// Description:
//
// This file contains the routines used to create a map of the LSPs installed.
// This map is used to order the relationship between LSPs. It is used by the
// LSP uninstaller code to determine which LSPs are dependent on each other.
// Winsock catalog. See instlsp.cpp for more information on running this code.
//
#include "instlsp.h"
////////////////////////////////////////////////////////////////////////////////
//
// Function Implementation
//
////////////////////////////////////////////////////////////////////////////////
//
// 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;
}
//
// Function: BuildLspMap
//
// Description:
// This routine builds a map of all LSPs installed according to what order
// they are in the catalog. That is, the information returned will be ordered
// in the way the LSPs need to be installed. For example if LSP1 is installed
// over the base TCP and UDP providers and LSP2 is installed over LSP1, then
// this routine will return two LSP_ENTRY structures with LSP1 first followed
// by LSP2. The algorithm for determining the order is to first sort by where
// a base provider ID occurs in an LSP chain with lower numbered ones first.
// For example, LSP1 layered directly over TCP will have a base ID (TCP) in
// chain position 1 while LSP (layered over LSP1) will have the base ID in
// chain index 2. This is the ChainOrder field (and it is the minimum value
// for all layered providers). After this first sort, it is possible to have
// several LSPs with the same ChainOrder value. Within these groupings the
// entries are sorted by the maximum LSP chain length. Each LSP has a number
// of layered providers each with its own chain (and the chains could be
// different lengths). The MaxChainLength value is the longest chain length
// of all providers belonging to a given LSP. Each grouping of LspOrder is then
// sorted by MaxChainLengthin ascending order.
//
LSP_ENTRY *
BuildLspMap(
WSAPROTOCOL_INFOW *pProviders,
int iProviderCount,
int *pLspCount
)
{
LSP_ENTRY *pLsps = NULL,
lsptmp;
DWORD *pBaseList = NULL;
int iLspCount = 0,
iSortLspCount = 0,
iOrphanCount = 0,
iBaseCount = 0,
iProviderPathLen,
ErrorCode,
LspOrder,
start,
end,
idx,
rc,
i, j, k;
// Retrieve how many orphaned chain entries are present
iOrphanCount = CountOrphanedChainEntries( pProviders, iProviderCount );
// Retrieve the LSP count
iSortLspCount = iLspCount = GetProviderCount( pProviders, iProviderCount, LAYERED_PROTOCOL );
if ( ( 0 == iOrphanCount ) && ( 0 == iLspCount ) )
{
fprintf( stderr, "BuildLspMap: No LSP installed on the system!\n");
goto cleanup;
}
// If orphaned entries are present, create another LSP_ENTRY and put all orphaned
// entries there.
if ( iOrphanCount > 0 )
iLspCount++;
// Allocate space for our structure which represents the LSPs installed
pLsps = (LSP_ENTRY *) LspAlloc(
sizeof( LSP_ENTRY ) * iLspCount,
&ErrorCode
);
if ( NULL == pLsps )
{
fprintf( stderr, "BuildLspMap: LspAlloc failed: %d\n", ErrorCode );
goto cleanup;
}
// If orphaned entries are present, allocate space to hold them
if ( iOrphanCount > 0 )
{
pLsps[ iLspCount-1 ].LayeredEntries = (WSAPROTOCOL_INFOW *)LspAlloc(
sizeof(WSAPROTOCOL_INFOW) * iOrphanCount, &ErrorCode );
if ( NULL == pLsps[ iLspCount-1 ].LayeredEntries )
{
fprintf( stderr, "BuildLspMap: LspAlloc failed: %d\n", ErrorCode );
goto cleanup;
}
pLsps[ iLspCount-1 ].OrphanedEntries = TRUE;
pLsps[ iLspCount-1 ].Count = iOrphanCount;
//
// Find the orphaned entries and save them off
//
idx = 0;
for(i=0; i < iProviderCount ;i++)
{
// Only investigate protocol chain entries (i.e. chainlen > 1)
if ( pProviders[ i ].ProtocolChain.ChainLen > 1 )
{
// Walk the catalog and look for the dummy entry (i.e. the ID in
// chain entry 0)
for(j=0; j < iProviderCount ;j++)
{
if ( i == j )
continue;
if ( pProviders[ i ].ProtocolChain.ChainEntries[ 0 ] ==
pProviders[ j ].dwCatalogEntryId )
{
break;
}
}
if ( j >= iProviderCount )
{
// If j is past iProviderCount, no match was found so this is
// an orphaned entry...save it off
memcpy( &pLsps[ iLspCount-1 ].LayeredEntries[ idx ],
&pProviders[ i ],
sizeof( WSAPROTOCOL_INFOW )
);
rc = AddGuidToLspEntry( &pLsps[ iLspCount-1 ], &pProviders[ i ].ProviderId,
&ErrorCode );
if ( SOCKET_ERROR == rc )
{
fprintf( stderr, "BuildLspMap: AddGuidToLspEntry failed: %d\n", ErrorCode );
goto cleanup;
}
idx++;
}
}
}
}
//
// Build a list of the valid LSPs installed on the system
//
idx = 0;
for(i=0; i < iProviderCount ;i++)
{
if ( LAYERED_PROTOCOL == pProviders[ i ].ProtocolChain.ChainLen )
{
// Copy the dummy entry
memcpy( &pLsps[ idx ].DummyEntry, &pProviders[ i ], sizeof( WSAPROTOCOL_INFOW ) );
// Get the DLL path
iProviderPathLen = MAX_PATH-1;
rc = WSCGetProviderPath(
&pLsps[ idx ].DummyEntry.ProviderId,
pLsps[ idx ].wszLspDll,
&iProviderPathLen,
&ErrorCode
);
if ( SOCKET_ERROR == rc )
{
fprintf( stderr, "BuildLspMap: WSCGetProviderPath failed: %d\n", ErrorCode );
goto cleanup;
}
//
// Now go find all the layered entries associated with the dummy provider
//
// First get the count
for(j=0; j < iProviderCount ;j++)
{
//
// Compare only the first entry against the dummy ID. Otherwise,
// we may pick up more than the provider's owned by this LSP
// (it may pick up other providers layered over this LSP.
//
if ( ( pProviders[ j ].ProtocolChain.ChainLen > 1 ) &&
( pProviders[ j ].ProtocolChain.ChainEntries[ 0 ] ==
pLsps[ idx ].DummyEntry.dwCatalogEntryId )
)
// if ( IsIdInChain( &pProviders[ j ], pLsps[ idx ].DummyEntry.dwCatalogEntryId ) )
{
pLsps[idx].Count++;
}
}
// Allocate space
pLsps[ idx ].LayeredEntries = (WSAPROTOCOL_INFOW *) LspAlloc(
sizeof( WSAPROTOCOL_INFOW ) * pLsps[ idx ].Count,
&ErrorCode
);
if ( NULL == pLsps[ idx ].LayeredEntries )
{
fprintf( stderr, "BuildLspMap: LspAlloc failed: %d\n", ErrorCode );
goto cleanup;
}
pLsps[ idx ].LayerChanged = (int *) LspAlloc(
sizeof( int ) * pLsps[ idx ].Count,
&ErrorCode
);
if ( NULL == pLsps[ idx ].LayerChanged )
{
fprintf( stderr, "BuildLspMap: LspAlloc failed: %d\n", ErrorCode );
goto cleanup;
}
// Now go find the entries
pLsps[idx].Count = 0;
for(j=0; j < iProviderCount ;j++)
{
if ( ( pProviders[ j ].ProtocolChain.ChainLen > 1 ) &&
( pProviders[ j ].ProtocolChain.ChainEntries[ 0 ] ==
pLsps[ idx ].DummyEntry.dwCatalogEntryId )
)
{
memcpy(
&pLsps[ idx ].LayeredEntries[pLsps[ idx ].Count],
&pProviders[ j ],
sizeof( WSAPROTOCOL_INFOW )
);
pLsps[idx].MaxChainLength = MAX(
pLsps[ idx ].MaxChainLength,
pLsps[ idx ].LayeredEntries[ pLsps[idx].Count ].ProtocolChain.ChainLen
);
// Mark this entry as visited
pProviders[ j ].dwProviderReserved = 1;
// Keep track of how many GUIDs are used to install the layered entries
rc = AddGuidToLspEntry( &pLsps[ idx ], &pProviders[ j ].ProviderId, &ErrorCode );
if ( SOCKET_ERROR == rc )
{
fprintf( stderr, "BuildLspMap: AddGuidToLspEntry failed: %d\n", ErrorCode );
goto cleanup;
}
pLsps[ idx ].Count++;
}
}
pLsps[ idx ].LspOrder = MAX_PROTOCOL_CHAIN;
idx++; // Increment index into the map
}
}
//
// We now have an array of "LSPs" -- now order them
//
// First get a list of base provider IDs
iBaseCount = GetProviderCount( pProviders, iProviderCount, BASE_PROTOCOL );
if ( 0 == iBaseCount )
{
fprintf( stderr, "BuildLspMap: GetProviderCount(BASE_PROTOCOL) returned zero!\n" );
goto cleanup;
}
// Allocate space for the array of base provider ID's
pBaseList = (DWORD *) LspAlloc(
sizeof( DWORD ) * iBaseCount,
&ErrorCode
);
if ( NULL == pBaseList )
{
fprintf( stderr, "BuildLspMap: HeapAlloc failed: %d\n", ErrorCode );
goto cleanup;
}
//
// Copy the base provider ID's to our array -- this array contains the catalog
// IDs of only base providers which will be used next to determine the order
// in which LSPs were installed.
//
idx = 0;
for(i=0; i < iProviderCount ;i++)
{
if ( BASE_PROTOCOL == pProviders[ i ].ProtocolChain.ChainLen )
{
pBaseList[ idx++ ] = pProviders[ i ].dwCatalogEntryId;
}
}
//
// For each layered protocol entry of an LSP find the lowest index in the protocol
// chain where a base provider resides. A protocol chain should always terminate
// in a base provider.
//
for(LspOrder = 1; LspOrder < MAX_PROTOCOL_CHAIN ;LspOrder++)
{
for(i=0; i < iSortLspCount ;i++)
{
for(j=0; j < pLsps[ i ].Count ;j++)
{
for(k=0; k < iBaseCount ;k++)
{
if ( pLsps[ i ].LayeredEntries[ j ].ProtocolChain.ChainEntries[ LspOrder ] ==
pBaseList[ k ] )
{
pLsps[ i ].LspOrder = MIN( pLsps[ i ].LspOrder, LspOrder );
break;
}
}
}
}
}
//
// Sort the entries according to the LspOrder field
//
for(i=0; i < iSortLspCount ;i++)
{
for(j=i; j < iSortLspCount ;j++)
{
if ( pLsps[ i ].LspOrder > pLsps[ j ].LspOrder )
{
// Exchange positions
memcpy( &lsptmp, &pLsps[ i ], sizeof( LSP_ENTRY ) );
memcpy( &pLsps[ i ], &pLsps[ j ], sizeof( LSP_ENTRY ) );
memcpy( &pLsps[ j ], &lsptmp, sizeof( LSP_ENTRY ) );
}
}
}
//
// Now need to sort by MaxChainLength withing the LspOrder groupings
//
for(LspOrder=1; LspOrder < MAX_PROTOCOL_CHAIN ;LspOrder++)
{
// Find the start and end positions within the array for the given
// LspOrder value
start = -1;
end = -1;
for(i=0; i < iSortLspCount ;i++)
{
if ( pLsps[ i ].LspOrder == LspOrder )
{
start = i;
break;
}
}
//
// Find the end position which is the LSP Map entry whose LspOrder
// value doesn't match the current one. This will give us the range
// of LSP entries whose LspOrder value is identical -- we need to
// sort the LSPs of the same LspOrder according to the MaxChainLength
//
if ( -1 != start )
{
for(j=start; j < iSortLspCount ;j++)
{
if ( pLsps[ j ].LspOrder != LspOrder )
{
end = j - 1;
break;
}
}
}
//
// If the following is true then all entries have the same order
// value. We still need to sort by MaxChainLength so set the end
// to the last LSP
//
if ( ( -1 != start ) && ( -1 == end ) )
{
end = iSortLspCount - 1;
}
if ( ( -1 != start ) && ( -1 != end ) )
{
for(i=start; i < end ;i++)
{
for(j=i; j < end ;j++)
{
if ( pLsps[ i ].MaxChainLength > pLsps[ j ].MaxChainLength )
{
memcpy( &lsptmp, &pLsps[ i ], sizeof( LSP_ENTRY ) );
memcpy( &pLsps[ i ], &pLsps[ j ], sizeof( LSP_ENTRY ) );
memcpy( &pLsps[ j ], &lsptmp, sizeof( LSP_ENTRY ) );
}
}
}
}
}
// Add the LSP dependency info to the map
rc = LspDependencyCheck( pLsps, iSortLspCount );
if ( SOCKET_ERROR == rc )
{
FreeLspMap( pLsps, iLspCount );
pLsps = NULL;
iLspCount = 0;
goto cleanup;
}
cleanup:
if ( NULL != pLspCount )
*pLspCount = iLspCount;
if ( NULL != pBaseList )
LspFree( pBaseList );
return pLsps;
}
//
// Function: PrintLspMap
//
// Description:
// Print the array of LSP_ENTRY structures to the console. The LSP_ENTRY
// array is ordered in the same order the LSPs were installed.
//
void
PrintLspMap(
LSP_ENTRY *pLspMap,
int iLspCount
)
{
WCHAR szGuidString[ MAX_PATH ];
int i, j, k;
if ( NULL == pLspMap )
{
printf( "\tNo LSPs currently installed\n\n" );
goto cleanup;
}
for(i=0; i < iLspCount ;i++)
{
if ( pLspMap[ i ].OrphanedEntries != TRUE )
{
// Display the LSP name and its DLL (and path)
printf( "%3d LSP: %ws DLL '%ws' ID: %d\n",
i,
pLspMap[ i ].DummyEntry.szProtocol,
pLspMap[ i ].wszLspDll,
pLspMap[ i ].DummyEntry.dwCatalogEntryId
);
// Display the GUIDs under which the layered entries of this LSP are installed
printf( "\t LSP Installed under %d GUIDs\n", pLspMap[ i ].LayeredGuidCount );
for(k=0; k < pLspMap[ i ].LayeredGuidCount ;k++)
{
StringFromGUID2( pLspMap[ i ].LayeredGuids[ k ], szGuidString, MAX_PATH-1 );
printf( "\t\t%ws\n", szGuidString );
}
}
else
{
printf("Orphaned layered chain entries:\n");
}
// Display the layered entries and the protocol chains
for(j=0; j < pLspMap[ i ].Count ;j++)
{
printf( "\t Layer %-5d \"%ws\" \n\t Chain %d [ ",
pLspMap[ i ].LayeredEntries[ j ].dwCatalogEntryId,
pLspMap[ i ].LayeredEntries[ j ].szProtocol,
pLspMap[ i ].LayeredEntries[ j ].ProtocolChain.ChainLen
);
for(k=0; k < pLspMap[ i ].LayeredEntries[ j ].ProtocolChain.ChainLen ;k++)
{
printf( "%d ", pLspMap[ i ].LayeredEntries[ j ].ProtocolChain.ChainEntries[ k ] );
}
printf( "]\n" );
}
// Display any LSPs which depend on this one (i.e. other LSPs layered over this one)
printf( "\t Dependent LSPs:\n" );
if ( pLspMap[ i ].DependentCount == 0 )
printf( "\t\tNone\n");
else
{
for(j=0; j < pLspMap[ i ].DependentCount ;j++)
{
printf("\t\t%d %ws\n",
pLspMap[ pLspMap[ i ].DependentLspIndexArray[ j ] ].DummyEntry.dwCatalogEntryId,
pLspMap[ pLspMap[ i ].DependentLspIndexArray[ j ] ].DummyEntry.szProtocol
);
}
}
printf( "\n" );
}
cleanup:
return;
}
//
// Function: FreeLspMap
//
// Description:
// Frees all memory associated with an LSP_ENTRY array.
//
void
FreeLspMap(
LSP_ENTRY *pLspMap,
int iLspCount
)
{
int i;
for(i=0; i < iLspCount ;i++)
{
// Free the layered providers first
if ( NULL != pLspMap[ i ].LayeredEntries )
LspFree( pLspMap[ i ].LayeredEntries );
if ( NULL != pLspMap[ i ].LayeredGuids )
LspFree( pLspMap[ i ].LayeredGuids );
if ( NULL != pLspMap[ i ].LayerChanged )
LspFree( pLspMap[ i ].LayerChanged );
if ( NULL != pLspMap[ i ].DependentLspIndexArray )
LspFree( pLspMap[ i ].DependentLspIndexArray );
}
LspFree( pLspMap );
}
//
// 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;
}
//
// Function: UpdateLspMap
//
// Description:
// This routine updates catalog entry IDs in the LSP map. In the event
// WSCUpdateProvider is not available, the uninstaller must remove all
// dependent LSPs and reinstall them. This requires updating any references
// to these reinstalled LSPs to their new values (as reinstalling a provider
// changes the catalog ID). After a provider is LSP, the uninstaller matches
// the older provider to the new to obtain the new provider ID (via
// MapNewEntriesToOld). This routine takes and old provider ID and updates all
// references within the LSP map to the new provider's ID.
//
void
UpdateLspMap(
LSP_ENTRY *pLspMap,
DWORD dwOldValue,
DWORD dwNewValue
)
{
int i, j;
// Go through all providers beloging to this LSP
for(i=0; i < pLspMap->Count ;i++)
{
// Go through the protocol chain and update references if they match
for(j=0; j < pLspMap->LayeredEntries[ i ].ProtocolChain.ChainLen ;j++)
{
if ( pLspMap->LayeredEntries[ i ].ProtocolChain.ChainEntries[ j ] ==
dwOldValue
)
{
pLspMap->LayeredEntries[ i ].ProtocolChain.ChainEntries[ j ] =
dwNewValue;
}
}
}
return;
}
//
// Function: MapNewEntriesToOld
//
// Description:
// This routine is used by the uninstaller if WSCUpdateProvider is not available.
// In this case, after one LSP is removed there may be others that referenced
// that LSP. The uninstaller removes those entries and reinstalls them (and
// removes the reference the the removed LSP). Once a dependent provider is
// reinstalled we need to see if even other LSP references the reinstalled
// provider and if so we need to update all references (catalog IDs) to that
// LSP. This routine takes the Winsock catalog after a dependent LSP has
// been resinstalled (pProvider and iProviderCount) and matches the newly
// installed providers back to the LSP map we started with. This is so we
// can get the older catalog ID along with the new catalog ID of each LSP
// entry.
//
void
MapNewEntriesToOld(
LSP_ENTRY *pEntry,
WSAPROTOCOL_INFOW *pProvider,
int iProviderCount
)
{
int i, j;
for(i=0; i < pEntry->Count ;i++)
{
for(j=0; j < iProviderCount ;j++)
{
if ( IsEqualProtocolEntries( &pEntry->LayeredEntries[ i ], &pProvider[ j ] ) )
{
pEntry->LayeredEntries[ i ].dwProviderReserved =
pProvider[ j ].dwCatalogEntryId;
dbgprint( "Mapped old %d to new %d\n",
pEntry->LayeredEntries[ i ].dwCatalogEntryId,
pProvider[ j ].dwCatalogEntryId
);
break;
}
}
}
}
//
// Function: AddGuidToLspEntry
//
// Description:
// This routine adds a GUID to the list of provider GUIDs for an LSP_ENTRY if
// it is unique. If the GUID already exists in the list it is not added again.
//
int
AddGuidToLspEntry(
LSP_ENTRY *entry,
GUID *guid,
int *lpErrno
)
{
BOOL bFound;
int rc,
i;
if ( 0 == entry->Count )
{
entry->LayeredGuids = (GUID *) LspAlloc(
sizeof( GUID ),
lpErrno
);
if ( NULL == entry->LayeredGuids )
{
fprintf( stderr, "AddGuidToLspEntry: LspAlloc failed: %d\n", *lpErrno );
goto cleanup;
}
memcpy( &entry->LayeredGuids[ 0 ], guid, sizeof( GUID ) );
entry->LayeredGuidCount++;
}
else
{
// See if we've already seen this guid
bFound = FALSE;
for(i=0; i < entry->LayeredGuidCount ;i++)
{
rc = memcmp( &entry->LayeredGuids[ i ], guid, sizeof( GUID ) );
if ( 0 == rc )
{
bFound = TRUE;
break;
}
}
if ( FALSE == bFound )
{
GUID *tmpguid = NULL;
// New GUID -- we need to add it to the array
tmpguid = (GUID *) LspAlloc(
sizeof( GUID ) * ( entry->LayeredGuidCount + 1 ),
lpErrno
);
if ( NULL == tmpguid )
{
fprintf( stderr, "AddGuidToLspEntry: LspAlloc failed: %d\n", *lpErrno );
goto cleanup;
}
memcpy( tmpguid, entry->LayeredGuids, sizeof(GUID) * entry->LayeredGuidCount );
memcpy( &tmpguid[ entry->LayeredGuidCount ], guid, sizeof( GUID ) );
LspFree( entry->LayeredGuids );
entry->LayeredGuids = tmpguid;
entry->LayeredGuidCount++;
}
}
return NO_ERROR;
cleanup:
return SOCKET_ERROR;
}
//
// Function: UpdateProviderOrder
//
// Desciption:
// This routine is called after removing and reinstalling an existing LSP (which
// is done when removing an LSP that other LSPs are layered over and the
// WSCUpdateProvider function is not available). After the LSP is re-installed
// the dwProviderReserved field of each of it's layered protocol entries contains
// its new catalog ID. This routine walks the original array describing the order
// of the Winsock catalog and updates the old ID with the new ID. This is done so
// once all the dependent LSPs are removed and re-installed, the catalog can be
// put back in its original order.
//
void
UpdateProviderOrder(
LSP_ENTRY *UpdatedEntry,
DWORD *OrderArray,
int ArrayCount
)
{
int i, j;
for(i=0; i < UpdatedEntry->Count ;i++)
{
for(j=0; j < ArrayCount ;j++)
{
// Replace an occurence of the old value with the new value
if ( OrderArray[ j ] == UpdatedEntry->LayeredEntries[ i ].dwCatalogEntryId )
{
OrderArray[ j ] = UpdatedEntry->LayeredEntries[ i ].dwProviderReserved;
}
}
}
}
//
// Function: MaxLayeredChainCount
//
// Description:
// This routine examines each LSP_ENTRY in an array to find the longest layered
// protocol chain count. This is typically used to find the maximum number of
// WSAPROTOCOL_INFOW objects required when manipulating providers (so that only
// one array has to be allocated which can handle all installed providers).
//
int
MaxLayeredChainCount(
LSP_ENTRY *pLspMap,
int LspCount
)
{
int MaxSize = 0,
i;
for(i=0; i < LspCount ;i++)
{
MaxSize = MAX( MaxSize, pLspMap[ i ].Count );
}
return MaxSize;
}