////////////////////////////////////////////////////////////////////////////// // // Copyright (c) 2000-2001 Microsoft Corporation // // Module Name: // TaskAnalyzeCluster.cpp // // Description: // CTaskAnalyzeCluster implementation. // // Maintained By: // Galen Barbee (GalenB) 02-FEB-2000 // ////////////////////////////////////////////////////////////////////////////// #include "pch.h" #include "TaskAnalyzeCluster.h" #include "ManagedDevice.h" #include // For CsRpcGetJoinVersionData() and constants like JoinVersion_v2_0_c_ifspec #include #include DEFINE_THISCLASS( "CTaskAnalyzeCluster" ) // // Failure code. // #define SSR_ANALYSIS_FAILED( _major, _minor, _hr ) \ { \ HRESULT hrTemp; \ BSTR bstrNotification = NULL; \ THR( HrLoadStringIntoBSTR( g_hInstance, IDS_ERR_ANALYSIS_FAILED_TRY_TO_REANALYZE, &bstrNotification ) ); \ hrTemp = THR( SendStatusReport( NULL, _major, _minor, 0, 1, 1, _hr, bstrNotification, NULL, NULL ) ); \ TraceSysFreeString( bstrNotification ); \ if ( FAILED( hrTemp ) ) \ { \ _hr = hrTemp; \ } \ } //**************************************************************************** // // Constants // //**************************************************************************** #define CHECKING_TIMEOUT 90 // seconds // ************************************************************************ // // Constructor / Destructor // // ************************************************************************ ////////////////////////////////////////////////////////////////////////////// // // HRESULT // CTaskAnalyzeCluster::S_HrCreateInstance( // IUnknown ** ppunkOut // ) // ////////////////////////////////////////////////////////////////////////////// HRESULT CTaskAnalyzeCluster::S_HrCreateInstance( IUnknown ** ppunkOut ) { TraceFunc( "" ); Assert( ppunkOut != NULL ); HRESULT hr; CTaskAnalyzeCluster * ptac = new CTaskAnalyzeCluster; if ( ptac != NULL ) { hr = THR( ptac->Init() ); if ( SUCCEEDED( hr ) ) { hr = THR( ptac->TypeSafeQI( IUnknown, ppunkOut ) ); } ptac->Release(); } else { hr = E_OUTOFMEMORY; } HRETURN( hr ); } //*** CTaskAnalyzeCluster::S_HrCreateInstance() ////////////////////////////////////////////////////////////////////////////// // // CTaskAnalyzeCluster::CTaskAnalyzeCluster( void ) // ////////////////////////////////////////////////////////////////////////////// CTaskAnalyzeCluster::CTaskAnalyzeCluster( void ) { TraceFunc( "" ); InterlockedIncrement( &g_cObjects ); TraceFuncExit(); } //*** CTaskAnalyzeCluster::CTaskAnalyzeCluster() ////////////////////////////////////////////////////////////////////////////// // // STDMETHODIMP // CTaskAnalyzeCluster::Init( void ) // ////////////////////////////////////////////////////////////////////////////// STDMETHODIMP CTaskAnalyzeCluster::Init( void ) { TraceFunc( "" ); HRESULT hr = S_OK; // IUnknown stuff Assert( m_cRef == 0 ); AddRef(); // Add one count // IDoTask / ITaskAnalyzeCluster Assert( m_cookieCompletion == 0 ); Assert( m_pcccb == NULL ); Assert( m_pcookies == NULL ); Assert( m_cNodes == 0 ); Assert( m_event == NULL ); Assert( m_cookieCluster == NULL ); Assert( m_fJoiningMode == FALSE ); Assert( m_cUserNodes == 0 ); Assert( m_pcookiesUser == NULL ); Assert( m_pnui == NULL ); Assert( m_pom == NULL ); Assert( m_ptm == NULL ); Assert( m_pcm == NULL ); Assert( m_fStop == false ); // INotifyUI Assert( m_cSubTasksDone == 0 ); Assert( m_hrStatus == 0 ); hr = HrGetComputerName( ComputerNameNetBIOS, &m_bstrNodeName ); HRETURN( hr ); } // Init() ////////////////////////////////////////////////////////////////////////////// // // CTaskAnalyzeCluster::~CTaskAnalyzeCluster( void ) // ////////////////////////////////////////////////////////////////////////////// CTaskAnalyzeCluster::~CTaskAnalyzeCluster( void ) { TraceFunc( "" ); // m_cRef // m_cookieCompletion if ( m_pcccb != NULL ) { m_pcccb->Release(); } if ( m_pcookies != NULL ) { THR( HrFreeCookies() ); } // m_cCookies // m_cNodes if ( m_event != NULL ) { CloseHandle( m_event ); } // m_cookieCluster TraceMoveFromMemoryList( m_bstrClusterName, g_GlobalMemoryList ); TraceSysFreeString( m_bstrClusterName ); TraceSysFreeString( m_bstrNodeName ); // m_fJoiningMode // m_cUserNodes if ( m_pcookiesUser != NULL ) { TraceFree( m_pcookiesUser ); } if ( m_pnui != NULL ) { m_pnui->Release(); } if ( m_pom != NULL ) { m_pom->Release(); } if ( m_ptm != NULL ) { m_ptm->Release(); } if ( m_pcm != NULL ) { m_pcm->Release(); } // if: TraceSysFreeString( m_bstrQuorumUID ); // m_cSubTasksDone // m_hrStatus InterlockedDecrement( &g_cObjects ); TraceFuncExit(); } //*** CTaskAnalyzeCluster::~CTaskAnalyzeCluster() // ************************************************************************ // // IUnknown // // ************************************************************************ ////////////////////////////////////////////////////////////////////////////// // // STDMETHODIMP // CTaskAnalyzeCluster::QueryInterface( // REFIID riidIn, // LPVOID * ppvOut // ) // ////////////////////////////////////////////////////////////////////////////// STDMETHODIMP CTaskAnalyzeCluster::QueryInterface( REFIID riidIn, LPVOID * ppvOut ) { TraceQIFunc( riidIn, ppvOut ); HRESULT hr = E_NOINTERFACE; if ( IsEqualIID( riidIn, IID_IUnknown ) ) { *ppvOut = static_cast< ITaskAnalyzeCluster * >( this ); hr = S_OK; } // if: IUnknown else if ( IsEqualIID( riidIn, IID_ITaskAnalyzeCluster ) ) { *ppvOut = TraceInterface( __THISCLASS__, ITaskAnalyzeCluster, this, 0 ); hr = S_OK; } // else if: ITaskAnalyzeCluster else if ( IsEqualIID( riidIn, IID_IDoTask ) ) { *ppvOut = TraceInterface( __THISCLASS__, IDoTask, this, 0 ); hr = S_OK; } // else if: IDoTask else if ( IsEqualIID( riidIn, IID_IClusCfgCallback ) ) { *ppvOut = TraceInterface( __THISCLASS__, IClusCfgCallback, this, 0 ); hr = S_OK; } // else if: IClusCfgCallback else if ( IsEqualIID( riidIn, IID_INotifyUI ) ) { *ppvOut = TraceInterface( __THISCLASS__, INotifyUI, this, 0 ); hr = S_OK; } // else if: INotifyUI if ( SUCCEEDED( hr ) ) { ((IUnknown*) *ppvOut)->AddRef(); } // if: success QIRETURN_IGNORESTDMARSHALLING( hr, riidIn ); } //*** CTaskAnalyzeCluster::QueryInterface() ////////////////////////////////////////////////////////////////////////////// // // STDMETHODIMP_( ULONG ) // CTaskAnalyzeCluster::AddRef( void ) // ////////////////////////////////////////////////////////////////////////////// STDMETHODIMP_( ULONG ) CTaskAnalyzeCluster::AddRef( void ) { TraceFunc( "[IUnknown]" ); InterlockedIncrement( &m_cRef ); RETURN( m_cRef ); } //*** CTaskAnalyzeCluster::AddRef() ////////////////////////////////////////////////////////////////////////////// // // STDMETHODIMP_( ULONG ) // CTaskAnalyzeCluster::Release( void ) // ////////////////////////////////////////////////////////////////////////////// STDMETHODIMP_( ULONG ) CTaskAnalyzeCluster::Release( void ) { TraceFunc( "[IUnknown]" ); LONG cRef; InterlockedDecrement( &m_cRef ); cRef = m_cRef; if ( cRef == 0 ) { TraceDo( delete this ); } RETURN( cRef ); } //*** CTaskAnalyzeCluster::Release() // ************************************************************************ // // IDoTask / ITaskAnalyzeCluster // // ************************************************************************ ////////////////////////////////////////////////////////////////////////////// // // STDMETHODIMP // CTaskAnalyzeCluster::BeginTask( void ); // ////////////////////////////////////////////////////////////////////////////// STDMETHODIMP CTaskAnalyzeCluster::BeginTask( void ) { TraceFunc( "[IDoTask]" ); HRESULT hr; DWORD dwCookie = 0; IServiceProvider * psp = NULL; IConnectionPointContainer * pcpc = NULL; IConnectionPoint * pcp = NULL; TraceInitializeThread( L"TaskAnalyzeCluster" ); // // Gather the managers we need to complete the task. // hr = THR( CoCreateInstance( CLSID_ServiceManager, NULL, CLSCTX_INPROC_SERVER, TypeSafeParams( IServiceProvider, &psp ) ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Checking_For_Existing_Cluster, TASKID_Minor_BeginTask_CoCreate_Service_Manager, hr ); goto Cleanup; } Assert( m_pnui == NULL ); Assert( m_ptm == NULL ); Assert( m_pom == NULL ); hr = THR( psp->TypeSafeQS( CLSID_NotificationManager, IConnectionPointContainer, &pcpc ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Checking_For_Existing_Cluster, TASKID_Minor_BeginTask_QueryService_Notification_Manager, hr ); goto Cleanup; } hr = THR( pcpc->FindConnectionPoint( IID_INotifyUI, &pcp ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Checking_For_Existing_Cluster, TASKID_Minor_BeginTask_NotificationMan_FindConnectionPoint, hr ); goto Cleanup; } pcp = TraceInterface( L"CTaskAnalyzeCluster!IConnectionPoint", IConnectionPoint, pcp, 1 ); hr = THR( pcp->TypeSafeQI( INotifyUI, &m_pnui ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Checking_For_Existing_Cluster, TASKID_Minor_BeginTask_NotificationMan_FindConnectionPoint_QI_INotifyUI, hr ); goto Cleanup; } hr = THR( psp->TypeSafeQS( CLSID_TaskManager, ITaskManager, &m_ptm ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Checking_For_Existing_Cluster, TASKID_Minor_BeginTask_QueryService_TaskManager, hr ); goto Cleanup; } hr = THR( psp->TypeSafeQS( CLSID_ObjectManager, IObjectManager, &m_pom ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Checking_For_Existing_Cluster, TASKID_Minor_BeginTask_QueryService_ObjectManager, hr ); goto Cleanup; } hr = THR( psp->TypeSafeQS( CLSID_ClusterConnectionManager, IConnectionManager, &m_pcm ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Checking_For_Existing_Cluster, TASKID_Minor_BeginTask_QueryService_ConnectionManager, hr ); goto Cleanup; } // if: // // Release the Service Manager. // psp->Release(); psp = NULL; // // Create an event to wait upon. // m_event = CreateEvent( NULL, TRUE, FALSE, NULL ); if ( m_event == NULL ) goto Win32Error; // // Register with the Notification Manager to get notified. // Assert( m_cCookies == 0 && m_pcookies == NULL && m_cSubTasksDone == 0 ); hr = THR( pcp->Advise( static_cast< INotifyUI * >( this ), &dwCookie ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Establish_Connection, TASKID_Minor_BeginTask_Advise, hr ); goto Cleanup; } // // Wait for the cluster connection to stablize. // hr = STHR( HrWaitForClusterConnection() ); if ( FAILED( hr ) ) goto Cleanup; if ( FAILED( m_hrStatus ) ) { hr = THR( m_hrStatus ); goto Cleanup; } Assert( m_bstrClusterName != NULL ); // // Tell the UI layer we are starting this task. // hr = THR( SendStatusReport( NULL, TASKID_Major_Establish_Connection, TASKID_Minor_Update_Progress, 0, CHECKING_TIMEOUT, 0, S_OK, NULL, NULL, NULL ) ); if ( FAILED( hr ) ) { goto Cleanup; } // if: // // Count the number of nodes to be analyzed. // hr = STHR( HrCountNumberOfNodes() ); if ( FAILED( hr ) ) goto Cleanup; if ( FAILED( m_hrStatus ) ) { hr = THR( m_hrStatus ); goto Cleanup; } // // Create separate tasks to gather node information. // hr = STHR( HrCreateSubTasksToGatherNodeInfo() ); if ( FAILED( hr ) ) goto Cleanup; if ( FAILED( m_hrStatus ) ) { hr = THR( m_hrStatus ); goto Cleanup; } // // Tell the UI layer we have completed this task. // hr = THR( SendStatusReport( NULL, TASKID_Major_Establish_Connection, TASKID_Minor_Update_Progress, 0, CHECKING_TIMEOUT, CHECKING_TIMEOUT, S_OK, NULL, NULL, NULL ) ); if ( FAILED( hr ) ) { goto Cleanup; } // if: // // Create separate tasks to gather node resources and networks. // hr = STHR( HrCreateSubTasksToGatherNodeResourcesAndNetworks() ); if ( FAILED( hr ) ) goto Cleanup; if ( FAILED( m_hrStatus ) ) { hr = THR( m_hrStatus ); goto Cleanup; } // // Count the number of nodes to be analyzed again. TaskGatherInformation // will delete the cookies of unresponsive nodes. // hr = STHR( HrCountNumberOfNodes() ); if ( FAILED( hr ) ) goto Cleanup; if ( FAILED( m_hrStatus ) ) { hr = THR( m_hrStatus ); goto Cleanup; } // // Create the feasibility task. // hr = STHR( HrCheckClusterFeasibility() ); if ( FAILED( hr ) ) goto Cleanup; if ( FAILED( m_hrStatus ) ) { hr = THR( m_hrStatus ); goto Cleanup; } Cleanup: if ( psp != NULL ) { psp->Release(); } if ( pcpc != NULL ) { pcpc->Release(); } if ( pcp != NULL ) { HRESULT hr2; hr2 = THR( pcp->Unadvise( dwCookie ) ); if ( FAILED( hr2 ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Client_And_Server_Log, TASKID_Minor_BeginTask_Unadvise, hr2 ); } pcp->Release(); } if ( m_cookieCompletion != 0 ) { if ( m_pom != NULL ) { HRESULT hr2; IUnknown * punk; hr2 = THR( m_pom->GetObject( DFGUID_StandardInfo, m_cookieCompletion, &punk ) ); if ( SUCCEEDED( hr2 ) ) { IStandardInfo * psi; hr2 = THR( punk->TypeSafeQI( IStandardInfo, &psi ) ); punk->Release(); if ( SUCCEEDED( hr2 ) ) { hr2 = THR( psi->SetStatus( hr ) ); psi->Release(); } else { SSR_ANALYSIS_FAILED( TASKID_Major_Client_And_Server_Log, TASKID_Minor_BeginTask_SetStatus, hr2 ); } } else { SSR_ANALYSIS_FAILED( TASKID_Major_Client_And_Server_Log, TASKID_Minor_BeginTask_GetObject, hr2 ); } } if ( m_pnui != NULL ) { // // Have the notification manager signal the completion cookie. // HRESULT hr2 = THR( m_pnui->ObjectChanged( m_cookieCompletion ) ); if ( FAILED( hr2 ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Client_And_Server_Log, TASKID_Minor_BeginTask_ObjectChanged, hr2 ); } } m_cookieCompletion = 0; } HRETURN( hr ); Win32Error: hr = THR( HRESULT_FROM_WIN32( GetLastError() ) ); SSR_ANALYSIS_FAILED( TASKID_Major_Client_And_Server_Log, TASKID_Minor_BeginTask_Win32Error, hr ); goto Cleanup; } //*** CTaskAnalyzeCluster::BeginTask() ////////////////////////////////////////////////////////////////////////////// // // STDMETHODIMP // CTaskAnalyzeCluster::StopTask( void ) // ////////////////////////////////////////////////////////////////////////////// STDMETHODIMP CTaskAnalyzeCluster::StopTask( void ) { TraceFunc( "[IDoTask]" ); HRESULT hr = S_OK; LogMsg( L"[MT] The client has requested that this task, TaskAnalyzeCluster, be canceled" ); m_fStop = true; HRETURN( hr ); } //*** CTaskAnalyzeCluster::StopTask() ////////////////////////////////////////////////////////////////////////////// // // STDMETHODIMP // CTaskAnalyzeCluster::SetJoiningMode( void ) // ////////////////////////////////////////////////////////////////////////////// STDMETHODIMP CTaskAnalyzeCluster::SetJoiningMode( void ) { TraceFunc( "[ITaskAnalyzeCluster]" ); HRESULT hr = S_OK; m_fJoiningMode = TRUE; HRETURN( hr ); } //*** CTaskAnalyzeCluster::SetJoiningMode() ////////////////////////////////////////////////////////////////////////////// // // STDMETHODIMP // CTaskAnalyzeCluster::SetCookie( // OBJECTCOOKIE cookieIn // ) // ////////////////////////////////////////////////////////////////////////////// STDMETHODIMP CTaskAnalyzeCluster::SetCookie( OBJECTCOOKIE cookieIn ) { TraceFunc( "[ITaskAnalyzeCluster]" ); HRESULT hr = S_OK; m_cookieCompletion = cookieIn; HRETURN( hr ); } //*** CTaskAnalyzeCluster::SetCookie() ////////////////////////////////////////////////////////////////////////////// // // STDMETHODIMP // CTaskAnalyzeCluster::SetClusterCookie( // OBJECTCOOKIE cookieClusterIn // ) // ////////////////////////////////////////////////////////////////////////////// STDMETHODIMP CTaskAnalyzeCluster::SetClusterCookie( OBJECTCOOKIE cookieClusterIn ) { TraceFunc( "[ITaskAnalyzeCluster]" ); HRESULT hr = S_OK; m_cookieCluster = cookieClusterIn; HRETURN( hr ); } //*** CTaskAnalyzeCluster::SetClusterCookie() //**************************************************************************** // // IClusCfgCallback // //**************************************************************************** ////////////////////////////////////////////////////////////////////////////// // // STDMETHODIMP // CTaskAnalyzeCluster::SendStatusReport( // LPCWSTR pcszNodeNameIn // , CLSID clsidTaskMajorIn // , CLSID clsidTaskMinorIn // , ULONG ulMinIn // , ULONG ulMaxIn // , ULONG ulCurrentIn // , HRESULT hrStatusIn // , LPCWSTR pcszDescriptionIn // , FILETIME * pftTimeIn // , LPCWSTR pcszReferenceIn // ) // ////////////////////////////////////////////////////////////////////////////// STDMETHODIMP CTaskAnalyzeCluster::SendStatusReport( LPCWSTR pcszNodeNameIn , CLSID clsidTaskMajorIn , CLSID clsidTaskMinorIn , ULONG ulMinIn , ULONG ulMaxIn , ULONG ulCurrentIn , HRESULT hrStatusIn , LPCWSTR pcszDescriptionIn , FILETIME * pftTimeIn , LPCWSTR pcszReferenceIn ) { TraceFunc( "[IClusCfgCallback]" ); HRESULT hr = S_OK; IServiceProvider * psp = NULL; IConnectionPointContainer * pcpc = NULL; IConnectionPoint * pcp = NULL; FILETIME ft; if ( m_pcccb == NULL ) { // // Collect the manager we need to complete this task. // hr = THR( CoCreateInstance( CLSID_ServiceManager, NULL, CLSCTX_INPROC_SERVER, TypeSafeParams( IServiceProvider, &psp ) ) ); if ( FAILED( hr ) ) goto Cleanup; hr = THR( psp->TypeSafeQS( CLSID_NotificationManager, IConnectionPointContainer, &pcpc ) ); if ( FAILED( hr ) ) goto Cleanup; hr = THR( pcpc->FindConnectionPoint( IID_IClusCfgCallback, &pcp ) ); if ( FAILED( hr ) ) goto Cleanup; pcp = TraceInterface( L"CConfigurationConnection!IConnectionPoint", IConnectionPoint, pcp, 1 ); hr = THR( pcp->TypeSafeQI( IClusCfgCallback, &m_pcccb ) ); if ( FAILED( hr ) ) goto Cleanup; m_pcccb = TraceInterface( L"CConfigurationConnection!IClusCfgCallback", IClusCfgCallback, m_pcccb, 1 ); psp->Release(); psp = NULL; } if ( pftTimeIn == NULL ) { GetSystemTimeAsFileTime( &ft ); pftTimeIn = &ft; } // if: // // Send the message! // hr = THR( m_pcccb->SendStatusReport( pcszNodeNameIn != NULL ? pcszNodeNameIn : m_bstrNodeName , clsidTaskMajorIn , clsidTaskMinorIn , ulMinIn , ulMaxIn , ulCurrentIn , hrStatusIn , pcszDescriptionIn , pftTimeIn , pcszReferenceIn ) ); if ( m_fStop ) { hr = E_ABORT; } // if: Cleanup: if ( psp != NULL ) { psp->Release(); } if ( pcpc != NULL ) { pcpc->Release(); } if ( pcp != NULL ) { pcp->Release(); } HRETURN( hr ); } //*** CTaskAnalyzeCluster::SendStatusReport() //**************************************************************************** // // INotifyUI // //**************************************************************************** ////////////////////////////////////////////////////////////////////////////// // // STDMETHODIMP // CTaskAnalyzeCluster::ObjectChanged( // OBJECTCOOKIE cookieIn // ) // ////////////////////////////////////////////////////////////////////////////// STDMETHODIMP CTaskAnalyzeCluster::ObjectChanged( OBJECTCOOKIE cookieIn ) { TraceFunc( "[INotifyUI]" ); BOOL b; ULONG cCookies; HRESULT hr = S_OK; Assert( cookieIn != 0 ); for ( cCookies = 0; cCookies < m_cCookies; cCookies ++ ) { Assert( m_pcookies != NULL ); if ( cookieIn == m_pcookies[ cCookies ] ) { // // Make sure it won't be signalled twice. // OBJECTCOOKIE cookie = m_pcookies[ cCookies ]; m_pcookies[ cCookies ] = NULL; // don't care if this fails, but it really shouldn't THR( m_pom->RemoveObject( cookie ) ); InterlockedIncrement( reinterpret_cast< long * >( &m_cSubTasksDone ) ); if ( m_cSubTasksDone == m_cCookies ) { // // Signal the event if all the nodes are done. // b = SetEvent( m_event ); if ( !b ) goto Win32Error; } // if: all done } // if: matched cookie } // for: cCookies Cleanup: HRETURN( hr ); Win32Error: hr = THR( HRESULT_FROM_WIN32( GetLastError() ) ); SSR_ANALYSIS_FAILED( TASKID_Major_Client_And_Server_Log, TASKID_Minor_ObjectChanged_Win32Error, hr ); goto Cleanup; } //*** CTaskAnalyzeCluster::ObjectChanged() //**************************************************************************** // // Private // //**************************************************************************** ////////////////////////////////////////////////////////////////////////////// // // HRESULT // CTaskAnalyzeCluster::HrWaitForClusterConnection( void ) // ////////////////////////////////////////////////////////////////////////////// HRESULT CTaskAnalyzeCluster::HrWaitForClusterConnection( void ) { TraceFunc( "" ); HRESULT hrStatus; ULONG ulCurrent; DWORD sc; OBJECTCOOKIE * pcookies; HRESULT hr = S_OK; BSTR bstrDescription = NULL; IUnknown * punk = NULL; ITaskGatherClusterInfo * ptgci = NULL; IStandardInfo * psi = NULL; // // Tell the UI layer that we are starting to search for an existing cluster. // THR( HrLoadStringIntoBSTR( g_hInstance, IDS_TASKID_MAJOR_CHECKING_FOR_EXISTING_CLUSTER, &bstrDescription ) ); hr = THR( SendStatusReport( NULL, TASKID_Major_Checking_For_Existing_Cluster, TASKID_Minor_Update_Progress, 0, CHECKING_TIMEOUT, 0, S_OK, bstrDescription, NULL, NULL ) ); if ( FAILED( hr ) ) goto Cleanup; // // Get the cluster name // hr = THR( m_pom->GetObject( DFGUID_StandardInfo, m_cookieCluster, &punk ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Checking_For_Existing_Cluster, TASKID_Minor_WaitForCluster_GetObject, hr ); goto Cleanup; } hr = THR( punk->TypeSafeQI( IStandardInfo, &psi ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Checking_For_Existing_Cluster, TASKID_Minor_WaitForCluster_GetObject_QI, hr ); goto Cleanup; } psi = TraceInterface( L"TaskAnalyzeCluster!IStandardInfo", IStandardInfo, psi, 1 ); punk->Release(); punk = NULL; // // Retrieve the cluster's name. // hr = THR( psi->GetName( &m_bstrClusterName ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Checking_For_Existing_Cluster, TASKID_Minor_WaitForCluster_GetName, hr ); goto Cleanup; } TraceMemoryAddBSTR( m_bstrClusterName ); TraceMoveToMemoryList( m_bstrClusterName, g_GlobalMemoryList ); // // Create a completion cookie list. // Assert( m_cCookies == 0 ); Assert( m_pcookies == NULL ); Assert( m_cSubTasksDone == 0 ); m_pcookies = reinterpret_cast< OBJECTCOOKIE * >( TraceAlloc( 0, sizeof( OBJECTCOOKIE ) ) ); if ( m_pcookies == NULL ) goto OutOfMemory; hr = THR( m_pom->FindObject( CLSID_ClusterCompletionCookie, m_cookieCluster, m_bstrClusterName, IID_NULL, &m_pcookies[ 0 ], &punk ) ); Assert( punk == NULL ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Checking_For_Existing_Cluster, TASKID_Minor_WaitForCluster_CreateCompletionCookie, hr ); goto Cleanup; } m_cCookies = 1; // // Create the task object. // hr = THR( m_ptm->CreateTask( TASK_GatherClusterInfo, &punk ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Checking_For_Existing_Cluster, TASKID_Minor_WaitForCluster_CreateTask, hr ); goto Cleanup; } Assert( punk != NULL ); hr = THR( punk->TypeSafeQI( ITaskGatherClusterInfo, &ptgci ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Checking_For_Existing_Cluster, TASKID_Minor_WaitForCluster_CreateTask_QI, hr ); goto Cleanup; } punk->Release(); punk = NULL; // // Set the object cookie in the task. // hr = THR( ptgci->SetCookie( m_cookieCluster ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Checking_For_Existing_Cluster, TASKID_Minor_WaitForCluster_SetCookie, hr ); goto Cleanup; } hr = THR( ptgci->SetCompletionCookie( m_pcookies[ 0 ] ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Checking_For_Existing_Cluster, TASKID_Minor_WaitForCluster_SetCompletionCookie, hr ); goto Cleanup; } // // Submit the task. // hr = THR( m_ptm->SubmitTask( ptgci ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Checking_For_Existing_Cluster, TASKID_Minor_WaitForCluster_SubmitTask, hr ); goto Cleanup; } // // Now wait for the work to be done. // for ( ulCurrent = 0, sc = WAIT_OBJECT_0 + 1 ; sc != WAIT_OBJECT_0 ; ) { MSG msg; while( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) ) { TranslateMessage( &msg ); DispatchMessage( &msg ); } sc = MsgWaitForMultipleObjectsEx( 1, &m_event, 1000, // 1 second QS_ALLEVENTS | QS_ALLINPUT | QS_ALLPOSTMESSAGE, 0 ); // // Tell the UI layer that we are still searching for the cluster. BUT // don't let the progress reach 100% if it is taking longer than // CHECKING_TIMEOUT seconds. // if ( ulCurrent != CHECKING_TIMEOUT ) { ulCurrent ++; Assert( ulCurrent != CHECKING_TIMEOUT ); hr = THR( SendStatusReport( NULL, TASKID_Major_Checking_For_Existing_Cluster, TASKID_Minor_Update_Progress, 0, CHECKING_TIMEOUT, ulCurrent, S_OK, NULL, NULL, NULL ) ); if ( FAILED( hr ) ) goto Cleanup; } } // for: sc != WAIT_OBJECT_0 // // Cleanup the completion cookies // THR( HrFreeCookies() ); // // Check out the status of the cluster. // hr = THR( psi->GetStatus( &hrStatus ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Checking_For_Existing_Cluster, TASKID_Minor_WaitForCluster_GetStatus, hr ); goto Cleanup; } // // If we are in joining mode and can't connect to the cluster, this // should be deemed a bad thing! // if ( m_fJoiningMode ) { // // JOINING // switch ( hrStatus ) { case S_OK: // // This is what we are expecting. // break; case HR_S_RPC_S_SERVER_UNAVAILABLE: { // // If we failed to connect to the server.... // THR( HrLoadStringIntoBSTR( g_hInstance, IDS_TASKID_MINOR_CLUSTER_NOT_FOUND, &bstrDescription ) ); hr = THR( SendStatusReport( m_bstrClusterName, TASKID_Major_Checking_For_Existing_Cluster, TASKID_Minor_Cluster_Not_Found, 0, CHECKING_TIMEOUT, CHECKING_TIMEOUT, HRESULT_FROM_WIN32( RPC_S_SERVER_UNAVAILABLE ), bstrDescription, NULL, NULL ) ); hr = THR( HRESULT_FROM_WIN32( RPC_S_SERVER_UNAVAILABLE ) ); } goto Cleanup; default: { // // If something else goes wrong, stop. // hr = THR( HrLoadStringIntoBSTR( g_hInstance, IDS_TASKID_MINOR_ERROR_CONTACTING_CLUSTER, &bstrDescription ) ); hr = THR( SendStatusReport( m_bstrClusterName, TASKID_Major_Checking_For_Existing_Cluster, TASKID_Minor_Error_Contacting_Cluster, 0, CHECKING_TIMEOUT, CHECKING_TIMEOUT, hrStatus, bstrDescription, NULL, NULL ) ); hr = THR( hrStatus ); } goto Cleanup; } // switch: hrStatus } // if: joining else { // // FORMING // switch ( hrStatus ) { case HR_S_RPC_S_SERVER_UNAVAILABLE: // // This is what we are expecting. // break; case HRESULT_FROM_WIN32( ERROR_CONNECTION_REFUSED ): case REGDB_E_CLASSNOTREG: case E_ACCESSDENIED: case S_OK: { // // If we are forming and we find an existing cluster with the same name // that we trying to form, we shouldn't let the user continue. // // NOTE that some error conditions indicate that "something" is hosting // the cluster name. // hr = THR( HrFormatStringIntoBSTR( g_hInstance , IDS_TASKID_MINOR_EXISTING_CLUSTER_FOUND , &bstrDescription , m_bstrClusterName ) ); hr = THR( SendStatusReport( m_bstrClusterName, TASKID_Major_Checking_For_Existing_Cluster, TASKID_Minor_Existing_Cluster_Found, 0, CHECKING_TIMEOUT, CHECKING_TIMEOUT, HRESULT_FROM_WIN32( ERROR_DUP_NAME ), bstrDescription, NULL, NULL ) ); hr = THR( HRESULT_FROM_WIN32( ERROR_DUP_NAME ) ); } goto Cleanup; default: { // // If something else goes wrong, stop. // hr = THR( HrLoadStringIntoBSTR( g_hInstance, IDS_TASKID_MINOR_ERROR_CONTACTING_CLUSTER, &bstrDescription ) ); hr = THR( SendStatusReport( m_bstrClusterName, TASKID_Major_Checking_For_Existing_Cluster, TASKID_Minor_Error_Contacting_Cluster, 0, CHECKING_TIMEOUT, CHECKING_TIMEOUT, hrStatus, bstrDescription, NULL, NULL ) ); hr = THR( hrStatus ); } goto Cleanup; } // switch: hrStatus } // else: forming if ( m_fJoiningMode ) { // // Memorize the cookies of the objects that the user entered. // hr = THR( HrGetUsersNodesCookies() ); if ( FAILED( hr ) ) goto Cleanup; // // Create cookies for the existing nodes. // hr = THR( HrAddJoinedNodes() ); if ( FAILED( hr ) ) goto Cleanup; } // // Tell the UI layer that we are done searching for the cluster. // hr = THR( SendStatusReport( NULL, TASKID_Major_Checking_For_Existing_Cluster, TASKID_Minor_Update_Progress, 0, CHECKING_TIMEOUT, CHECKING_TIMEOUT, S_OK, NULL, NULL, NULL ) ); if ( FAILED( hr ) ) goto Cleanup; Cleanup: if ( punk != NULL ) { punk->Release(); } if ( psi != NULL ) { psi->Release(); } TraceSysFreeString( bstrDescription ); if ( ptgci != NULL ) { ptgci->Release(); } HRETURN( hr ); OutOfMemory: hr = E_OUTOFMEMORY; SSR_ANALYSIS_FAILED( TASKID_Major_Checking_For_Existing_Cluster, TASKID_Minor_WaitForCluster_OutOfMemory, hr ); goto Cleanup; } //*** CTaskAnalyzeCluster::HrWaitForClusterConnection() ////////////////////////////////////////////////////////////////////////////// // // HRESULT // CTaskAnalyzeCluster::HrCountNumberOfNodes( void ) // ////////////////////////////////////////////////////////////////////////////// HRESULT CTaskAnalyzeCluster::HrCountNumberOfNodes() { TraceFunc( "" ); HRESULT hr; OBJECTCOOKIE cookie; OBJECTCOOKIE cookieDummy; IUnknown * punk = NULL; IEnumCookies * pec = NULL; // // Make sure all the node object that (will) make up the cluster // are in a stable state. // hr = THR( m_pom->FindObject( CLSID_NodeType, m_cookieCluster, NULL, DFGUID_EnumCookies, &cookieDummy, &punk ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Establish_Connection, TASKID_Minor_CountNodes_FindObject, hr ); goto Cleanup; } hr = THR( punk->TypeSafeQI( IEnumCookies, &pec ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Establish_Connection, TASKID_Minor_CountNodes_FindObject_QI, hr ); goto Cleanup; } pec = TraceInterface( L"CTaskAnalyzeCluster!IEnumCookies", IEnumCookies, pec, 1 ); punk->Release(); punk = NULL; // While we're checking the node's statuses, we'll also count how // many nodes there are. m_cNodes = 0; Assert( hr == S_OK ); while ( hr == S_OK ) { HRESULT hrStatus; ULONG celtDummy; hr = STHR( pec->Next( 1, &cookie, &celtDummy ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Establish_Connection, TASKID_Minor_CountNodes_EnumNodes_Next, hr ); goto Cleanup; } if ( hr == S_FALSE ) break; // exit condition m_cNodes ++; } // while: hr == S_OK if ( hr == S_FALSE) { hr = S_OK; } Cleanup: if ( punk != NULL ) { punk->Release(); } if ( pec != NULL ) { pec->Release(); } HRETURN( hr ); } //*** CTaskAnalyzeCluster::HrCountNumberOfNodes() ////////////////////////////////////////////////////////////////////////////// // // HRESULT // HrCreateSubTasksToGatherNodeInfo( void ) // ////////////////////////////////////////////////////////////////////////////// HRESULT CTaskAnalyzeCluster::HrCreateSubTasksToGatherNodeInfo( void ) { TraceFunc( "" ); HRESULT hr; ULONG cNode; ULONG cNodesToProcess; ULONG ulCurrent; DWORD sc; OBJECTCOOKIE cookie; OBJECTCOOKIE cookieDummy; OBJECTCOOKIE cookieNode; BSTR bstrName = NULL; BSTR bstrNotification = NULL; IUnknown * punk = NULL; IConnectionPoint * pcp = NULL; IClusCfgNodeInfo * pccni = NULL; IEnumCookies * pec = NULL; ITaskGatherNodeInfo * ptgni = NULL; IStandardInfo * psi = NULL; IStandardInfo ** psiCompletion = NULL; Assert( m_hrStatus == S_OK ); // // Get the enum of the nodes. // hr = THR( m_pom->FindObject( CLSID_NodeType, m_cookieCluster, NULL, DFGUID_EnumCookies, &cookieDummy, &punk ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Establish_Connection, TASKID_Minor_CreateNodeTasks_FindObject, hr ); goto Cleanup; } hr = THR( punk->TypeSafeQI( IEnumCookies, &pec ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Establish_Connection, TASKID_Minor_CreateNodeTasks_FindObject_QI, hr ); goto Cleanup; } pec = TraceInterface( L"CTaskAnalyzeCluster!IEnumCookies", IEnumCookies, pec, 1 ); punk->Release(); punk = NULL; // // Allocate a buffer to collect cookies // Assert( m_cCookies == 0 ); Assert( m_pcookies == NULL ); Assert( m_cSubTasksDone == 0 ); m_pcookies = reinterpret_cast< OBJECTCOOKIE * >( TraceAlloc( 0, m_cNodes * sizeof( OBJECTCOOKIE ) ) ); if ( m_pcookies == NULL ) goto OutOfMemory; // // KB: gpease 29-NOV-2000 // Create a list of "interesting" completion cookie StandardInfo-s. If any of the // statuses return from this list are FAILED, then abort the analysis. // psiCompletion = reinterpret_cast< IStandardInfo ** >( TraceAlloc( HEAP_ZERO_MEMORY, m_cNodes * sizeof( IStandardInfo * ) ) ); if ( psiCompletion == NULL ) goto OutOfMemory; // // Loop thru the nodes, creating cookies and allocating a gather task for // that node. // for ( cNode = 0; cNode < m_cNodes; cNode ++ ) { LPWSTR psz; ULONG celtDummy; ULONG idx; BOOL fFound; // // Grab the next node. // hr = STHR( pec->Next( 1, &cookieNode, &celtDummy ) ); if ( hr == S_FALSE ) break; // exit condition if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Establish_Connection, TASKID_Minor_CreateNodeTasks_EnumNodes_Next, hr ); goto Cleanup; } // // Get the nodes name. We are using this to distinguish one nodes // completion cookie from another. It might also make debugging // easier (??). // hr = THR( m_pom->GetObject( DFGUID_NodeInformation, cookieNode, &punk ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Establish_Connection, TASKID_Minor_CreateNodeTasks_EnumNodes_GetObject, hr ); goto Cleanup; } hr = THR( punk->TypeSafeQI( IClusCfgNodeInfo, &pccni ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Establish_Connection, TASKID_Minor_CreateNodeTasks_EnumNodes_GetObject_QI, hr ); goto Cleanup; } punk->Release(); punk = NULL; hr = THR( pccni->GetName( &bstrName ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Establish_Connection, TASKID_Minor_CreateNodeTasks_EnumNodes_GetName, hr ); goto Cleanup; } TraceMemoryAddBSTR( bstrName ); // // Create a completion cookie. // hr = THR( m_pom->FindObject( IID_NULL, m_cookieCluster, bstrName, DFGUID_StandardInfo, &m_pcookies[ cNode ], &punk ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Establish_Connection, TASKID_Minor_CreateNodeTasks_EnumNodes_CompletionCookie_FindObject, hr ); goto Cleanup; } // // Increment the cookie counter. // m_cCookies ++; // // See if this node is one of the user entered nodes. // if ( !m_fJoiningMode ) { // // All nodes are "interesting" during a form operation. // Assert( m_cUserNodes == 0 ); Assert( m_pcookiesUser == NULL ); fFound = TRUE; } else { // // Only the nodes the user entered are interesting during a join operation. // for ( fFound = FALSE, idx = 0; idx < m_cUserNodes; idx ++ ) { if ( m_pcookiesUser[ idx ] == cookieNode ) { fFound = TRUE; break; } } } if ( fFound ) { hr = THR( punk->TypeSafeQI( IStandardInfo, &psiCompletion[ cNode ] ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Establish_Connection, TASKID_Minor_CreateNodeTasks_EnumNodes_CompletionCookie_FindObject_QI, hr ); goto Cleanup; } } else { Assert( psiCompletion[ cNode ] == NULL ); } punk->Release(); punk = NULL; // // Create a task to gather this nodes information. // hr = THR( m_ptm->CreateTask( TASK_GatherNodeInfo, &punk ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Establish_Connection, TASKID_Minor_CreateNodeTasks_EnumNodes_CreateTask, hr ); goto Cleanup; } hr = THR( punk->TypeSafeQI( ITaskGatherNodeInfo, &ptgni ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Establish_Connection, TASKID_Minor_CreateNodeTasks_EnumNodes_QI_GatherNodeInfo, hr ); goto Cleanup; } punk->Release(); punk = NULL; // // Set the tasks completion cookie. // hr = THR( ptgni->SetCompletionCookie( m_pcookies[ cNode ] ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Establish_Connection, TASKID_Minor_CreateNodeTasks_EnumNodes_SetCompletionCookie, hr ); goto Cleanup; } // // Tell it what node it is suppose to gather information from. // hr = THR( ptgni->SetCookie( cookieNode ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Establish_Connection, TASKID_Minor_CreateNodeTasks_EnumNodes_SetCookie, hr ); goto Cleanup; } // // Submit the task. // hr = THR( m_ptm->SubmitTask( ptgni ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Establish_Connection, TASKID_Minor_CreateNodeTasks_EnumNodes_SubmitTask, hr ); goto Cleanup; } // // Cleanup for the next node. // pccni->Release(); pccni = NULL; TraceSysFreeString( bstrName ); bstrName = NULL; ptgni->Release(); ptgni = NULL; } // while: looping thru nodes Assert( m_cCookies == m_cNodes ); // // Reset the signal event. // { BOOL bRet = ResetEvent( m_event ); Assert( bRet ); } // // Now wait for the work to be done. // for ( ulCurrent = 0, sc = WAIT_OBJECT_0 + 1 ; sc != WAIT_OBJECT_0 ; ) { MSG msg; while( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) ) { TranslateMessage( &msg ); DispatchMessage( &msg ); } sc = MsgWaitForMultipleObjectsEx( 1, &m_event, INFINITE, QS_ALLEVENTS | QS_ALLINPUT | QS_ALLPOSTMESSAGE, 0 ); if ( ulCurrent != CHECKING_TIMEOUT ) { ulCurrent ++; Assert( ulCurrent != CHECKING_TIMEOUT ); hr = THR( SendStatusReport( NULL, TASKID_Major_Establish_Connection, TASKID_Minor_Update_Progress, 0, CHECKING_TIMEOUT, ulCurrent, S_OK, NULL, NULL, NULL ) ); if ( FAILED( hr ) ) goto Cleanup; } } // while: sc == WAIT_OBJECT_0 // // Now check the results using the list of completion cookie StandardInfo-s // built earlier of interesting objects. If any of these "interesting" cookies // return a FAILED status, then abort the analysis. // for ( cNode = 0, cNodesToProcess = 0; cNode < m_cNodes; cNode++ ) { HRESULT hrStatus; if ( psiCompletion[ cNode ] == NULL ) continue; hr = THR( psiCompletion[ cNode ]->GetStatus( &hrStatus ) ); if ( FAILED( hrStatus ) ) { hr = THR( hrStatus ); goto Cleanup; } if ( hrStatus == S_OK ) { cNodesToProcess++; } // if: } // for: cNode if ( cNodesToProcess == 0 ) { BSTR bstr = NULL; hr = HRESULT_FROM_WIN32( TW32( ERROR_NODE_NOT_AVAILABLE ) ); THR( HrLoadStringIntoBSTR( g_hInstance, IDS_TASKID_MINOR_NO_NODES_TO_PROCESS, &bstr ) ); THR( SendStatusReport( bstrName , TASKID_Major_Establish_Connection , TASKID_Minor_No_Nodes_To_Process , 0 , 1 , 1 , hr , bstr , NULL , NULL ) ); TraceSysFreeString( bstr ); goto Cleanup; } // if: hr = S_OK; Cleanup: THR( HrFreeCookies() ); TraceSysFreeString( bstrName ); TraceSysFreeString( bstrNotification ); if ( punk != NULL ) { punk->Release(); } if ( pccni != NULL ) { pccni->Release(); } if ( pec != NULL ) { pec->Release(); } if ( ptgni != NULL ) { ptgni->Release(); } if ( psi != NULL ) { psi->Release(); } if ( psiCompletion != NULL ) { for ( cNode = 0; cNode < m_cNodes; cNode++ ) { if ( psiCompletion[ cNode ] != NULL ) { psiCompletion[ cNode ]->Release(); } } TraceFree( psiCompletion ); } HRETURN( hr ); //Win32Error: hr = HRESULT_FROM_WIN32( TW32( GetLastError() ) ); SSR_ANALYSIS_FAILED( TASKID_Major_Establish_Connection, TASKID_Minor_CreateNodeTasks_Win32Error, hr ); goto Cleanup; OutOfMemory: hr = E_OUTOFMEMORY; SSR_ANALYSIS_FAILED( TASKID_Major_Establish_Connection, TASKID_Minor_CreateNodeTasks_OutOfMemory, hr ); goto Cleanup; } //*** CTaskAnalyzeCluster::HrCreateSubTasksToGatherNodeInfo() ////////////////////////////////////////////////////////////////////////////// // // HRESULT // HrCreateSubTasksToGatherNodeResourcesAndNetworks( void ) // ////////////////////////////////////////////////////////////////////////////// HRESULT CTaskAnalyzeCluster::HrCreateSubTasksToGatherNodeResourcesAndNetworks( void ) { TraceFunc( "" ); HRESULT hr; ULONG idxNode; ULONG ulCurrent; DWORD sc; OBJECTCOOKIE cookie; OBJECTCOOKIE cookieDummy; OBJECTCOOKIE cookieNode; OBJECTCOOKIE * pcookies; BSTR bstrName = NULL; BSTR bstrNotification = NULL; IUnknown * punk = NULL; IConnectionPoint * pcp = NULL; IClusCfgNodeInfo * pccni = NULL; IEnumCookies * pec = NULL; ITaskGatherInformation * ptgi = NULL; IStandardInfo * psi = NULL; IStandardInfo ** ppsiStatuses = NULL; Assert( m_hrStatus == S_OK ); // // Tell the UI layer we are starting to retrieve the resources/networks. // hr = THR( SendStatusReport( NULL, TASKID_Major_Find_Devices, TASKID_Minor_Update_Progress, 0, CHECKING_TIMEOUT, 0, S_OK, NULL, NULL, NULL ) ); if ( FAILED( hr ) ) goto Cleanup; // // Get the enum of the nodes. // hr = THR( m_pom->FindObject( CLSID_NodeType, m_cookieCluster, NULL, DFGUID_EnumCookies, &cookieDummy, &punk ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Find_Devices, TASKID_Minor_GatherInformation_FindObject, hr ); goto Cleanup; } hr = THR( punk->TypeSafeQI( IEnumCookies, &pec ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Find_Devices, TASKID_Minor_GatherInformation_FindObject_QI, hr ); goto Cleanup; } pec = TraceInterface( L"CTaskAnalyzeCluster!IEnumCookies", IEnumCookies, pec, 1 ); punk->Release(); punk = NULL; // // Allocate a buffer to collect cookies // Assert( m_cCookies == 0 ); Assert( m_pcookies == NULL ); Assert( m_cSubTasksDone == 0 ); m_pcookies = reinterpret_cast< OBJECTCOOKIE * >( TraceAlloc( 0, m_cNodes * sizeof( OBJECTCOOKIE ) ) ); if ( m_pcookies == NULL ) goto OutOfMemory; ppsiStatuses = reinterpret_cast< IStandardInfo ** >( TraceAlloc( 0, m_cNodes * sizeof( IStandardInfo * ) ) ); if ( ppsiStatuses == NULL ) goto OutOfMemory; // // Loop thru the nodes, creating cookies and allocating a gather task for // that node. // for ( idxNode = 0 ; idxNode < m_cNodes ; idxNode++ ) { LPWSTR psz; ULONG celtDummy; // // Grab the next node. // hr = STHR( pec->Next( 1, &cookieNode, &celtDummy ) ); if ( hr == S_FALSE ) break; // exit condition if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Find_Devices, TASKID_Minor_GatherInformation_EnumNodes_Next, hr ); goto Cleanup; } // // Get the node's name. We are using this to distinguish one node's // completion cookie from another. It might also make debugging // easier (??). // hr = THR( m_pom->GetObject( DFGUID_NodeInformation, cookieNode, &punk ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Find_Devices, TASKID_Minor_GatherInformation_EnumNodes_GetObject, hr ); goto Cleanup; } hr = THR( punk->TypeSafeQI( IClusCfgNodeInfo, &pccni ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Find_Devices, TASKID_Minor_GatherInformation_EnumNodes_GetObject_QI, hr ); goto Cleanup; } punk->Release(); punk = NULL; hr = THR( pccni->GetName( &bstrName ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Find_Devices, TASKID_Minor_GatherInformation_EnumNodes_GetName, hr ); goto Cleanup; } TraceMemoryAddBSTR( bstrName ); // // Create a completion cookie. // hr = THR( m_pom->FindObject( IID_NULL, m_cookieCluster, bstrName, DFGUID_StandardInfo, &m_pcookies[ idxNode ], &punk ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Find_Devices, TASKID_Minor_GatherInformation_EnumNodes_CompletionCookie_FindObject, hr ); goto Cleanup; } hr = THR( punk->TypeSafeQI( IStandardInfo, &ppsiStatuses[ idxNode ] ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Find_Devices, TASKID_Minor_GatherInformation_EnumNodes_CompletionCookie_FindObject_QI, hr ); goto Cleanup; } punk->Release(); punk = NULL; // // Increment the cookie counter. // m_cCookies ++; // // Create a task to gather this node's information. // hr = THR( m_ptm->CreateTask( TASK_GatherInformation, &punk ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Find_Devices, TASKID_Minor_GatherInformation_EnumNodes_CreateTask, hr ); goto Cleanup; } TraceMoveFromMemoryList( punk, g_GlobalMemoryList ); hr = THR( punk->TypeSafeQI( ITaskGatherInformation, &ptgi ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Find_Devices, TASKID_Minor_GatherInformation_EnumNodes_QI_GatherNodeInfo, hr ); goto Cleanup; } punk->Release(); punk = NULL; // // Set the tasks completion cookie. // hr = THR( ptgi->SetCompletionCookie( m_pcookies[ idxNode ] ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Find_Devices, TASKID_Minor_GatherInformation_EnumNodes_SetCompletionCookie, hr ); goto Cleanup; } // // Tell it what node it is suppose to gather information from. // hr = THR( ptgi->SetNodeCookie( cookieNode ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Find_Devices, TASKID_Minor_GatherInformation_EnumNodes_SetCookie, hr ); goto Cleanup; } // // Tell it if we are joining or not. // if ( m_fJoiningMode ) { hr = THR( ptgi->SetJoining() ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Find_Devices, TASKID_Minor_GatherInformation_EnumNodes_SetJoining, hr ); goto Cleanup; } } // // Submit the task. // hr = THR( m_ptm->SubmitTask( ptgi ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Find_Devices, TASKID_Minor_GatherInformation_EnumNodes_SubmitTask, hr ); goto Cleanup; } // // Cleanup for the next node. // pccni->Release(); pccni = NULL; TraceSysFreeString( bstrName ); bstrName = NULL; ptgi->Release(); ptgi = NULL; } // while: looping thru nodes Assert( m_cCookies == m_cNodes ); // // Reset the signal event. // { BOOL bRet = ResetEvent( m_event ); Assert( bRet ); } // // Now wait for the work to be done. // for ( ulCurrent = 0, sc = WAIT_OBJECT_0 + 1 ; sc != WAIT_OBJECT_0 ; ) { MSG msg; while( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) ) { TranslateMessage( &msg ); DispatchMessage( &msg ); } sc = MsgWaitForMultipleObjectsEx( 1, &m_event, INFINITE, QS_ALLEVENTS | QS_ALLINPUT | QS_ALLPOSTMESSAGE, 0 ); if ( ulCurrent != CHECKING_TIMEOUT ) { ulCurrent ++; Assert( ulCurrent != CHECKING_TIMEOUT ); hr = THR( SendStatusReport( NULL, TASKID_Major_Find_Devices, TASKID_Minor_Update_Progress, 0, CHECKING_TIMEOUT, ulCurrent, S_OK, NULL, NULL, NULL ) ); if ( FAILED( hr ) ) goto Cleanup; } } // while: sc == WAIT_OBJECT_0 // // See if anything went wrong. // for ( idxNode = 0 ; idxNode < m_cNodes ; idxNode++ ) { HRESULT hrStatus; if ( ppsiStatuses[ idxNode ] == NULL ) continue; hr = THR( ppsiStatuses[ idxNode ]->GetStatus( &hrStatus ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Find_Devices, TASKID_Minor_GatherInformation_GetStatus, hr ); goto Cleanup; } if ( FAILED( hrStatus ) ) { hr = THR( hrStatus ); goto Cleanup; } } // // Tell the UI we are done. // hr = THR( SendStatusReport( NULL , TASKID_Major_Find_Devices , TASKID_Minor_Update_Progress , 0 , CHECKING_TIMEOUT , CHECKING_TIMEOUT , S_OK , NULL , NULL , NULL ) ); Cleanup: THR( HrFreeCookies() ); TraceSysFreeString( bstrName ); TraceSysFreeString( bstrNotification ); if ( punk != NULL ) { punk->Release(); } if ( pccni != NULL ) { pccni->Release(); } if ( pec != NULL ) { pec->Release(); } if ( ptgi != NULL ) { ptgi->Release(); } if ( psi != NULL ) { psi->Release(); } if ( ppsiStatuses != NULL ) { for ( idxNode = 0 ; idxNode < m_cNodes ; idxNode++ ) { if ( ppsiStatuses[ idxNode ] != NULL ) { ppsiStatuses[ idxNode ]->Release(); } } TraceFree( ppsiStatuses ); } HRETURN( hr ); //Win32Error: hr = HRESULT_FROM_WIN32( TW32( GetLastError() ) ); SSR_ANALYSIS_FAILED( TASKID_Major_Find_Devices, TASKID_Minor_GatherInformation_Win32Error, hr ); goto Cleanup; OutOfMemory: hr = E_OUTOFMEMORY; SSR_ANALYSIS_FAILED( TASKID_Major_Find_Devices, TASKID_Minor_GatherInformation_OutOfMemory, hr ); goto Cleanup; } //*** CTaskAnalyzeCluster::HrCreateSubTasksToGatherNodeResourcesAndNetworks() ////////////////////////////////////////////////////////////////////////////// // // HRESULT // CTaskAnalyzeCluster::HrCheckClusterFeasibility( void ) // ////////////////////////////////////////////////////////////////////////////// HRESULT CTaskAnalyzeCluster::HrCheckClusterFeasibility( void ) { TraceFunc( "" ); HRESULT hr; BOOL fNeedToCheckMembership = FALSE; IEnumNodes * pen = NULL; IClusCfgNodeInfo * pccni = NULL; // // Notify the UI layer that we have started. // hr = THR( SendStatusReport( NULL, TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_Update_Progress, 0, 5, 0, S_OK, NULL, NULL, NULL ) ); if ( FAILED( hr ) ) goto Cleanup; // // Check membership. // hr = THR( HrCheckClusterMembership() ); if ( FAILED( hr ) ) goto Cleanup; hr = THR( SendStatusReport( NULL, TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_Update_Progress, 0, 5, 1, S_OK, NULL, NULL, NULL ) ); if ( FAILED( hr ) ) goto Cleanup; // // Check version interoperability. // hr = STHR( HrCheckInteroperability() ); if ( FAILED( hr ) ) goto Cleanup; hr = THR( SendStatusReport( NULL, TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_Update_Progress, 0, 5, 2, S_OK, NULL, NULL, NULL ) ); if ( FAILED( hr ) ) goto Cleanup; // // Compare the devices. // hr = THR( HrCompareResources() ); if ( FAILED( hr ) ) goto Cleanup; hr = THR( SendStatusReport( NULL, TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_Update_Progress, 0, 5, 3, S_OK, NULL, NULL, NULL ) ); if ( FAILED( hr ) ) goto Cleanup; // // Compare the networks. // hr = THR( HrCompareNetworks() ); if ( FAILED( hr ) ) goto Cleanup; hr = THR( SendStatusReport( NULL, TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_Update_Progress, 0, 5, 4, S_OK, NULL, NULL, NULL ) ); if ( FAILED( hr ) ) goto Cleanup; // // Now check to see if the nodes can all see the selected quorum resource. // hr = THR( HrCheckForCommonQuorumResource() ); if ( FAILED( hr ) ) goto Cleanup; // // Notify the UI layer that we are done. // hr = THR( SendStatusReport( NULL, TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_Update_Progress, 0, 5, 5, S_OK, NULL, NULL, NULL ) ); Cleanup: if ( pen != NULL ) { pen->Release(); } if ( pccni != NULL ) { pccni->Release(); } HRETURN( hr ); } //*** CTaskAnalyzeCluster::HrCheckClusterFeasibility() ////////////////////////////////////////////////////////////////////////////// // // HRESULT // CTaskAnalyzeCluster::HrAddJoinedNodes( void ) // ////////////////////////////////////////////////////////////////////////////// HRESULT CTaskAnalyzeCluster::HrAddJoinedNodes( void ) { TraceFunc( "" ); HRESULT hr; ULONG idx; DWORD dw; DWORD dwType; DWORD cchName; WCHAR szName[ DNS_MAX_NAME_BUFFER_LENGTH ]; OBJECTCOOKIE cookieDummy; LPWSTR pszDomain; BSTR bstrFQDNName = NULL; BSTR bstrBindingString = NULL; HCLUSTER hCluster = NULL; HCLUSENUM hClusEnum = NULL; IUnknown * punkDummy = NULL; IUnknown * punk = NULL; IClusCfgServer * piccs = NULL; // CLSID clsidLog; // CopyMemory( &clsidLog, &TASKID_Major_Establish_Connection, sizeof( clsidLog ) ); hr = THR( m_pcm->GetConnectionToObject( m_cookieCluster, &punk ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_HrAddJoinedNodes_GetConnectionObject, hr ); goto Cleanup; } // if: hr = THR( punk->TypeSafeQI( IClusCfgServer, &piccs ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_HrAddJoinedNodes_ConfigConnection_QI, hr ); goto Cleanup; } // if: hr = THR( piccs->GetBindingString( &bstrBindingString ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_HrAddJoinedNodes_GetBindingString, hr ); goto Cleanup; } // if: TraceMemoryAddBSTR( bstrBindingString ); pszDomain = wcschr( m_bstrClusterName, L'.' ); // we don't need to move past the dot. hCluster = OpenCluster( bstrBindingString ); if ( hCluster == NULL ) { hr = HRESULT_FROM_WIN32( TW32( GetLastError() ) ); SSR_ANALYSIS_FAILED( TASKID_Major_Establish_Connection, TASKID_Minor_AddJoinedNodes_OpenCluster, hr ); goto Cleanup; } hClusEnum = ClusterOpenEnum( hCluster, CLUSTER_ENUM_NODE ); if ( hClusEnum == NULL ) { hr = HRESULT_FROM_WIN32( TW32( GetLastError() ) ); SSR_ANALYSIS_FAILED( TASKID_Major_Establish_Connection, TASKID_Minor_AddJoinedNodes_ClusterOpenEnum, hr ); goto Cleanup; } for ( idx = 0; ; idx ++ ) { // // Cleanup // TraceSysFreeString( bstrFQDNName ); bstrFQDNName = NULL; // TraceSysFreeString( bstrBindingString ); // bstrBindingString = NULL; // // Get the next node name from the cluster. // cchName = ARRAYSIZE( szName ); // can't wrap can return ERROR_NO_MORE_ITEMS. dw = ClusterEnum( hClusEnum, idx, &dwType, szName, &cchName ); if ( dw == ERROR_NO_MORE_ITEMS ) break; // exit condition if ( dw != ERROR_SUCCESS ) { hr = HRESULT_FROM_WIN32( TW32( dw ) ); SSR_ANALYSIS_FAILED( TASKID_Major_Establish_Connection, TASKID_Minor_AddJoinedNodes_ClusterEnum, hr ); goto Cleanup; } // // Build the FQDN name of the node. // cchName += wcslen( pszDomain ) + 1 /* NULL */; bstrFQDNName = TraceSysAllocStringLen( NULL, cchName ); if ( bstrFQDNName == NULL ) goto OutOfMemory; wcscpy( bstrFQDNName, szName ); wcscat( bstrFQDNName, pszDomain ); // hr = THR( HrCreateBinding( this, &clsidLog, bstrFQDNName, &bstrBindingString ) ); // if ( FAILED( hr ) ) // { // hr = HR_S_RPC_S_SERVER_UNAVAILABLE; // goto Cleanup; // } // // Prime the object manager to retrieve the node information. // // can't wrap - should return E_PENDING hr = m_pom->FindObject( CLSID_NodeType, m_cookieCluster, bstrFQDNName, DFGUID_NodeInformation, &cookieDummy, &punkDummy ); if ( FAILED( hr ) ) { Assert( punkDummy == NULL ); if ( hr == E_PENDING ) { continue; // expected error } THR( hr ); SSR_ANALYSIS_FAILED( TASKID_Major_Establish_Connection, TASKID_Minor_AddJoinedNodes_FindObject, hr ); goto Cleanup; } punkDummy->Release(); punkDummy = NULL; } // for: idx hr = S_OK; Cleanup: Assert( punkDummy == NULL ); TraceSysFreeString( bstrFQDNName ); TraceSysFreeString( bstrBindingString ); if ( punk != NULL ) { punk->Release(); } // if: if ( piccs != NULL ) { piccs->Release(); } if ( hClusEnum != NULL ) { ClusterCloseEnum( hClusEnum ); } if ( hCluster != NULL ) { CloseCluster( hCluster ); } HRETURN( hr ); OutOfMemory: hr = E_OUTOFMEMORY; SSR_ANALYSIS_FAILED( TASKID_Major_Establish_Connection, TASKID_Minor_AddJoinedNodes_OutOfMemory, hr ); goto Cleanup; } //*** CTaskAnalyzeCluster::HrAddJoinedNodes() ////////////////////////////////////////////////////////////////////////////// // // HRESULT // CTaskAnalyzeCluster::HrCheckClusterMembership( void ) // // ERROR_CLUSTER_NODE_EXISTS // ERROR_CLUSTER_NODE_ALREADY_MEMBER // ////////////////////////////////////////////////////////////////////////////// HRESULT CTaskAnalyzeCluster::HrCheckClusterMembership( void ) { TraceFunc( "" ); HRESULT hr; OBJECTCOOKIE cookieDummy; IClusCfgClusterInfo * pccci; BSTR bstrNodeName = NULL; BSTR bstrClusterName = NULL; BSTR bstrNotification = NULL; IUnknown * punk = NULL; IEnumNodes * pen = NULL; IClusCfgNodeInfo * pccni = NULL; // // Ask the object manager for the node enumerator. // hr = THR( m_pom->FindObject( CLSID_NodeType, m_cookieCluster, NULL, DFGUID_EnumNodes,&cookieDummy, &punk ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_CheckMembership_FindObject, hr ); goto Cleanup; } hr = THR( punk->TypeSafeQI( IEnumNodes, &pen ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_CheckMembership_FindObject_QI, hr ); goto Cleanup; } // // If we are joining an existing cluster, make sure that all the other // nodes are members of the same cluster. // Assert( SUCCEEDED( hr ) ); while ( SUCCEEDED( hr ) ) { ULONG celtDummy; // // Cleanup // if ( pccni != NULL ) { pccni->Release(); pccni = NULL; } TraceSysFreeString( bstrClusterName ); bstrClusterName = NULL; // // Get the next node. // hr = STHR( pen->Next( 1, &pccni, &celtDummy ) ); if ( hr == S_FALSE ) break; // exit condition if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_CheckMembership_EnumNode_Next, hr ); goto Cleanup; } // // Check to see if we need to "form a cluster" by seeing if any // of the nodes are already clustered. // hr = STHR( pccni->IsMemberOfCluster() ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_CheckMembership_EnumNode_IsMemberOfCluster, hr ); goto Cleanup; } if ( hr == S_OK ) { // // Retrieve the name and make sure they match. // hr = THR( pccni->GetClusterConfigInfo( &pccci ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_CheckMembership_EnumNode_GetClusterConfigInfo, hr ); goto Cleanup; } hr = THR( pccci->GetName( &bstrClusterName ) ); pccci->Release(); // release promptly if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_CheckMembership_EnumNode_GetName, hr ); goto Cleanup; } TraceMemoryAddBSTR( bstrClusterName ); hr = THR( pccni->GetName( &bstrNodeName ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_CheckMembership_EnumNode_GetNodeName, hr ); goto Cleanup; } TraceMemoryAddBSTR( bstrNodeName ); if ( StrCmpI( m_bstrClusterName, bstrClusterName ) != 0 ) { // // They don't match! Tell the UI layer! // hr = THR( pccni->GetName( &bstrNodeName ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_CheckMembership_EnumNode_GetNodeName, hr ); goto Cleanup; } TraceMemoryAddBSTR( bstrNodeName ); hr = THR( HrFormatMessageIntoBSTR( g_hInstance, IDS_TASKID_MINOR_CLUSTER_NAME_MISMATCH, &bstrNotification, bstrClusterName ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_CheckMembership_EnumNode_FormatMessage, hr ); goto Cleanup; } hr = HRESULT_FROM_WIN32( TW32( ERROR_INVALID_DATA ) ); THR( SendStatusReport( bstrNodeName, TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_Cluster_Name_Mismatch, 0, 1, 1, hr, bstrNotification, NULL, NULL ) ); // // We don't care what the return value is since we are bailing the analysis. // goto Cleanup; } // if: cluster names don't match else { hr = STHR( HrIsUserAddedNode( bstrNodeName ) ); if ( FAILED( hr ) ) { goto Cleanup; } // if: if ( hr == S_OK ) { hr = THR( HrFormatMessageIntoBSTR( g_hInstance, IDS_TASKID_MINOR_NODE_ALREADY_IS_MEMBER, &bstrNotification, bstrNodeName, bstrClusterName ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_CheckMembership_EnumNode_FormatMessage1, hr ); goto Cleanup; } // // Make this a success code because we don't want to abort. We simply want to tell the user... // hr = MAKE_HRESULT( SEVERITY_SUCCESS, FACILITY_WIN32, ERROR_CLUSTER_NODE_ALREADY_MEMBER ); THR( SendStatusReport( bstrNodeName, TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_Cluster_Name_Match, 0, 1, 1, hr, bstrNotification, NULL, NULL ) ); } // if: } // else: cluster names do match then this node is already a member of this cluster TraceSysFreeString( bstrNodeName ); bstrNodeName = NULL; } // if: cluster member } // while: hr hr = THR( HrFormatMessageIntoBSTR( g_hInstance, IDS_TASKID_MINOR_CLUSTER_MEMBERSHIP_VERIFIED, &bstrNotification ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_CheckMembership_FormatMessage, hr ); goto Cleanup; } hr = THR( SendStatusReport( NULL, TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_Cluster_Membership_Verified, 0, 1, 1, hr, NULL, NULL, NULL ) ); Cleanup: if ( punk != NULL ) { punk->Release(); } TraceSysFreeString( bstrNodeName ); TraceSysFreeString( bstrClusterName ); TraceSysFreeString( bstrNotification ); HRETURN( hr ); } //*** CTaskAnalyzeCluster::HrCheckClusterMembership() ////////////////////////////////////////////////////////////////////////////// // // HRESULT // CTaskAnalyzeCluster::HrCompareResources( void ) // ////////////////////////////////////////////////////////////////////////////// HRESULT CTaskAnalyzeCluster::HrCompareResources( void ) { TraceFunc( "" ); OBJECTCOOKIE cookie; OBJECTCOOKIE cookieNode; OBJECTCOOKIE cookieDummy; OBJECTCOOKIE cookieFirst; BSTR bstrUIDExisting; ULONG celtDummy; IClusCfgManagedResourceInfo * pccmriNew = NULL; HRESULT hr = S_OK; BSTR bstrName = NULL; BSTR bstrUID = NULL; BSTR bstrNotification = NULL; BSTR bstrResName = NULL; IUnknown * punk = NULL; IEnumCookies * pecNodes = NULL; IEnumClusCfgManagedResources * peccmr = NULL; IEnumClusCfgManagedResources * peccmrCluster = NULL; IClusCfgManagedResourceInfo * pccmri = NULL; IClusCfgManagedResourceInfo * pccmriCluster = NULL; IClusCfgNodeInfo * pccni = NULL; // // Get the node cookie enumerator. // hr = THR( m_pom->FindObject( CLSID_NodeType, m_cookieCluster, NULL, DFGUID_EnumCookies, &cookieDummy, &punk ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Find_Devices, TASKID_Minor_Compare_Enum_Nodes_Find_Object, hr ); goto Cleanup; } hr = THR( punk->TypeSafeQI( IEnumCookies, &pecNodes ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Find_Devices, TASKID_Minor_Compare_Enum_Nodes_Find_Object_QI, hr ); goto Cleanup; } pecNodes = TraceInterface( L"CTaskAnalyzeCluster!IEnumCookies", IEnumCookies, pecNodes, 1 ); punk->Release(); punk = NULL; // // If forming, it doesn't matter who we pick to prime the cluster configuration // if ( !m_fJoiningMode ) { // // The first guy thru, we just copy his resources under the cluster // configuration. // hr = THR( pecNodes->Next( 1, &cookieFirst, &celtDummy ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Find_Devices, TASKID_Minor_Compare_Enum_Nodes_Next, hr ); goto Cleanup; } } // if: not joining else { // // We are joining nodes to the cluster. Find a node that has current // configuration and use it to prime the new configuration. // for ( ;; ) { // // Cleanup // if ( pccni != NULL ) { pccni->Release(); pccni = NULL; } hr = STHR( pecNodes->Next( 1, &cookieFirst, &celtDummy ) ); if ( hr == S_FALSE ) { // // We shouldn't make it here. There should be at least one node // in the cluster that we are joining. // hr = THR( HRESULT_FROM_WIN32( ERROR_NOT_FOUND ) ); SSR_ANALYSIS_FAILED( TASKID_Major_Find_Devices, TASKID_Minor_Compare_Resources_Find_Formed_Node_Next, hr ); goto Cleanup; } if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Find_Devices, TASKID_Minor_Compare_Resources_Find_Formed_Node_Next, hr ); goto Cleanup; } // // Retrieve the node information. // hr = THR( m_pom->GetObject( DFGUID_NodeInformation, cookieFirst, &punk ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Find_Devices, TASKID_Minor_CompareResources_NodeInfo_FindObject, hr ); goto Cleanup; } hr = THR( punk->TypeSafeQI( IClusCfgNodeInfo, &pccni ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Find_Devices, TASKID_Minor_CompareResources_NodeInfo_FindObject_QI, hr ); goto Cleanup; } pccni = TraceInterface( L"CTaskAnalyzeCluster!IClusCfgNodeInfo", IClusCfgNodeInfo, pccni, 1 ); punk->Release(); punk = NULL; hr = STHR( pccni->IsMemberOfCluster() ); if ( hr == S_OK ) break; // exit condition } // for: ever } // else: joining // // Retrieve the node's name for error messages. // hr = THR( HrRetrieveCookiesName( TASKID_Major_Find_Devices, cookieFirst, &bstrName ) ); if ( FAILED( hr ) ) goto Cleanup; // // Retrieve the managed resources enumer. // hr = THR( m_pom->FindObject( CLSID_ManagedResourceType, cookieFirst, NULL, DFGUID_EnumManageableResources, &cookieDummy, &punk ) ); if ( hr == HRESULT_FROM_WIN32( ERROR_NOT_FOUND ) ) { hr = THR( HrLoadStringIntoBSTR( g_hInstance, IDS_TASKID_MINOR_NO_MANAGED_RESOURCES_FOUND, &bstrNotification ) ); if ( FAILED( hr ) ) goto Cleanup; hr = THR( SendStatusReport( bstrName, TASKID_Major_Find_Devices, TASKID_Minor_No_Managed_Resources_Found, 0, 1, 1, MAKE_HRESULT( 0, FACILITY_WIN32, ERROR_NOT_FOUND ), bstrNotification, NULL, NULL ) ); if ( FAILED( hr ) ) goto Cleanup; hr = HRESULT_FROM_WIN32( ERROR_NOT_FOUND ); // fall thru - the while ( hr == S_OK ) will be false and keep going } else if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Find_Devices, TASKID_Minor_Compare_Resources_Enum_First_Node_Find_Object, hr ); goto Cleanup; } else { hr = THR( punk->TypeSafeQI( IEnumClusCfgManagedResources, &peccmr ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Find_Devices, TASKID_Minor_Compare_Resources_Enum_First_Node_Find_Object_QI, hr ); goto Cleanup; } peccmr = TraceInterface( L"CTaskAnalyzeCluster!IEnumClusCfgManagedResources", IEnumClusCfgManagedResources, peccmr, 1 ); punk->Release(); punk = NULL; } // // Loop thru the first nodes resources create an equalivant resource // under the cluster configuration object/cookie. // while ( hr == S_OK ) { // Cleanup if ( pccmri != NULL ) { pccmri->Release(); pccmri = NULL; } // Get next resource hr = STHR( peccmr->Next( 1, &pccmri, &celtDummy ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Find_Devices, TASKID_Minor_Compare_Resources_Enum_First_Node_Next, hr ); goto Cleanup; } if ( hr == S_FALSE ) break; // exit condition // create a new object hr = THR( HrCreateNewManagedResourceInClusterConfiguration( pccmri, &pccmriNew ) ); if ( FAILED( hr ) ) goto Cleanup; hr = STHR( pccmriNew->IsQuorumDevice() ); if ( hr == S_OK ) { Assert( m_bstrQuorumUID == NULL ); hr = THR( pccmriNew->GetUID( &m_bstrQuorumUID ) ); TraceMemoryAddBSTR( m_bstrQuorumUID ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Find_Devices, TASKID_Minor_Compare_Resources_Enum_First_Node_Get_Quorum_UID, hr ); goto Cleanup; } // Checking that the quorum is joinable if we are in join mode. if ( ( hr == S_OK ) && m_fJoiningMode ) { hr = THR( pccmriNew->IsDeviceJoinable() ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Find_Devices, TASKID_Minor_Compare_Resources_Enum_First_Node_Is_Device_Joinable, hr ); goto Cleanup; } else if ( hr == S_FALSE ) { // Souldn't allow this to proceed, no joinable quorum in join mode. hr = THR( HrLoadStringIntoBSTR( g_hInstance, IDS_TASKID_MINOR_MISSING_JOINABLE_QUORUM_RESOURCE, &bstrNotification ) ); hr = THR( SendStatusReport( NULL, TASKID_Major_Find_Devices, TASKID_Minor_Compare_Resources_Enum_First_Node_Is_Device_Joinable, 0, 1, 1, HRESULT_FROM_WIN32( TW32( ERROR_QUORUM_DISK_NOT_FOUND ) ), bstrNotification, NULL, NULL ) ); hr = HRESULT_FROM_WIN32( TW32( ERROR_QUORUM_DISK_NOT_FOUND ) ); goto Cleanup; } } // if: pccmriNew->Release(); pccmriNew = NULL; } else { pccmriNew->Release(); pccmriNew = NULL; hr = S_OK; } } // while: S_OK hr = THR( pecNodes->Reset() ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Find_Devices, TASKID_Minor_Compare_Resources_Enum_Reset, hr ); goto Cleanup; } // // Loop thru the rest of the nodes comparing the resources. // for ( ; ; ) { // // Cleanup // if ( peccmr != NULL ) { peccmr->Release(); peccmr = NULL; } TraceSysFreeString( bstrName ); bstrName = NULL; // // Get the next node. // hr = STHR( pecNodes->Next( 1, &cookieNode, &celtDummy ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Find_Devices, TASKID_Minor_Compare_Resources_Enum_Nodes_Next, hr ); goto Cleanup; } if ( hr == S_FALSE ) break; // exit condition // // Skip the "first" node since we already have its configuration. // if ( cookieFirst == cookieNode ) continue; // // Retrieve the node's name for error messages. // hr = THR( HrRetrieveCookiesName( TASKID_Major_Find_Devices, cookieNode, &bstrName ) ); if ( FAILED( hr ) ) goto Cleanup; // // Retrieve the managed resources enumer. // hr = THR( m_pom->FindObject( CLSID_ManagedResourceType, cookieNode, NULL, DFGUID_EnumManageableResources, &cookieDummy, &punk ) ); if ( hr == HRESULT_FROM_WIN32( ERROR_NOT_FOUND ) ) { hr = THR( HrLoadStringIntoBSTR( g_hInstance, IDS_TASKID_MINOR_NO_MANAGED_RESOURCES_FOUND, &bstrNotification ) ); if ( FAILED( hr ) ) goto Cleanup; hr = THR( SendStatusReport( bstrName, TASKID_Major_Find_Devices, TASKID_Minor_No_Managed_Resources_Found, 0, 1, 1, MAKE_HRESULT( 0, FACILITY_WIN32, ERROR_NOT_FOUND ), bstrNotification, NULL, NULL ) ); if ( FAILED( hr ) ) goto Cleanup; continue; // skip this node } else if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Find_Devices, TASKID_Minor_Compare_Resources_Enum_Nodes_Find_Object, hr ); goto Cleanup; } hr = THR( punk->TypeSafeQI( IEnumClusCfgManagedResources, &peccmr ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Find_Devices, TASKID_Minor_Compare_Resources_Enum_Nodes_Find_Object_QI, hr ); goto Cleanup; } peccmr = TraceInterface( L"CTaskAnalyzeCluster!IEnumClusCfgManagedResources", IEnumClusCfgManagedResources, peccmr, 1 ); punk->Release(); punk = NULL; // // Loop thru the managed resources already that the node has. // for ( ; ; ) { // // Cleanup // if ( pccmri != NULL ) { pccmri->Release(); pccmri = NULL; } TraceSysFreeString( bstrUID ); bstrUID = NULL; if ( peccmrCluster != NULL ) { peccmrCluster->Release(); peccmrCluster = NULL; } // // Get next resource // hr = STHR( peccmr->Next( 1, &pccmri, &celtDummy ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Find_Devices, TASKID_Minor_Compare_Resources_Enum_Nodes_Enum_Resources_Next, hr ); goto Cleanup; } if ( hr == S_FALSE ) break; // exit condition pccmri = TraceInterface( L"CTaskAnalyzeCluster!IClusCfgManagedResourceInfo", IClusCfgManagedResourceInfo, pccmri, 1 ); // // Grab the resource's UUID. // hr = THR( pccmri->GetUID( &bstrUID ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Find_Devices, TASKID_Minor_Compare_Resources_Enum_Nodes_Enum_Resources_GetUID, hr ); goto Cleanup; } TraceMemoryAddBSTR( bstrUID ); // // See if it matches a resource already in the cluster configuration. // hr = THR( m_pom->FindObject( CLSID_ManagedResourceType, m_cookieCluster, NULL, DFGUID_EnumManageableResources, &cookieDummy, &punk ) ); if ( hr == HRESULT_FROM_WIN32( ERROR_NOT_FOUND ) ) { hr = S_FALSE; // create a new object. // fall thru } else if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Find_Devices, TASKID_Minor_Compare_Resources_Enum_Nodes_Enum_Resources_Enum_Cluster_Find_Object, hr ); goto Cleanup; } hr = THR( punk->TypeSafeQI( IEnumClusCfgManagedResources, &peccmrCluster ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Find_Devices, TASKID_Minor_Compare_Resources_Enum_Nodes_Enum_Resources_Enum_Cluster_Find_Object_QI, hr ); goto Cleanup; } punk->Release(); punk = NULL; // // Loop thru the configured cluster resources to see what matches. // while( hr == S_OK ) { HRESULT hrCluster; BOOL fMatch; // // Cleanup // if ( pccmriCluster != NULL ) { pccmriCluster->Release(); pccmriCluster = NULL; } hr = STHR( peccmrCluster->Next( 1, &pccmriCluster, &celtDummy ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Find_Devices, TASKID_Minor_Compare_Resources_Enum_Nodes_Enum_Resources_Enum_Cluster_Next, hr ); goto Cleanup; } if ( hr == S_FALSE ) break; // exit condition hr = THR( pccmriCluster->GetUID( &bstrUIDExisting ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Find_Devices, TASKID_Minor_Compare_Resources_Enum_Nodes_Enum_Resources_Enum_Cluster_GetUID, hr ); goto Cleanup; } TraceMemoryAddBSTR( bstrUIDExisting ); fMatch = ( wcscmp( bstrUID, bstrUIDExisting ) == 0 ); TraceSysFreeString( bstrUIDExisting ); if ( !fMatch ) continue; // keep looping // // A resource is already in the database. See if it is the same from // the POV of management. // // // Check the quorum capabilities. // hrCluster = STHR( pccmriCluster->IsQuorumCapable() ); if ( FAILED( hrCluster ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Find_Devices, TASKID_Minor_Compare_Resources_Enum_Nodes_Enum_Resources_Enum_Cluster_IsQuorumCapable_Cluster, hr ); goto Cleanup; } hr = STHR( pccmri->IsQuorumCapable() ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Find_Devices, TASKID_Minor_Compare_Resources_Enum_Nodes_Enum_Resources_Enum_Cluster_IsQuorumCapable_Node, hr ); goto Cleanup; } if ( hr != hrCluster ) { // // The quorum capabilities don't match. Tell the user. // BSTR bstrResource; hr = THR( pccmriCluster->GetName( &bstrResource ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Find_Devices, TASKID_Minor_Compare_Resources_Enum_Nodes_Enum_Resources_Enum_Cluster_GetName, hr ); goto Cleanup; } hr = THR( HrFormatMessageIntoBSTR( g_hInstance, IDS_TASKID_MINOR_RESOURCE_CAPABILITIES_DONT_MATCH, &bstrNotification, bstrResource ) ); TraceSysFreeString( bstrResource ); hr = THR( SendStatusReport( bstrName, TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_Resource_Capabilities_Dont_Match, 0, 1, 1, E_FAIL, bstrNotification, NULL, NULL ) ); hr = THR( E_FAIL ); goto Cleanup; // bail! } // // // If we made it here then we think it truely is the same resource. The // rest is stuff we need to fixup during the commit phase. // // // // Is this node wants its resources managed, mark it as being managed in the cluster // configuration as well. // hr = STHR( pccmri->IsManaged() ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Find_Devices, TASKID_Minor_Compare_Resources_Enum_Nodes_Enum_Resources_Enum_Cluster_IsManaged, hr ); goto Cleanup; } if ( hr == S_OK ) { hr = THR( pccmriCluster->SetManaged( TRUE ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Find_Devices, TASKID_Minor_Compare_Resources_Enum_Nodes_Enum_Resources_Enum_Cluster_SetManaged, hr ); goto Cleanup; } // // Since this node manages this resource, it should be able to provide us with a name. // We will use this name to overwrite whatever we currently have, except for the quorum // resource, which already has the correct name. // hr = STHR( pccmri->IsQuorumDevice() ); if ( hr == S_FALSE ) { hr = THR( pccmri->GetName( &bstrResName ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Find_Devices, TASKID_Minor_Compare_Resources_Enum_Nodes_Enum_Resources_Enum_Cluster_GetResName, hr ); goto Cleanup; } TraceMemoryAddBSTR( bstrResName ); hr = THR( pccmriCluster->SetName( bstrResName ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Find_Devices, TASKID_Minor_Compare_Resources_Enum_Nodes_Enum_Resources_Enum_Cluster_SetResName, hr ); goto Cleanup; } TraceSysFreeString( bstrResName ); bstrResName = NULL; } } // // Check to see if the resource is the quorum resource. If so, mark that // we found a common quorum resource. // if ( m_bstrQuorumUID == NULL ) { // // No previous quorum has been set. See if this is the quorum resource. // hr = STHR( pccmri->IsQuorumDevice() ); if ( hr == S_OK ) { // // Yes it is. The mark it in the configuration as such. // hr = THR( pccmriCluster->SetQuorumedDevice( TRUE ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Find_Devices, TASKID_Minor_Compare_Resources_Enum_Nodes_Enum_Resources_Enum_Cluster_SetQuorumDevice_Cluster, hr ); goto Cleanup; } // // Remember that this resource is the quorum. // hr = THR( pccmriCluster->GetUID( &m_bstrQuorumUID ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Find_Devices, TASKID_Minor_Compare_Resources_Enum_Nodes_Enum_Resources_Enum_Cluster_SetQuorumDevice_GetUID, hr ); goto Cleanup; } TraceMemoryAddBSTR( m_bstrQuorumUID ); } } else if ( wcscmp( m_bstrQuorumUID, bstrUID ) == 0 ) { // // This is the same quorum. Mark the Node's configuration. // hr = THR( pccmri->SetQuorumedDevice( TRUE ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Find_Devices, TASKID_Minor_Compare_Resources_Enum_Nodes_Enum_Resources_Enum_Cluster_SetQuorumDevice_Node_True, hr ); goto Cleanup; } } else { // // Otherwize, make sure that the device isn't marked as quorum. (paranoid) // hr = THR( pccmri->SetQuorumedDevice( FALSE ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Find_Devices, TASKID_Minor_Compare_Resources_Enum_Nodes_Enum_Resources_Enum_Cluster_SetQuorumDevice_Node_False, hr ); goto Cleanup; } } // // Exit the loop with S_OK so we don't create a new resource. // hr = S_OK; break; // exit loop } // while: S_OK if ( hr == S_FALSE ) { // // Need to create a new object. // Assert( pccmri != NULL ); hr = THR( HrCreateNewManagedResourceInClusterConfiguration( pccmri, &pccmriNew ) ); if ( FAILED( hr ) ) goto Cleanup; Assert( hr == S_OK ); hr = STHR( pccmriNew->IsQuorumDevice() ); if ( hr == S_OK ) { // // Remember the quorum device's UID. // Assert( m_bstrQuorumUID == NULL ); m_bstrQuorumUID = bstrUID; bstrUID = NULL; } else { pccmriNew->Release(); pccmriNew = NULL; hr = S_OK; } } // if: object not found } // for: resources } // for: nodes hr = S_OK; Cleanup: if ( pccmriNew != NULL ) { pccmriNew->Release(); } // if: TraceSysFreeString( bstrNotification ); TraceSysFreeString( bstrName ); TraceSysFreeString( bstrUID ); TraceSysFreeString( bstrNotification ); TraceSysFreeString( bstrResName ); if ( punk != NULL ) { punk->Release(); } if ( pecNodes != NULL ) { pecNodes->Release(); } if ( peccmr != NULL ) { peccmr->Release(); } if ( peccmrCluster != NULL ) { peccmrCluster->Release(); } if ( pccmri != NULL ) { pccmri->Release(); } if ( pccmriCluster != NULL ) { pccmriCluster->Release(); } if ( pccni != NULL ) { pccni->Release(); } HRETURN( hr ); } //*** CTaskAnalyzeCluster::HrCompareResources() ////////////////////////////////////////////////////////////////////////////// // // HRESULT // CTaskAnalyzeCluster::HrCreateNewManagedResourceInClusterConfiguration( // IClusCfgManagedResourceInfo * pccmriIn, // IClusCfgManagedResourceInfo ** ppccmriNewOut // ) // ////////////////////////////////////////////////////////////////////////////// HRESULT CTaskAnalyzeCluster::HrCreateNewManagedResourceInClusterConfiguration( IClusCfgManagedResourceInfo * pccmriIn, IClusCfgManagedResourceInfo ** ppccmriNewOut ) { TraceFunc( "" ); HRESULT hr; OBJECTCOOKIE cookieDummy; BSTR bstrUID = NULL; IUnknown * punk = NULL; IGatherData * pgd = NULL; IClusCfgManagedResourceInfo * pccmri = NULL; // // TODO: gpease 28-JUN-2000 // Make this dynamic - for now we'll just create a "managed device." // // grab the name hr = THR( pccmriIn->GetUID( &bstrUID ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Find_Devices, TASKID_Minor_Create_Resource_GetUID, hr ); goto Cleanup; } TraceMemoryAddBSTR( bstrUID ); // create an object in the object manager. hr = THR( m_pom->FindObject( CLSID_ManagedResourceType, m_cookieCluster, bstrUID, DFGUID_ManagedResource, &cookieDummy, &punk ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Find_Devices, TASKID_Minor_Create_Resource_FindObject, hr ); goto Cleanup; } // find the IGatherData interface hr = THR( punk->TypeSafeQI( IGatherData, &pgd ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Find_Devices, TASKID_Minor_Create_Resource_FindObject_QI, hr ); goto Cleanup; } // have the new object gather all information it needs hr = THR( pgd->Gather( m_cookieCluster, pccmriIn ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Find_Devices, TASKID_Minor_Create_Resource_Gather, hr ); goto Cleanup; } // hand the object out if requested if ( ppccmriNewOut != NULL ) { // find the IClusCfgManagedResourceInfo hr = THR( punk->TypeSafeQI( IClusCfgManagedResourceInfo, &pccmri ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Find_Devices, TASKID_Minor_Create_Resource_QI, hr ); goto Cleanup; } *ppccmriNewOut = TraceInterface( L"ManagedDevice!ICCMRI", IClusCfgManagedResourceInfo, pccmri, 0 ); (*ppccmriNewOut)->AddRef(); } Cleanup: TraceSysFreeString( bstrUID ); if ( pccmri != NULL ) { pccmri->Release(); } if ( pgd != NULL ) { pgd->Release(); } if ( punk != NULL ) { punk->Release(); } HRETURN( hr ); } //*** CTaskAnalyzeCluster::HrCreateNewManagedResourceInClusterConfiguration() ////////////////////////////////////////////////////////////////////////////// // // HRESULT // CTaskAnalyzeCluster::HrCheckForCommonQuorumResource( void ) // ////////////////////////////////////////////////////////////////////////////// HRESULT CTaskAnalyzeCluster::HrCheckForCommonQuorumResource( void ) { TraceFunc( "" ); HRESULT hr; OBJECTCOOKIE cookie; OBJECTCOOKIE cookieDummy; ULONG cMatchedNodes = 0; ULONG cAnalyzedNodes = 0; BOOL fNodeCanAccess = FALSE; BSTR bstrUID = NULL; BSTR bstrNotification = NULL; BSTR bstrNodeName = NULL; IUnknown * punk = NULL; IEnumCookies * pecNodes = NULL; IEnumClusCfgManagedResources * peccmr = NULL; IClusCfgManagedResourceInfo * pccmri = NULL; IClusCfgNodeInfo * piccni = NULL; // // BUGBUG: 08-MAY-2001 GalenB // // There is no status or progress for this feasibility step. It simply "hangs" until it succeeds or fails. // /* THR( HrLoadStringIntoBSTR( g_hInstance, IDS_TASKID_MINOR_FOUND_COMMON_QUORUM_RESOURCE, &bstrNotification ) ); hr = THR( SendStatusReport( NULL, TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_Finding_Common_Quorum_Device, 0, 0, 1, S_OK, bstrNotification, NULL, NULL ) ); */ if ( m_bstrQuorumUID != NULL ) { // // Grab the cookie enumer for nodes in our cluster configuration. // hr = THR( m_pom->FindObject( CLSID_NodeType, m_cookieCluster, NULL, DFGUID_EnumCookies, &cookieDummy, &punk ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_Check_Common_FindObject, hr ); goto Cleanup; } hr = THR( punk->TypeSafeQI( IEnumCookies, &pecNodes ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_Check_Common_FindObject_QI, hr ); goto Cleanup; } pecNodes = TraceInterface( L"CTaskAnalyzeCluster!IEnumCookies", IEnumCookies, pecNodes, 1 ); punk->Release(); punk = NULL; // // Scan the cluster configurations looking for the quorum resource. // for ( ;; ) { ULONG celtDummy; if ( peccmr != NULL ) { peccmr->Release(); peccmr = NULL; } // if: hr = STHR( pecNodes->Next( 1, &cookie, &celtDummy ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_Check_Common_Enum_Nodes_Next, hr ); goto Cleanup; } // if: if ( hr == S_FALSE ) break; // exit condition hr = THR( m_pom->GetObject( DFGUID_NodeInformation, cookie, &punk ) ); if ( FAILED( hr ) ) goto Cleanup; hr = THR( punk->TypeSafeQI( IClusCfgNodeInfo, &piccni ) ); if ( FAILED( hr ) ) goto Cleanup; punk->Release(); punk = NULL; TraceSysFreeString( bstrNodeName ); bstrNodeName = NULL; hr = THR( piccni->GetName( &bstrNodeName ) ); if ( FAILED( hr ) ) goto Cleanup; TraceMemoryAddBSTR( bstrNodeName ); // // increment counter for a "nice" progress bar // cAnalyzedNodes ++; THR( HrFormatStringIntoBSTR( g_hInstance, IDS_TASKID_MINOR_FINDING_COMMON_QUORUM_DEVICE, &bstrNotification, bstrNodeName ) ); hr = THR( SendStatusReport( NULL, TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_Finding_Common_Quorum_Device, 0, m_cNodes + 1, cAnalyzedNodes, S_OK, bstrNotification, NULL, NULL ) ); // // Grab the managed resource enumer for resources that our node has. // hr = THR( m_pom->FindObject( CLSID_ManagedResourceType, cookie, NULL, DFGUID_EnumManageableResources, &cookieDummy, &punk ) ); if ( hr == HRESULT_FROM_WIN32( ERROR_NOT_FOUND ) ) { continue; // ignore and continue } else if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_Check_Common_Enum_Nodes_FindObject, hr ); goto Cleanup; } hr = THR( punk->TypeSafeQI( IEnumClusCfgManagedResources, &peccmr ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_Check_Common_Enum_Nodes_FindObject_QI, hr ); goto Cleanup; } peccmr = TraceInterface( L"CTaskAnalyzeCluster!IEnumClusCfgManagedResources", IEnumClusCfgManagedResources, peccmr, 1 ); punk->Release(); punk = NULL; fNodeCanAccess = FALSE; // // Loop thru the resources trying to match the UID of the quorum resource. // for ( ;; ) { ULONG celtDummy; TraceSysFreeString( bstrUID ); bstrUID = NULL; if ( pccmri != NULL ) { pccmri->Release(); pccmri = NULL; } hr = STHR( peccmr->Next( 1, &pccmri, &celtDummy ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_Check_Common_Enum_Nodes_Enum_Resources_Next, hr ); goto Cleanup; } if ( hr == S_FALSE ) break; // exit condition pccmri = TraceInterface( L"CTaskAnalyzeCluster!IClusCfgManagedResourceInfo", IClusCfgManagedResourceInfo, pccmri, 1 ); hr = THR( pccmri->GetUID( &bstrUID ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_Check_Common_Enum_Nodes_Enum_Resources_GetUID, hr ); goto Cleanup; } TraceMemoryAddBSTR( bstrUID ); if ( wcscmp( bstrUID, m_bstrQuorumUID ) != 0 ) continue; // doesn't match - keep going cMatchedNodes ++; fNodeCanAccess = TRUE; break; // exit condition } // while: S_OK // // Give the UI feedback if this node has no access to the quorum // if ( !fNodeCanAccess ) { THR( HrLoadStringIntoBSTR( g_hInstance, IDS_TASKID_MINOR_NODE_CANNOT_ACCESS_QUORUM, &bstrNotification ) ); hr = THR( SendStatusReport( bstrNodeName, TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_Node_Cannot_Access_Quorum, 0, 1, 1, HRESULT_FROM_WIN32( TW32( ERROR_QUORUM_DISK_NOT_FOUND ) ), bstrNotification, NULL, NULL ) ); } // if ( !fNodeCanAccess ) } // while: S_OK } // if: m_bstrQuorumUID != NULL // // Figure out if we ended up with a common quorum device. // if ( cMatchedNodes == m_cNodes ) { // // We found a device that can be used as a common quorum device. // THR( HrLoadStringIntoBSTR( g_hInstance, IDS_TASKID_MINOR_FOUND_COMMON_QUORUM_RESOURCE, &bstrNotification ) ); hr = THR( SendStatusReport( NULL, TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_Finding_Common_Quorum_Device, 0, m_cNodes + 1, m_cNodes + 1, S_OK, bstrNotification, NULL, NULL ) ); // error checked outside if/else statement } else { if ( ( m_cNodes == 1 ) && ( !m_fJoiningMode ) ) { // // We didn't find a common quorum device, but we're only forming. We can // create the cluster with a local quorum. Just put up a warning. // THR( HrLoadStringIntoBSTR( g_hInstance, IDS_TASKID_MINOR_FORCED_LOCAL_QUORUM, &bstrNotification ) ); hr = THR( SendStatusReport( NULL, TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_Finding_Common_Quorum_Device, 0, m_cNodes + 1, m_cNodes + 1, MAKE_HRESULT( SEVERITY_SUCCESS, FACILITY_WIN32, ERROR_QUORUM_DISK_NOT_FOUND ), bstrNotification, NULL, NULL ) ); // error checked outside if/else statement } else { // // We didn't find a common quorum device. // THR( HrLoadStringIntoBSTR( g_hInstance, IDS_TASKID_MINOR_MISSING_COMMON_QUORUM_RESOURCE, &bstrNotification ) ); hr = THR( SendStatusReport( NULL, TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_Finding_Common_Quorum_Device, 0, m_cNodes + 1, m_cNodes + 1, HRESULT_FROM_WIN32( TW32( ERROR_QUORUM_DISK_NOT_FOUND ) ), bstrNotification, NULL, NULL ) ); // we always bail. hr = HRESULT_FROM_WIN32( TW32( ERROR_QUORUM_DISK_NOT_FOUND ) ); goto Cleanup; } } // // Check to see if any of the SendStatusReports() returned anything // of interest. // if ( FAILED( hr ) ) goto Cleanup; hr = S_OK; Cleanup: if ( punk != NULL ) { punk->Release(); } // if: if ( piccni != NULL ) { piccni->Release(); } // if: TraceSysFreeString( bstrNotification ); TraceSysFreeString( bstrUID ); if ( pccmri != NULL ) { pccmri->Release(); } // if: if ( peccmr != NULL ) { peccmr->Release(); } // if: if ( pecNodes != NULL ) { pecNodes->Release(); } // if: HRETURN( hr ); } //*** CTaskAnalyzeCluster::HrCheckForCommonQuorumResource() ////////////////////////////////////////////////////////////////////////////// // // HRESULT // CTaskAnalyzeCluster::HrCompareNetworks( void ) // ////////////////////////////////////////////////////////////////////////////// HRESULT CTaskAnalyzeCluster::HrCompareNetworks( void ) { TraceFunc( "" ); OBJECTCOOKIE cookie; OBJECTCOOKIE cookieNode; OBJECTCOOKIE cookieDummy; OBJECTCOOKIE cookieFirst; BSTR bstrUIDExisting; ULONG celtDummy; IClusCfgNetworkInfo * pccmriNew; HRESULT hr = S_OK; BSTR bstrUID = NULL; BSTR bstrName = NULL; BSTR bstrNotification = NULL; IUnknown * punk = NULL; IEnumCookies * pecNodes = NULL; IEnumClusCfgNetworks * peccn = NULL; IEnumClusCfgNetworks * peccnCluster = NULL; IClusCfgNetworkInfo * pccni = NULL; IClusCfgNetworkInfo * pccniCluster = NULL; IClusCfgNodeInfo * pccNode = NULL; hr = THR( m_pom->FindObject( CLSID_NodeType, m_cookieCluster, NULL, DFGUID_EnumCookies, &cookieDummy, &punk ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Find_Devices, TASKID_Minor_CompareNetworks_EnumNodes_FindObject, hr ); goto Cleanup; } hr = THR( punk->TypeSafeQI( IEnumCookies, &pecNodes ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Find_Devices, TASKID_Minor_CompareNetworks_EnumNodes_FindObject_QI, hr ); goto Cleanup; } pecNodes = TraceInterface( L"CTaskAnalyzeCluster!IEnumCookies", IEnumCookies, pecNodes, 1 ); punk->Release(); punk = NULL; if ( !m_fJoiningMode ) { // // The first guy thru, we just copy his networks under the cluster // configuration. // hr = THR( pecNodes->Next( 1, &cookieFirst, &celtDummy ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Find_Devices, TASKID_Minor_CompareNetworks_EnumNodes_Next, hr ); goto Cleanup; } } else { // // We are joining nodes to the cluster. Find a node that has current // configuration and use it to prime the new configuration. // for ( ;; ) { // // Cleanup // if ( pccNode != NULL ) { pccNode->Release(); pccNode = NULL; } hr = STHR( pecNodes->Next( 1, &cookieFirst, &celtDummy ) ); if ( hr == S_FALSE ) { // // We shouldn't make it here. There should be at least one node // in the cluster that we are joining. // hr = THR( HRESULT_FROM_WIN32( ERROR_NOT_FOUND ) ); SSR_ANALYSIS_FAILED( TASKID_Major_Find_Devices, TASKID_Minor_Compare_Resources_Find_Formed_Node_Next, hr ); goto Cleanup; } if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Find_Devices, TASKID_Minor_Compare_Resources_Find_Formed_Node_Next, hr ); goto Cleanup; } // // Retrieve the node information. // hr = THR( m_pom->GetObject( DFGUID_NodeInformation, cookieFirst, &punk ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Find_Devices, TASKID_Minor_CompareResources_NodeInfo_FindObject, hr ); goto Cleanup; } hr = THR( punk->TypeSafeQI( IClusCfgNodeInfo, &pccNode ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Find_Devices, TASKID_Minor_CompareResources_NodeInfo_FindObject_QI, hr ); goto Cleanup; } pccNode = TraceInterface( L"CTaskAnalyzeCluster!IClusCfgNodeInfo", IClusCfgNodeInfo, pccNode, 1 ); punk->Release(); punk = NULL; hr = STHR( pccNode->IsMemberOfCluster() ); if ( hr == S_OK ) break; // exit condition } // for: ever } // else: joining // // Retrieve the node name in case of errors. // hr = THR( HrRetrieveCookiesName( TASKID_Major_Find_Devices, cookieFirst, &bstrName ) ); if ( FAILED( hr ) ) goto Cleanup; // // Retrieve the networks enumer. // hr = THR( m_pom->FindObject( CLSID_NetworkType, cookieFirst, NULL, DFGUID_EnumManageableNetworks, &cookieDummy, &punk ) ); if ( hr == HRESULT_FROM_WIN32( ERROR_NOT_FOUND ) ) { hr = THR( HrLoadStringIntoBSTR( g_hInstance, IDS_TASKID_MINOR_NO_MANAGED_NETWORKS_FOUND, &bstrNotification ) ); hr = THR( SendStatusReport( bstrName, TASKID_Major_Find_Devices, TASKID_Minor_No_Managed_Networks_Found, 0, 1, 1, MAKE_HRESULT( 0, FACILITY_WIN32, ERROR_NOT_FOUND ), bstrNotification, NULL, NULL ) ); if ( FAILED( hr ) ) goto Cleanup; hr = HRESULT_FROM_WIN32( ERROR_NOT_FOUND ); // fall thru - the while ( hr == S_OK ) will be false and keep going } else if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Find_Devices, TASKID_Minor_CompareNetworks_EnumResources_FindObject, hr ); goto Cleanup; } else { hr = THR( punk->TypeSafeQI( IEnumClusCfgNetworks, &peccn ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Find_Devices, TASKID_Minor_CompareNetworks_EnumResources_FindObject_QI, hr ); goto Cleanup; } peccn = TraceInterface( L"CTaskAnalyzeCluster!IEnumClusCfgNetworks", IEnumClusCfgNetworks, peccn, 1 ); punk->Release(); punk = NULL; } // // Loop thru the first nodes networks create an equalivant network // under the cluster configuration object/cookie. // while ( hr == S_OK ) { // Cleanup if ( pccni != NULL ) { pccni->Release(); pccni = NULL; } // Get next network hr = STHR( peccn->Next( 1, &pccni, &celtDummy ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Find_Devices, TASKID_Minor_CompareNetworks_EnumNodes_EnumNetwork_Next, hr ); goto Cleanup; } if ( hr == S_FALSE ) break; // exit condition pccni = TraceInterface( L"CTaskAnalyzeCluster!IClusCfgNetworkInfo", IClusCfgNetworkInfo, pccni, 1 ); // create a new object hr = THR( HrCreateNewNetworkInClusterConfiguration( pccni, NULL ) ); if ( FAILED( hr ) ) goto Cleanup; } // while: S_OK // // Reset the enumeration. // hr = THR( pecNodes->Reset() ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Find_Devices, TASKID_Minor_CompareNetworks_EnumNodes_Reset, hr ); goto Cleanup; } // // Loop thru the rest of the nodes comparing the networks. // do { // // Cleanup // if ( peccn != NULL ) { peccn->Release(); peccn = NULL; } TraceSysFreeString( bstrName ); bstrName = NULL; // // Get the next node. // hr = STHR( pecNodes->Next( 1, &cookieNode, &celtDummy ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Find_Devices, TASKID_Minor_CompareNetworks_EnumNodes_NextNode, hr ); goto Cleanup; } if ( hr == S_FALSE ) break; // exit condition if ( cookieNode == cookieFirst ) continue; // skip it // // Retrieve the node's name // hr = THR( HrRetrieveCookiesName( TASKID_Major_Find_Devices, cookieNode, &bstrName ) ); if ( FAILED( hr ) ) goto Cleanup; // // Retrieve the networks enumer. // hr = THR( m_pom->FindObject( CLSID_NetworkType, cookieNode, NULL, DFGUID_EnumManageableNetworks, &cookieDummy, &punk ) ); if ( hr == HRESULT_FROM_WIN32( ERROR_NOT_FOUND ) ) { hr = THR( HrLoadStringIntoBSTR( g_hInstance, IDS_TASKID_MINOR_NO_MANAGED_NETWORKS_FOUND, &bstrNotification ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Find_Devices, TASKID_Minor_CompareNetworks_EnumNodes_Next_LoadString, hr ); goto Cleanup; } hr = THR( SendStatusReport( bstrName, TASKID_Major_Find_Devices, TASKID_Minor_No_Managed_Networks_Found, 0, 1, 1, MAKE_HRESULT( 0, FACILITY_WIN32, ERROR_NOT_FOUND ), bstrNotification, NULL, NULL ) ); if ( FAILED( hr ) ) goto Cleanup; continue; // skip this node } else if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Find_Devices, TASKID_Minor_CompareNetworks_EnumNodes_Next_FindObject, hr ); goto Cleanup; } hr = THR( punk->TypeSafeQI( IEnumClusCfgNetworks, &peccn ) ); if ( FAILED( hr ) ) goto Cleanup; peccn = TraceInterface( L"CTaskAnalyzeCluster!IEnumClusCfgNetworks", IEnumClusCfgNetworks, peccn, 1 ); punk->Release(); punk = NULL; // // Loop thru the networks already that the node has. // do { // // Cleanup // if ( pccni != NULL ) { pccni->Release(); pccni = NULL; } TraceSysFreeString( bstrUID ); bstrUID = NULL; if ( peccnCluster != NULL ) { peccnCluster->Release(); peccnCluster = NULL; } // // Get next network // hr = STHR( peccn->Next( 1, &pccni, &celtDummy ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Find_Devices, TASKID_Minor_CompareNetworks_EnumNodes_EnumNetworks_Next, hr ); goto Cleanup; } if ( hr == S_FALSE ) break; // exit condition pccni = TraceInterface( L"CTaskAnalyzeCluster!IClusCfgNetworkInfo", IClusCfgNetworkInfo, pccni, 1 ); // // Grab the network's UUID. // hr = THR( pccni->GetUID( &bstrUID ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Find_Devices, TASKID_Minor_CompareNetworks_EnumNodes_EnumNetworks_GetUID, hr ); goto Cleanup; } TraceMemoryAddBSTR( bstrUID ); // // See if it matches a network already in the cluster configuration. // hr = THR( m_pom->FindObject( CLSID_NetworkType, m_cookieCluster, NULL, DFGUID_EnumManageableNetworks, &cookieDummy, &punk ) ); if ( hr == HRESULT_FROM_WIN32( ERROR_NOT_FOUND ) ) { hr = S_FALSE; // create a new object. // fall thru } else if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Find_Devices, TASKID_Minor_CompareNetworks_EnumNodes_EnumNetworks_FindObject, hr ); goto Cleanup; } hr = THR( punk->TypeSafeQI( IEnumClusCfgNetworks, &peccnCluster ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Find_Devices, TASKID_Minor_CompareNetworks_EnumNodes_EnumNetworks_FindObject_QI, hr ); goto Cleanup; } peccnCluster = TraceInterface( L"CTaskAnalyzeCluster!IEnumClusCfgNetworks", IEnumClusCfgNetworks, peccnCluster, 1 ); punk->Release(); punk = NULL; // // Loop thru the configured cluster network to see what matches. // while( hr == S_OK ) { HRESULT hrCluster; BOOL fMatch; // // Cleanup // if ( pccniCluster != NULL ) { pccniCluster->Release(); pccniCluster = NULL; } hr = STHR( peccnCluster->Next( 1, &pccniCluster, &celtDummy ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Find_Devices, TASKID_Minor_CompareNetworks_EnumNodes_EnumNetworks_Cluster_Next, hr ); goto Cleanup; } if ( hr == S_FALSE ) break; // exit condition pccniCluster = TraceInterface( L"CTaskAnalyzeCluster!IClusCfgNetworkInfo", IClusCfgNetworkInfo, pccniCluster, 1 ); hr = THR( pccniCluster->GetUID( &bstrUIDExisting ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Find_Devices, TASKID_Minor_CompareNetworks_EnumNodes_EnumNetworks_Cluster_GetUID, hr ); goto Cleanup; } TraceMemoryAddBSTR( bstrUIDExisting ); fMatch = ( wcscmp( bstrUID, bstrUIDExisting ) == 0 ); TraceSysFreeString( bstrUIDExisting ); if ( !fMatch ) continue; // keep looping // // // If we made it here then we think it truely is the same network. The // rest is stuff we need to fixup during the commit phase. // // // // Exit the loop with S_OK so we don't create a new network. // hr = S_OK; break; // exit loop } // while: S_OK if ( hr == S_FALSE ) { // // Need to create a new object. // Assert( pccni != NULL ); hr = THR( HrCreateNewNetworkInClusterConfiguration( pccni, NULL ) ); if ( FAILED( hr ) ) goto Cleanup; } // if: object not found } while ( hr == S_OK ); // networks } while ( hr == S_OK ); // nodes hr = S_OK; Cleanup: TraceSysFreeString( bstrUID ); TraceSysFreeString( bstrName ); TraceSysFreeString( bstrNotification ); if ( punk != NULL ) { punk->Release(); } if ( pecNodes != NULL ) { pecNodes->Release(); } if ( peccn != NULL ) { peccn->Release(); } if ( peccnCluster != NULL ) { peccnCluster->Release(); } if ( pccni != NULL ) { pccni->Release(); } if ( pccniCluster != NULL ) { pccniCluster->Release(); } if ( pccNode != NULL ) { pccNode->Release(); } HRETURN( hr ); } //*** CTaskAnalyzeCluster::HrCompareNetworks() ////////////////////////////////////////////////////////////////////////////// // // HRESULT // CTaskAnalyzeCluster::HrCreateNewNetworkInClusterConfiguration( // IClusCfgNetworkInfo * pccniIn, // IClusCfgNetworkInfo ** pccniNewOut // ) // ////////////////////////////////////////////////////////////////////////////// HRESULT CTaskAnalyzeCluster::HrCreateNewNetworkInClusterConfiguration( IClusCfgNetworkInfo * pccniIn, IClusCfgNetworkInfo ** ppccniNewOut ) { TraceFunc( "" ); HRESULT hr; OBJECTCOOKIE cookieDummy; BSTR bstrUID = NULL; IUnknown * punk = NULL; IGatherData * pgd = NULL; IClusCfgNetworkInfo * pccni = NULL; // grab the name hr = THR( pccniIn->GetUID( &bstrUID ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Find_Devices, TASKID_Minor_CreateNetwork_GetUID, hr ); goto Cleanup; } TraceMemoryAddBSTR( bstrUID ); // create an object in the object manager. hr = THR( m_pom->FindObject( CLSID_NetworkType, m_cookieCluster, bstrUID, DFGUID_NetworkResource, &cookieDummy, &punk ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Find_Devices, TASKID_Minor_CreateNetwork_FindObject, hr ); goto Cleanup; } // find the IGatherData interface hr = THR( punk->TypeSafeQI( IGatherData, &pgd ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Find_Devices, TASKID_Minor_CreateNetwork_FindObject_QI, hr ); goto Cleanup; } // have the new object gather all information it needs hr = THR( pgd->Gather( m_cookieCluster, pccniIn ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Find_Devices, TASKID_Minor_CreateNetwork_Gather, hr ); goto Cleanup; } // hand the object out if requested if ( ppccniNewOut != NULL ) { // find the IClusCfgManagedResourceInfo hr = THR( punk->TypeSafeQI( IClusCfgNetworkInfo, &pccni ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Find_Devices, TASKID_Minor_CreateNetwork_QI, hr ); goto Cleanup; } *ppccniNewOut = TraceInterface( L"ManagedDevice!ICCNI", IClusCfgNetworkInfo, pccni, 0 ); (*ppccniNewOut)->AddRef(); } Cleanup: TraceSysFreeString( bstrUID ); if ( pccni != NULL ) { pccni->Release(); } if ( pgd != NULL ) { pgd->Release(); } if ( punk != NULL ) { punk->Release(); } HRETURN( hr ); } //*** CTaskAnalyzeCluster::HrCreateNewNetworkInClusterConfiguration() ////////////////////////////////////////////////////////////////////////////// // // // HRESULT // CTaskAnalyzeCluster::HrFreeCookies( void ) // ////////////////////////////////////////////////////////////////////////////// HRESULT CTaskAnalyzeCluster::HrFreeCookies( void ) { TraceFunc( "" ); HRESULT hr; HRESULT hrReturn = S_OK; Assert( m_pom != NULL ); while( m_cCookies != 0 ) { m_cCookies --; if ( m_pcookies[ m_cCookies ] != NULL ) { hr = THR( m_pom->RemoveObject( m_pcookies[ m_cCookies ] ) ); if ( FAILED( hr ) ) { hrReturn = hr; } } } Assert( m_cCookies == 0 ); m_cSubTasksDone = 0; TraceFree( m_pcookies ); m_pcookies = NULL; HRETURN( hrReturn ); } //*** CTaskAnalyzeCluster::HrFreeCookies() ////////////////////////////////////////////////////////////////////////////// // // // HRESULT // CTaskAnalyzeCluster::HrRetrieveCookiesName( // CLSID clsidMajorIn, // OBJECTCOOKIE cookieIn, // BSTR * pbstrNameOut // ) // ////////////////////////////////////////////////////////////////////////////// HRESULT CTaskAnalyzeCluster::HrRetrieveCookiesName( CLSID clsidMajorIn, OBJECTCOOKIE cookieIn, BSTR * pbstrNameOut ) { TraceFunc( "" ); HRESULT hr; IUnknown * punk = NULL; IStandardInfo * psi = NULL; Assert( cookieIn != NULL ); Assert( pbstrNameOut != NULL ); // // Retrieve the node name in case of errors. // hr = THR( m_pom->GetObject( DFGUID_StandardInfo, cookieIn, &punk ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( clsidMajorIn, TASKID_Minor_HrRetrieveCookiesName_FindObject_StandardInfo, hr ); goto Cleanup; } hr = THR( punk->TypeSafeQI( IStandardInfo, &psi ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( clsidMajorIn, TASKID_Minor_HrRetrieveCookiesName_FindObject_StandardInfo_QI_psi, hr ); goto Cleanup; } hr = THR( psi->GetName( pbstrNameOut ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( clsidMajorIn, TASKID_Minor_HrRetrieveCookiesName_GetName, hr ); goto Cleanup; } TraceMemoryAddBSTR( *pbstrNameOut ); Cleanup: if ( punk != NULL ) { punk->Release(); } if ( psi != NULL ) { psi->Release(); } HRETURN( hr ); } //*** CTaskAnalyzeCluster::HrRetrieveCookiesName ////////////////////////////////////////////////////////////////////////////// // // HRESULT // CTaskAnalyzeCluster::HrCheckInteroperability( void ) // ////////////////////////////////////////////////////////////////////////////// HRESULT CTaskAnalyzeCluster::HrCheckInteroperability( void ) { TraceFunc( "" ); Assert( m_pcm != NULL ); HRESULT hr = S_OK; RPC_STATUS rpcs = RPC_S_OK; RPC_BINDING_HANDLE rbhBindingHandle = NULL; LPWSTR pszBindingString = NULL; BSTR bstrNodeName = NULL; BSTR bstrNotification = NULL; BSTR bstrBindingString = NULL; DWORD sc; IUnknown * punk = NULL; bool fAllNodesMatch; DWORD dwSponsorNodeId; DWORD dwClusterHighestVersion; DWORD dwClusterLowestVersion; DWORD dwJoinStatus; DWORD dwNodeHighestVersion; DWORD dwNodeLowestVersion; bool fVersionMismatch = false; IClusCfgServer * piccs = NULL; // // If were are forming there is no need to do this check. // if ( !m_fJoiningMode ) { goto Cleanup; } // if: // // Tell the UI were are starting this. // hr = THR( HrLoadStringIntoBSTR( g_hInstance, IDS_TASKID_MINOR_CHECKINTEROPERABILITY, &bstrNotification ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_HrCheckInteroperability_LoadString_Checking, hr ); goto Cleanup; } hr = THR( SendStatusReport( NULL, TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_CheckInteroperability, 0, 0, 1, S_OK, bstrNotification, NULL, NULL ) ); if ( FAILED( hr ) ) goto Cleanup; // // All nodes must be at the same level diring a bulk add. // hr = STHR( HrEnsureAllJoiningNodesSameVersion( &dwNodeHighestVersion, &dwNodeLowestVersion, &fAllNodesMatch ) ); if ( FAILED( hr ) ) { goto Error; } // if: // // Just bail if no nodes found that are joining, then there isn't a need to // do this check. // if ( hr == S_FALSE ) goto Cleanup; if ( !fAllNodesMatch ) { hr = THR( HRESULT_FROM_WIN32( ERROR_CLUSTER_INCOMPATIBLE_VERSIONS ) ); goto Cleanup; } // if: hr = THR( m_pcm->GetConnectionToObject( m_cookieCluster, &punk ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_HrCheckInteroperability_GetConnectionObject, hr ); goto Cleanup; } // if: hr = THR( punk->TypeSafeQI( IClusCfgServer, &piccs ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_HrCheckInteroperability_ConfigConnection_QI, hr ); goto Error; } // if: hr = THR( piccs->GetBindingString( &bstrBindingString ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_HrCheckInteroperability_GetBindingString, hr ); goto Error; } // if: TraceMemoryAddBSTR( bstrBindingString ); // Create a string binding handle. rpcs = TW32( RpcStringBindingComposeW( L"6e17aaa0-1a47-11d1-98bd-0000f875292e" , L"ncadg_ip_udp" , bstrBindingString , NULL , NULL , &pszBindingString ) ); if ( rpcs != RPC_S_OK ) { SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_HrCheckInteroperability_RpcStringBindingComposeW, hr ); goto RpcError; } // if: RpcStringBindingComposeW() failed // Get the actual binding handle rpcs = TW32( RpcBindingFromStringBindingW( pszBindingString, &rbhBindingHandle ) ); if ( rpcs != RPC_S_OK ) { SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_HrCheckInteroperability_RpcBindingFromStringBindingW, hr ); goto RpcError; } // if: RpcBindingFromStringBindingW() failed // Resolve the binding handle rpcs = TW32( RpcEpResolveBinding( rbhBindingHandle, JoinVersion_v2_0_c_ifspec ) ); if ( rpcs != RPC_S_OK ) { SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_HrCheckInteroperability_RpcEpResolveBinding, hr ); goto RpcError; } // if: RpcEpResolveBinding() failed // Set RPC security rpcs = TW32( RpcBindingSetAuthInfoW( rbhBindingHandle , NULL , RPC_C_AUTHN_LEVEL_CONNECT , RPC_C_AUTHN_WINNT , NULL , RPC_C_AUTHZ_NAME ) ); if ( rpcs != RPC_S_OK ) { SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_HrCheckInteroperability_RpcBindingSetAuthInfoW, hr ); goto RpcError; } // if: RpcBindingSetAuthInfoW() failed // // Get and verify the sponsor version // // // From Whistler onwards, CsRpcGetJoinVersionData() will return a failure code in its last parameter // if the version of this node is not compatible with the sponsor version. Prior to this, the last // parameter always contained a success value and the cluster versions had to be compared subsequent to this // call. This will, however, still have to be done as long as interoperability with Win2K // is a requirement, since Win2K sponsors do not return an error in the last parameter. // sc = TW32( CsRpcGetJoinVersionData( rbhBindingHandle , 0 , dwNodeHighestVersion , dwNodeLowestVersion , &dwSponsorNodeId , &dwClusterHighestVersion , &dwClusterLowestVersion , &dwJoinStatus ) ); if ( sc != ERROR_SUCCESS ) { hr = HRESULT_FROM_WIN32( sc ); SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_HrCheckInteroperability_CsRpcGetJoinVersionData, hr ); goto Cleanup; } // if: CsRpcGetJoinVersionData() failed LogMsg( "[MT] ( Node Highest, Node Lowest ) = ( %#08x, %#08x ), ( Cluster Highest, Cluster Lowest ) = ( %#08x, %#08x )." , dwNodeHighestVersion , dwNodeLowestVersion , dwClusterHighestVersion , dwClusterLowestVersion ); if ( dwJoinStatus == ERROR_SUCCESS ) { DWORD dwClusterMajorVersion = CLUSTER_GET_MAJOR_VERSION( dwClusterHighestVersion ); Assert( dwClusterMajorVersion >= ( CLUSTER_INTERNAL_CURRENT_MAJOR_VERSION - 1 ) ); // // Only want to join clusters that are no more than one version back. // if ( dwClusterMajorVersion < ( CLUSTER_INTERNAL_CURRENT_MAJOR_VERSION - 1 ) ) { fVersionMismatch = true; } // if: } // if: the join status was ok else { fVersionMismatch = true; } // else: join is not possible if ( fVersionMismatch ) { hr = THR( HRESULT_FROM_WIN32( ERROR_CLUSTER_INCOMPATIBLE_VERSIONS ) ); } // if: there was a version mismatch else { Assert( hr == S_OK ); } goto UpdateStatus; RpcError: hr = HRESULT_FROM_WIN32( rpcs ); Error: UpdateStatus: { HRESULT hr2; hr2 = THR( SendStatusReport( NULL, TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_CheckInteroperability, 0, 1, 1, hr, NULL, NULL, NULL ) ); if ( FAILED( hr2 ) ) { hr = hr2; } } Cleanup: if ( punk != NULL ) { punk->Release(); } // if: if ( rbhBindingHandle != NULL ) { RpcBindingFree( &rbhBindingHandle ); } // if: if ( pszBindingString != NULL ) { RpcStringFree( &pszBindingString ); } // if: if ( piccs != NULL ) { piccs->Release(); } // if: TraceSysFreeString( bstrNotification ); TraceSysFreeString( bstrNodeName ); TraceSysFreeString( bstrBindingString ); HRETURN( hr ); } //*** CTaskAnalyzeCluster::HrCheckInteroperability() ////////////////////////////////////////////////////////////////////////////// // // HRESULT // CTaskAnalyzeCluster::HrEnsureAllJoiningNodesSameVersion( // DWORD * pdwNodeHighestVersionOut, // DWORD * pdwNodeLowestVersionOut, // bool * pfAllNodesMatchOut // ) // ////////////////////////////////////////////////////////////////////////////// HRESULT CTaskAnalyzeCluster::HrEnsureAllJoiningNodesSameVersion( DWORD * pdwNodeHighestVersionOut, DWORD * pdwNodeLowestVersionOut, bool * pfAllNodesMatchOut ) { TraceFunc( "" ); Assert( m_fJoiningMode ); Assert( pdwNodeHighestVersionOut != NULL ); Assert( pdwNodeLowestVersionOut != NULL ); Assert( pfAllNodesMatchOut != NULL ); HRESULT hr = S_OK; OBJECTCOOKIE cookieDummy; IUnknown * punk = NULL; IEnumNodes * pen = NULL; IClusCfgNodeInfo * pccni = NULL; DWORD rgdwNodeHighestVersion[ 2 ]; DWORD rgdwNodeLowestVersion[ 2 ]; int idx = 0; BSTR bstrDescription = NULL; BSTR bstrNodeName = NULL; BSTR bstrFirstNodeName = NULL; BOOL fFoundAtLeastOneJoiningNode = FALSE; *pfAllNodesMatchOut = true; ZeroMemory( rgdwNodeHighestVersion, sizeof( rgdwNodeHighestVersion ) ); ZeroMemory( rgdwNodeLowestVersion, sizeof( rgdwNodeLowestVersion ) ); // // Ask the object manager for the node enumerator. // hr = THR( m_pom->FindObject( CLSID_NodeType, m_cookieCluster, NULL, DFGUID_EnumNodes, &cookieDummy, &punk ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_HrEnsureAllJoiningNodesSameVersion_FindObject, hr ); goto Cleanup; } hr = THR( punk->TypeSafeQI( IEnumNodes, &pen ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_HrEnsureAllJoiningNodesSameVersion_FindObject_QI, hr ); goto Cleanup; } // // Look at each node and ensure that they all have the same version. // Assert( SUCCEEDED( hr ) ); while ( SUCCEEDED( hr ) ) { ULONG celtDummy; // // Cleanup // if ( pccni != NULL ) { pccni->Release(); pccni = NULL; } // if: // // Get the next node. // hr = STHR( pen->Next( 1, &pccni, &celtDummy ) ); if ( hr == S_FALSE ) { break; // exit condition } // if: if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_HrEnsureAllJoiningNodesSameVersion_EnumNode_Next, hr ); goto Cleanup; } // if: hr = STHR( pccni->IsMemberOfCluster() ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_HrEnsureAllJoiningNodesSameVersion_Node_IsMemberOfCluster, hr ); goto Cleanup; } // if: // // Only want to check those nodes that are not already members of a cluster. The nodes being added. // if ( hr == S_FALSE ) { fFoundAtLeastOneJoiningNode = TRUE; hr = THR( pccni->GetClusterVersion( &rgdwNodeHighestVersion[ idx ], &rgdwNodeLowestVersion[ idx ] ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_HrEnsureAllJoiningNodesSameVersion_Node_GetClusterVersion, hr ); goto Cleanup; } // if: idx++; // // Need to get the another node's version. // if ( idx == 1 ) { WCHAR * psz = NULL; hr = THR( pccni->GetName( &bstrFirstNodeName ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_HrEnsureAllJoiningNodesSameVersion_GetName, hr ); goto Cleanup; } // if: psz = wcschr( bstrFirstNodeName, L'.' ); if ( psz != NULL ) { *psz = L'\0'; // change from an FQDN to a simple node name. } // if: continue; } // if: // // Let's compare two nodes at a time... // if ( idx == 2 ) { if ( ( rgdwNodeHighestVersion[ 0 ] == rgdwNodeHighestVersion[ 1 ] ) && ( rgdwNodeLowestVersion[ 1 ] == rgdwNodeLowestVersion[ 1 ] ) ) { idx = 1; // reset to put the next node's version values at the second position... continue; } // if: else { *pfAllNodesMatchOut = false; hr = THR( pccni->GetName( &bstrNodeName ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_HrEnsureAllJoiningNodesSameVersion_GetName, hr ); goto Cleanup; } // if: hr = THR( HrFormatStringIntoBSTR( g_hInstance, IDS_TASKID_MINOR_NODES_VERSION_MISMATCH, &bstrDescription, bstrFirstNodeName ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_HrEnsureAllJoiningNodesSameVersion_FormatString, hr ); goto Cleanup; } // if: hr = THR( SendStatusReport( bstrNodeName, TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_CheckInteroperability, 0, 0, 1, HRESULT_FROM_WIN32( ERROR_CLUSTER_INCOMPATIBLE_VERSIONS ), bstrDescription, NULL, NULL ) ); goto Cleanup; } // else: } // if: } // if: } // while: hr if ( !fFoundAtLeastOneJoiningNode ) { THR( HrLoadStringIntoBSTR( g_hInstance, IDS_TASKID_MINOR_NO_JOINING_NODES_FOUND_FOR_VERSION_CHECK, &bstrDescription ) ); hr = THR( SendStatusReport( NULL, TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_CheckInteroperability, 0, 1, 1, S_FALSE, bstrDescription, NULL, NULL ) ); hr = S_FALSE; goto Cleanup; } // // Fill in the out args... // *pdwNodeHighestVersionOut = rgdwNodeHighestVersion[ 0 ]; *pdwNodeLowestVersionOut = rgdwNodeLowestVersion[ 0 ]; hr = S_OK; Cleanup: if ( pccni != NULL ) { pccni->Release(); } // if: if ( pen != NULL ) { pen->Release(); } // if: if ( punk != NULL ) { punk->Release(); } // if: TraceSysFreeString( bstrNodeName ); TraceSysFreeString( bstrFirstNodeName ); TraceSysFreeString( bstrDescription ); HRETURN( hr ); } //*** CTaskAnalyzeCluster::HrEnsureAllJoiningNodesSameVersion() ////////////////////////////////////////////////////////////////////////////// // // HRESULT // CTaskAnalyzeCluster::HrGetUsersNodesCookies( void ) // ////////////////////////////////////////////////////////////////////////////// HRESULT CTaskAnalyzeCluster::HrGetUsersNodesCookies( void ) { TraceFunc( "" ); HRESULT hr; ULONG ulDummy; OBJECTCOOKIE cookie; OBJECTCOOKIE cookieDummy; ULONG cNode; IUnknown * punk = NULL; IEnumCookies * pec = NULL; // // Get the cookie enumerator. // hr = THR( m_pom->FindObject( CLSID_NodeType, m_cookieCluster, NULL, DFGUID_EnumCookies, &cookieDummy, &punk ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Establish_Connection, TASKID_Minor_GetUsersNodesCookies_FindObject, hr ); goto Cleanup; } hr = THR( punk->TypeSafeQI( IEnumCookies, &pec ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Establish_Connection, TASKID_Minor_GetUsersNodesCookies_FindObject_QI, hr ); goto Cleanup; } pec = TraceInterface( L"CTaskAnalyzeCluster!IEnumCookies", IEnumCookies, pec, 1 ); punk->Release(); punk = NULL; // // Enumerate the cookies to figure out how big a buffer to allocate. // for ( m_cUserNodes = 0; ; ) { hr = STHR( pec->Next( 1, &cookie, &ulDummy ) ); if ( hr == S_FALSE ) break; // exit condition if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Establish_Connection, TASKID_Minor_GetUsersNodesCookies_EnumCookies_Next, hr ); goto Cleanup; } m_cUserNodes ++; } // for: ever // // Allocate a buffer for the cookies. // m_pcookiesUser = (OBJECTCOOKIE *) TraceAlloc( 0, sizeof( OBJECTCOOKIE ) * m_cUserNodes ); if ( m_pcookiesUser == NULL ) goto OutOfMemory; // // Reset the enumerator. // hr = THR( pec->Reset() ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Establish_Connection, TASKID_Minor_GetUsersNodesCookies_EnumCookies_Reset, hr ); goto Cleanup; } // // Enumerate them again this time putting the cookies into the buffer. // for ( cNode = 0; cNode < m_cUserNodes; cNode ++ ) { hr = THR( pec->Next( 1, &m_pcookiesUser[ cNode ], &ulDummy ) ); AssertMsg( hr != S_FALSE, "We should never hit this because the count of nodes should change!" ); if ( hr != S_OK ) { SSR_ANALYSIS_FAILED( TASKID_Major_Establish_Connection, TASKID_Minor_GetUsersNodesCookies_EnumCookies_Next2, hr ); goto Cleanup; } } // for: Assert( cNode == m_cUserNodes ); #ifdef DEBUG hr = STHR( pec->Next( 1, &cookie, &ulDummy ) ); Assert( hr == S_FALSE ); #endif hr = S_OK; Cleanup: if ( punk != NULL ) { punk->Release(); } if ( pec != NULL ) { pec->Release(); } HRETURN( hr ); OutOfMemory: hr = E_OUTOFMEMORY; SSR_ANALYSIS_FAILED( TASKID_Major_Establish_Connection, TASKID_Minor_GetUsersNodesCookies_OutOfMemory, hr ); goto Cleanup; } //*** CTaskAnalyzeCluster::HrGetUsersNodesCookies() ////////////////////////////////////////////////////////////////////////////// // // HRESULT // CTaskAnalyzeCluster::HrIsUserAddedNode( BSTR bstrNodeNameIn ) // ////////////////////////////////////////////////////////////////////////////// HRESULT CTaskAnalyzeCluster::HrIsUserAddedNode( BSTR bstrNodeNameIn ) { TraceFunc( "HrGetUsersNodesCookies( ... )\n" ); HRESULT hr; ULONG cNode; IUnknown * punk = NULL; IClusCfgNodeInfo * pccni = NULL; BSTR bstrNodeName = NULL; for ( cNode = 0; cNode < m_cUserNodes; cNode ++ ) { hr = THR( m_pom->GetObject( DFGUID_NodeInformation, m_pcookiesUser[ cNode ], &punk ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_HrIsUserAddedNode_GetObject, hr ); goto Cleanup; } // if: hr = THR( punk->TypeSafeQI( IClusCfgNodeInfo, &pccni ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_HrIsUserAddedNode_GetObject_QI, hr ); goto Cleanup; } punk->Release(); punk = NULL; hr = THR( pccni->GetName( &bstrNodeName ) ); if ( FAILED( hr ) ) { SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_HrIsUserAddedNode_GetName, hr ); goto Cleanup; } TraceMemoryAddBSTR( bstrNodeName ); pccni->Release(); pccni = NULL; if ( wcscmp( bstrNodeNameIn, bstrNodeName ) == 0 ) { hr = S_OK; break; } // if: TraceSysFreeString( bstrNodeName ); bstrNodeName = NULL; hr = S_FALSE; } // for: Cleanup: if ( pccni != NULL ) { pccni->Release(); } // if: if ( punk != NULL ) { punk->Release(); } // if: TraceSysFreeString( bstrNodeName ); HRETURN( hr ); } //*** CTaskAnalyzeCluster::HrIsUserAddedNode()