////////////////////////////////////////////////////////////////////////////// // // Copyright (c) 2000-2002 Microsoft Corporation // // Module Name: // CTaskUpgradeNT4.cpp // // Description: // Implementation file for the CTaskUpgradeNT4 class. // // Header File: // CTaskUpgradeNT4.h // // Maintained By: // David Potter (DavidP) 25-MAR-2002 // Vij Vasu (Vvasu) 18-APR-2000 // ////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// // Include Files ////////////////////////////////////////////////////////////////////////////// // Precompiled header for this DLL. #include "Pch.h" // The header file for this module. #include "CTaskUpgradeNT4.h" ////////////////////////////////////////////////////////////////////////////// // Macro Definitions ////////////////////////////////////////////////////////////////////////////// // Needed for tracing. DEFINE_THISCLASS( "CTaskUpgradeNT4" ) // Name of the cluster service executable #define CLUSSVC_EXECUTABLE_NAME L"ClusSvc.exe" // Multi-sz string of cluster service dependencies #define CLUSSVC_DEPENDENCY_MULTISZ L"ClusNet\0RpcSs\0W32Time\0NetMan" ///////////////////////////////////////////////////////////////////////////// //++ // // CTaskUpgradeNT4::CTaskUpgradeNT4 // // Description: // Constructor of the CTaskUpgradeNT4 class. // // Arguments: // const CClusOCMApp & rAppIn // Reference to the CClusOCMApp object that is hosting this task. // // Return Value: // None. // //-- ///////////////////////////////////////////////////////////////////////////// CTaskUpgradeNT4::CTaskUpgradeNT4( const CClusOCMApp & rAppIn ) : BaseClass( rAppIn ) { TraceFunc( "" ); TraceFuncExit(); } //*** CTaskUpgradeNT4::CTaskUpgradeNT4() ///////////////////////////////////////////////////////////////////////////// //++ // // CTaskUpgradeNT4::~CTaskUpgradeNT4 // // Description: // Destructor of the CTaskUpgradeNT4 class. // // Arguments: // None. // // Return Value: // None. // //-- ///////////////////////////////////////////////////////////////////////////// CTaskUpgradeNT4::~CTaskUpgradeNT4( void ) { TraceFunc( "" ); TraceFuncExit(); } //*** CTaskUpgradeNT4::~CTaskUpgradeNT4() ///////////////////////////////////////////////////////////////////////////// //++ // // DWORD // CTaskUpgradeNT4::DwOcQueueFileOps // // Description: // This function handles the OC_QUEUE_FILE_OPS messages from the Optional // Components Manager. It installs the files needed for an upgrade from // Windows 2000. // // Arguments: // HSPFILEQ hSetupFileQueueIn // Handle to the file queue to operate upon. // // Return Value: // NO_ERROR if all went well. // Other Win32 error codes on failure. // //-- ///////////////////////////////////////////////////////////////////////////// DWORD CTaskUpgradeNT4::DwOcQueueFileOps( HSPFILEQ hSetupFileQueueIn ) { TraceFunc( "" ); LogMsg( "Entering " __FUNCTION__ "()" ); DWORD dwReturnValue = NO_ERROR; // The base class helper function does everything that we need to do here. // So, just call it. dwReturnValue = TW32( BaseClass::DwOcQueueFileOps( hSetupFileQueueIn, INF_SECTION_NT4_UPGRADE ) ); LogMsg( "Return Value is %#x.", dwReturnValue ); RETURN( dwReturnValue ); } //*** CTaskUpgradeNT4::DwOcQueueFileOps() ///////////////////////////////////////////////////////////////////////////// //++ // // DWORD // CTaskUpgradeNT4::DwOcCompleteInstallation // // Description: // This function handles the OC_COMPLETE_INSTALLATION messages from the // Optional Components Manager during an upgrade from Windows 2000. // // Registry operations, COM component registrations, creation of servies // etc. are performed in this function. // // Arguments: // None. // // Return Value: // NO_ERROR if all went well. // Other Win32 error codes on failure. // //-- ///////////////////////////////////////////////////////////////////////////// DWORD CTaskUpgradeNT4::DwOcCompleteInstallation( void ) { TraceFunc( "" ); LogMsg( "Entering " __FUNCTION__ "()" ); DWORD dwReturnValue = NO_ERROR; // Call the base class helper function to perform some registry and service // related configuration from the INF file. dwReturnValue = TW32( BaseClass::DwOcCompleteInstallation( INF_SECTION_NT4_UPGRADE ) ); // // Change the cluster service display name, description, dependencies, failure actions // and executable name. // while( dwReturnValue == NO_ERROR ) { // Pointer the the cluster service directory. const WCHAR * pcszInstallDir = NULL; // Smart pointer to the cluster service display name string. SmartSz sszClusSvcDispName; // Smart pointer to the cluster service description string. SmartSz sszClusSvcDesc; // Smart pointer to the cluster service binary path string. SmartSz sszClusSvcBinPath; // Smart pointer to the cluster service. SmartServiceHandle shClusSvc; // Connect to the Service Control Manager SmartServiceHandle shServiceMgr( OpenSCManager( NULL, NULL, GENERIC_READ | GENERIC_WRITE ) ); if ( shServiceMgr.HHandle() == NULL ) { dwReturnValue = TW32( GetLastError() ); LogMsg( "Error %#x occurred trying to open a connection to the local service control manager.", dwReturnValue ); break; } // if: opening the SCM was unsuccessful // Open a handle to the Cluster Service. shClusSvc.Assign( OpenService( shServiceMgr, L"ClusSvc", SERVICE_ALL_ACCESS ) ); if ( shClusSvc.HHandle() == NULL ) { dwReturnValue = TW32( GetLastError() ); LogMsg( "Error %#x occurred trying to open a handle to the cluster service.", dwReturnValue ); break; } // if: the handle could not be opened // Load the cluster service name string. dwReturnValue = DwLoadString( IDS_CLUSSVC_DISPLAY_NAME, sszClusSvcDispName ); if ( dwReturnValue != ERROR_SUCCESS ) { LogMsg( "Error %#x occurred trying load the display name of the cluster service.", dwReturnValue ); break; } // if: we could not load the cluster service display name string LogMsg( "The new cluster service display name is '%ws'.", sszClusSvcDispName.PMem() ); // Load the cluster service description string. dwReturnValue = DwLoadString( IDS_CLUSSVC_SERVICE_DESC, sszClusSvcDesc ); if ( dwReturnValue != ERROR_SUCCESS ) { LogMsg( "Error %#x occurred trying load the description of the cluster service.", dwReturnValue ); break; } // if: we could not load the cluster service description string LogMsg( "The new cluster service description is '%ws'.", sszClusSvcDesc.PMem() ); // // Form the service binary path by appending the name of the cluster service executable to // the cluster service directory. // // Do not free the pointer returned by this call. dwReturnValue = TW32( DwGetClusterServiceDirectory( pcszInstallDir ) ); if ( dwReturnValue != NO_ERROR ) { LogMsg( "Error %#x occurred trying to determine the directory in which the cluster binaries are installed.", dwReturnValue ); break; } // if: we could not get the cluster service installation directory LogMsg( "The cluster service directory is '%ws'.", pcszInstallDir ); { WCHAR * pszTempPtr; // Length of the the install directory string, not including the terminating L'\0' size_t cchInstallDirLen = wcslen( pcszInstallDir ); // Length of the cluster service executable name, including the terminating L'\0' size_t cchClusSvcExeLen = RTL_NUMBER_OF( CLUSSVC_EXECUTABLE_NAME ); size_t cchRemaining = cchInstallDirLen + 1 + cchClusSvcExeLen; // Allocate memory for the cluster service binary path (the extra character is for the intervening L'\\'. sszClusSvcBinPath.Assign( new WCHAR[ cchInstallDirLen + 1 + cchClusSvcExeLen ] ); if ( sszClusSvcBinPath.FIsEmpty() ) { dwReturnValue = TW32( ERROR_NOT_ENOUGH_MEMORY ); LogMsg( "An error occurred trying to allocate memory for the cluster service binary path." ); break; } // if: an error occurred trying to allocate memory for the cluster service binary path pszTempPtr = sszClusSvcBinPath.PMem(); // Copy the install directory string to the newly allocated buffer. THR( StringCchCopyNExW( pszTempPtr, cchRemaining, pcszInstallDir, cchInstallDirLen, &pszTempPtr, &cchRemaining, 0 ) ); // Copy the trailing L'\\' character *(pszTempPtr++) = L'\\'; cchRemaining--; // Copy the cluster service executable name. THR( StringCchCopyNW( pszTempPtr, cchRemaining, CLUSSVC_EXECUTABLE_NAME, cchClusSvcExeLen ) ); LogMsg( "The new cluster service binary path is '%ws'.", sszClusSvcBinPath.PMem() ); } // Change the binary path, dependency list and display name. if ( ChangeServiceConfig( shClusSvc.HHandle() // handle to service , SERVICE_NO_CHANGE // type of service , SERVICE_NO_CHANGE // when to start service , SERVICE_NO_CHANGE // severity of start failure , sszClusSvcBinPath.PMem() // service binary file name , NULL // load ordering group name , NULL // tag identifier , CLUSSVC_DEPENDENCY_MULTISZ // array of dependency names , NULL // account name , NULL // account password , sszClusSvcDispName.PMem() // display name ) == FALSE ) { dwReturnValue = TW32( GetLastError() ); LogMsg( "Error %#x occurred trying to change the cluster service configuration.", dwReturnValue ); break; } // if: ChangeServiceConfig() failed LogMsg( "The cluster service binary path, dependency list and display name have been changed." ); // Change the service description { SERVICE_DESCRIPTION sdServiceDescription; sdServiceDescription.lpDescription = sszClusSvcDesc.PMem(); if ( ChangeServiceConfig2( shClusSvc.HHandle() // handle to service , SERVICE_CONFIG_DESCRIPTION // information level , &sdServiceDescription // new data ) == FALSE ) { dwReturnValue = TW32( GetLastError() ); LogMsg( "Error %#x occurred trying to change the cluster service description.", dwReturnValue ); break; } // if: ChangeServiceConfig2() failed } LogMsg( "The cluster service description has been changed." ); // Change the cluster service failure actions. dwReturnValue = TW32( ClRtlSetSCMFailureActions( NULL ) ); if ( dwReturnValue != ERROR_SUCCESS ) { LogMsg( "Error %#x occurred trying to set the cluster service failure actions.", dwReturnValue ); break; } // if: ClRtlSetSCMFailureActions() failed LogMsg( "The cluster service failure actions have been changed." ); LogMsg( "The cluster service configuration has been changed." ); break; } // while: the call to the base class function has succeeded LogMsg( "Return Value is %#x.", dwReturnValue ); RETURN( dwReturnValue ); } //*** CTaskUpgradeNT4::DwOcCompleteInstallation() ///////////////////////////////////////////////////////////////////////////// //++ // // DWORD // CTaskUpgradeNT4::DwOcCleanup // // Description: // This function handles the OC_CLEANUP messages from the // Optional Components Manager during an upgrade from Windows 2000. // // If an error has previously occurred during this task, cleanup operations // are performed. Otherwise nothing is done by this function. // // Arguments: // None. // // Return Value: // NO_ERROR if all went well. // Other Win32 error codes on failure. // //-- ///////////////////////////////////////////////////////////////////////////// DWORD CTaskUpgradeNT4::DwOcCleanup( void ) { TraceFunc( "" ); LogMsg( "Entering " __FUNCTION__ "()" ); DWORD dwReturnValue = NO_ERROR; // The base class helper function does everything that we need to do here. // So, just call it. dwReturnValue = TW32( BaseClass::DwOcCleanup( INF_SECTION_NT4_UPGRADE_CLEANUP ) ); LogMsg( "Return Value is %#x.", dwReturnValue ); RETURN( dwReturnValue ); } //*** CTaskUpgradeNT4::DwOcCleanup() ///////////////////////////////////////////////////////////////////////////// //++ // // DWORD // CTaskUpgradeNT4::DwSetDirectoryIds // // Description: // This function maps ids specified in the INF file to directories. // The cluster installation directory is got from the service control // manager, since it is possible the the cluster binaries are installed // in a non-default location. // // Arguments: // None. // // Return Value: // NO_ERROR if all went well. // Other Win32 error codes on failure. // //-- ///////////////////////////////////////////////////////////////////////////// DWORD CTaskUpgradeNT4::DwSetDirectoryIds() { TraceFunc( "" ); LogMsg( "Entering " __FUNCTION__ "()" ); DWORD dwReturnValue = NO_ERROR; do { const WCHAR * pcszInstallDir = NULL; // If we are here, the this node is already a part of a cluster. So, get the // installation directory from SCM. LogMsg( "This node is part of a cluster. Trying to determine the installation directory." ); // Do not free the pointer returned by this call. dwReturnValue = TW32( DwGetClusterServiceDirectory( pcszInstallDir ) ); if ( dwReturnValue != NO_ERROR ) { LogMsg( "Error %#x occurred trying to determine the directory in which the cluster binaries are installed.", dwReturnValue ); break; } // if: we could not get the cluster service installation directory LogMsg( "The cluster binaries are installed in the directory '%ws'.", pcszInstallDir ); // Create the mapping between the directory id and the path if ( SetupSetDirectoryId( RGetApp().RsicGetSetupInitComponent().ComponentInfHandle , CLUSTER_DEFAULT_INSTALL_DIRID , pcszInstallDir ) == FALSE ) { dwReturnValue = TW32( GetLastError() ); LogMsg( "Error %#x occurred trying set the cluster install directory id.", dwReturnValue ); break; } // if: SetupSetDirectoryId() failed LogMsg( "The id %d maps to '%ws'.", CLUSTER_DEFAULT_INSTALL_DIRID, pcszInstallDir ); } while ( false ); // dummy do-while loop to avoid gotos LogMsg( "Return Value is %#x.", dwReturnValue ); RETURN( dwReturnValue ); } //*** CTaskUpgradeNT4::DwSetDirectoryIds()