// // Function: RemoveProvider // // Description: // This function removes a layered provider. Things can get tricky if // we're removing a layered provider which has been layered over by // another provider. This routine first creates the LSP map to determine // if other LSPs on the system reference the LSP we want to remove. If // there are we must fix those LSPs before deleting the target LSP. // If we're on a platform that supports WSCUpdateProvider its simply a // matter of removing any reference to the target LSP's layered protocol // chains and the dummy hidden entry. // // If we're not on a WSCUpdateProvider enabled system, then its very tricky. // We must uninstall the dependent LSPs first followed by reinstalling them // in the same order they were originally installed. For example if LSP1, // LSP2, and LSP3 are installed (in that order) and this routine is invoked // to remove LSP1, we must uninstall LSP3 and LSP2 followed by re-installing // (LSP2 first then LSP3). For each LSP added back we must fix up the protocol // chains of the next higher LSP so the reference the new catalog IDs (since // the action of installing an LSP assigns a new catalog ID). // // NOTE: If WSCUpdateProvider is not supported there is the possiblity of // another process changing the Winsock catalog at the same time we're // trying to fix it back up. If this occurs it is possible for the // corruption to occur. // int RemoveProvider( WINSOCK_CATALOG Catalog, // Catalog to remove an LSP from DWORD dwProviderId // Catalog ID of LSPs hidden entry ) { WSAPROTOCOL_INFOW *pProvider = NULL, *pLayeredEntries = NULL; LSP_ENTRY *pLspMap = NULL, *pLspMapEntryDel = NULL; DWORD *pdwCatalogOrder = NULL; INT iProviderCount = 0, iLayerCount = 0, iLspCount = 0, ErrorCode, Status, rc, i, j, k, l; Status = SOCKET_ERROR; // Enumerate the catalog pProvider = EnumerateProviders( Catalog, &iProviderCount ); if ( pProvider == NULL ) { fprintf( stderr, "RemoveProvider: Unable to enumerate catalog!\n" ); goto cleanup; } // Allocate an array to save of the provider order in case we have to // do uninstall and reinstall providers pdwCatalogOrder = (DWORD *) LspAlloc( sizeof( DWORD ) * iProviderCount, &ErrorCode ); if ( NULL == pdwCatalogOrder ) { fprintf( stderr, "RemoveProvider: LspAlloc failed: %d\n", ErrorCode ); goto cleanup; } for(i=0; i < iProviderCount ; i++) { pdwCatalogOrder[ i ] = pProvider[ i ].dwCatalogEntryId; } // Build a map of the LSPs installed on the system pLspMap = BuildLspMap( pProvider, iProviderCount, &iLspCount ); if ( NULL == pLspMap ) { fprintf( stderr, "RemoveProvider: Unable to build LSP map!\n" ); goto cleanup; } // Validate the catalog entry ID to remove pLspMapEntryDel = NULL; for(i=0; ( i < iLspCount ) && ( NULL == pLspMapEntryDel ) ; i++) { if ( dwProviderId == pLspMap[ i ].DummyEntry.dwCatalogEntryId ) { pLspMapEntryDel = &pLspMap[ i ]; } else { for(j=0; j < pLspMap[ i ].Count ; j++) { if ( dwProviderId == pLspMap[ i ].LayeredEntries[ j ].dwCatalogEntryId ) { // In this case the user supplied the catalog ID of an LSP protocol // chain entry -- not the hidden layered entry (dummy). Here we'll // reset the dwProviderId to that of the dummy hidden entry. // if ( pLspMap[ i ].OrphanedEntries != TRUE ) { printf( "Catalog ID %d is a layered protocol entry and not the hidden\n" "provider representing the entire LSP. The LSP which owns this\n" "provider is ID %d (%ws). This entire LSP will be removed!\n", dwProviderId, pLspMap[ i ].DummyEntry.dwCatalogEntryId, pLspMap[ i ].DummyEntry.szProtocol ); dwProviderId = pLspMap[ i ].DummyEntry.dwCatalogEntryId; pLspMapEntryDel = &pLspMap[ i ]; } else { printf( "Catalog ID %d is one of %d orphaned protocol entries.\n" "These entries could be causing serious problems and\n" "will be removed. The following providers are to be\n" "deleted:\n", pLspMap[ i ].LayeredEntries[ j ].dwCatalogEntryId, pLspMap[ i ].Count ); for(k=0; k < pLspMap[ i ].Count ; k++) { printf(" %d: %ws\n", pLspMap[ i ].LayeredEntries[ k ].dwCatalogEntryId, pLspMap[ i ].LayeredEntries[ k ].szProtocol ); } pLspMapEntryDel = &pLspMap[ i ]; } break; } } } } // Make sure we found a provider to remove if ( NULL == pLspMapEntryDel ) { fprintf( stderr, "\n\nError! Invalid Winsock catalog ID supplied: %d\n", dwProviderId ); goto cleanup; } // // Print which entries are being removed // printf( "\nThe following LSP entries will be removed:\n" ); if ( pLspMapEntryDel->OrphanedEntries != TRUE ) { printf( "LSP Hidden ID: %6d Name %ws\n", pLspMapEntryDel->DummyEntry.dwCatalogEntryId, pLspMapEntryDel->DummyEntry.szProtocol ); } else { printf( "Orphaned LSP protocol chain entries:\n"); } for(i=0; i < pLspMapEntryDel->Count ; i++) { printf( "LSP Layer ID: %6d Name %ws\n", pLspMapEntryDel->LayeredEntries[ i ].dwCatalogEntryId, pLspMapEntryDel->LayeredEntries[ i ].szProtocol ); } ErrorCode = NO_ERROR; if ( 0 != pLspMapEntryDel->DependentCount ) { int iLspIdx; printf( "\n\nOther LSPs are dependent on this one! " "Additional cleanup is required..\n\n" ); for(i=0; i < pLspMapEntryDel->DependentCount ; i++) { iLspIdx = pLspMapEntryDel->DependentLspIndexArray[ i ]; printf( "Fixing LSP index %d: %ws\n", pLspMap[ iLspIdx ].DummyEntry.dwCatalogEntryId, pLspMap[ iLspIdx ].DummyEntry.szProtocol ); // Remove any reference to the deleted LSPs dummy catalog ID for(j=0; j < pLspMap[ iLspIdx ].Count ; j++) { if ( IsIdInChain( &pLspMap[ iLspIdx ].LayeredEntries[ j ], pLspMapEntryDel->DummyEntry.dwCatalogEntryId ) ) { printf( "Removing ID %d from layered chain %d: %ws\n", pLspMapEntryDel->DummyEntry.dwCatalogEntryId, pLspMap[ iLspIdx ].LayeredEntries[ j ].dwCatalogEntryId, pLspMap[ iLspIdx ].LayeredEntries[ j ].szProtocol ); // Remove the deleted LSPs ID from the chain rc = RemoveIdFromChain( &pLspMap[ iLspIdx ].LayeredEntries[ j ], pLspMapEntryDel->DummyEntry.dwCatalogEntryId ); if ( FALSE == rc ) { fprintf( stderr, "RemoveProvider: ID not found in chain!\n" ); continue; } pLspMap[ iLspIdx ].LayerChanged[ j ] = TRUE; } } // Remove any reference to the deleted LSPs layered entries catalog // IDs from the layers of the dependent LSP for(l=0; l < pLspMapEntryDel->Count ; l++) { for(j=0; j < pLspMap[ iLspIdx ].Count ; j++) { if ( IsIdInChain( &pLspMap[ iLspIdx ].LayeredEntries[ j ], pLspMapEntryDel->LayeredEntries[ l ].dwCatalogEntryId ) ) { printf( "Removing ID %d from layered chain %d: %ws\n", pLspMapEntryDel->DummyEntry.dwCatalogEntryId, pLspMap[ iLspIdx ].LayeredEntries[ j ].dwCatalogEntryId, pLspMap[ iLspIdx ].LayeredEntries[ j ].szProtocol ); // Remove the deleted LSPs ID from the chain rc = RemoveIdFromChain( &pLspMap[ iLspIdx ].LayeredEntries[ j ], pLspMapEntryDel->LayeredEntries[ l ].dwCatalogEntryId ); if ( FALSE == rc ) { fprintf( stderr, "RemoveProvider: ID not found in chain!\n" ); continue; } pLspMap[ iLspIdx ].LayerChanged[ j ] = TRUE; } } } } // // All dependent LSPs should no longer reference any of the LSPs IDs which is // to be removed. Now we must write our changes back to the catalog. Life // is easy if we're on a system that supports WSCUpdateProvider. // if ( NULL != fnWscUpdateProvider ) { // // Life is good, simply call UpdateProvider on each entry in the LSP map // that was updated. // for(i=0; i < pLspMapEntryDel->DependentCount ; i++) { iLspIdx = pLspMapEntryDel->DependentLspIndexArray[ i ]; for(j=0; j < pLspMap[ iLspIdx ].Count; j++) { if ( TRUE == pLspMap[ iLspIdx ].LayerChanged[ j ] ) { rc = UpdateProvider( Catalog, &pLspMap[ iLspIdx ].LayeredEntries[ j ].ProviderId, pLspMap[ iLspIdx ].wszLspDll, &pLspMap[ iLspIdx ].LayeredEntries[ j ], 1, &ErrorCode ); } } } } else // fnWscUpdateProvider == NULL { int MaxLayers = 0; // // Life isn't so good. We need to remove all dependent LSPs first in the // reverse order they were installed so that if something fails, we // won't leave the catalog in a bad state. Then we need to reinstall // them in the same order they were originally installed and fix any // of the remaining dependent LSPs to reference the correct catalog IDs // before they are also reinstalled. // // Find the maximum protocol chain length of all the LSPs since we need // scratch space. We do the allocation first before making changes to // the catalog. MaxLayers = MaxLayeredChainCount( pLspMap, iLspCount ); pLayeredEntries = (WSAPROTOCOL_INFOW *) LspAlloc( sizeof( WSAPROTOCOL_INFOW ) * MaxLayers, &ErrorCode ); if ( NULL == pLayeredEntries ) { fprintf( stderr, "RemoveProvider: LspAlloc failed: %d\n", ErrorCode ); goto cleanup; } // Remove the dependent LSPs in reverse order. NOTE: We don't have to // remove the dummy hidden entries since there is no information // in those providers that need updating. for(i=0; i < pLspMapEntryDel->DependentCount ; i++) { iLspIdx = pLspMapEntryDel->DependentLspIndexArray[ i ]; for(j=0; j < pLspMap[ iLspIdx ].LayeredGuidCount ; j++) { rc = DeinstallProvider( Catalog, &pLspMap[ iLspIdx ].LayeredGuids[ j ] ); if ( SOCKET_ERROR == rc ) { fprintf( stderr, "RemoveProvider: An error occured trying to remove an LSP.\n" "\t\tThis may be due to another process changing the Catalog\n" "\t\tAborting...\n" ); goto cleanup; } } } // All the dependent LSP layers have been removed, now add them // back in reverse order for(i=pLspMapEntryDel->DependentCount-1; i >= 0 ; i--) { iLspIdx = pLspMapEntryDel->DependentLspIndexArray[ i ]; // Install the layered entries for(j=0; j < pLspMap[ iLspIdx ].LayeredGuidCount ; j++) { iLayerCount = MaxLayers; rc = GetLayeredEntriesByGuid( pLayeredEntries, &iLayerCount, pLspMap[ iLspIdx ].LayeredEntries, pLspMap[ iLspIdx ].Count, &pLspMap[ iLspIdx ].LayeredGuids[ j ] ); rc = InstallProvider( Catalog, &pLspMap[ iLspIdx ].LayeredGuids[ j ], pLspMap[ iLspIdx ].wszLspDll, pLayeredEntries, iLayerCount ); } // Enumerate catalog to find new IDs DWORD ProviderLen = iProviderCount * sizeof( WSAPROTOCOL_INFOW ); int NewProviderCount = EnumerateProvidersExisting( Catalog, pProvider, &ProviderLen ); if ( SOCKET_ERROR == NewProviderCount ) { fprintf( stderr, "RemoveProvider: EnumerateProvidersExisting failed: %d\n", GetLastError() ); } // Update the old references to the new MapNewEntriesToOld( &pLspMap[ iLspIdx ], pProvider, NewProviderCount ); // Update the provider order array with the new provider values UpdateProviderOrder( &pLspMap[ iLspIdx ], pdwCatalogOrder, iProviderCount ); // For the remaining LSPs which we still need to install, update any // references to the removed LSPs with their new IDs for(k=i-1; k >= 0 ; k--) { int iLspIdx2 = pLspMapEntryDel->DependentLspIndexArray[ k ]; printf( "Updating IDs for index %d\n", iLspIdx2 ); for(l=0; l < pLspMap[ iLspIdx ].Count ; l++) { UpdateLspMap( &pLspMap[ iLspIdx2 ], pLspMap[ iLspIdx ].LayeredEntries[ l ].dwCatalogEntryId, pLspMap[ iLspIdx ].LayeredEntries[ l ].dwProviderReserved ); } } } // Reorder the catalog back to what it was before. Since we've added // back all the LSPs we removed earlier, the catalog should be the // same size as when we started. rc = WriteProviderOrder( Catalog, pdwCatalogOrder, iProviderCount, &ErrorCode ); if ( SOCKET_ERROR == rc ) { fprintf( stderr, "RemoveProvider: WriteProviderOrder failed: %d\n", ErrorCode ); } } } // // Now all dependencies have been fixed, remove the specified provider // // Remove the layered protocol entries for(i=0; i < pLspMapEntryDel->LayeredGuidCount ; i++) { rc = DeinstallProvider( Catalog, &pLspMapEntryDel->LayeredGuids[ i ] ); } // Remove the dummy entry rc = DeinstallProvider( Catalog, &pLspMapEntryDel->DummyEntry.ProviderId ); Status = NO_ERROR; cleanup: // // Cleanup allocations // if ( NULL != pLayeredEntries ) LspFree( pLayeredEntries ); if ( NULL != pProvider ) FreeProviders(pProvider); if ( NULL != pLspMap ) FreeLspMap( pLspMap, iLspCount ); if ( NULL != pdwCatalogOrder ) LspFree( pdwCatalogOrder ); return Status; }
// // Function: main // // Description: // Parse the command line arguments and call either the install, remove, // print, etc. routines. // int _cdecl main(int argc, char *argv[]) { WSADATA wsd; LPWSAPROTOCOL_INFOW pProtocolInfo = NULL; LSP_ENTRY *pLspMap=NULL; #ifdef _WIN64 WINSOCK_CATALOG eCatalog = LspCatalog64Only; #else WINSOCK_CATALOG eCatalog = LspCatalog32Only; #endif INT iTotalProtocols = 0, iLspCount = 0, i; DWORD *pdwCatalogIdArray = NULL, dwCatalogIdArrayCount = 0, // How many to install over dwRemoveCatalogId = 0; BOOL bInstall = TRUE, bInstallOverAll = FALSE, bRemoveAllLayeredEntries = FALSE, bPrintProviders = FALSE, bDisplayOnlyLayeredEntries = FALSE, bVerbose = FALSE, bMapLsp = FALSE, bArgsOkay = FALSE, bIFSProvider = FALSE; char *lpszLspName = NULL, *lpszLspPathAndFile = NULL, *lpszLspPathAndFile32 = NULL; int rc; //////////////////////////////////////////////////////////////////////////// // // Initialization and Command Line Parsing // //////////////////////////////////////////////////////////////////////////// // Load Winsock rc = WSAStartup( MAKEWORD(2,2), &wsd ); if ( 0 != rc ) { fprintf( stderr, "Unable to load Winsock: %d\n", rc ); return -1; } // Initialize data structures LspCreateHeap( &rc ); __try { InitializeCriticalSection( &gDebugCritSec ); } __except( EXCEPTION_EXECUTE_HANDLER ) { goto cleanup; } // First count how many catalog parameters are supplied so we can dynamically // allocate the right sized buffer for(i=1; i < argc ;i++) { if ( strncmp( argv[ i ], "-o", 2 ) == 0 ) dwCatalogIdArrayCount++; } // Allocate space for the array of catalog IDs if ( 0 < dwCatalogIdArrayCount ) { pdwCatalogIdArray = (DWORD *) LspAlloc( sizeof( DWORD ) * dwCatalogIdArrayCount, &rc ); if ( NULL == pdwCatalogIdArray ) { goto cleanup; } } // Set back to zero so we can use it as the index into our array dwCatalogIdArrayCount = 0; // Parse the command line for(i=1; i < argc ;i++) { if ( ( 2 != strlen( argv[i] ) ) && ( '-' != argv[i][0] ) && ( '/' != argv[i][0] ) ) { goto cleanup; } switch ( tolower( argv[i][1] ) ) { case 'a': // Install LSP over all currently installed providers bInstallOverAll = TRUE; break; case 'c': // For 64-bit: which catalog to operate on? if (i+1 >= argc) goto cleanup; switch (tolower(argv[i+1][0])) { case 'b': // Both Winsock catalogs eCatalog = LspCatalogBoth; break; case '6': // 64-bit Winsock catalog only eCatalog = LspCatalog64Only; break; case '3': // 32-bit Winsock catalog only eCatalog = LspCatalog32Only; break; default: goto cleanup; break; } i++; break; case 'd': // Full path and filename to LSP if ( i+1 >= argc ) goto cleanup; if (_strnicmp(argv[i], "-d32", 4)) lpszLspPathAndFile32 = argv[ ++i ]; else lpszLspPathAndFile = argv[ ++i ]; break; case 'f': // Uninstall all layered providers bRemoveAllLayeredEntries = TRUE; bInstall = FALSE; break; case 'h': // Install as an IFS provider bIFSProvider = TRUE; break; case 'i': // install bInstall = TRUE; break; case 'l': // print the layered providers only bPrintProviders = TRUE; bDisplayOnlyLayeredEntries = TRUE; break; case 'm': // Map and print the LSP structure bMapLsp = TRUE; bInstall = FALSE; break; case 'n': // name of the LSP to install (not the DLL name) if (i+1 >= argc) goto cleanup; lpszLspName = argv[++i]; break; case 'o': // catalog id (to install over) if (i+1 >= argc) goto cleanup; pdwCatalogIdArray[dwCatalogIdArrayCount++] = atoi(argv[++i]); break; case 'p': // print the catalog bPrintProviders = TRUE; bDisplayOnlyLayeredEntries = FALSE; break; case 'r': // remove an LSP bInstall = FALSE; if (i+1 >= argc) goto cleanup; dwRemoveCatalogId = atol(argv[++i]); break; case 'v': // verbose mode (when printing with -p option) bVerbose = TRUE; break; default: goto cleanup; break; } } #ifndef _WIN64 if ( LspCatalog64Only == eCatalog ) { fprintf(stderr, "\n\nUnable to manipulate 64-bit Winsock catalog from 32-bit process!\n\n"); goto cleanup; } #endif bArgsOkay = TRUE; gModule = LoadUpdateProviderFunction(); if ( TRUE == bPrintProviders ) { // Print the 32-bit catalog if ( ( LspCatalogBoth == eCatalog ) || ( LspCatalog32Only == eCatalog ) ) { printf( "\n\nWinsock 32-bit Catalog:\n" ); printf( "=======================\n" ); PrintProviders( LspCatalog32Only, bDisplayOnlyLayeredEntries, bVerbose ); } // Print the 64-bit catalog if ( ( LspCatalogBoth == eCatalog ) || ( LspCatalog64Only == eCatalog ) ) { printf( "\n\nWinsock 64-bit Catalog:\n" ); printf( "=======================\n" ); PrintProviders( LspCatalog64Only, bDisplayOnlyLayeredEntries, bVerbose ); } } else if ( TRUE == bInstall ) { if ( NULL == lpszLspPathAndFile ) { fprintf( stderr, "\n\nError! Please specify path and filename of LSP!\n\n"); bArgsOkay = FALSE; goto cleanup; } if ( TRUE == bInstallOverAll ) { // Make sure user didn't specify '-a' and '-o' flags if ( 0 != dwCatalogIdArrayCount ) { fprintf( stderr, "\n\nError! Cannot specify both '-a' and '-o' flags!\n\n" ); goto cleanup; } // Enumerate the appropriate catalog we will be working on pProtocolInfo = EnumerateProviders( eCatalog, &iTotalProtocols ); if ( NULL == pProtocolInfo ) { fprintf( stderr, "%s: EnumerateProviders: Unable to enumerate Winsock catalog\n", argv[ 0 ] ); goto cleanup; } // Count how many non layered protocol entries there are for(i=0; i < iTotalProtocols ;i++) { if ( LAYERED_PROTOCOL != pProtocolInfo[ i ].ProtocolChain.ChainLen ) dwCatalogIdArrayCount++; } // Allocate space for all the entries pdwCatalogIdArray = (DWORD *) LspAlloc( sizeof( DWORD ) * dwCatalogIdArrayCount, &rc ); if ( NULL == pdwCatalogIdArray ) { fprintf( stderr, "%s: LspAlloc failed: %d\n", argv[ 0 ], rc ); goto cleanup; } // Get the catalog IDs for all existing providers dwCatalogIdArrayCount = 0 ; for(i=0; i < iTotalProtocols ;i++) { if ( LAYERED_PROTOCOL != pProtocolInfo[ i ].ProtocolChain.ChainLen ) { pdwCatalogIdArray[ dwCatalogIdArrayCount++ ] = pProtocolInfo[ i ].dwCatalogEntryId; } } FreeProviders( pProtocolInfo ); pProtocolInfo = NULL; } // Install the LSP with the supplied parameters rc = InstallLsp( eCatalog, lpszLspName, lpszLspPathAndFile, lpszLspPathAndFile32, dwCatalogIdArrayCount, pdwCatalogIdArray, bIFSProvider, bInstallOverAll ); } else if ( TRUE == bMapLsp ) { // Display the 32-bit LSP catalog map if ( ( LspCatalogBoth == eCatalog ) || ( LspCatalog32Only == eCatalog ) ) { printf("\n32-bit Winsock LSP Map:\n\n"); pProtocolInfo = EnumerateProviders( LspCatalog32Only, &iTotalProtocols ); if ( NULL == pProtocolInfo ) { fprintf(stderr, "%s: EnumerateProviders: Unable to enumerate Winsock catalog\n", argv[ 0 ] ); goto cleanup; } pLspMap = BuildLspMap( pProtocolInfo, iTotalProtocols, &iLspCount ); if ( NULL == pLspMap ) { printf( "\nNo LSPs are installed\n\n" ); } else { PrintLspMap( pLspMap, iLspCount ); FreeLspMap( pLspMap, iLspCount ); pLspMap = NULL; } FreeProviders( pProtocolInfo ); pProtocolInfo = NULL; } // Display the 64-bit LSP catalog map if ( ( LspCatalogBoth == eCatalog ) || ( LspCatalog64Only == eCatalog ) ) { printf("\n64-bit Winsock LSP Map:\n\n"); pProtocolInfo = EnumerateProviders( LspCatalog64Only, &iTotalProtocols ); if ( NULL == pProtocolInfo ) { fprintf(stderr, "%s: EnumerateProviders: Unable to enumerate Winsock catalog\n", argv[ 0 ] ); goto cleanup; } pLspMap = BuildLspMap( pProtocolInfo, iTotalProtocols, &iLspCount ); if ( NULL == pLspMap ) { printf( "\nNo LSPs are installed\n\n" ); } else { PrintLspMap( pLspMap, iLspCount ); FreeLspMap( pLspMap, iLspCount ); pLspMap = NULL; } FreeProviders( pProtocolInfo ); pProtocolInfo = NULL; } } else { // We must be removing an LSP if ( TRUE == bRemoveAllLayeredEntries ) { if ( ( LspCatalogBoth == eCatalog ) || ( LspCatalog32Only == eCatalog ) ) RemoveAllLayeredEntries( LspCatalog32Only ); if ( ( LspCatalogBoth == eCatalog ) || ( LspCatalog64Only == eCatalog ) ) RemoveAllLayeredEntries( LspCatalog64Only ); } else { // Make sure a catalog entry to remove was supplied if ( dwRemoveCatalogId == 0 ) { bArgsOkay = FALSE; goto cleanup; } if ( ( LspCatalogBoth == eCatalog ) || ( LspCatalog32Only == eCatalog ) ) RemoveProvider( LspCatalog32Only, dwRemoveCatalogId ); if ( ( LspCatalogBoth == eCatalog ) || ( LspCatalog64Only == eCatalog ) ) RemoveProvider( LspCatalog64Only, dwRemoveCatalogId ); } } cleanup: if ( FALSE == bArgsOkay ) usage( argv[ 0 ] ); // // When invoked on Vista under non elevated permissions, the EXE is launched in // a new CMD window. The following getchar stops the window from exiting // immediately so you can see what its output was. // printf("Press any key to continue...\n"); getchar(); // // Free any dynamic allocations and/or handles // if ( NULL != pdwCatalogIdArray ) LspFree( pdwCatalogIdArray ); if ( NULL != pProtocolInfo) FreeProviders( pProtocolInfo ); if ( NULL != pLspMap ) FreeLspMap( pLspMap, iLspCount ); if ( NULL != gModule ) FreeLibrary( gModule ); LspDestroyHeap( ); DeleteCriticalSection( &gDebugCritSec ); WSACleanup(); return 0; }
// // 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: 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; }