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