////////////////////////////////////////////////////////////////////////////// // // Copyright (c) 2000-2002 Microsoft Corporation // // Module Name: // CTaskUpgrade.cpp // // Description: // Implementation file for the CTaskUpgrade class. // // Header File: // CTaskUpgrade.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" #include // The header file for this module. #include "CTaskUpgrade.h" // For COM category operations #include // To define guid values #include // For CLSID_ClusCfgResTypeGenScript and CLSID_ClusCfgResTypeMajorityNodeSet #include // For CATID_ClusCfgStartupListeners #include ////////////////////////////////////////////////////////////////////////////// // Macro Definitions ////////////////////////////////////////////////////////////////////////////// // Needed for tracing. DEFINE_THISCLASS( "CTaskUpgrade" ) ///////////////////////////////////////////////////////////////////////////// //++ // // CTaskUpgrade::CTaskUpgrade // // Description: // Constructor of the CTaskUpgrade class. // // Arguments: // const CClusOCMApp & rAppIn // Reference to the CClusOCMApp object that is hosting this task. // // Return Value: // None. // //-- ///////////////////////////////////////////////////////////////////////////// CTaskUpgrade::CTaskUpgrade( const CClusOCMApp & rAppIn ) : BaseClass( rAppIn ) , m_fClusDirFound( false ) { TraceFunc( "" ); // // Make sure that this object is being instatiated only when required. // // Assert that this is an upgrade. Assert( rAppIn.FIsUpgrade() != false ); // Assert that we will upgrade binaries only if they were previously // installed Assert( rAppIn.CisGetClusterInstallState() != eClusterInstallStateUnknown ); TraceFuncExit(); } //*** CTaskUpgrade::CTaskUpgrade() ///////////////////////////////////////////////////////////////////////////// //++ // // CTaskUpgrade::~CTaskUpgrade // // Description: // Destructor of the CTaskUpgrade class. // // Arguments: // None. // // Return Value: // None. // //-- ///////////////////////////////////////////////////////////////////////////// CTaskUpgrade::~CTaskUpgrade( void ) { TraceFunc( "" ); TraceFuncExit(); } //*** CTaskUpgrade::~CTaskUpgrade() ///////////////////////////////////////////////////////////////////////////// //++ // // DWORD // CTaskUpgrade::DwOcCompleteInstallation // // Description: // This is a helper function that performs some of the more common // operations done by handlers of the OC_COMPLETE_INSTALLATION message. // // Registry operations, COM component registrations, creation of servies // etc. listed in the input section are processed by this function. // This function is meant to be called by derived classes only. // // Arguments: // const WCHAR * pcszInstallSectionNameIn // Name of the section which contains details registry entries, // COM components, etc., that need to be set up. // // Return Value: // NO_ERROR if all went well. // Other Win32 error codes on failure. // //-- ///////////////////////////////////////////////////////////////////////////// DWORD CTaskUpgrade::DwOcCompleteInstallation( const WCHAR * pcszInstallSectionNameIn ) { 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( pcszInstallSectionNameIn ) ); // // Register the Generic Script resource type extension for cluster startup notifications // if ( dwReturnValue == NO_ERROR ) { HRESULT hrTemp; TraceFlow( "Attempting to register the Generic Script resource type extension for cluster startup notifications." ); LogMsg( "Attempting to register the Generic Script resource type extension for cluster startup notifications." ); hrTemp = THR( HrRegisterForStartupNotifications( CLSID_ClusCfgResTypeGenScript ) ); if ( FAILED( hrTemp ) ) { // This is not a fatal error. So, log it and continue. TraceFlow1( "Non-fatal error %#x occurred registering the Generic Script resource type extension for cluster startup notifications." , hrTemp ); LogMsg( "Non-fatal error %#x occurred registering the Generic Script resource type extension for cluster startup notifications." , hrTemp ); } // if: we could not register the Generic Script resource type extension for cluster startup notifications else { TraceFlow( "Successfully registered the Generic Script resource type extension for cluster startup notifications." ); LogMsg( "Successfully registered the Generic Script resource type extension for cluster startup notifications." ); } // else: the registration was successful } // if: the call to the base class function succeeded // // Register the Majority Node Set resource type extension for cluster startup notifications // if ( dwReturnValue == NO_ERROR ) { HRESULT hrTemp; TraceFlow( "Attempting to register the Majority Node Set resource type extension for cluster startup notifications." ); LogMsg( "Attempting to register the Majority Node Set resource type extension for cluster startup notifications." ); hrTemp = THR( HrRegisterForStartupNotifications( CLSID_ClusCfgResTypeMajorityNodeSet ) ); if ( FAILED( hrTemp ) ) { // This is not a fatal error. So, log it and continue. TraceFlow1( "Non-fatal error %#x occurred registering the Majority Node Set resource type extension for cluster startup notifications." , hrTemp ); LogMsg( "Non-fatal error %#x occurred registering the Majority Node Set resource type extension for cluster startup notifications." , hrTemp ); } // if: we could not register the Majority Node Set resource type extension for cluster startup notifications else { TraceFlow( "Successfully registered the Majority Node Set resource type extension for cluster startup notifications." ); LogMsg( "Successfully registered the Majority Node Set resource type extension for cluster startup notifications." ); } // else: the registration was successful } // if: the call to the base class function succeeded TraceFlow1( "Return Value is %#x.", dwReturnValue ); LogMsg( "Return Value is %#x.", dwReturnValue ); RETURN( dwReturnValue ); } //*** CTaskUpgrade::DwOcCompleteInstallation() ///////////////////////////////////////////////////////////////////////////// //++ // // DWORD // CTaskUpgrade::DwGetClusterServiceDirectory // // Description: // This function returns a pointer to the directory in which the cluster // service binaries are installed. This memory pointed to by this pointer // should not be freed by the caller. // // Arguments: // const WCHAR *& rpcszDirNamePtrIn // Reference to the pointer to install directory. The caller should not // free this memory. // // Return Value: // NO_ERROR if all went well. // Other Win32 error codes on failure. // //-- ///////////////////////////////////////////////////////////////////////////// DWORD CTaskUpgrade::DwGetClusterServiceDirectory( const WCHAR *& rpcszDirNamePtrIn ) { TraceFunc( "" ); LogMsg( "Entering " __FUNCTION__ "()" ); DWORD dwReturnValue = NO_ERROR; // Check if we have already got the cluster service directory. If we already have, // then return this value. while( !m_fClusDirFound ) { // Instantiate a smart pointer to the QUERY_SERVICE_CONFIG structure. typedef CSmartGenericPtr< CPtrTrait< QUERY_SERVICE_CONFIG > > SmartServiceConfig; // Connect to the Service Control Manager SmartServiceHandle shServiceMgr( OpenSCManager( NULL, NULL, GENERIC_READ ) ); // Some arbitrary value. DWORD cbServiceConfigBufSize = 256; // Was the service control manager database opened successfully? if ( shServiceMgr.HHandle() == NULL ) { dwReturnValue = TW32( GetLastError() ); TraceFlow1( "Error %#x occurred trying to open a connection to the local service control manager.", dwReturnValue ); 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. SmartServiceHandle shService( OpenService( shServiceMgr, L"ClusSvc", GENERIC_READ ) ); // Was the handle to the service opened? if ( shService.HHandle() == NULL ) { dwReturnValue = TW32( GetLastError() ); TraceFlow1( "Error %#x occurred trying to open a handle to the cluster service.", dwReturnValue ); LogMsg( "Error %#x occurred trying to open a handle to the cluster service.", dwReturnValue ); break; } // if: the handle could not be opened do { DWORD cbRequiredSize = 0; // Allocate memory for the service configuration info buffer. The memory is automatically freed when the // object is destroyed. SmartServiceConfig spscServiceConfig( reinterpret_cast< QUERY_SERVICE_CONFIG * >( new BYTE[ cbServiceConfigBufSize ] ) ); // Did the memory allocation succeed if ( spscServiceConfig.FIsEmpty() ) { dwReturnValue = TW32( ERROR_NOT_ENOUGH_MEMORY ); TraceFlow( "Error: There was not enough memory to get the cluster service configuration information." ); LogMsg( "Error: There was not enough memory to get the cluster service configuration information." ); break; } // if: memory allocation failed // Get the configuration information. if ( QueryServiceConfig( shService.HHandle() , spscServiceConfig.PMem() , cbServiceConfigBufSize , &cbRequiredSize ) == FALSE ) { dwReturnValue = GetLastError(); if ( dwReturnValue != ERROR_INSUFFICIENT_BUFFER ) { TW32( dwReturnValue ); TraceFlow1( "Error %#x occurred trying to get the cluster service configuration information.", dwReturnValue ); LogMsg( "Error %#x occurred trying to get the cluster service configuration information.", dwReturnValue ); break; } // if: something has really gone wrong // We need to allocate more memory - try again dwReturnValue = NO_ERROR; cbServiceConfigBufSize = cbRequiredSize; } // if: QueryServiceConfig() failed else { // Find the last backslash character in the service binary path. WCHAR * pszPathName = spscServiceConfig.PMem()->lpBinaryPathName; WCHAR * pszLastBackslash = wcsrchr( pszPathName, L'\\' ); if ( pszLastBackslash != NULL ) { // Terminate the string here. *pszLastBackslash = L'\0'; } // if: we found the last backslash // Move the service binary path to the beginning of the buffer. MoveMemory( spscServiceConfig.PMem(), pszPathName, ( wcslen( pszPathName ) + 1 ) * sizeof( *pszPathName ) ); // Store the pointer to the buffer in the member variable and // detach this memory from the smart pointer (this will not delete the memory). m_sszClusterServiceDir.Assign( reinterpret_cast< WCHAR * >( spscServiceConfig.PRelease() ) ); // Indicate the we have successfully found the cluster service directory. m_fClusDirFound = true; break; } // else: QueryServiceConfig() has succeeded } while( true ); // while: loop infinitely // We are done break; } // Initialize the output. rpcszDirNamePtrIn = m_sszClusterServiceDir.PMem(); LogMsg( "Return Value is %#x.", dwReturnValue ); TraceFlow1( "Return Value is %#x.", dwReturnValue ); RETURN( dwReturnValue ); } //*** CTaskUpgrade::DwGetClusterServiceDirectory() ///////////////////////////////////////////////////////////////////////////// //++ // // HRESULT // CTaskUpgrade::HrRegisterForStartupNotifications // // Description: // This function registers a COM component for receiving cluster startup // notifications. // // Arguments: // const CLSID & rclsidComponentIn // Reference to the CLSID of the component that is to receive cluster // startup notifications. // // Return Value: // S_OK if all went well. // Other HRESULTS failure. // //-- ///////////////////////////////////////////////////////////////////////////// HRESULT CTaskUpgrade::HrRegisterForStartupNotifications( const CLSID & rclsidComponentIn ) { TraceFunc( "" ); LogMsg( "Entering " __FUNCTION__ "()" ); HRESULT hr = S_OK; CoInitializeEx( NULL, COINIT_MULTITHREADED ); do { CSmartIfacePtr< ICatRegister > spcrCatReg; { ICatRegister * pcrCatReg = NULL; hr = THR( CoCreateInstance( CLSID_StdComponentCategoriesMgr , NULL , CLSCTX_INPROC_SERVER , __uuidof( pcrCatReg ) , reinterpret_cast< void ** >( &pcrCatReg ) ) ); if ( FAILED( hr ) ) { LogMsg( "Error %#x occurred trying to create the StdComponentCategoriesMgr component.", hr ); TraceFlow1( "Error %#x occurred trying to create the StdComponentCategoriesMgr component.", hr ); break; } // if: we could not create the StdComponentCategoriesMgr component // Assign to a smart pointer for automatic release. spcrCatReg.Attach( pcrCatReg ); } { CATID rgCatId[ 1 ]; rgCatId[ 0 ] = CATID_ClusCfgStartupListeners; hr = THR( spcrCatReg->RegisterClassImplCategories( rclsidComponentIn, ARRAYSIZE( rgCatId ), rgCatId ) ); if ( FAILED( hr ) ) { LogMsg( "Error %#x occurred trying to register the component for cluster startup notifications.", hr ); TraceFlow1( "Error %#x occurred during the call to ICatRegister::UnRegisterClassImplCategories().", hr ); break; } // if: we could not register the component for startup notifications } LogMsg( "Successfully registered for startup notifications." ); TraceFlow( "Successfully registered for startup notifications." ); } while( false ); // dummy do-while loop to avoid gotos CoUninitialize(); LogMsg( "Return Value is %#x.", hr ); TraceFlow1( "Return Value is %#x.", hr ); HRETURN( hr ); } //*** CTaskUpgrade::HrRegisterForStartupNotifications()