#include #include #include #include #include extern "C" { #include } ///////////////////////////////////////////////////////////////////////////// //++ // // RemoveNetworkProvider // // Routine Description: // This routine uninstalls the Clustering Service Network Provider. // // Arguments: // None // // Return Value: // (DWORD) ERROR_SUCCESS - indicates success // Any other value is a Win32 error code. // // Note: // This function was adapted from removeNetworkProvider in the NT 4.0 // Cluster "setup" program. // //-- ///////////////////////////////////////////////////////////////////////////// DWORD RemoveNetworkProvider( void ) { DWORD dwReturnValue; LONG lReturnValue; // // The inf file will take care of deleting the clusnet winsock key. // We just need to delete clusnet from the list of winsock transports. // // // Open the winsock service parameters key. // HKEY hWinsockParametersRegKey; lReturnValue = RegOpenKeyEx( HKEY_LOCAL_MACHINE, TEXT("System\\CurrentControlSet\\Services\\WinSock\\Parameters"), (DWORD) 0L, // reserved MAXIMUM_ALLOWED, (PHKEY) &hWinsockParametersRegKey ); dwReturnValue = (DWORD) lReturnValue; if ( lReturnValue == (LONG) ERROR_SUCCESS ) { // // Update the winsock transports list. // // Allocate memory into which to read the Winsock Transports List. LPBYTE pWinsockTransportsList; DWORD dwWinsockTransportsListSize = 200; // arbitrary size pWinsockTransportsList = (LPBYTE) LocalAlloc( LPTR, dwWinsockTransportsListSize ); // Was the buffer for the Winsock Transports List allocated? if ( pWinsockTransportsList != (LPBYTE) NULL ) { // Read the Winsock Transports List from the registry. DWORD dwRegKeyType; lReturnValue = RegQueryValueEx( hWinsockParametersRegKey, TEXT("Transports"), (LPDWORD) NULL, &dwRegKeyType, pWinsockTransportsList, &dwWinsockTransportsListSize ); // Was the Winsock Transports List read on the first attempt? if ( lReturnValue != (LONG) ERROR_SUCCESS ) { // Was the buffer too small? if ( lReturnValue == (LONG) ERROR_MORE_DATA ) { // The Winsock Transports List was not read form the registry because // the buffer was too small. Increase the size of the buffer. pWinsockTransportsList = (LPBYTE) LocalReAlloc( pWinsockTransportsList, (UINT) dwWinsockTransportsListSize, (UINT) LMEM_ZEROINIT ); // Was the buffer reallocation successfull? if ( pWinsockTransportsList != (LPBYTE) NULL ) { // Attempt to read the Wincosk Transports List a second time. lReturnValue = RegQueryValueEx( hWinsockParametersRegKey, TEXT("Transports"), (LPDWORD) NULL, &dwRegKeyType, pWinsockTransportsList, &dwWinsockTransportsListSize ); // Was the Winsock Transports List read on the second attempt? if ( lReturnValue != (LONG) ERROR_SUCCESS ) { dwReturnValue = (DWORD) lReturnValue; } // Was the Winsock Transports List read on the second attempt? } // Was the buffer reallocation successfull? else { dwReturnValue = GetLastError(); } // Was the buffer reallocation successfull? } // Was the buffer too small? } // Was the Winsock Transports List read on the first attempt? // At this point variable lReturnValue indicates whether the Winsock // Transports List was read from the registry. if ( lReturnValue == (LONG) ERROR_SUCCESS ) { // Is the type of the registry value correct? if ( dwRegKeyType == (DWORD) REG_MULTI_SZ ) { LPTSTR ptszOldTransportsList; ptszOldTransportsList = (LPTSTR) pWinsockTransportsList; LPTSTR ptszNewTransportList; ptszNewTransportList = (LPTSTR) LocalAlloc( LMEM_FIXED, dwWinsockTransportsListSize ); // Was the buffer for the new Winsock Transports List allocated successfully? if ( ptszNewTransportList != (LPTSTR) NULL ) { // Start building a list of Winsock Transports that does not include // the Clustering Service Network Provider. LPTSTR ptszNextTransport; ptszNextTransport = ptszNewTransportList; // Initialize the size of the new Winsock Transports List to zero. dwWinsockTransportsListSize = (DWORD) 0L; DWORD dwIndividualTransportLength; while ( *ptszOldTransportsList != UNICODE_NULL ) { dwIndividualTransportLength = _tcslen(ptszOldTransportsList) + 1; // This comparison is case insensitive, like registry values. if ( _tcsicmp( ptszOldTransportsList, TEXT("ClusNet") ) != 0 ) { _tcscpy( ptszNextTransport, ptszOldTransportsList ); ptszNextTransport += dwIndividualTransportLength; dwWinsockTransportsListSize += dwIndividualTransportLength * sizeof(WCHAR); }; ptszOldTransportsList += dwIndividualTransportLength; } // end of while loop *ptszNextTransport = UNICODE_NULL; dwWinsockTransportsListSize += sizeof( UNICODE_NULL ); // Save the new Winsock Transports List in the registry. ASSERT( dwWinsockTransportsListSize != 0L ); lReturnValue = RegSetValueEx( hWinsockParametersRegKey, TEXT("Transports"), NULL, dwRegKeyType, (CONST BYTE *) ptszNewTransportList, dwWinsockTransportsListSize ); if ( lReturnValue == (LONG) ERROR_SUCCESS ) { // // Poke winsock to update the Winsock2 config // WSA_SETUP_DISPOSITION disposition; dwReturnValue = MigrateWinsockConfiguration( &disposition, NULL, NULL ); } else { dwReturnValue = (DWORD) lReturnValue; } // Free the buffer for the new Winsock Transports List. LocalFree( ptszNewTransportList ); } else { dwReturnValue = GetLastError(); } // Was the buffer for the new Winsock Transports List allocated successfully? } else { dwReturnValue = ERROR_INVALID_PARAMETER; } // Is the type of the registry value correct? } // Did one of the attempts to read the Winsock Transports List succeed? // Free the buffer for the Winsock Transports List. if ( pWinsockTransportsList != (LPBYTE) NULL ) { LocalFree( pWinsockTransportsList ); } } // Was the buffer for the Winsock Transports List allocated? else { dwReturnValue = GetLastError(); } // Was the buffer for the Winsock Transports List allocated? } // Was the Winsock Parameters key opened? return ( dwReturnValue ); }