Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

7441 lines
216 KiB

  1. //////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) 2002 Microsoft Corporation
  4. //
  5. // Module Name:
  6. // TaskAnalyzeClusterBase.cpp
  7. //
  8. // Description:
  9. // CTaskAnalyzeClusterBase implementation.
  10. //
  11. // Maintained By:
  12. // Galen Barbee (GalenB) 01-APR-2002
  13. //
  14. //////////////////////////////////////////////////////////////////////////////
  15. //////////////////////////////////////////////////////////////////////////////
  16. // Include Files
  17. //////////////////////////////////////////////////////////////////////////////
  18. #include "Pch.h"
  19. #include "TaskAnalyzeClusterBase.h"
  20. #include "ManagedResource.h"
  21. #include <NameUtil.h>
  22. // For CsRpcGetJoinVersionData() and constants like JoinVersion_v2_0_c_ifspec
  23. #include <StatusReports.h>
  24. //////////////////////////////////////////////////////////////////////////////
  25. // Constant Definitions
  26. //////////////////////////////////////////////////////////////////////////////
  27. DEFINE_THISCLASS( "CTaskAnalyzeClusterBase" )
  28. #define CHECKING_TIMEOUT 90 // seconds
  29. //*************************************************************************//
  30. /////////////////////////////////////////////////////////////////////////////
  31. // CTaskAnalyzeClusterBase class
  32. /////////////////////////////////////////////////////////////////////////////
  33. //////////////////////////////////////////////////////////////////////////////
  34. //++
  35. //
  36. // CTaskAnalyzeClusterBase::CTaskAnalyzeClusterBase
  37. //
  38. // Description:
  39. // Construcor
  40. //
  41. // Arguments:
  42. // None.
  43. //
  44. // Return Values:
  45. // None.
  46. //
  47. //--
  48. //////////////////////////////////////////////////////////////////////////////
  49. CTaskAnalyzeClusterBase::CTaskAnalyzeClusterBase( void )
  50. : m_cRef( 1 )
  51. {
  52. TraceFunc( "" );
  53. InterlockedIncrement( &g_cObjects );
  54. TraceFuncExit();
  55. } //*** CTaskAnalyzeClusterBase::CTaskAnalyzeClusterBase
  56. //////////////////////////////////////////////////////////////////////////////
  57. //++
  58. //
  59. // CTaskAnalyzeClusterBase::~CTaskAnalyzeClusterBase
  60. //
  61. // Description:
  62. // Destrucor
  63. //
  64. // Arguments:
  65. // None.
  66. //
  67. // Return Values:
  68. // None.
  69. //
  70. //--
  71. //////////////////////////////////////////////////////////////////////////////
  72. CTaskAnalyzeClusterBase::~CTaskAnalyzeClusterBase( void )
  73. {
  74. TraceFunc( "" );
  75. ULONG idx;
  76. for ( idx = 0; idx < m_idxQuorumToCleanupNext; idx++ )
  77. {
  78. ((*m_prgQuorumsToCleanup)[ idx ])->Release();
  79. } // for:
  80. TraceFree( m_prgQuorumsToCleanup );
  81. // m_cRef
  82. // m_cookieCompletion
  83. if ( m_pcccb != NULL )
  84. {
  85. m_pcccb->Release();
  86. }
  87. if ( m_pcookies != NULL )
  88. {
  89. THR( HrFreeCookies() );
  90. }
  91. // m_cCookies
  92. // m_cNodes
  93. if ( m_event != NULL )
  94. {
  95. CloseHandle( m_event );
  96. }
  97. // m_cookieCluster
  98. TraceMoveFromMemoryList( m_bstrClusterName, g_GlobalMemoryList );
  99. TraceSysFreeString( m_bstrClusterName );
  100. TraceSysFreeString( m_bstrNodeName );
  101. // m_fJoiningMode
  102. // m_cUserNodes
  103. TraceFree( m_pcookiesUser );
  104. if ( m_pnui != NULL )
  105. {
  106. m_pnui->Release();
  107. }
  108. if ( m_pom != NULL )
  109. {
  110. m_pom->Release();
  111. }
  112. if ( m_ptm != NULL )
  113. {
  114. m_ptm->Release();
  115. }
  116. if ( m_pcm != NULL )
  117. {
  118. m_pcm->Release();
  119. } // if:
  120. TraceSysFreeString( m_bstrQuorumUID );
  121. // m_cSubTasksDone
  122. // m_hrStatus
  123. InterlockedDecrement( &g_cObjects );
  124. TraceFuncExit();
  125. } //*** CTaskAnalyzeClusterBase::~CTaskAnalyzeClusterBase
  126. //*************************************************************************//
  127. /////////////////////////////////////////////////////////////////////////////
  128. // CTaskAnalyzeClusterBase - IUknkown interface.
  129. /////////////////////////////////////////////////////////////////////////////
  130. //////////////////////////////////////////////////////////////////////////////
  131. //++
  132. //
  133. // CTaskAnalyzeClusterBase::UlAddRef
  134. //
  135. // Description:
  136. // Increment the reference count of this object by one.
  137. //
  138. // Arguments:
  139. // None.
  140. //
  141. // Return Value:
  142. // The new reference count.
  143. //
  144. //--
  145. //////////////////////////////////////////////////////////////////////////////
  146. ULONG
  147. CTaskAnalyzeClusterBase::UlAddRef( void )
  148. {
  149. TraceFunc( "[IUnknown]" );
  150. InterlockedIncrement( &m_cRef );
  151. CRETURN( m_cRef );
  152. } //*** CTaskAnalyzeClusterBase::UlAddRef
  153. //////////////////////////////////////////////////////////////////////////////
  154. //++
  155. //
  156. // CTaskAnalyzeClusterBase::UlRelease
  157. //
  158. // Description:
  159. // Decrement the reference count of this object by one.
  160. //
  161. // Arguments:
  162. // None.
  163. //
  164. // Return Value:
  165. // The new reference count.
  166. //
  167. //--
  168. //////////////////////////////////////////////////////////////////////////////
  169. ULONG
  170. CTaskAnalyzeClusterBase::UlRelease( void )
  171. {
  172. TraceFunc( "[IUnknown]" );
  173. LONG cRef;
  174. cRef = InterlockedDecrement( &m_cRef );
  175. if ( cRef == 0 )
  176. {
  177. TraceDo( delete this );
  178. }
  179. CRETURN( cRef );
  180. } //*** CTaskAnalyzeClusterBase::UlRelease
  181. //*************************************************************************//
  182. /////////////////////////////////////////////////////////////////////////////
  183. // CTaskAnalyzeClusterBase - IDoTask/ITaskAnalyzeCluster interface.
  184. /////////////////////////////////////////////////////////////////////////////
  185. //////////////////////////////////////////////////////////////////////////////
  186. //++
  187. //
  188. // CTaskAnalyzeClusterBase::HrBeginTask
  189. //
  190. // Description:
  191. // Task entry point.
  192. //
  193. // Arguments:
  194. // None.
  195. //
  196. // Return Value:
  197. // S_OK
  198. // Success
  199. //
  200. // HRESULT failure.
  201. //
  202. //--
  203. //////////////////////////////////////////////////////////////////////////////
  204. HRESULT
  205. CTaskAnalyzeClusterBase::HrBeginTask( void )
  206. {
  207. TraceFunc( "[IDoTask]" );
  208. HRESULT hr;
  209. DWORD dwCookie = 0;
  210. TraceFlow1( "[MT] CTaskAnalyzeClusterBase::BeginTask() Thread id %d", GetCurrentThreadId() );
  211. IServiceProvider * psp = NULL;
  212. IConnectionPointContainer * pcpc = NULL;
  213. IConnectionPoint * pcp = NULL;
  214. TraceInitializeThread( L"" );
  215. LogMsg( L"[MT] [CTaskAnalyzeClusterBase] Beginning task..." );
  216. //
  217. // Gather the managers we need to complete the task.
  218. //
  219. hr = THR( CoCreateInstance( CLSID_ServiceManager, NULL, CLSCTX_INPROC_SERVER, TypeSafeParams( IServiceProvider, &psp ) ) );
  220. if ( FAILED( hr ) )
  221. {
  222. SSR_ANALYSIS_FAILED( TASKID_Major_Checking_For_Existing_Cluster, TASKID_Minor_BeginTask_CoCreate_Service_Manager, hr );
  223. goto Cleanup;
  224. }
  225. Assert( m_pnui == NULL );
  226. Assert( m_ptm == NULL );
  227. Assert( m_pom == NULL );
  228. hr = THR( psp->TypeSafeQS( CLSID_NotificationManager, IConnectionPointContainer, &pcpc ) );
  229. if ( FAILED( hr ) )
  230. {
  231. SSR_ANALYSIS_FAILED( TASKID_Major_Checking_For_Existing_Cluster, TASKID_Minor_BeginTask_QueryService_Notification_Manager, hr );
  232. goto Cleanup;
  233. }
  234. hr = THR( pcpc->FindConnectionPoint( IID_INotifyUI, &pcp ) );
  235. if ( FAILED( hr ) )
  236. {
  237. SSR_ANALYSIS_FAILED( TASKID_Major_Checking_For_Existing_Cluster, TASKID_Minor_BeginTask_NotificationMan_FindConnectionPoint, hr );
  238. goto Cleanup;
  239. }
  240. pcp = TraceInterface( L"CTaskAnalyzeClusterBase!IConnectionPoint", IConnectionPoint, pcp, 1 );
  241. hr = THR( pcp->TypeSafeQI( INotifyUI, &m_pnui ) );
  242. if ( FAILED( hr ) )
  243. {
  244. SSR_ANALYSIS_FAILED( TASKID_Major_Checking_For_Existing_Cluster, TASKID_Minor_BeginTask_NotificationMan_FindConnectionPoint_QI_INotifyUI, hr );
  245. goto Cleanup;
  246. }
  247. hr = THR( psp->TypeSafeQS( CLSID_TaskManager, ITaskManager, &m_ptm ) );
  248. if ( FAILED( hr ) )
  249. {
  250. SSR_ANALYSIS_FAILED( TASKID_Major_Checking_For_Existing_Cluster, TASKID_Minor_BeginTask_QueryService_TaskManager, hr );
  251. goto Cleanup;
  252. }
  253. hr = THR( psp->TypeSafeQS( CLSID_ObjectManager, IObjectManager, &m_pom ) );
  254. if ( FAILED( hr ) )
  255. {
  256. SSR_ANALYSIS_FAILED( TASKID_Major_Checking_For_Existing_Cluster, TASKID_Minor_BeginTask_QueryService_ObjectManager, hr );
  257. goto Cleanup;
  258. }
  259. hr = THR( psp->TypeSafeQS( CLSID_ClusterConnectionManager, IConnectionManager, &m_pcm ) );
  260. if ( FAILED( hr ) )
  261. {
  262. SSR_ANALYSIS_FAILED( TASKID_Major_Checking_For_Existing_Cluster, TASKID_Minor_BeginTask_QueryService_ConnectionManager, hr );
  263. goto Cleanup;
  264. } // if:
  265. //
  266. // Release the Service Manager.
  267. //
  268. psp->Release();
  269. psp = NULL;
  270. //
  271. // Create an event to wait upon.
  272. //
  273. m_event = CreateEvent( NULL, TRUE, FALSE, NULL );
  274. if ( m_event == NULL )
  275. {
  276. hr = HRESULT_FROM_WIN32( TW32( GetLastError() ) );
  277. SSR_ANALYSIS_FAILED( TASKID_Major_Client_And_Server_Log, TASKID_Minor_BeginTask_Win32Error, hr );
  278. goto Cleanup;
  279. }
  280. //
  281. // Register with the Notification Manager to get notified.
  282. //
  283. Assert( ( m_cCookies == 0 ) && ( m_pcookies == NULL ) && ( m_cSubTasksDone == 0 ) );
  284. hr = THR( pcp->Advise( static_cast< INotifyUI * >( this ), &dwCookie ) );
  285. if ( FAILED( hr ) )
  286. {
  287. SSR_ANALYSIS_FAILED( TASKID_Major_Establish_Connection, TASKID_Minor_BeginTask_Advise, hr );
  288. goto Cleanup;
  289. }
  290. //
  291. // Wait for the cluster connection to stablize.
  292. //
  293. hr = STHR( HrWaitForClusterConnection() );
  294. if ( FAILED( hr ) )
  295. {
  296. goto Cleanup;
  297. }
  298. if ( FAILED( m_hrStatus ) )
  299. {
  300. hr = THR( m_hrStatus );
  301. goto Cleanup;
  302. }
  303. Assert( m_bstrClusterName != NULL );
  304. //
  305. // Tell the UI layer we are starting this task.
  306. //
  307. hr = THR( SendStatusReport( m_bstrNodeName,
  308. TASKID_Major_Update_Progress,
  309. TASKID_Major_Establish_Connection,
  310. 0,
  311. CHECKING_TIMEOUT,
  312. 0,
  313. S_OK,
  314. NULL,
  315. NULL,
  316. NULL
  317. ) );
  318. if ( FAILED( hr ) )
  319. {
  320. goto Cleanup;
  321. } // if:
  322. //
  323. // Count the number of nodes to be analyzed.
  324. //
  325. hr = STHR( HrCountNumberOfNodes() );
  326. if ( FAILED( hr ) )
  327. {
  328. goto Cleanup;
  329. }
  330. if ( FAILED( m_hrStatus ) )
  331. {
  332. hr = THR( m_hrStatus );
  333. goto Cleanup;
  334. }
  335. //
  336. // Create separate tasks to gather node information.
  337. //
  338. hr = STHR( HrCreateSubTasksToGatherNodeInfo() );
  339. if ( FAILED( hr ) )
  340. {
  341. goto Cleanup;
  342. }
  343. if ( FAILED( m_hrStatus ) )
  344. {
  345. hr = THR( m_hrStatus );
  346. goto Cleanup;
  347. }
  348. //
  349. // Tell the UI layer we have completed this task.
  350. //
  351. hr = THR( SendStatusReport( m_bstrNodeName,
  352. TASKID_Major_Update_Progress,
  353. TASKID_Major_Establish_Connection,
  354. 0,
  355. CHECKING_TIMEOUT,
  356. CHECKING_TIMEOUT,
  357. S_OK,
  358. NULL,
  359. NULL,
  360. NULL
  361. ) );
  362. if ( FAILED( hr ) )
  363. {
  364. goto Cleanup;
  365. } // if:
  366. //
  367. // Create separate tasks to gather node resources and networks.
  368. //
  369. hr = STHR( HrCreateSubTasksToGatherNodeResourcesAndNetworks() );
  370. if ( FAILED( hr ) )
  371. {
  372. goto Cleanup;
  373. }
  374. if ( FAILED( m_hrStatus ) )
  375. {
  376. hr = THR( m_hrStatus );
  377. goto Cleanup;
  378. }
  379. //
  380. // Count the number of nodes to be analyzed again. TaskGatherInformation
  381. // will delete the cookies of unresponsive nodes.
  382. //
  383. hr = STHR( HrCountNumberOfNodes() );
  384. if ( FAILED( hr ) )
  385. {
  386. goto Cleanup;
  387. }
  388. if ( FAILED( m_hrStatus ) )
  389. {
  390. hr = THR( m_hrStatus );
  391. goto Cleanup;
  392. }
  393. //
  394. // Create the feasibility task.
  395. //
  396. hr = STHR( HrCheckClusterFeasibility() );
  397. if ( FAILED( hr ) )
  398. {
  399. goto Cleanup;
  400. }
  401. if ( FAILED( m_hrStatus ) )
  402. {
  403. hr = THR( m_hrStatus );
  404. goto Cleanup;
  405. }
  406. Cleanup:
  407. STHR( HrCleanupTask( hr ) );
  408. if ( psp != NULL )
  409. {
  410. psp->Release();
  411. }
  412. if ( pcpc != NULL )
  413. {
  414. pcpc->Release();
  415. }
  416. if ( pcp != NULL )
  417. {
  418. HRESULT hr2;
  419. hr2 = THR( pcp->Unadvise( dwCookie ) );
  420. if ( FAILED( hr2 ) )
  421. {
  422. SSR_ANALYSIS_FAILED( TASKID_Major_Client_And_Server_Log, TASKID_Minor_BeginTask_Unadvise, hr2 );
  423. }
  424. pcp->Release();
  425. }
  426. if ( m_cookieCompletion != 0 )
  427. {
  428. if ( m_pom != NULL )
  429. {
  430. HRESULT hr2;
  431. IUnknown * punk;
  432. hr2 = THR( m_pom->GetObject( DFGUID_StandardInfo, m_cookieCompletion, &punk ) );
  433. if ( SUCCEEDED( hr2 ) )
  434. {
  435. IStandardInfo * psi;
  436. hr2 = THR( punk->TypeSafeQI( IStandardInfo, &psi ) );
  437. punk->Release();
  438. if ( SUCCEEDED( hr2 ) )
  439. {
  440. hr2 = THR( psi->SetStatus( hr ) );
  441. psi->Release();
  442. }
  443. else
  444. {
  445. SSR_ANALYSIS_FAILED( TASKID_Major_Client_And_Server_Log, TASKID_Minor_BeginTask_SetStatus, hr2 );
  446. }
  447. }
  448. else
  449. {
  450. SSR_ANALYSIS_FAILED( TASKID_Major_Client_And_Server_Log, TASKID_Minor_BeginTask_GetObject, hr2 );
  451. }
  452. }
  453. if ( m_pnui != NULL )
  454. {
  455. //
  456. // Have the notification manager signal the completion cookie.
  457. //
  458. HRESULT hr2 = THR( m_pnui->ObjectChanged( m_cookieCompletion ) );
  459. if ( FAILED( hr2 ) )
  460. {
  461. SSR_ANALYSIS_FAILED( TASKID_Major_Client_And_Server_Log, TASKID_Minor_BeginTask_ObjectChanged, hr2 );
  462. hr = hr2;
  463. } // if:
  464. } // if:
  465. m_cookieCompletion = 0;
  466. } // if: completion cookie was obtained
  467. LogMsg( L"[MT] [CTaskAnalyzeClusterBase] Exiting task. The task was%ws cancelled.", m_fStop == FALSE ? L" not" : L"" );
  468. HRETURN( hr );
  469. } //*** CTaskAnalyzeClusterBase::HrBeginTask
  470. //////////////////////////////////////////////////////////////////////////////
  471. //++
  472. //
  473. // CTaskAnalyzeClusterBase::HrStopTask
  474. //
  475. // Description:
  476. // Stop task entry point.
  477. //
  478. // Arguments:
  479. // None.
  480. //
  481. // Return Value:
  482. // S_OK
  483. // Success
  484. //
  485. // HRESULT failure.
  486. //
  487. //--
  488. //////////////////////////////////////////////////////////////////////////////
  489. HRESULT
  490. CTaskAnalyzeClusterBase::HrStopTask( void )
  491. {
  492. TraceFunc( "[IDoTask]" );
  493. HRESULT hr = S_OK;
  494. m_fStop = TRUE;
  495. LogMsg( L"[MT] [CTaskAnalyzeClusterBase] Calling StopTask() on all remaining sub-tasks." );
  496. THR( HrNotifyAllTasksToStop() );
  497. HRETURN( hr );
  498. } //*** CTaskAnalyzeClusterBase::HrStopTask
  499. //////////////////////////////////////////////////////////////////////////////
  500. //++
  501. //
  502. // CTaskAnalyzeClusterBase::HrSetJoiningMode
  503. //
  504. // Description:
  505. // Tell this task whether we are joining nodes to the cluster?
  506. //
  507. // Arguments:
  508. // None.
  509. //
  510. // Return Value:
  511. // S_OK
  512. // Success
  513. //
  514. // HRESULT failure.
  515. //
  516. //--
  517. //////////////////////////////////////////////////////////////////////////////
  518. HRESULT
  519. CTaskAnalyzeClusterBase::HrSetJoiningMode( void )
  520. {
  521. TraceFunc( "" );
  522. HRESULT hr = S_OK;
  523. m_fJoiningMode = TRUE;
  524. HRETURN( hr );
  525. } //*** CTaskAnalyzeClusterBase::HrSetJoiningMode
  526. //////////////////////////////////////////////////////////////////////////////
  527. //++
  528. //
  529. // CTaskAnalyzeClusterBase::HrSetCookie
  530. //
  531. // Description:
  532. // Receive the completion cookier from the task creator.
  533. //
  534. // Arguments:
  535. // cookieIn
  536. // The completion cookie to send back to the creator when this
  537. // task is complete.
  538. //
  539. // Return Value:
  540. // S_OK
  541. // Success
  542. //
  543. // HRESULT failure.
  544. //
  545. //--
  546. //////////////////////////////////////////////////////////////////////////////
  547. HRESULT
  548. CTaskAnalyzeClusterBase::HrSetCookie(
  549. OBJECTCOOKIE cookieIn
  550. )
  551. {
  552. TraceFunc( "" );
  553. HRESULT hr = S_OK;
  554. m_cookieCompletion = cookieIn;
  555. HRETURN( hr );
  556. } //*** CTaskAnalyzeClusterBase::HrSetCookie
  557. //////////////////////////////////////////////////////////////////////////////
  558. //++
  559. //
  560. // CTaskAnalyzeClusterBase::HrSetClusterCookie
  561. //
  562. // Description:
  563. // Receive the object manager cookie of the cluster that we are going
  564. // to analyze.
  565. //
  566. // Arguments:
  567. // cookieClusterIn
  568. // The cookie for the cluster to work on.
  569. //
  570. // Return Value:
  571. // S_OK
  572. // Success
  573. //
  574. // HRESULT failure.
  575. //
  576. //--
  577. //////////////////////////////////////////////////////////////////////////////
  578. HRESULT
  579. CTaskAnalyzeClusterBase::HrSetClusterCookie(
  580. OBJECTCOOKIE cookieClusterIn
  581. )
  582. {
  583. TraceFunc( "" );
  584. HRESULT hr = S_OK;
  585. m_cookieCluster = cookieClusterIn;
  586. HRETURN( hr );
  587. } //*** CTaskAnalyzeClusterBase::HrSetClusterCookie
  588. //*************************************************************************//
  589. /////////////////////////////////////////////////////////////////////////////
  590. // CTaskAnalyzeClusterBase - IClusCfgCallback interface.
  591. /////////////////////////////////////////////////////////////////////////////
  592. //////////////////////////////////////////////////////////////////////////////
  593. //++
  594. //
  595. // CTaskAnalyzeClusterBase::SendStatusReport
  596. //
  597. // Description:
  598. //
  599. // Arguments:
  600. //
  601. // Return Value:
  602. // S_OK
  603. // Success
  604. //
  605. // HRESULT failure.
  606. //
  607. //--
  608. //////////////////////////////////////////////////////////////////////////////
  609. STDMETHODIMP
  610. CTaskAnalyzeClusterBase::SendStatusReport(
  611. LPCWSTR pcszNodeNameIn
  612. , CLSID clsidTaskMajorIn
  613. , CLSID clsidTaskMinorIn
  614. , ULONG ulMinIn
  615. , ULONG ulMaxIn
  616. , ULONG ulCurrentIn
  617. , HRESULT hrStatusIn
  618. , LPCWSTR pcszDescriptionIn
  619. , FILETIME * pftTimeIn
  620. , LPCWSTR pcszReferenceIn
  621. )
  622. {
  623. TraceFunc( "[IClusCfgCallback]" );
  624. Assert( pcszNodeNameIn != NULL );
  625. HRESULT hr = S_OK;
  626. IServiceProvider * psp = NULL;
  627. IConnectionPointContainer * pcpc = NULL;
  628. IConnectionPoint * pcp = NULL;
  629. FILETIME ft;
  630. if ( m_pcccb == NULL )
  631. {
  632. //
  633. // Collect the manager we need to complete this task.
  634. //
  635. hr = THR( CoCreateInstance( CLSID_ServiceManager, NULL, CLSCTX_INPROC_SERVER, TypeSafeParams( IServiceProvider, &psp ) ) );
  636. if ( FAILED( hr ) )
  637. {
  638. goto Cleanup;
  639. }
  640. hr = THR( psp->TypeSafeQS( CLSID_NotificationManager, IConnectionPointContainer, &pcpc ) );
  641. if ( FAILED( hr ) )
  642. {
  643. goto Cleanup;
  644. }
  645. hr = THR( pcpc->FindConnectionPoint( IID_IClusCfgCallback, &pcp ) );
  646. if ( FAILED( hr ) )
  647. {
  648. goto Cleanup;
  649. }
  650. pcp = TraceInterface( L"CConfigurationConnection!IConnectionPoint", IConnectionPoint, pcp, 1 );
  651. hr = THR( pcp->TypeSafeQI( IClusCfgCallback, &m_pcccb ) );
  652. if ( FAILED( hr ) )
  653. {
  654. goto Cleanup;
  655. }
  656. //m_pcccb = TraceInterface( L"CConfigurationConnection!IClusCfgCallback", IClusCfgCallback, m_pcccb, 1 );
  657. psp->Release();
  658. psp = NULL;
  659. }
  660. if ( pftTimeIn == NULL )
  661. {
  662. GetSystemTimeAsFileTime( &ft );
  663. pftTimeIn = &ft;
  664. } // if:
  665. //
  666. // Send the message!
  667. //
  668. hr = THR( m_pcccb->SendStatusReport(
  669. pcszNodeNameIn != NULL ? pcszNodeNameIn : m_bstrNodeName
  670. , clsidTaskMajorIn
  671. , clsidTaskMinorIn
  672. , ulMinIn
  673. , ulMaxIn
  674. , ulCurrentIn
  675. , hrStatusIn
  676. , pcszDescriptionIn
  677. , pftTimeIn
  678. , pcszReferenceIn
  679. ) );
  680. if ( m_fStop == TRUE )
  681. {
  682. hr = E_ABORT;
  683. } // if:
  684. Cleanup:
  685. if ( psp != NULL )
  686. {
  687. psp->Release();
  688. }
  689. if ( pcpc != NULL )
  690. {
  691. pcpc->Release();
  692. }
  693. if ( pcp != NULL )
  694. {
  695. pcp->Release();
  696. }
  697. HRETURN( hr );
  698. } //*** CTaskAnalyzeClusterBase::SendStatusReport
  699. //*************************************************************************//
  700. /////////////////////////////////////////////////////////////////////////////
  701. // CTaskAnalyzeClusterBase - INotifyUI interface.
  702. /////////////////////////////////////////////////////////////////////////////
  703. //////////////////////////////////////////////////////////////////////////////
  704. //++
  705. //
  706. // CTaskAnalyzeClusterBase::ObjectChanged
  707. //
  708. // Description:
  709. //
  710. // Arguments:
  711. //
  712. // Return Value:
  713. // S_OK
  714. // Success
  715. //
  716. // HRESULT failure.
  717. //
  718. //--
  719. //////////////////////////////////////////////////////////////////////////////
  720. STDMETHODIMP
  721. CTaskAnalyzeClusterBase::ObjectChanged(
  722. OBJECTCOOKIE cookieIn
  723. )
  724. {
  725. TraceFunc( "[INotifyUI]" );
  726. Assert( cookieIn != 0 );
  727. HRESULT hr = S_OK;
  728. BOOL fSuccess;
  729. ULONG idx;
  730. TraceFlow1( "[MT] CTaskAnalyzeClusterBase::ObjectChanged() Thread id %d", GetCurrentThreadId() );
  731. LogMsg( L"[MT:CTaskAnalyzeClusterBase] Looking for the completion cookie %u.", cookieIn );
  732. for ( idx = 0 ; idx < m_cCookies ; idx ++ )
  733. {
  734. Assert( m_pcookies != NULL );
  735. if ( cookieIn == m_pcookies[ idx ] )
  736. {
  737. LogMsg( L"[CTaskAnalyzeClusterBase] Clearing completion cookie %u at array index %u", cookieIn, idx );
  738. //
  739. // Make sure it won't be signalled twice.
  740. //
  741. m_pcookies[ idx ] = NULL;
  742. // don't care if this fails, but it really shouldn't
  743. THR( HrRemoveTaskFromTrackingList( cookieIn ) );
  744. // don't care if this fails, but it really shouldn't
  745. THR( m_pom->RemoveObject( cookieIn ) );
  746. InterlockedIncrement( reinterpret_cast< long * >( &m_cSubTasksDone ) );
  747. if ( m_cSubTasksDone == m_cCookies )
  748. {
  749. //
  750. // Signal the event if all the nodes are done.
  751. //
  752. fSuccess = SetEvent( m_event );
  753. if ( fSuccess == FALSE )
  754. {
  755. hr = HRESULT_FROM_WIN32( TW32( GetLastError() ) );
  756. SSR_ANALYSIS_FAILED( TASKID_Major_Client_And_Server_Log, TASKID_Minor_ObjectChanged_Win32Error, hr );
  757. goto Cleanup;
  758. } // if:
  759. } // if: all done
  760. } // if: matched cookie
  761. } // for: each cookies in the array
  762. Cleanup:
  763. HRETURN( hr );
  764. } //*** CTaskAnalyzeClusterBase::ObjectChanged
  765. //*************************************************************************//
  766. /////////////////////////////////////////////////////////////////////////////
  767. // CTaskAnalyzeClusterBase - Protected methods.
  768. /////////////////////////////////////////////////////////////////////////////
  769. //////////////////////////////////////////////////////////////////////////////
  770. //++
  771. //
  772. // CTaskAnalyzeClusterBase::HrInit
  773. //
  774. // Description:
  775. // Initialize the object.
  776. //
  777. // Arguments:
  778. // None.
  779. //
  780. // Return Values:
  781. // S_OK - Success.
  782. // Other HRESULTs.
  783. //
  784. //--
  785. //////////////////////////////////////////////////////////////////////////////
  786. HRESULT
  787. CTaskAnalyzeClusterBase::HrInit( void )
  788. {
  789. TraceFunc( "" );
  790. HRESULT hr = S_OK;
  791. // IUnknown stuff
  792. Assert( m_cRef == 1 );
  793. // IDoTask / ITaskAnalyzeClusterMinConfig
  794. Assert( m_cookieCompletion == 0 );
  795. Assert( m_pcccb == NULL );
  796. Assert( m_pcookies == NULL );
  797. Assert( m_cNodes == 0 );
  798. Assert( m_event == NULL );
  799. Assert( m_cookieCluster == NULL );
  800. Assert( m_fJoiningMode == FALSE );
  801. Assert( m_cUserNodes == 0 );
  802. Assert( m_pcookiesUser == NULL );
  803. Assert( m_prgQuorumsToCleanup == NULL );
  804. Assert( m_idxQuorumToCleanupNext == 0 );
  805. Assert( m_pnui == NULL );
  806. Assert( m_pom == NULL );
  807. Assert( m_ptm == NULL );
  808. Assert( m_pcm == NULL );
  809. Assert( m_fStop == FALSE );
  810. // INotifyUI
  811. Assert( m_cSubTasksDone == 0 );
  812. Assert( m_hrStatus == 0 );
  813. hr = THR( HrGetComputerName(
  814. ComputerNameDnsHostname
  815. , &m_bstrNodeName
  816. , TRUE // fBestEffortIn
  817. ) );
  818. if ( FAILED( hr ) )
  819. {
  820. goto Cleanup;
  821. } // if:
  822. Cleanup:
  823. HRETURN( hr );
  824. } //*** CTaskAnalyzeClusterBase::HrInit
  825. //////////////////////////////////////////////////////////////////////////////
  826. //++
  827. //
  828. // CTaskAnalyzeClusterBase::HrWaitForClusterConnection
  829. //
  830. // Description:
  831. //
  832. // Arguments:
  833. //
  834. // Return Value:
  835. // S_OK
  836. // Success
  837. //
  838. // HRESULT failure.
  839. //
  840. //--
  841. //////////////////////////////////////////////////////////////////////////////
  842. HRESULT
  843. CTaskAnalyzeClusterBase::HrWaitForClusterConnection( void )
  844. {
  845. TraceFunc( "" );
  846. HRESULT hrStatus;
  847. ULONG ulCurrent;
  848. DWORD sc;
  849. HRESULT hr = S_OK;
  850. IUnknown * punk = NULL;
  851. ITaskGatherClusterInfo * ptgci = NULL;
  852. IStandardInfo * psi = NULL;
  853. TraceFlow1( "[MT] CTaskAnalyzeClusterBase::HrWaitForClusterConnection() Thread id %d", GetCurrentThreadId() );
  854. //
  855. // Get the cluster name
  856. //
  857. hr = THR( m_pom->GetObject( DFGUID_StandardInfo, m_cookieCluster, &punk ) );
  858. if ( FAILED( hr ) )
  859. {
  860. SSR_ANALYSIS_FAILED( TASKID_Major_Checking_For_Existing_Cluster, TASKID_Minor_WaitForCluster_GetObject, hr );
  861. goto Cleanup;
  862. }
  863. hr = THR( punk->TypeSafeQI( IStandardInfo, &psi ) );
  864. if ( FAILED( hr ) )
  865. {
  866. SSR_ANALYSIS_FAILED( TASKID_Major_Checking_For_Existing_Cluster, TASKID_Minor_WaitForCluster_GetObject_QI, hr );
  867. goto Cleanup;
  868. }
  869. //psi = TraceInterface( L"TaskAnalyzeClusterBase!IStandardInfo", IStandardInfo, psi, 1 );
  870. punk->Release();
  871. punk = NULL;
  872. //
  873. // Retrieve the cluster's name.
  874. //
  875. hr = THR( psi->GetName( &m_bstrClusterName ) );
  876. if ( FAILED( hr ) )
  877. {
  878. SSR_ANALYSIS_FAILED( TASKID_Major_Checking_For_Existing_Cluster, TASKID_Minor_WaitForCluster_GetName, hr );
  879. goto Cleanup;
  880. }
  881. TraceMemoryAddBSTR( m_bstrClusterName );
  882. //
  883. // Tell the UI layer that we are starting to search for an existing cluster.
  884. //
  885. hr = THR( HrSendStatusReport(
  886. m_bstrClusterName
  887. , TASKID_Major_Update_Progress
  888. , TASKID_Major_Checking_For_Existing_Cluster
  889. , 0
  890. , CHECKING_TIMEOUT
  891. , 0
  892. , S_OK
  893. , IDS_TASKID_MINOR_CHECKING_FOR_EXISTING_CLUSTER
  894. ) );
  895. if ( FAILED( hr ) )
  896. {
  897. goto Cleanup;
  898. }
  899. //
  900. // Create a completion cookie list.
  901. //
  902. Assert( m_cCookies == 0 );
  903. Assert( m_pcookies == NULL );
  904. Assert( m_cSubTasksDone == 0 );
  905. m_pcookies = reinterpret_cast< OBJECTCOOKIE * >( TraceAlloc( 0, sizeof( OBJECTCOOKIE ) ) );
  906. if ( m_pcookies == NULL )
  907. {
  908. hr = THR( E_OUTOFMEMORY );
  909. SSR_ANALYSIS_FAILED( TASKID_Major_Checking_For_Existing_Cluster, TASKID_Minor_WaitForCluster_OutOfMemory, hr );
  910. goto Cleanup;
  911. }
  912. hr = THR( m_pom->FindObject( CLSID_ClusterCompletionCookie, m_cookieCluster, m_bstrClusterName, IID_NULL, &m_pcookies[ 0 ], &punk ) );
  913. Assert( punk == NULL );
  914. if ( FAILED( hr ) )
  915. {
  916. SSR_ANALYSIS_FAILED( TASKID_Major_Checking_For_Existing_Cluster, TASKID_Minor_WaitForCluster_CreateCompletionCookie, hr );
  917. goto Cleanup;
  918. }
  919. m_cCookies = 1;
  920. //
  921. // Create the task object.
  922. //
  923. hr = THR( m_ptm->CreateTask( TASK_GatherClusterInfo, &punk ) );
  924. if ( FAILED( hr ) )
  925. {
  926. SSR_ANALYSIS_FAILED( TASKID_Major_Checking_For_Existing_Cluster, TASKID_Minor_WaitForCluster_CreateTask, hr );
  927. goto Cleanup;
  928. }
  929. Assert( punk != NULL );
  930. hr = THR( punk->TypeSafeQI( ITaskGatherClusterInfo, &ptgci ) );
  931. if ( FAILED( hr ) )
  932. {
  933. SSR_ANALYSIS_FAILED( TASKID_Major_Checking_For_Existing_Cluster, TASKID_Minor_WaitForCluster_CreateTask_QI, hr );
  934. goto Cleanup;
  935. }
  936. //
  937. // Set the object cookie in the task.
  938. //
  939. hr = THR( ptgci->SetCookie( m_cookieCluster ) );
  940. if ( FAILED( hr ) )
  941. {
  942. SSR_ANALYSIS_FAILED( TASKID_Major_Checking_For_Existing_Cluster, TASKID_Minor_WaitForCluster_SetCookie, hr );
  943. goto Cleanup;
  944. }
  945. LogMsg( L"[CTaskAnalyzeClusterBase] Setting completion cookie %u at array index 0 into the gather cluster information task for node %ws", m_pcookies[ 0 ], m_bstrClusterName );
  946. hr = THR( ptgci->SetCompletionCookie( m_pcookies[ 0 ] ) );
  947. if ( FAILED( hr ) )
  948. {
  949. SSR_ANALYSIS_FAILED( TASKID_Major_Checking_For_Existing_Cluster, TASKID_Minor_WaitForCluster_SetCompletionCookie, hr );
  950. goto Cleanup;
  951. }
  952. //
  953. // Submit the task.
  954. //
  955. hr = THR( m_ptm->SubmitTask( ptgci ) );
  956. if ( FAILED( hr ) )
  957. {
  958. SSR_ANALYSIS_FAILED( TASKID_Major_Checking_For_Existing_Cluster, TASKID_Minor_WaitForCluster_SubmitTask, hr );
  959. goto Cleanup;
  960. }
  961. hr = THR( HrAddTaskToTrackingList( punk, m_pcookies[ 0 ] ) );
  962. if ( FAILED( hr ) )
  963. {
  964. goto Cleanup;
  965. } // if:
  966. punk->Release();
  967. punk = NULL;
  968. //
  969. // Now wait for the work to be done.
  970. //
  971. for ( ulCurrent = 0, sc = WAIT_OBJECT_0 + 1
  972. ; ( sc != WAIT_OBJECT_0 ) && ( m_fStop == FALSE )
  973. ;
  974. )
  975. {
  976. MSG msg;
  977. while( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )
  978. {
  979. TranslateMessage( &msg );
  980. DispatchMessage( &msg );
  981. }
  982. sc = MsgWaitForMultipleObjectsEx( 1,
  983. &m_event,
  984. 1000, // 1 second
  985. QS_ALLEVENTS | QS_ALLINPUT | QS_ALLPOSTMESSAGE,
  986. 0
  987. );
  988. //
  989. // Tell the UI layer that we are still searching for the cluster. BUT
  990. // don't let the progress reach 100% if it is taking longer than
  991. // CHECKING_TIMEOUT seconds.
  992. //
  993. if ( ulCurrent != CHECKING_TIMEOUT )
  994. {
  995. ulCurrent ++;
  996. Assert( ulCurrent != CHECKING_TIMEOUT );
  997. hr = THR( SendStatusReport( m_bstrClusterName,
  998. TASKID_Major_Update_Progress,
  999. TASKID_Major_Checking_For_Existing_Cluster,
  1000. 0,
  1001. CHECKING_TIMEOUT,
  1002. ulCurrent,
  1003. S_OK,
  1004. NULL,
  1005. NULL,
  1006. NULL
  1007. ) );
  1008. if ( FAILED( hr ) )
  1009. {
  1010. goto Cleanup;
  1011. }
  1012. }
  1013. } // for: sc != WAIT_OBJECT_0
  1014. //
  1015. // Cleanup the completion cookies
  1016. //
  1017. THR( HrFreeCookies() );
  1018. if ( m_fStop == TRUE )
  1019. {
  1020. goto Cleanup;
  1021. } // if:
  1022. //
  1023. // Retrieve the cluster's name again, because it might have been renamed.
  1024. //
  1025. TraceSysFreeString( m_bstrClusterName );
  1026. m_bstrClusterName = NULL;
  1027. hr = THR( psi->GetName( &m_bstrClusterName ) );
  1028. if ( FAILED( hr ) )
  1029. {
  1030. SSR_ANALYSIS_FAILED( TASKID_Major_Checking_For_Existing_Cluster, TASKID_Minor_WaitForCluster_GetName, hr );
  1031. goto Cleanup;
  1032. }
  1033. TraceMemoryAddBSTR( m_bstrClusterName );
  1034. //
  1035. // Check out the status of the cluster.
  1036. //
  1037. hr = THR( psi->GetStatus( &hrStatus ) );
  1038. if ( FAILED( hr ) )
  1039. {
  1040. SSR_ANALYSIS_FAILED( TASKID_Major_Checking_For_Existing_Cluster, TASKID_Minor_WaitForCluster_GetStatus, hr );
  1041. goto Cleanup;
  1042. }
  1043. //
  1044. // If we are adding nodes and can't connect to the cluster, this
  1045. // should be deemed a bad thing!
  1046. //
  1047. if ( m_fJoiningMode )
  1048. {
  1049. //
  1050. // ADDING
  1051. //
  1052. switch ( hrStatus )
  1053. {
  1054. case S_OK:
  1055. //
  1056. // This is what we are expecting.
  1057. //
  1058. break;
  1059. case HR_S_RPC_S_SERVER_UNAVAILABLE:
  1060. {
  1061. //
  1062. // If we failed to connect to the server....
  1063. //
  1064. THR( HrSendStatusReport(
  1065. m_bstrClusterName
  1066. , TASKID_Major_Checking_For_Existing_Cluster
  1067. , TASKID_Minor_Cluster_Not_Found
  1068. , 1
  1069. , 1
  1070. , 1
  1071. , HRESULT_FROM_WIN32( RPC_S_SERVER_UNAVAILABLE )
  1072. , IDS_TASKID_MINOR_CLUSTER_NOT_FOUND
  1073. ) );
  1074. hr = THR( HRESULT_FROM_WIN32( RPC_S_SERVER_UNAVAILABLE ) );
  1075. }
  1076. goto Cleanup;
  1077. default:
  1078. {
  1079. //
  1080. // If something else goes wrong, stop.
  1081. //
  1082. THR( HrSendStatusReport(
  1083. m_bstrClusterName
  1084. , TASKID_Major_Checking_For_Existing_Cluster
  1085. , TASKID_Minor_Error_Contacting_Cluster
  1086. , 1
  1087. , 1
  1088. , 1
  1089. , hrStatus
  1090. , IDS_TASKID_MINOR_ERROR_CONTACTING_CLUSTER
  1091. ) );
  1092. hr = THR( hrStatus );
  1093. }
  1094. goto Cleanup;
  1095. } // switch: hrStatus
  1096. } // if: adding
  1097. else
  1098. {
  1099. //
  1100. // CREATING
  1101. //
  1102. switch ( hrStatus )
  1103. {
  1104. case HR_S_RPC_S_SERVER_UNAVAILABLE:
  1105. //
  1106. // This is what we are expecting.
  1107. //
  1108. break;
  1109. case HRESULT_FROM_WIN32( ERROR_CONNECTION_REFUSED ):
  1110. case REGDB_E_CLASSNOTREG:
  1111. case E_ACCESSDENIED:
  1112. case S_OK:
  1113. {
  1114. BSTR bstrDescription = NULL;
  1115. //
  1116. // If we are forming and we find an existing cluster with the same name
  1117. // that we trying to form, we shouldn't let the user continue.
  1118. //
  1119. // NOTE that some error conditions indicate that "something" is hosting
  1120. // the cluster name.
  1121. //
  1122. hr = THR( HrFormatStringIntoBSTR(
  1123. g_hInstance
  1124. , IDS_TASKID_MINOR_EXISTING_CLUSTER_FOUND
  1125. , &bstrDescription
  1126. , m_bstrClusterName
  1127. ) );
  1128. THR( SendStatusReport(
  1129. m_bstrClusterName
  1130. , TASKID_Major_Checking_For_Existing_Cluster
  1131. , TASKID_Minor_Existing_Cluster_Found
  1132. , 1
  1133. , 1
  1134. , 1
  1135. , HRESULT_FROM_WIN32( ERROR_CLUSTER_CANT_CREATE_DUP_CLUSTER_NAME )
  1136. , bstrDescription
  1137. , NULL
  1138. , NULL
  1139. ) );
  1140. TraceSysFreeString( bstrDescription );
  1141. hr = THR( HRESULT_FROM_WIN32( ERROR_CLUSTER_CANT_CREATE_DUP_CLUSTER_NAME ) );
  1142. }
  1143. goto Cleanup;
  1144. default:
  1145. {
  1146. //
  1147. // If something else goes wrong, stop.
  1148. //
  1149. THR( HrSendStatusReport(
  1150. m_bstrClusterName
  1151. , TASKID_Major_Checking_For_Existing_Cluster
  1152. , TASKID_Minor_Error_Contacting_Cluster
  1153. , 1
  1154. , 1
  1155. , 1
  1156. , hrStatus
  1157. , IDS_TASKID_MINOR_ERROR_CONTACTING_CLUSTER
  1158. ) );
  1159. hr = THR( hrStatus );
  1160. }
  1161. goto Cleanup;
  1162. } // switch: hrStatus
  1163. } // else: creating
  1164. if ( m_fJoiningMode )
  1165. {
  1166. //
  1167. // Memorize the cookies of the objects that the user entered.
  1168. //
  1169. hr = THR( HrGetUsersNodesCookies() );
  1170. if ( FAILED( hr ) )
  1171. {
  1172. goto Cleanup;
  1173. }
  1174. //
  1175. // Create cookies for the existing nodes.
  1176. //
  1177. hr = THR( HrAddJoinedNodes() );
  1178. if ( FAILED( hr ) )
  1179. {
  1180. goto Cleanup;
  1181. }
  1182. } // if: adding nodes to an existing cluster
  1183. //
  1184. // Tell the UI layer that we are done searching for the cluster.
  1185. //
  1186. hr = THR( SendStatusReport( m_bstrClusterName,
  1187. TASKID_Major_Update_Progress,
  1188. TASKID_Major_Checking_For_Existing_Cluster,
  1189. 0,
  1190. CHECKING_TIMEOUT,
  1191. CHECKING_TIMEOUT,
  1192. S_OK,
  1193. NULL,
  1194. NULL,
  1195. NULL
  1196. ) );
  1197. if ( FAILED( hr ) )
  1198. {
  1199. goto Cleanup;
  1200. }
  1201. Cleanup:
  1202. if ( punk != NULL )
  1203. {
  1204. punk->Release();
  1205. }
  1206. if ( psi != NULL )
  1207. {
  1208. psi->Release();
  1209. }
  1210. if ( ptgci != NULL )
  1211. {
  1212. ptgci->Release();
  1213. }
  1214. HRETURN( hr );
  1215. } //*** CTaskAnalyzeClusterBase::HrWaitForClusterConnection
  1216. //////////////////////////////////////////////////////////////////////////////
  1217. //++
  1218. //
  1219. // CTaskAnalyzeClusterBase::HrCountNumberOfNodes
  1220. //
  1221. // Description:
  1222. //
  1223. // Arguments:
  1224. //
  1225. // Return Value:
  1226. // S_OK
  1227. // Success
  1228. //
  1229. // HRESULT failure.
  1230. //
  1231. //--
  1232. //////////////////////////////////////////////////////////////////////////////
  1233. HRESULT
  1234. CTaskAnalyzeClusterBase::HrCountNumberOfNodes( void )
  1235. {
  1236. TraceFunc( "" );
  1237. HRESULT hr;
  1238. OBJECTCOOKIE cookieDummy;
  1239. IUnknown * punk = NULL;
  1240. IEnumCookies * pec = NULL;
  1241. //
  1242. // Make sure all the node object that (will) make up the cluster
  1243. // are in a stable state.
  1244. //
  1245. hr = THR( m_pom->FindObject( CLSID_NodeType, m_cookieCluster, NULL, DFGUID_EnumCookies, &cookieDummy, &punk ) );
  1246. if ( FAILED( hr ) )
  1247. {
  1248. SSR_ANALYSIS_FAILED( TASKID_Major_Establish_Connection, TASKID_Minor_CountNodes_FindObject, hr );
  1249. goto Cleanup;
  1250. }
  1251. hr = THR( punk->TypeSafeQI( IEnumCookies, &pec ) );
  1252. if ( FAILED( hr ) )
  1253. {
  1254. SSR_ANALYSIS_FAILED( TASKID_Major_Establish_Connection, TASKID_Minor_CountNodes_FindObject_QI, hr );
  1255. goto Cleanup;
  1256. }
  1257. //pec = TraceInterface( L"CTaskAnalyzeClusterBase!IEnumCookies", IEnumCookies, pec, 1 );
  1258. punk->Release();
  1259. punk = NULL;
  1260. //
  1261. // Count how many nodes there are.
  1262. //
  1263. hr = THR( pec->Count( &m_cNodes ) );
  1264. if ( FAILED( hr ) )
  1265. {
  1266. SSR_ANALYSIS_FAILED( TASKID_Major_Establish_Connection, TASKID_Minor_CountNodes_EnumNodes_Count, hr );
  1267. goto Cleanup;
  1268. } // if: error getting count of nodes
  1269. Assert( hr == S_OK );
  1270. Cleanup:
  1271. if ( punk != NULL )
  1272. {
  1273. punk->Release();
  1274. }
  1275. if ( pec != NULL )
  1276. {
  1277. pec->Release();
  1278. }
  1279. HRETURN( hr );
  1280. } //*** CTaskAnalyzeClusterBase::HrCountNumberOfNodes
  1281. //////////////////////////////////////////////////////////////////////////////
  1282. //++
  1283. //
  1284. // CTaskAnalyzeClusterBase::HrCreateSubTasksToGatherNodeInfo
  1285. //
  1286. // Description:
  1287. //
  1288. // Arguments:
  1289. //
  1290. // Return Value:
  1291. // S_OK
  1292. // Success
  1293. //
  1294. // HRESULT failure.
  1295. //
  1296. //--
  1297. //////////////////////////////////////////////////////////////////////////////
  1298. HRESULT
  1299. CTaskAnalyzeClusterBase::HrCreateSubTasksToGatherNodeInfo( void )
  1300. {
  1301. TraceFunc( "" );
  1302. Assert( m_hrStatus == S_OK );
  1303. HRESULT hr;
  1304. ULONG cNode;
  1305. ULONG cNodesToProcess;
  1306. ULONG ulCurrent;
  1307. DWORD sc;
  1308. OBJECTCOOKIE cookieDummy;
  1309. OBJECTCOOKIE cookieNode;
  1310. BSTR bstrName = NULL;
  1311. IUnknown * punk = NULL;
  1312. IClusCfgNodeInfo * pccni = NULL;
  1313. IEnumCookies * pec = NULL;
  1314. ITaskGatherNodeInfo * ptgni = NULL;
  1315. IStandardInfo * psi = NULL;
  1316. IStandardInfo ** psiCompletion = NULL;
  1317. TraceFlow1( "[MT] CTaskAnalyzeClusterBase::HrCreateSubTasksToGatherNodeInfo() Thread id %d", GetCurrentThreadId() );
  1318. hr = THR( SendStatusReport(
  1319. m_bstrClusterName
  1320. , TASKID_Major_Update_Progress
  1321. , TASKID_Major_Check_Node_Feasibility
  1322. , 0
  1323. , CHECKING_TIMEOUT
  1324. , 0
  1325. , S_OK
  1326. , NULL
  1327. , NULL
  1328. , NULL
  1329. ) );
  1330. if ( FAILED( hr ) )
  1331. {
  1332. goto Cleanup;
  1333. }
  1334. //
  1335. // Get the enum of the nodes.
  1336. //
  1337. hr = THR( m_pom->FindObject( CLSID_NodeType, m_cookieCluster, NULL, DFGUID_EnumCookies, &cookieDummy, &punk ) );
  1338. if ( FAILED( hr ) )
  1339. {
  1340. SSR_ANALYSIS_FAILED( TASKID_Major_Establish_Connection, TASKID_Minor_CreateNodeTasks_FindObject, hr );
  1341. goto Cleanup;
  1342. }
  1343. hr = THR( punk->TypeSafeQI( IEnumCookies, &pec ) );
  1344. if ( FAILED( hr ) )
  1345. {
  1346. SSR_ANALYSIS_FAILED( TASKID_Major_Establish_Connection, TASKID_Minor_CreateNodeTasks_FindObject_QI, hr );
  1347. goto Cleanup;
  1348. }
  1349. //pec = TraceInterface( L"CTaskAnalyzeClusterBase!IEnumCookies", IEnumCookies, pec, 1 );
  1350. punk->Release();
  1351. punk = NULL;
  1352. //
  1353. // Allocate a buffer to collect cookies
  1354. //
  1355. Assert( m_cCookies == 0 );
  1356. Assert( m_pcookies == NULL );
  1357. Assert( m_cSubTasksDone == 0 );
  1358. m_pcookies = reinterpret_cast< OBJECTCOOKIE * >( TraceAlloc( 0, m_cNodes * sizeof( OBJECTCOOKIE ) ) );
  1359. if ( m_pcookies == NULL )
  1360. {
  1361. hr = THR( E_OUTOFMEMORY );
  1362. SSR_ANALYSIS_FAILED( TASKID_Major_Establish_Connection, TASKID_Minor_CreateNodeTasks_OutOfMemory, hr );
  1363. goto Cleanup;
  1364. }
  1365. //
  1366. // KB: gpease 29-NOV-2000
  1367. // Create a list of "interesting" completion cookie StandardInfo-s. If any of the
  1368. // statuses return from this list are FAILED, then abort the analysis.
  1369. //
  1370. psiCompletion = reinterpret_cast< IStandardInfo ** >( TraceAlloc( HEAP_ZERO_MEMORY, m_cNodes * sizeof( IStandardInfo * ) ) );
  1371. if ( psiCompletion == NULL )
  1372. {
  1373. hr = THR( E_OUTOFMEMORY );
  1374. SSR_ANALYSIS_FAILED( TASKID_Major_Establish_Connection, TASKID_Minor_CreateNodeTasks_OutOfMemory, hr );
  1375. goto Cleanup;
  1376. }
  1377. //
  1378. // Loop thru the nodes, creating cookies and allocating a gather task for
  1379. // that node.
  1380. //
  1381. for ( cNode = 0 ; ( cNode < m_cNodes ) && ( m_fStop == FALSE ) ; cNode ++ )
  1382. {
  1383. ULONG celtDummy;
  1384. ULONG idx;
  1385. BOOL fFound;
  1386. //
  1387. // Grab the next node.
  1388. //
  1389. hr = STHR( pec->Next( 1, &cookieNode, &celtDummy ) );
  1390. if ( hr == S_FALSE )
  1391. {
  1392. break; // exit condition
  1393. }
  1394. if ( FAILED( hr ) )
  1395. {
  1396. SSR_ANALYSIS_FAILED( TASKID_Major_Establish_Connection, TASKID_Minor_CreateNodeTasks_EnumNodes_Next, hr );
  1397. goto Cleanup;
  1398. }
  1399. //
  1400. // Get the node's name. We are using this to distinguish one node's
  1401. // completion cookie from another. It might also make debugging
  1402. // easier (??).
  1403. //
  1404. hr = THR( m_pom->GetObject( DFGUID_NodeInformation, cookieNode, &punk ) );
  1405. if ( FAILED( hr ) )
  1406. {
  1407. SSR_ANALYSIS_FAILED( TASKID_Major_Establish_Connection, TASKID_Minor_CreateNodeTasks_EnumNodes_GetObject, hr );
  1408. goto Cleanup;
  1409. }
  1410. hr = THR( punk->TypeSafeQI( IClusCfgNodeInfo, &pccni ) );
  1411. if ( FAILED( hr ) )
  1412. {
  1413. SSR_ANALYSIS_FAILED( TASKID_Major_Establish_Connection, TASKID_Minor_CreateNodeTasks_EnumNodes_GetObject_QI, hr );
  1414. goto Cleanup;
  1415. }
  1416. punk->Release();
  1417. punk = NULL;
  1418. hr = THR( pccni->GetName( &bstrName ) );
  1419. if ( FAILED( hr ) )
  1420. {
  1421. SSR_ANALYSIS_FAILED( TASKID_Major_Establish_Connection, TASKID_Minor_CreateNodeTasks_EnumNodes_GetName, hr );
  1422. goto Cleanup;
  1423. }
  1424. TraceMemoryAddBSTR( bstrName );
  1425. //
  1426. // Create a completion cookie.
  1427. //
  1428. hr = THR( m_pom->FindObject( IID_NULL, m_cookieCluster, bstrName, DFGUID_StandardInfo, &m_pcookies[ cNode ], &punk ) );
  1429. if ( FAILED( hr ) )
  1430. {
  1431. SSR_ANALYSIS_FAILED( TASKID_Major_Establish_Connection, TASKID_Minor_CreateNodeTasks_EnumNodes_CompletionCookie_FindObject, hr );
  1432. goto Cleanup;
  1433. }
  1434. //
  1435. // Increment the cookie counter.
  1436. //
  1437. m_cCookies ++;
  1438. //
  1439. // See if this node is one of the user entered nodes.
  1440. //
  1441. if ( m_fJoiningMode == FALSE )
  1442. {
  1443. //
  1444. // All nodes are "interesting" during a form operation.
  1445. //
  1446. Assert( m_cUserNodes == 0 );
  1447. Assert( m_pcookiesUser == NULL );
  1448. fFound = TRUE;
  1449. } // if: creating a new cluster
  1450. else
  1451. {
  1452. //
  1453. // Only the nodes the user entered are interesting during an add
  1454. // nodes operation.
  1455. //
  1456. for ( fFound = FALSE, idx = 0 ; idx < m_cUserNodes ; idx ++ )
  1457. {
  1458. if ( m_pcookiesUser[ idx ] == cookieNode )
  1459. {
  1460. fFound = TRUE;
  1461. break;
  1462. }
  1463. } // for: each node entered by the user
  1464. } // else: adding nodes to an existing cluster
  1465. if ( fFound == TRUE )
  1466. {
  1467. hr = THR( punk->TypeSafeQI( IStandardInfo, &psiCompletion[ cNode ] ) );
  1468. if ( FAILED( hr ) )
  1469. {
  1470. SSR_ANALYSIS_FAILED( TASKID_Major_Establish_Connection, TASKID_Minor_CreateNodeTasks_EnumNodes_CompletionCookie_FindObject_QI, hr );
  1471. goto Cleanup;
  1472. }
  1473. }
  1474. else
  1475. {
  1476. Assert( psiCompletion[ cNode ] == NULL );
  1477. }
  1478. punk->Release();
  1479. punk = NULL;
  1480. //
  1481. // Create a task to gather this nodes information.
  1482. //
  1483. hr = THR( m_ptm->CreateTask( TASK_GatherNodeInfo, &punk ) );
  1484. if ( FAILED( hr ) )
  1485. {
  1486. SSR_ANALYSIS_FAILED( TASKID_Major_Establish_Connection, TASKID_Minor_CreateNodeTasks_EnumNodes_CreateTask, hr );
  1487. goto Cleanup;
  1488. }
  1489. hr = THR( punk->TypeSafeQI( ITaskGatherNodeInfo, &ptgni ) );
  1490. if ( FAILED( hr ) )
  1491. {
  1492. SSR_ANALYSIS_FAILED( TASKID_Major_Establish_Connection, TASKID_Minor_CreateNodeTasks_EnumNodes_QI_GatherNodeInfo, hr );
  1493. goto Cleanup;
  1494. }
  1495. //
  1496. // Set the tasks completion cookie.
  1497. //
  1498. LogMsg( L"[CTaskAnalyzeClusterBase] Setting completion cookie %u at array index %u into the gather node information task for node %ws", m_pcookies[ cNode ], cNode, bstrName );
  1499. hr = THR( ptgni->SetCompletionCookie( m_pcookies[ cNode ] ) );
  1500. if ( FAILED( hr ) )
  1501. {
  1502. SSR_ANALYSIS_FAILED( TASKID_Major_Establish_Connection, TASKID_Minor_CreateNodeTasks_EnumNodes_SetCompletionCookie, hr );
  1503. goto Cleanup;
  1504. }
  1505. //
  1506. // Tell it what node it is suppose to gather information from.
  1507. //
  1508. hr = THR( ptgni->SetCookie( cookieNode ) );
  1509. if ( FAILED( hr ) )
  1510. {
  1511. SSR_ANALYSIS_FAILED( TASKID_Major_Establish_Connection, TASKID_Minor_CreateNodeTasks_EnumNodes_SetCookie, hr );
  1512. goto Cleanup;
  1513. }
  1514. //
  1515. // Tell it whether it is a user-added node or not.
  1516. //
  1517. hr = THR( ptgni->SetUserAddedNodeFlag( fFound ) );
  1518. if ( FAILED( hr ) )
  1519. {
  1520. SSR_ANALYSIS_FAILED( TASKID_Major_Establish_Connection, TASKID_Minor_CreateNodeTasks_EnumNodes_SetUserAddedNodeFlag, hr );
  1521. goto Cleanup;
  1522. }
  1523. //
  1524. // Submit the task.
  1525. //
  1526. hr = THR( m_ptm->SubmitTask( ptgni ) );
  1527. if ( FAILED( hr ) )
  1528. {
  1529. SSR_ANALYSIS_FAILED( TASKID_Major_Establish_Connection, TASKID_Minor_CreateNodeTasks_EnumNodes_SubmitTask, hr );
  1530. goto Cleanup;
  1531. }
  1532. hr = THR( HrAddTaskToTrackingList( punk, m_pcookies[ cNode ] ) );
  1533. if ( FAILED( hr ) )
  1534. {
  1535. goto Cleanup;
  1536. } // if:
  1537. punk->Release();
  1538. punk = NULL;
  1539. //
  1540. // Cleanup for the next node.
  1541. //
  1542. pccni->Release();
  1543. pccni = NULL;
  1544. TraceSysFreeString( bstrName );
  1545. bstrName = NULL;
  1546. ptgni->Release();
  1547. ptgni = NULL;
  1548. } // for: looping thru nodes
  1549. Assert( m_cCookies == m_cNodes );
  1550. //
  1551. // Reset the signal event.
  1552. //
  1553. {
  1554. BOOL bRet = FALSE;
  1555. bRet = ResetEvent( m_event );
  1556. Assert( bRet == TRUE );
  1557. }
  1558. //
  1559. // Now wait for the work to be done.
  1560. //
  1561. for ( ulCurrent = 0, sc = WAIT_OBJECT_0 + 1
  1562. ; ( sc != WAIT_OBJECT_0 ) && ( m_fStop == FALSE )
  1563. ;
  1564. )
  1565. {
  1566. MSG msg;
  1567. while( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )
  1568. {
  1569. TranslateMessage( &msg );
  1570. DispatchMessage( &msg );
  1571. }
  1572. sc = MsgWaitForMultipleObjectsEx(
  1573. 1
  1574. , &m_event
  1575. , INFINITE
  1576. , QS_ALLEVENTS | QS_ALLINPUT | QS_ALLPOSTMESSAGE
  1577. , 0
  1578. );
  1579. if ( ulCurrent != CHECKING_TIMEOUT )
  1580. {
  1581. ulCurrent ++;
  1582. Assert( ulCurrent != CHECKING_TIMEOUT );
  1583. hr = THR( SendStatusReport( m_bstrNodeName,
  1584. TASKID_Major_Update_Progress,
  1585. TASKID_Major_Establish_Connection,
  1586. 0,
  1587. CHECKING_TIMEOUT,
  1588. ulCurrent,
  1589. S_OK,
  1590. NULL,
  1591. NULL,
  1592. NULL
  1593. ) );
  1594. if ( FAILED( hr ) )
  1595. {
  1596. goto Cleanup;
  1597. }
  1598. }
  1599. } // for: sc == WAIT_OBJECT_0
  1600. //
  1601. // Now check the results using the list of completion cookie StandardInfo-s
  1602. // built earlier of interesting objects. If any of these "interesting" cookies
  1603. // return a FAILED status, then abort the analysis.
  1604. //
  1605. for ( cNode = 0 , cNodesToProcess = 0 ; ( cNode < m_cNodes ) && ( m_fStop == FALSE ); cNode++ )
  1606. {
  1607. HRESULT hrStatus;
  1608. if ( psiCompletion[ cNode ] == NULL )
  1609. {
  1610. continue;
  1611. }
  1612. hr = THR( psiCompletion[ cNode ]->GetStatus( &hrStatus ) );
  1613. if ( FAILED( hrStatus ) )
  1614. {
  1615. hr = THR( hrStatus );
  1616. goto Cleanup;
  1617. }
  1618. if ( hrStatus == S_OK )
  1619. {
  1620. cNodesToProcess++;
  1621. } // if:
  1622. } // for: cNode
  1623. if ( cNodesToProcess == 0 )
  1624. {
  1625. hr = HRESULT_FROM_WIN32( TW32( ERROR_NODE_NOT_AVAILABLE ) );
  1626. THR( HrSendStatusReport(
  1627. m_bstrNodeName
  1628. , TASKID_Major_Establish_Connection
  1629. , TASKID_Minor_No_Nodes_To_Process
  1630. , 1
  1631. , 1
  1632. , 1
  1633. , hr
  1634. , IDS_TASKID_MINOR_NO_NODES_TO_PROCESS
  1635. ) );
  1636. goto Cleanup;
  1637. } // if:
  1638. hr = S_OK;
  1639. Cleanup:
  1640. THR( SendStatusReport(
  1641. m_bstrClusterName
  1642. , TASKID_Major_Update_Progress
  1643. , TASKID_Major_Check_Node_Feasibility
  1644. , 0
  1645. , CHECKING_TIMEOUT
  1646. , CHECKING_TIMEOUT
  1647. , S_OK
  1648. , NULL
  1649. , NULL
  1650. , NULL
  1651. ) );
  1652. THR( HrFreeCookies() );
  1653. TraceSysFreeString( bstrName );
  1654. if ( punk != NULL )
  1655. {
  1656. punk->Release();
  1657. }
  1658. if ( pccni != NULL )
  1659. {
  1660. pccni->Release();
  1661. }
  1662. if ( pec != NULL )
  1663. {
  1664. pec->Release();
  1665. }
  1666. if ( ptgni != NULL )
  1667. {
  1668. ptgni->Release();
  1669. }
  1670. if ( psi != NULL )
  1671. {
  1672. psi->Release();
  1673. }
  1674. if ( psiCompletion != NULL )
  1675. {
  1676. for ( cNode = 0 ; cNode < m_cNodes ; cNode++ )
  1677. {
  1678. if ( psiCompletion[ cNode ] != NULL )
  1679. {
  1680. psiCompletion[ cNode ]->Release();
  1681. }
  1682. }
  1683. TraceFree( psiCompletion );
  1684. }
  1685. HRETURN( hr );
  1686. } //*** CTaskAnalyzeClusterBase::HrCreateSubTasksToGatherNodeInfo
  1687. //////////////////////////////////////////////////////////////////////////////
  1688. //++
  1689. //
  1690. // CTaskAnalyzeClusterBase::HrCreateSubTasksToGatherNodeResourcesAndNetworks
  1691. //
  1692. // Description:
  1693. //
  1694. // Arguments:
  1695. //
  1696. // Return Value:
  1697. // S_OK
  1698. // Success
  1699. //
  1700. // HRESULT failure.
  1701. //
  1702. //--
  1703. //////////////////////////////////////////////////////////////////////////////
  1704. HRESULT
  1705. CTaskAnalyzeClusterBase::HrCreateSubTasksToGatherNodeResourcesAndNetworks( void )
  1706. {
  1707. TraceFunc( "" );
  1708. HRESULT hr;
  1709. ULONG idxNode;
  1710. ULONG ulCurrent;
  1711. DWORD sc;
  1712. OBJECTCOOKIE cookieDummy;
  1713. OBJECTCOOKIE cookieNode;
  1714. BSTR bstrName = NULL;
  1715. IUnknown * punk = NULL;
  1716. IClusCfgNodeInfo * pccni = NULL;
  1717. IEnumCookies * pec = NULL;
  1718. ITaskGatherInformation * ptgi = NULL;
  1719. IStandardInfo * psi = NULL;
  1720. IStandardInfo ** ppsiStatuses = NULL;
  1721. TraceFlow1( "[MT] CTaskAnalyzeClusterBase::HrCreateSubTasksToGatherNodeResourcesAndNetworks() Thread id %d", GetCurrentThreadId() );
  1722. Assert( m_hrStatus == S_OK );
  1723. //
  1724. // Tell the UI layer we are starting to retrieve the resources/networks.
  1725. //
  1726. hr = THR( SendStatusReport( m_bstrClusterName,
  1727. TASKID_Major_Update_Progress,
  1728. TASKID_Major_Find_Devices,
  1729. 0,
  1730. CHECKING_TIMEOUT,
  1731. 0,
  1732. S_OK,
  1733. NULL,
  1734. NULL,
  1735. NULL
  1736. ) );
  1737. if ( FAILED( hr ) )
  1738. {
  1739. goto Cleanup;
  1740. }
  1741. //
  1742. // Get the enum of the nodes.
  1743. //
  1744. hr = THR( m_pom->FindObject( CLSID_NodeType, m_cookieCluster, NULL, DFGUID_EnumCookies, &cookieDummy, &punk ) );
  1745. if ( FAILED( hr ) )
  1746. {
  1747. SSR_ANALYSIS_FAILED( TASKID_Major_Find_Devices, TASKID_Minor_GatherInformation_FindObject, hr );
  1748. goto Cleanup;
  1749. }
  1750. hr = THR( punk->TypeSafeQI( IEnumCookies, &pec ) );
  1751. if ( FAILED( hr ) )
  1752. {
  1753. SSR_ANALYSIS_FAILED( TASKID_Major_Find_Devices, TASKID_Minor_GatherInformation_FindObject_QI, hr );
  1754. goto Cleanup;
  1755. }
  1756. pec = TraceInterface( L"CTaskAnalyzeClusterBase!IEnumCookies", IEnumCookies, pec, 1 );
  1757. punk->Release();
  1758. punk = NULL;
  1759. //
  1760. // Allocate a buffer to collect cookies
  1761. //
  1762. Assert( m_cCookies == 0 );
  1763. Assert( m_pcookies == NULL );
  1764. Assert( m_cSubTasksDone == 0 );
  1765. m_pcookies = reinterpret_cast< OBJECTCOOKIE * >( TraceAlloc( HEAP_ZERO_MEMORY, m_cNodes * sizeof( OBJECTCOOKIE ) ) );
  1766. if ( m_pcookies == NULL )
  1767. {
  1768. hr = THR( E_OUTOFMEMORY );
  1769. SSR_ANALYSIS_FAILED( TASKID_Major_Find_Devices, TASKID_Minor_GatherInformation_OutOfMemory, hr );
  1770. goto Cleanup;
  1771. }
  1772. ppsiStatuses = reinterpret_cast< IStandardInfo ** >( TraceAlloc( HEAP_ZERO_MEMORY, m_cNodes * sizeof( IStandardInfo * ) ) );
  1773. if ( ppsiStatuses == NULL )
  1774. {
  1775. hr = THR( E_OUTOFMEMORY );
  1776. SSR_ANALYSIS_FAILED( TASKID_Major_Find_Devices, TASKID_Minor_GatherInformation_OutOfMemory, hr );
  1777. goto Cleanup;
  1778. }
  1779. //
  1780. // Loop thru the nodes, creating cookies and allocating a gather task for
  1781. // that node.
  1782. //
  1783. for ( idxNode = 0 ; ( idxNode < m_cNodes ) && ( m_fStop == FALSE ); idxNode++ )
  1784. {
  1785. ULONG celtDummy;
  1786. //
  1787. // Grab the next node.
  1788. //
  1789. hr = STHR( pec->Next( 1, &cookieNode, &celtDummy ) );
  1790. if ( hr == S_FALSE )
  1791. {
  1792. break; // exit condition
  1793. }
  1794. if ( FAILED( hr ) )
  1795. {
  1796. SSR_ANALYSIS_FAILED( TASKID_Major_Find_Devices, TASKID_Minor_GatherInformation_EnumNodes_Next, hr );
  1797. goto Cleanup;
  1798. }
  1799. //
  1800. // Get the node's name. We are using this to distinguish one node's
  1801. // completion cookie from another. It might also make debugging
  1802. // easier (??).
  1803. //
  1804. hr = THR( m_pom->GetObject( DFGUID_NodeInformation, cookieNode, &punk ) );
  1805. if ( FAILED( hr ) )
  1806. {
  1807. SSR_ANALYSIS_FAILED( TASKID_Major_Find_Devices, TASKID_Minor_GatherInformation_EnumNodes_GetObject, hr );
  1808. goto Cleanup;
  1809. }
  1810. hr = THR( punk->TypeSafeQI( IClusCfgNodeInfo, &pccni ) );
  1811. if ( FAILED( hr ) )
  1812. {
  1813. SSR_ANALYSIS_FAILED( TASKID_Major_Find_Devices, TASKID_Minor_GatherInformation_EnumNodes_GetObject_QI, hr );
  1814. goto Cleanup;
  1815. }
  1816. punk->Release();
  1817. punk = NULL;
  1818. hr = THR( pccni->GetName( &bstrName ) );
  1819. if ( FAILED( hr ) )
  1820. {
  1821. SSR_ANALYSIS_FAILED( TASKID_Major_Find_Devices, TASKID_Minor_GatherInformation_EnumNodes_GetName, hr );
  1822. goto Cleanup;
  1823. }
  1824. TraceMemoryAddBSTR( bstrName );
  1825. //
  1826. // Create a completion cookie.
  1827. //
  1828. hr = THR( m_pom->FindObject( IID_NULL, m_cookieCluster, bstrName, DFGUID_StandardInfo, &m_pcookies[ idxNode ], &punk ) );
  1829. if ( FAILED( hr ) )
  1830. {
  1831. SSR_ANALYSIS_FAILED( TASKID_Major_Find_Devices, TASKID_Minor_GatherInformation_EnumNodes_CompletionCookie_FindObject, hr );
  1832. goto Cleanup;
  1833. }
  1834. hr = THR( punk->TypeSafeQI( IStandardInfo, &ppsiStatuses[ idxNode ] ) );
  1835. if ( FAILED( hr ) )
  1836. {
  1837. SSR_ANALYSIS_FAILED( TASKID_Major_Find_Devices, TASKID_Minor_GatherInformation_EnumNodes_CompletionCookie_FindObject_QI, hr );
  1838. goto Cleanup;
  1839. }
  1840. punk->Release();
  1841. punk = NULL;
  1842. //
  1843. // Increment the cookie counter.
  1844. //
  1845. m_cCookies ++;
  1846. //
  1847. // Create a task to gather this node's information.
  1848. //
  1849. hr = THR( m_ptm->CreateTask( TASK_GatherInformation, &punk ) );
  1850. if ( FAILED( hr ) )
  1851. {
  1852. SSR_ANALYSIS_FAILED( TASKID_Major_Find_Devices, TASKID_Minor_GatherInformation_EnumNodes_CreateTask, hr );
  1853. goto Cleanup;
  1854. }
  1855. TraceMoveFromMemoryList( punk, g_GlobalMemoryList );
  1856. hr = THR( punk->TypeSafeQI( ITaskGatherInformation, &ptgi ) );
  1857. if ( FAILED( hr ) )
  1858. {
  1859. SSR_ANALYSIS_FAILED( TASKID_Major_Find_Devices, TASKID_Minor_GatherInformation_EnumNodes_QI_GatherNodeInfo, hr );
  1860. goto Cleanup;
  1861. }
  1862. //
  1863. // Set the tasks completion cookie.
  1864. //
  1865. hr = THR( ptgi->SetCompletionCookie( m_pcookies[ idxNode ] ) );
  1866. if ( FAILED( hr ) )
  1867. {
  1868. SSR_ANALYSIS_FAILED( TASKID_Major_Find_Devices, TASKID_Minor_GatherInformation_EnumNodes_SetCompletionCookie, hr );
  1869. goto Cleanup;
  1870. }
  1871. //
  1872. // Tell it what node it is suppose to gather information from.
  1873. //
  1874. hr = THR( ptgi->SetNodeCookie( cookieNode ) );
  1875. if ( FAILED( hr ) )
  1876. {
  1877. SSR_ANALYSIS_FAILED( TASKID_Major_Find_Devices, TASKID_Minor_GatherInformation_EnumNodes_SetCookie, hr );
  1878. goto Cleanup;
  1879. }
  1880. //
  1881. // Tell it if we are creating or adding.
  1882. //
  1883. if ( m_fJoiningMode )
  1884. {
  1885. hr = THR( ptgi->SetJoining() );
  1886. if ( FAILED( hr ) )
  1887. {
  1888. SSR_ANALYSIS_FAILED( TASKID_Major_Find_Devices, TASKID_Minor_GatherInformation_EnumNodes_SetJoining, hr );
  1889. goto Cleanup;
  1890. }
  1891. } // if: adding nodes to an existing cluster
  1892. hr = THR( ptgi->SetMinimalConfiguration( BMinimalConfiguration() ) );
  1893. if ( FAILED( hr ) )
  1894. {
  1895. SSR_ANALYSIS_FAILED( TASKID_Major_Find_Devices, TASKID_Minor_GatherInformation_EnumNodes_SetMinimalConfiguration, hr );
  1896. goto Cleanup;
  1897. } // if:
  1898. //
  1899. // Submit the task.
  1900. //
  1901. hr = THR( m_ptm->SubmitTask( ptgi ) );
  1902. if ( FAILED( hr ) )
  1903. {
  1904. SSR_ANALYSIS_FAILED( TASKID_Major_Find_Devices, TASKID_Minor_GatherInformation_EnumNodes_SubmitTask, hr );
  1905. goto Cleanup;
  1906. }
  1907. hr = THR( HrAddTaskToTrackingList( punk, m_pcookies[ idxNode ] ) );
  1908. if ( FAILED( hr ) )
  1909. {
  1910. goto Cleanup;
  1911. } // if:
  1912. punk->Release();
  1913. punk = NULL;
  1914. //
  1915. // Cleanup for the next node.
  1916. //
  1917. pccni->Release();
  1918. pccni = NULL;
  1919. TraceSysFreeString( bstrName );
  1920. bstrName = NULL;
  1921. ptgi->Release();
  1922. ptgi = NULL;
  1923. } // for: looping thru nodes
  1924. Assert( m_cCookies == m_cNodes );
  1925. //
  1926. // Reset the signal event.
  1927. //
  1928. {
  1929. BOOL bRet = FALSE;
  1930. bRet = ResetEvent( m_event );
  1931. Assert( bRet == TRUE );
  1932. }
  1933. //
  1934. // Now wait for the work to be done.
  1935. //
  1936. for ( ulCurrent = 0, sc = WAIT_OBJECT_0 + 1
  1937. ; ( sc != WAIT_OBJECT_0 ) && ( m_fStop == FALSE )
  1938. ;
  1939. )
  1940. {
  1941. MSG msg;
  1942. while( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )
  1943. {
  1944. TranslateMessage( &msg );
  1945. DispatchMessage( &msg );
  1946. }
  1947. sc = MsgWaitForMultipleObjectsEx(
  1948. 1
  1949. , &m_event
  1950. , INFINITE
  1951. , QS_ALLEVENTS | QS_ALLINPUT | QS_ALLPOSTMESSAGE
  1952. , 0
  1953. );
  1954. if ( ulCurrent != CHECKING_TIMEOUT )
  1955. {
  1956. ulCurrent ++;
  1957. Assert( ulCurrent != CHECKING_TIMEOUT );
  1958. hr = THR( SendStatusReport( m_bstrClusterName,
  1959. TASKID_Major_Update_Progress,
  1960. TASKID_Major_Find_Devices,
  1961. 0,
  1962. CHECKING_TIMEOUT,
  1963. ulCurrent,
  1964. S_OK,
  1965. NULL,
  1966. NULL,
  1967. NULL
  1968. ) );
  1969. if ( FAILED( hr ) )
  1970. {
  1971. goto Cleanup;
  1972. }
  1973. }
  1974. } // while: sc == WAIT_OBJECT_0
  1975. //
  1976. // See if anything went wrong.
  1977. //
  1978. for ( idxNode = 0 ; ( idxNode < m_cNodes ) && ( m_fStop == FALSE ); idxNode++ )
  1979. {
  1980. HRESULT hrStatus;
  1981. if ( ppsiStatuses[ idxNode ] == NULL )
  1982. {
  1983. continue;
  1984. }
  1985. hr = THR( ppsiStatuses[ idxNode ]->GetStatus( &hrStatus ) );
  1986. if ( FAILED( hr ) )
  1987. {
  1988. SSR_ANALYSIS_FAILED( TASKID_Major_Find_Devices, TASKID_Minor_GatherInformation_GetStatus, hr );
  1989. goto Cleanup;
  1990. }
  1991. if ( FAILED( hrStatus ) )
  1992. {
  1993. hr = THR( hrStatus );
  1994. goto Cleanup;
  1995. }
  1996. }
  1997. //
  1998. // Tell the UI we are done.
  1999. //
  2000. THR( SendStatusReport(
  2001. m_bstrClusterName
  2002. , TASKID_Major_Update_Progress
  2003. , TASKID_Major_Find_Devices
  2004. , 0
  2005. , CHECKING_TIMEOUT
  2006. , CHECKING_TIMEOUT
  2007. , S_OK
  2008. , NULL
  2009. , NULL
  2010. , NULL
  2011. ) );
  2012. Cleanup:
  2013. THR( HrFreeCookies() );
  2014. TraceSysFreeString( bstrName );
  2015. if ( punk != NULL )
  2016. {
  2017. punk->Release();
  2018. }
  2019. if ( pccni != NULL )
  2020. {
  2021. pccni->Release();
  2022. }
  2023. if ( pec != NULL )
  2024. {
  2025. pec->Release();
  2026. }
  2027. if ( ptgi != NULL )
  2028. {
  2029. ptgi->Release();
  2030. }
  2031. if ( psi != NULL )
  2032. {
  2033. psi->Release();
  2034. }
  2035. if ( ppsiStatuses != NULL )
  2036. {
  2037. for ( idxNode = 0 ; idxNode < m_cNodes ; idxNode++ )
  2038. {
  2039. if ( ppsiStatuses[ idxNode ] != NULL )
  2040. {
  2041. ppsiStatuses[ idxNode ]->Release();
  2042. }
  2043. }
  2044. TraceFree( ppsiStatuses );
  2045. }
  2046. HRETURN( hr );
  2047. } //*** CTaskAnalyzeClusterBase::HrCreateSubTasksToGatherNodeResourcesAndNetworks
  2048. //////////////////////////////////////////////////////////////////////////////
  2049. //++
  2050. //
  2051. // CTaskAnalyzeClusterBase::HrCheckClusterFeasibility
  2052. //
  2053. // Description:
  2054. //
  2055. // Arguments:
  2056. //
  2057. // Return Value:
  2058. // S_OK
  2059. // Success
  2060. //
  2061. // HRESULT failure.
  2062. //
  2063. //--
  2064. //////////////////////////////////////////////////////////////////////////////
  2065. HRESULT
  2066. CTaskAnalyzeClusterBase::HrCheckClusterFeasibility( void )
  2067. {
  2068. TraceFunc( "" );
  2069. HRESULT hr = S_OK;
  2070. TraceFlow1( "[MT] CTaskAnalyzeClusterBase::HrCheckClusterFeasibility() Thread id %d", GetCurrentThreadId() );
  2071. //
  2072. // Notify the UI layer that we have started.
  2073. //
  2074. hr = THR( SendStatusReport(
  2075. m_bstrClusterName
  2076. , TASKID_Major_Update_Progress
  2077. , TASKID_Major_Check_Cluster_Feasibility
  2078. , 0
  2079. , 8
  2080. , 0
  2081. , hr
  2082. , NULL
  2083. , NULL
  2084. , NULL
  2085. ) );
  2086. if ( FAILED( hr ) )
  2087. {
  2088. goto Cleanup;
  2089. } // if
  2090. //
  2091. // Check membership.
  2092. //
  2093. hr = THR( HrCheckClusterMembership() );
  2094. if ( FAILED( hr ) )
  2095. {
  2096. goto Cleanup;
  2097. } // if
  2098. hr = THR( SendStatusReport(
  2099. m_bstrClusterName
  2100. , TASKID_Major_Update_Progress
  2101. , TASKID_Major_Check_Cluster_Feasibility
  2102. , 0
  2103. , 8
  2104. , 1
  2105. , hr
  2106. , NULL
  2107. , NULL
  2108. , NULL
  2109. ) );
  2110. if ( FAILED( hr ) )
  2111. {
  2112. goto Cleanup;
  2113. } // if
  2114. //
  2115. // Look for nodes not in the cluster's domain.
  2116. //
  2117. hr = THR( HrCheckNodeDomains() );
  2118. if ( FAILED( hr ) )
  2119. {
  2120. goto Cleanup;
  2121. } // if
  2122. hr = THR( SendStatusReport(
  2123. m_bstrClusterName
  2124. , TASKID_Major_Update_Progress
  2125. , TASKID_Major_Check_Cluster_Feasibility
  2126. , 0
  2127. , 8
  2128. , 2
  2129. , hr
  2130. , NULL
  2131. , NULL
  2132. , NULL
  2133. ) );
  2134. if ( FAILED( hr ) )
  2135. {
  2136. goto Cleanup;
  2137. } // if
  2138. //
  2139. // Check platform interoperability.
  2140. //
  2141. hr = THR( HrCheckPlatformInteroperability() );
  2142. if ( FAILED( hr ) )
  2143. {
  2144. goto Cleanup;
  2145. } // if
  2146. hr = THR( SendStatusReport(
  2147. m_bstrClusterName
  2148. , TASKID_Major_Update_Progress
  2149. , TASKID_Major_Check_Cluster_Feasibility
  2150. , 0
  2151. , 8
  2152. , 3
  2153. , hr
  2154. , NULL
  2155. , NULL
  2156. , NULL
  2157. ) );
  2158. if ( FAILED( hr ) )
  2159. {
  2160. goto Cleanup;
  2161. } // if
  2162. //
  2163. // Check version interoperability.
  2164. //
  2165. hr = STHR( HrCheckInteroperability() );
  2166. if ( FAILED( hr ) )
  2167. {
  2168. goto Cleanup;
  2169. } // if
  2170. hr = THR( SendStatusReport(
  2171. m_bstrClusterName
  2172. , TASKID_Major_Update_Progress
  2173. , TASKID_Major_Check_Cluster_Feasibility
  2174. , 0
  2175. , 8
  2176. , 4
  2177. , hr
  2178. , NULL
  2179. , NULL
  2180. , NULL
  2181. ) );
  2182. if ( FAILED( hr ) )
  2183. {
  2184. goto Cleanup;
  2185. } // if
  2186. //
  2187. // Compare drive letter mappings to make sure we don't have any conflicts.
  2188. //
  2189. hr = THR( HrCompareDriveLetterMappings() );
  2190. if ( FAILED( hr ) )
  2191. {
  2192. goto Cleanup;
  2193. } // if
  2194. hr = THR( SendStatusReport(
  2195. m_bstrClusterName
  2196. , TASKID_Major_Update_Progress
  2197. , TASKID_Major_Check_Cluster_Feasibility
  2198. , 0
  2199. , 8
  2200. , 5
  2201. , hr
  2202. , NULL
  2203. , NULL
  2204. , NULL
  2205. ) );
  2206. if ( FAILED( hr ) )
  2207. {
  2208. goto Cleanup;
  2209. } // if
  2210. //
  2211. // Compare resources on each node and in the cluster.
  2212. //
  2213. hr = THR( HrCompareResources() );
  2214. if ( FAILED( hr ) )
  2215. {
  2216. goto Cleanup;
  2217. } // if
  2218. hr = THR( SendStatusReport(
  2219. m_bstrClusterName
  2220. , TASKID_Major_Update_Progress
  2221. , TASKID_Major_Check_Cluster_Feasibility
  2222. , 0
  2223. , 8
  2224. , 6
  2225. , hr
  2226. , NULL
  2227. , NULL
  2228. , NULL
  2229. ) );
  2230. if ( FAILED( hr ) )
  2231. {
  2232. goto Cleanup;
  2233. } // if
  2234. //
  2235. // Compare the networks.
  2236. //
  2237. hr = THR( HrCompareNetworks() );
  2238. if ( FAILED( hr ) )
  2239. {
  2240. goto Cleanup;
  2241. } // if
  2242. hr = THR( SendStatusReport(
  2243. m_bstrClusterName
  2244. , TASKID_Major_Update_Progress
  2245. , TASKID_Major_Check_Cluster_Feasibility
  2246. , 0
  2247. , 8
  2248. , 7
  2249. , hr
  2250. , NULL
  2251. , NULL
  2252. , NULL
  2253. ) );
  2254. if ( FAILED( hr ) )
  2255. {
  2256. goto Cleanup;
  2257. } // if
  2258. //
  2259. // Now check to see if the nodes can all see the selected quorum resource.
  2260. //
  2261. hr = THR( HrCheckForCommonQuorumResource() );
  2262. if ( FAILED( hr ) )
  2263. {
  2264. goto Cleanup;
  2265. } // if
  2266. Cleanup:
  2267. //
  2268. // Notify the UI layer that we are done.
  2269. //
  2270. THR( SendStatusReport(
  2271. m_bstrClusterName
  2272. , TASKID_Major_Update_Progress
  2273. , TASKID_Major_Check_Cluster_Feasibility
  2274. , 0
  2275. , 8
  2276. , 8
  2277. , hr
  2278. , NULL
  2279. , NULL
  2280. , NULL
  2281. ) );
  2282. HRETURN( hr );
  2283. } //*** CTaskAnalyzeClusterBase::HrCheckClusterFeasibility
  2284. //////////////////////////////////////////////////////////////////////////////
  2285. //++
  2286. //
  2287. // CTaskAnalyzeClusterBase::HrAddJoinedNodes
  2288. //
  2289. // Description:
  2290. //
  2291. // Arguments:
  2292. //
  2293. // Return Value:
  2294. // S_OK
  2295. // Success
  2296. //
  2297. // HRESULT failure.
  2298. //
  2299. //--
  2300. //////////////////////////////////////////////////////////////////////////////
  2301. HRESULT
  2302. CTaskAnalyzeClusterBase::HrAddJoinedNodes( void )
  2303. {
  2304. TraceFunc( "" );
  2305. HRESULT hr = S_OK;
  2306. long idxNode = 0;
  2307. long cNodes = 0;
  2308. BSTR* rgbstrNodeNames = NULL;
  2309. OBJECTCOOKIE cookieDummy;
  2310. BSTR bstrNodeFQN = NULL;
  2311. size_t idxClusterDomain = 0;
  2312. IUnknown * punkDummy = NULL;
  2313. IUnknown * punk = NULL;
  2314. IClusCfgServer * piccs = NULL;
  2315. IClusCfgNodeInfo * piccni = NULL;
  2316. IClusCfgClusterInfo * piccci = NULL;
  2317. IClusCfgClusterInfoEx * picccie = NULL;
  2318. TraceFlow1( "[MT] CTaskAnalyzeClusterBase::HrAddJoinedNodes() Thread id %d", GetCurrentThreadId() );
  2319. hr = THR( HrSendStatusReport(
  2320. m_bstrClusterName
  2321. , TASKID_Major_Check_Cluster_Feasibility
  2322. , TASKID_Minor_AddJoinedNodes
  2323. , 0
  2324. , 1
  2325. , 0
  2326. , hr
  2327. , IDS_TASKID_MINOR_ADD_JOINED_NODES
  2328. ) );
  2329. if ( FAILED( hr ) )
  2330. {
  2331. goto Cleanup;
  2332. } // if:
  2333. hr = THR( m_pcm->GetConnectionToObject( m_cookieCluster, &punk ) );
  2334. if ( FAILED( hr ) )
  2335. {
  2336. SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_HrAddJoinedNodes_GetConnectionObject, hr );
  2337. goto Cleanup;
  2338. } // if:
  2339. hr = THR( punk->TypeSafeQI( IClusCfgServer, &piccs ) );
  2340. if ( FAILED( hr ) )
  2341. {
  2342. SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_HrAddJoinedNodes_ConfigConnection_QI, hr );
  2343. goto Cleanup;
  2344. } // if:
  2345. hr = THR( piccs->GetClusterNodeInfo( &piccni ) );
  2346. if ( FAILED( hr ) )
  2347. {
  2348. SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_HrAddJoinedNodes_GetNodeInfo, hr );
  2349. goto Cleanup;
  2350. } // if:
  2351. hr = THR( piccni->GetClusterConfigInfo( &piccci ) );
  2352. if ( FAILED( hr ) )
  2353. {
  2354. SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_HrAddJoinedNodes_GetConfigInfo, hr );
  2355. goto Cleanup;
  2356. } // if:
  2357. hr = THR( piccci->TypeSafeQI( IClusCfgClusterInfoEx, &picccie ) );
  2358. if ( FAILED( hr ) )
  2359. {
  2360. THR( HrSendStatusReport(
  2361. m_bstrClusterName
  2362. , TASKID_Major_Check_Cluster_Feasibility
  2363. , TASKID_Minor_HrAddJoinedNodes_ClusterInfoEx_QI
  2364. , 0
  2365. , 1
  2366. , 1
  2367. , hr
  2368. , IDS_ERR_NO_RC2_INTERFACE
  2369. ) );
  2370. goto Cleanup;
  2371. } // if:
  2372. hr = THR( HrFindDomainInFQN( m_bstrClusterName, &idxClusterDomain ) );
  2373. if ( FAILED( hr ) )
  2374. {
  2375. SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_HrAddJoinedNodes_HrFindDomainInFQN, hr );
  2376. goto Cleanup;
  2377. } // if
  2378. hr = THR( picccie->GetNodeNames( &cNodes, &rgbstrNodeNames ) );
  2379. if ( FAILED( hr ) )
  2380. {
  2381. SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_HrAddJoinedNodes_GetNodeNames, hr );
  2382. goto Cleanup;
  2383. } // if
  2384. for ( idxNode = 0; idxNode < cNodes; ++idxNode )
  2385. {
  2386. //
  2387. // Build the FQName of the node.
  2388. //
  2389. hr = THR( HrMakeFQN( rgbstrNodeNames[ idxNode ], m_bstrClusterName + idxClusterDomain, TRUE /*Accept non-RFC characters*/, &bstrNodeFQN ) );
  2390. if ( FAILED( hr ) )
  2391. {
  2392. SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_HrAddJoinedNodes_HrMakeFQN, hr );
  2393. goto Cleanup;
  2394. } // if
  2395. LogMsg( L"[MT] Connecting to cluster node '%ws'", bstrNodeFQN );
  2396. //
  2397. // Prime the object manager to retrieve the node information.
  2398. //
  2399. // can't wrap - should return E_PENDING
  2400. hr = m_pom->FindObject( CLSID_NodeType, m_cookieCluster, bstrNodeFQN, DFGUID_NodeInformation, &cookieDummy, &punkDummy );
  2401. if ( SUCCEEDED( hr ) )
  2402. {
  2403. Assert( punkDummy != NULL );
  2404. punkDummy->Release();
  2405. punkDummy = NULL;
  2406. } // if
  2407. else if ( hr == E_PENDING )
  2408. {
  2409. hr = S_OK;
  2410. } // else
  2411. else // !SUCCEEDED( hr ) && ( hr != E_PENDING )
  2412. {
  2413. THR( hr );
  2414. SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_AddJoinedNodes_FindObject, hr );
  2415. goto Cleanup;
  2416. } // else
  2417. TraceSysFreeString( bstrNodeFQN );
  2418. bstrNodeFQN = NULL;
  2419. } // for: idx
  2420. Cleanup:
  2421. THR( HrSendStatusReport(
  2422. m_bstrClusterName
  2423. , TASKID_Major_Check_Cluster_Feasibility
  2424. , TASKID_Minor_AddJoinedNodes
  2425. , 0
  2426. , 1
  2427. , 1
  2428. , hr
  2429. , IDS_TASKID_MINOR_ADD_JOINED_NODES
  2430. ) );
  2431. Assert( punkDummy == NULL );
  2432. TraceSysFreeString( bstrNodeFQN );
  2433. if ( punk != NULL )
  2434. {
  2435. punk->Release();
  2436. } // if:
  2437. if ( piccs != NULL )
  2438. {
  2439. piccs->Release();
  2440. } // if
  2441. if ( piccni != NULL )
  2442. {
  2443. piccni->Release();
  2444. } // if:
  2445. if ( piccci != NULL )
  2446. {
  2447. piccci->Release();
  2448. } // if:
  2449. if ( picccie != NULL )
  2450. {
  2451. picccie->Release();
  2452. } // if:
  2453. if ( rgbstrNodeNames != NULL )
  2454. {
  2455. for ( idxNode = 0; idxNode < cNodes; idxNode += 1 )
  2456. {
  2457. SysFreeString( rgbstrNodeNames[ idxNode ] );
  2458. } // for
  2459. CoTaskMemFree( rgbstrNodeNames );
  2460. } // if
  2461. HRETURN( hr );
  2462. } //*** CTaskAnalyzeClusterBase::HrAddJoinedNodes
  2463. //////////////////////////////////////////////////////////////////////////////
  2464. //++
  2465. //
  2466. // CTaskAnalyzeClusterBase::HrCheckDomainMembership
  2467. //
  2468. // Description:
  2469. // Determine whether all participating nodes are in the cluster's domain.
  2470. //
  2471. // Arguments:
  2472. // None.
  2473. //
  2474. // Return Value:
  2475. // S_OK
  2476. //
  2477. // HRESULT failure.
  2478. //
  2479. //--
  2480. //////////////////////////////////////////////////////////////////////////////
  2481. HRESULT
  2482. CTaskAnalyzeClusterBase::HrCheckNodeDomains( void )
  2483. {
  2484. TraceFunc( "" );
  2485. HRESULT hr = S_OK;
  2486. OBJECTCOOKIE ocNodeEnum = 0;
  2487. IUnknown * punkNodeEnum = NULL;
  2488. IEnumNodes * pen = NULL;
  2489. IClusCfgNodeInfo ** prgccni = NULL;
  2490. DWORD cNodeInfoObjects = 0;
  2491. DWORD idxNodeInfo = 0;
  2492. BSTR bstrNodeName = NULL;
  2493. size_t idxClusterDomain = 0;
  2494. ULONG cNodesFetched = 0;
  2495. BSTR bstrDescription = NULL;
  2496. BSTR bstrReference = NULL;
  2497. hr = THR( HrSendStatusReport(
  2498. m_bstrClusterName
  2499. , TASKID_Major_Check_Cluster_Feasibility
  2500. , TASKID_Minor_CheckNodeDomains
  2501. , 0
  2502. , 1
  2503. , 0
  2504. , S_OK
  2505. , IDS_TASKID_MINOR_CHECK_NODE_DOMAINS
  2506. ) );
  2507. if ( FAILED( hr ) )
  2508. {
  2509. goto Cleanup;
  2510. } // if:
  2511. //
  2512. // Get a pointer to the domain portion of the cluster's name.
  2513. //
  2514. hr = THR( HrFindDomainInFQN( m_bstrClusterName, &idxClusterDomain ) );
  2515. if ( FAILED( hr ) )
  2516. {
  2517. SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_CheckNodeDomains_HrFindDomainInClusterFQN, hr );
  2518. goto Cleanup;
  2519. } // if
  2520. //
  2521. // Ask the object manager for the node enumerator.
  2522. //
  2523. hr = THR( m_pom->FindObject( CLSID_NodeType,
  2524. m_cookieCluster,
  2525. NULL,
  2526. DFGUID_EnumNodes,
  2527. &ocNodeEnum,
  2528. &punkNodeEnum
  2529. ) );
  2530. if ( FAILED( hr ) )
  2531. {
  2532. SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_CheckNodeDomains_FindObject, hr );
  2533. goto Cleanup;
  2534. } // if
  2535. hr = THR( punkNodeEnum->TypeSafeQI( IEnumNodes, &pen ) );
  2536. if ( FAILED( hr ) )
  2537. {
  2538. SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_CheckNodeDomains_QI, hr );
  2539. goto Cleanup;
  2540. } // if
  2541. //
  2542. // Get array of node objects.
  2543. //
  2544. hr = THR( pen->Count( &cNodeInfoObjects ) );
  2545. if ( FAILED( hr ) )
  2546. {
  2547. SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_CheckNodeDomains_Count, hr );
  2548. goto Cleanup;
  2549. } // if
  2550. if ( cNodeInfoObjects == 0 )
  2551. {
  2552. // Nothing to check, so no more work to do.
  2553. hr = S_OK;
  2554. goto Cleanup;
  2555. } // if
  2556. prgccni = new IClusCfgNodeInfo*[ cNodeInfoObjects ];
  2557. if ( prgccni == NULL )
  2558. {
  2559. hr = THR( E_OUTOFMEMORY );
  2560. SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_CheckNodeDomains_New, hr );
  2561. goto Cleanup;
  2562. } // if
  2563. ZeroMemory( prgccni, cNodeInfoObjects * sizeof( *prgccni ) );
  2564. do
  2565. {
  2566. hr = STHR( pen->Next( cNodeInfoObjects, prgccni, &cNodesFetched ) );
  2567. if ( FAILED( hr ) )
  2568. {
  2569. SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_CheckNodeDomains_Next, hr );
  2570. goto Cleanup;
  2571. } // if
  2572. //
  2573. // Step through node array, checking domain of each against cluster's domain.
  2574. //
  2575. for ( idxNodeInfo = 0; idxNodeInfo < cNodesFetched; idxNodeInfo += 1 )
  2576. {
  2577. size_t idxNodeDomain = 0;
  2578. hr = THR( prgccni[ idxNodeInfo ]->GetName( &bstrNodeName ) );
  2579. if ( FAILED( hr ) )
  2580. {
  2581. SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_CheckNodeDomains_GetName, hr );
  2582. goto Cleanup;
  2583. } // if
  2584. TraceMemoryAddBSTR( bstrNodeName );
  2585. // Done with the node, but might reuse array, so dispose node now.
  2586. prgccni[ idxNodeInfo ]->Release();
  2587. prgccni[ idxNodeInfo ] = NULL;
  2588. hr = THR( HrFindDomainInFQN( bstrNodeName, &idxNodeDomain ) );
  2589. if ( FAILED( hr ) )
  2590. {
  2591. SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_CheckNodeDomains_HrFindDomainInNodeFQN, hr );
  2592. goto Cleanup;
  2593. } // if
  2594. if ( ClRtlStrICmp( bstrNodeName + idxNodeDomain, m_bstrClusterName + idxClusterDomain ) != 0 )
  2595. {
  2596. DWORD scError = TW32( ERROR_INVALID_DATA );
  2597. hr = THR( HrFormatMessageIntoBSTR(
  2598. g_hInstance
  2599. , IDS_TASKID_MINOR_CHECK_NODE_DOMAINS_ERROR_REF
  2600. , &bstrReference
  2601. , bstrNodeName
  2602. , bstrNodeName + idxNodeDomain
  2603. , m_bstrClusterName + idxClusterDomain
  2604. ) );
  2605. if ( FAILED( hr ) )
  2606. {
  2607. SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_CheckNodeDomains_FormatMessage, hr );
  2608. goto Cleanup;
  2609. } // if
  2610. hr = THR( HrLoadStringIntoBSTR( g_hInstance, IDS_TASKID_MINOR_CHECK_NODE_DOMAINS_ERROR, &bstrDescription ) );
  2611. if ( FAILED( hr ) )
  2612. {
  2613. SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_CheckNodeDomains_LoadString, hr );
  2614. goto Cleanup;
  2615. } // if:
  2616. hr = HRESULT_FROM_WIN32( scError );
  2617. THR( SendStatusReport(
  2618. m_bstrClusterName
  2619. , TASKID_Major_Check_Cluster_Feasibility
  2620. , TASKID_Minor_CheckNodeDomains
  2621. , 0
  2622. , 1
  2623. , 1
  2624. , hr
  2625. , bstrDescription
  2626. , NULL
  2627. , bstrReference
  2628. ) );
  2629. goto Cleanup;
  2630. } // if node domain does not match cluster's
  2631. TraceSysFreeString( bstrNodeName );
  2632. bstrNodeName = NULL;
  2633. } // for each node
  2634. } while ( cNodesFetched > 0 ); // while enumerator has more nodes
  2635. // Might have finished the loop with S_FALSE, so replace with S_OK to signal normal completion.
  2636. hr = S_OK;
  2637. Cleanup:
  2638. THR( HrSendStatusReport(
  2639. m_bstrClusterName
  2640. , TASKID_Major_Check_Cluster_Feasibility
  2641. , TASKID_Minor_CheckNodeDomains
  2642. , 0
  2643. , 1
  2644. , 1
  2645. , hr
  2646. , IDS_TASKID_MINOR_CHECK_NODE_DOMAINS
  2647. ) );
  2648. if ( punkNodeEnum != NULL )
  2649. {
  2650. punkNodeEnum->Release();
  2651. } // if:
  2652. if ( pen != NULL )
  2653. {
  2654. pen->Release();
  2655. } // if:
  2656. if ( prgccni != NULL )
  2657. {
  2658. for ( idxNodeInfo = 0; idxNodeInfo < cNodeInfoObjects; idxNodeInfo += 1 )
  2659. {
  2660. if ( prgccni[ idxNodeInfo ] != NULL )
  2661. {
  2662. prgccni[ idxNodeInfo ]->Release();
  2663. } // if
  2664. } // for
  2665. delete [] prgccni;
  2666. } // if
  2667. TraceSysFreeString( bstrNodeName );
  2668. TraceSysFreeString( bstrReference );
  2669. HRETURN( hr );
  2670. } //*** CTaskAnalyzeClusterBase::HrCheckNodeDomains
  2671. //////////////////////////////////////////////////////////////////////////////
  2672. //++
  2673. //
  2674. // CTaskAnalyzeClusterBase::HrCheckClusterMembership
  2675. //
  2676. // Description:
  2677. //
  2678. // Arguments:
  2679. //
  2680. // Return Value:
  2681. // S_OK
  2682. // Success
  2683. //
  2684. // HRESULT failure.
  2685. //
  2686. // ERROR_CLUSTER_NODE_EXISTS
  2687. // ERROR_CLUSTER_NODE_ALREADY_MEMBER
  2688. //
  2689. //--
  2690. //////////////////////////////////////////////////////////////////////////////
  2691. HRESULT
  2692. CTaskAnalyzeClusterBase::HrCheckClusterMembership( void )
  2693. {
  2694. TraceFunc( "" );
  2695. HRESULT hr = S_OK;
  2696. OBJECTCOOKIE cookieDummy;
  2697. IClusCfgClusterInfo * pccci;
  2698. BSTR bstrNodeName = NULL;
  2699. BSTR bstrClusterName = NULL;
  2700. BSTR bstrNotification = NULL;
  2701. IUnknown * punk = NULL;
  2702. IEnumNodes * pen = NULL;
  2703. IClusCfgNodeInfo * pccni = NULL;
  2704. TraceFlow1( "[MT] CTaskAnalyzeClusterBase::HrCheckClusterMembership() Thread id %d", GetCurrentThreadId() );
  2705. hr = THR( HrSendStatusReport(
  2706. m_bstrClusterName
  2707. , TASKID_Major_Check_Cluster_Feasibility
  2708. , TASKID_Minor_Check_Cluster_Membership
  2709. , 0
  2710. , 1
  2711. , 0
  2712. , hr
  2713. , IDS_TASKID_MINOR_CHECK_CLUSTER_MEMBERSHIP
  2714. ) );
  2715. if ( FAILED( hr ) )
  2716. {
  2717. goto Cleanup;
  2718. } // if:
  2719. //
  2720. // Ask the object manager for the node enumerator.
  2721. //
  2722. hr = THR( m_pom->FindObject( CLSID_NodeType, m_cookieCluster, NULL, DFGUID_EnumNodes,&cookieDummy, &punk ) );
  2723. if ( FAILED( hr ) )
  2724. {
  2725. SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_CheckMembership_FindObject, hr );
  2726. goto Cleanup;
  2727. }
  2728. hr = THR( punk->TypeSafeQI( IEnumNodes, &pen ) );
  2729. if ( FAILED( hr ) )
  2730. {
  2731. SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_CheckMembership_FindObject_QI, hr );
  2732. goto Cleanup;
  2733. }
  2734. //
  2735. // If we are adding nodes to an existing cluster, make sure that all the
  2736. // other nodes are members of the same cluster.
  2737. //
  2738. Assert( SUCCEEDED( hr ) );
  2739. while ( SUCCEEDED( hr ) )
  2740. {
  2741. ULONG celtDummy;
  2742. //
  2743. // Cleanup
  2744. //
  2745. if ( pccni != NULL )
  2746. {
  2747. pccni->Release();
  2748. pccni = NULL;
  2749. }
  2750. TraceSysFreeString( bstrClusterName );
  2751. bstrClusterName = NULL;
  2752. //
  2753. // Get the next node.
  2754. //
  2755. hr = STHR( pen->Next( 1, &pccni, &celtDummy ) );
  2756. if ( hr == S_FALSE )
  2757. {
  2758. break; // exit condition
  2759. }
  2760. if ( FAILED( hr ) )
  2761. {
  2762. SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_CheckMembership_EnumNode_Next, hr );
  2763. goto Cleanup;
  2764. }
  2765. //
  2766. // Check to see if we need to "form a cluster" by seeing if any
  2767. // of the nodes are already clustered.
  2768. //
  2769. hr = STHR( pccni->IsMemberOfCluster() );
  2770. if ( FAILED( hr ) )
  2771. {
  2772. SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_CheckMembership_EnumNode_IsMemberOfCluster, hr );
  2773. goto Cleanup;
  2774. }
  2775. if ( hr == S_OK )
  2776. {
  2777. //
  2778. // Retrieve the name and make sure they match.
  2779. //
  2780. hr = THR( pccni->GetClusterConfigInfo( &pccci ) );
  2781. if ( FAILED( hr ) )
  2782. {
  2783. SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_CheckMembership_EnumNode_GetClusterConfigInfo, hr );
  2784. goto Cleanup;
  2785. }
  2786. hr = THR( pccci->GetName( &bstrClusterName ) );
  2787. pccci->Release(); // release promptly
  2788. if ( FAILED( hr ) )
  2789. {
  2790. SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_CheckMembership_EnumNode_GetName, hr );
  2791. goto Cleanup;
  2792. }
  2793. TraceMemoryAddBSTR( bstrClusterName );
  2794. hr = THR( pccni->GetName( &bstrNodeName ) );
  2795. if ( FAILED( hr ) )
  2796. {
  2797. SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_CheckMembership_EnumNode_GetNodeName, hr );
  2798. goto Cleanup;
  2799. }
  2800. TraceMemoryAddBSTR( bstrNodeName );
  2801. if ( ClRtlStrICmp( m_bstrClusterName, bstrClusterName ) != 0 )
  2802. {
  2803. //
  2804. // They don't match! Tell the UI layer!
  2805. //
  2806. hr = THR( HrFormatMessageIntoBSTR( g_hInstance, IDS_TASKID_MINOR_CLUSTER_NAME_MISMATCH, &bstrNotification, bstrClusterName ) );
  2807. if ( FAILED( hr ) )
  2808. {
  2809. SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_CheckMembership_EnumNode_FormatMessage, hr );
  2810. goto Cleanup;
  2811. }
  2812. hr = HRESULT_FROM_WIN32( TW32( ERROR_INVALID_DATA ) );
  2813. THR( SendStatusReport( bstrNodeName,
  2814. TASKID_Major_Check_Cluster_Feasibility,
  2815. TASKID_Minor_Cluster_Name_Mismatch,
  2816. 1,
  2817. 1,
  2818. 1,
  2819. hr,
  2820. bstrNotification,
  2821. NULL,
  2822. NULL
  2823. ) );
  2824. //
  2825. // We don't care what the return value is since we are bailing the analysis.
  2826. //
  2827. goto Cleanup;
  2828. } // if: cluster names don't match
  2829. else
  2830. {
  2831. hr = STHR( HrIsUserAddedNode( bstrNodeName ) );
  2832. if ( FAILED( hr ) )
  2833. {
  2834. goto Cleanup;
  2835. } // if:
  2836. if ( hr == S_OK )
  2837. {
  2838. hr = THR( HrFormatMessageIntoBSTR( g_hInstance, IDS_TASKID_MINOR_NODE_ALREADY_IS_MEMBER, &bstrNotification, bstrNodeName, bstrClusterName ) );
  2839. if ( FAILED( hr ) )
  2840. {
  2841. SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_CheckMembership_EnumNode_FormatMessage1, hr );
  2842. goto Cleanup;
  2843. }
  2844. //
  2845. // Make this a success code because we don't want to abort. We simply want to tell the user...
  2846. //
  2847. hr = MAKE_HRESULT( SEVERITY_SUCCESS, FACILITY_WIN32, ERROR_CLUSTER_NODE_ALREADY_MEMBER );
  2848. THR( SendStatusReport( bstrNodeName,
  2849. TASKID_Major_Check_Cluster_Feasibility,
  2850. TASKID_Minor_Cluster_Name_Match,
  2851. 1,
  2852. 1,
  2853. 1,
  2854. hr,
  2855. bstrNotification,
  2856. NULL,
  2857. NULL
  2858. ) );
  2859. } // if:
  2860. } // else: cluster names do match then this node is already a member of this cluster
  2861. TraceSysFreeString( bstrNodeName );
  2862. bstrNodeName = NULL;
  2863. } // if: cluster member
  2864. } // while: hr
  2865. hr = THR( HrFormatMessageIntoBSTR( g_hInstance, IDS_TASKID_MINOR_CLUSTER_MEMBERSHIP_VERIFIED, &bstrNotification ) );
  2866. if ( FAILED( hr ) )
  2867. {
  2868. SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_CheckMembership_FormatMessage, hr );
  2869. goto Cleanup;
  2870. }
  2871. THR( HrSendStatusReport(
  2872. m_bstrClusterName
  2873. , TASKID_Minor_Check_Cluster_Membership
  2874. , TASKID_Minor_Cluster_Membership_Verified
  2875. , 1
  2876. , 1
  2877. , 1
  2878. , hr
  2879. , IDS_TASKID_CLUSTER_MEMBERSHIP_VERIFIED
  2880. ) );
  2881. Cleanup:
  2882. THR( HrSendStatusReport(
  2883. m_bstrClusterName
  2884. , TASKID_Major_Check_Cluster_Feasibility
  2885. , TASKID_Minor_Check_Cluster_Membership
  2886. , 0
  2887. , 1
  2888. , 1
  2889. , hr
  2890. , IDS_TASKID_MINOR_CHECK_CLUSTER_MEMBERSHIP
  2891. ) );
  2892. if ( pen != NULL )
  2893. {
  2894. pen->Release();
  2895. } // if:
  2896. if ( punk != NULL )
  2897. {
  2898. punk->Release();
  2899. } // if:
  2900. TraceSysFreeString( bstrNodeName );
  2901. TraceSysFreeString( bstrClusterName );
  2902. TraceSysFreeString( bstrNotification );
  2903. HRETURN( hr );
  2904. } //*** CTaskAnalyzeClusterBase::HrCheckClusterMembership
  2905. //////////////////////////////////////////////////////////////////////////////
  2906. //++
  2907. //
  2908. // CTaskAnalyzeClusterBase::HrCompareResources
  2909. //
  2910. // Description:
  2911. //
  2912. // Arguments:
  2913. //
  2914. // Return Value:
  2915. // S_OK
  2916. // Success
  2917. //
  2918. // HRESULT failure.
  2919. //
  2920. //--
  2921. //////////////////////////////////////////////////////////////////////////////
  2922. HRESULT
  2923. CTaskAnalyzeClusterBase::HrCompareResources( void )
  2924. {
  2925. TraceFunc( "" );
  2926. HRESULT hr = S_OK;
  2927. OBJECTCOOKIE cookieNode;
  2928. OBJECTCOOKIE cookieDummy;
  2929. OBJECTCOOKIE cookieClusterNode;
  2930. ULONG celtDummy;
  2931. BSTR bstrNotification = NULL;
  2932. BSTR bstrClusterNodeName = NULL;
  2933. BSTR bstrClusterResUID = NULL;
  2934. BSTR bstrClusterResName = NULL;
  2935. BSTR bstrNodeName = NULL;
  2936. BSTR bstrNodeResUID = NULL;
  2937. BSTR bstrNodeResName = NULL;
  2938. BSTR bstrQuorumName = NULL;
  2939. IClusCfgManagedResourceInfo * pccmriNew = NULL;
  2940. IUnknown * punk = NULL;
  2941. IEnumCookies * pecNodes = NULL;
  2942. IEnumClusCfgManagedResources * peccmr = NULL;
  2943. IEnumClusCfgManagedResources * peccmrCluster = NULL;
  2944. IClusCfgManagedResourceInfo * pccmri = NULL;
  2945. IClusCfgManagedResourceInfo * pccmriCluster = NULL;
  2946. IClusCfgVerifyQuorum * piccvq = NULL;
  2947. TraceFlow1( "[MT] CTaskAnalyzeClusterBase::HrCompareResources() Thread id %d", GetCurrentThreadId() );
  2948. hr = THR( HrSendStatusReport(
  2949. m_bstrClusterName
  2950. , TASKID_Major_Check_Cluster_Feasibility
  2951. , TASKID_Minor_Compare_Resources
  2952. , 0
  2953. , 1
  2954. , 0
  2955. , hr
  2956. , IDS_TASKID_MINOR_COMPARE_RESOURCES
  2957. ) );
  2958. if ( FAILED( hr ) )
  2959. {
  2960. goto Cleanup;
  2961. } // if:
  2962. hr = THR( HrGetAClusterNodeCookie( &pecNodes, &cookieClusterNode ) );
  2963. if ( FAILED( hr ) )
  2964. {
  2965. goto Cleanup;
  2966. } // if:
  2967. //
  2968. // Retrieve the node's name for error messages.
  2969. //
  2970. hr = THR( HrRetrieveCookiesName( m_pom, cookieClusterNode, &bstrClusterNodeName ) );
  2971. if ( FAILED( hr ) )
  2972. {
  2973. goto Cleanup;
  2974. } // if:
  2975. //
  2976. // Retrieve the managed resources enumerator.
  2977. //
  2978. hr = THR( m_pom->FindObject( CLSID_ManagedResourceType, cookieClusterNode, NULL, DFGUID_EnumManageableResources, &cookieDummy, &punk ) );
  2979. if ( hr == HRESULT_FROM_WIN32( ERROR_NOT_FOUND ) )
  2980. {
  2981. hr = THR( HrSendStatusReport(
  2982. m_bstrClusterName
  2983. , TASKID_Minor_Compare_Resources
  2984. , TASKID_Minor_No_Managed_Resources_Found
  2985. , 1
  2986. , 1
  2987. , 1
  2988. , MAKE_HRESULT( 0, FACILITY_WIN32, ERROR_NOT_FOUND )
  2989. , IDS_TASKID_MINOR_NO_MANAGED_RESOURCES_FOUND
  2990. ) );
  2991. if ( FAILED( hr ) )
  2992. {
  2993. goto Cleanup;
  2994. }
  2995. hr = HRESULT_FROM_WIN32( ERROR_NOT_FOUND );
  2996. // fall thru - the while ( hr == S_OK ) will be FALSE and keep going
  2997. } // if: no manageable resources are available for the cluster node
  2998. else if ( FAILED( hr ) )
  2999. {
  3000. SSR_ANALYSIS_FAILED( TASKID_Minor_Compare_Resources, TASKID_Minor_Compare_Resources_Enum_First_Node_Find_Object, hr );
  3001. goto Cleanup;
  3002. } // else if: error finding manageable resources for the cluster node
  3003. else
  3004. {
  3005. hr = THR( punk->TypeSafeQI( IEnumClusCfgManagedResources, &peccmrCluster ) );
  3006. if ( FAILED( hr ) )
  3007. {
  3008. SSR_ANALYSIS_FAILED( TASKID_Minor_Compare_Resources, TASKID_Minor_Compare_Resources_Enum_First_Node_Find_Object_QI, hr );
  3009. goto Cleanup;
  3010. }
  3011. punk->Release();
  3012. punk = NULL;
  3013. } // else: found manageable resources for the cluster node
  3014. //
  3015. // Loop thru the resources of the node selected as the cluster node
  3016. // to create an equivalent resource under the cluster configuration
  3017. // object/cookie.
  3018. //
  3019. while ( ( hr == S_OK ) && ( m_fStop == FALSE ) )
  3020. {
  3021. //
  3022. // Cleanup
  3023. //
  3024. if ( pccmriCluster != NULL )
  3025. {
  3026. pccmriCluster->Release();
  3027. pccmriCluster = NULL;
  3028. }
  3029. //
  3030. // Get next resource.
  3031. //
  3032. hr = STHR( peccmrCluster->Next( 1, &pccmriCluster, &celtDummy ) );
  3033. if ( FAILED( hr ) )
  3034. {
  3035. SSR_ANALYSIS_FAILED( TASKID_Minor_Compare_Resources, TASKID_Minor_Compare_Resources_Enum_First_Node_Next, hr );
  3036. goto Cleanup;
  3037. }
  3038. if ( hr == S_FALSE )
  3039. {
  3040. break; // exit condition
  3041. }
  3042. //
  3043. // Create a new object. If min config was selected this new object will be marked as not managed.
  3044. //
  3045. hr = THR( HrCreateNewResourceInCluster( pccmriCluster, &pccmriNew ) );
  3046. if ( FAILED( hr ) )
  3047. {
  3048. goto Cleanup;
  3049. } // if:
  3050. hr = STHR( pccmriNew->IsQuorumResource() );
  3051. if ( hr == S_OK )
  3052. {
  3053. Assert( m_bstrQuorumUID == NULL );
  3054. hr = THR( pccmriNew->GetUID( &m_bstrQuorumUID ) );
  3055. if ( FAILED( hr ) )
  3056. {
  3057. SSR_ANALYSIS_FAILED( TASKID_Minor_Compare_Resources, TASKID_Minor_Compare_Resources_Enum_First_Node_Get_Quorum_UID, hr );
  3058. goto Cleanup;
  3059. } // if:
  3060. TraceMemoryAddBSTR( m_bstrQuorumUID );
  3061. LogMsg( L"[MT][1] Found the quorum resource '%ws' on node '%ws' and setting it as the quorum resource.", m_bstrQuorumUID, bstrClusterNodeName );
  3062. Assert( pccmriNew->IsManaged() == S_OK );
  3063. //
  3064. // Since this is the quorum resource then it needs to be managed. If min config was selected it will not be managed.
  3065. //
  3066. //hr = THR( pccmriNew->SetManaged( TRUE ) );
  3067. //if ( FAILED( hr ) )
  3068. //{
  3069. // goto Cleanup;
  3070. //} // if:
  3071. //
  3072. // Tell the UI which resource is the quorum.
  3073. //
  3074. hr = THR( pccmriNew->GetName( &bstrQuorumName ) );
  3075. if ( FAILED( hr ) )
  3076. {
  3077. goto Cleanup;
  3078. } // if:
  3079. TraceMemoryAddBSTR( bstrQuorumName );
  3080. hr = THR( ::HrFormatDescriptionAndSendStatusReport(
  3081. m_pcccb
  3082. , m_bstrClusterName
  3083. , TASKID_Minor_Compare_Resources
  3084. , TASKID_Minor_Compare_Resources_Enum_First_Node_Quorum
  3085. , 1
  3086. , 1
  3087. , 1
  3088. , hr
  3089. , IDS_TASKID_MINOR_COMPARE_RESOURCES_ENUM_FIRST_NODE_QUORUM
  3090. , bstrQuorumName
  3091. ) );
  3092. if ( FAILED( hr ) )
  3093. {
  3094. goto Cleanup;
  3095. } // if:
  3096. //
  3097. // Check that the quorum supports adding nodes to the cluster
  3098. // if we are in add mode.
  3099. //
  3100. if ( m_fJoiningMode )
  3101. {
  3102. hr = pccmriNew->TypeSafeQI( IClusCfgVerifyQuorum, &piccvq );
  3103. if ( hr == E_NOINTERFACE )
  3104. {
  3105. LogMsg( L"[MT] The quorum resource \"%ws\" does not support IClusCfgVerifyQuorum and we cannot determine if multi nodes is supported.", m_bstrQuorumUID );
  3106. hr = S_OK;
  3107. } // if:
  3108. else if ( FAILED( hr ) )
  3109. {
  3110. goto Cleanup;
  3111. } // else if:
  3112. else
  3113. {
  3114. hr = STHR( piccvq->IsMultiNodeCapable() );
  3115. if ( FAILED( hr ) )
  3116. {
  3117. SSR_ANALYSIS_FAILED( TASKID_Minor_Compare_Resources, TASKID_Minor_Compare_Resources_Enum_First_Node_Is_Device_Joinable, hr );
  3118. goto Cleanup;
  3119. }
  3120. else if ( hr == S_FALSE )
  3121. {
  3122. THR( HrSendStatusReport(
  3123. m_bstrClusterName
  3124. , TASKID_Minor_Compare_Resources
  3125. , TASKID_Minor_Compare_Resources_Enum_First_Node_Is_Device_Joinable
  3126. , 1
  3127. , 1
  3128. , 1
  3129. , HRESULT_FROM_WIN32( TW32( ERROR_QUORUM_DISK_NOT_FOUND ) )
  3130. , IDS_TASKID_MINOR_MISSING_JOINABLE_QUORUM_RESOURCE
  3131. ) );
  3132. hr = HRESULT_FROM_WIN32( TW32( ERROR_QUORUM_DISK_NOT_FOUND ) );
  3133. goto Cleanup;
  3134. } // else if: Quorum resource is not multi node capable.
  3135. piccvq->Release();
  3136. piccvq = NULL;
  3137. } // else: This resource support IClusCfgVerifyQuorum
  3138. } // if: Are we adding nodes?
  3139. pccmriNew->Release();
  3140. pccmriNew = NULL;
  3141. } // if: Is this the quorum resource?
  3142. else
  3143. {
  3144. pccmriNew->Release();
  3145. pccmriNew = NULL;
  3146. hr = S_OK;
  3147. } // else: It is not the quorum resource.
  3148. } // while: more resources on the selected cluster node
  3149. if ( m_fStop == TRUE )
  3150. {
  3151. goto Cleanup;
  3152. } // if:
  3153. hr = THR( pecNodes->Reset() );
  3154. if ( FAILED( hr ) )
  3155. {
  3156. SSR_ANALYSIS_FAILED( TASKID_Minor_Compare_Resources, TASKID_Minor_Compare_Resources_Enum_Reset, hr );
  3157. goto Cleanup;
  3158. }
  3159. //
  3160. // If this is an add nodes operation, a quorum resource must have been
  3161. // found in the existing cluster.
  3162. //
  3163. Assert( ( m_fJoiningMode == FALSE ) || ( m_bstrQuorumUID != NULL ) );
  3164. //
  3165. // Loop thru the rest of the nodes comparing the resources.
  3166. //
  3167. for ( ; m_fStop == FALSE; )
  3168. {
  3169. //
  3170. // Cleanup
  3171. //
  3172. if ( peccmr != NULL )
  3173. {
  3174. peccmr->Release();
  3175. peccmr = NULL;
  3176. } // if:
  3177. TraceSysFreeString( bstrNodeName );
  3178. bstrNodeName = NULL;
  3179. //
  3180. // Get the next node.
  3181. //
  3182. hr = STHR( pecNodes->Next( 1, &cookieNode, &celtDummy ) );
  3183. if ( FAILED( hr ) )
  3184. {
  3185. SSR_ANALYSIS_FAILED( TASKID_Minor_Compare_Resources, TASKID_Minor_Compare_Resources_Enum_Nodes_Next, hr );
  3186. goto Cleanup;
  3187. }
  3188. if ( hr == S_FALSE )
  3189. {
  3190. break; // exit condition
  3191. }
  3192. //
  3193. // Skip the selected cluster node since we already have its
  3194. // configuration.
  3195. //
  3196. if ( cookieClusterNode == cookieNode )
  3197. {
  3198. continue;
  3199. }
  3200. //
  3201. // Retrieve the node's name for error messages.
  3202. //
  3203. hr = THR( HrRetrieveCookiesName( m_pom, cookieNode, &bstrNodeName ) );
  3204. if ( FAILED( hr ) )
  3205. {
  3206. goto Cleanup;
  3207. }
  3208. //
  3209. // Retrieve the managed resources enumerator.
  3210. //
  3211. hr = THR( m_pom->FindObject( CLSID_ManagedResourceType, cookieNode, NULL, DFGUID_EnumManageableResources, &cookieDummy, &punk ) );
  3212. if ( hr == HRESULT_FROM_WIN32( ERROR_NOT_FOUND ) )
  3213. {
  3214. hr = THR( HrSendStatusReport(
  3215. m_bstrClusterName
  3216. , TASKID_Minor_Compare_Resources
  3217. , TASKID_Minor_No_Managed_Resources_Found
  3218. , 1
  3219. , 1
  3220. , 1
  3221. , MAKE_HRESULT( 0, FACILITY_WIN32, ERROR_NOT_FOUND )
  3222. , IDS_TASKID_MINOR_NO_MANAGED_RESOURCES_FOUND
  3223. ) );
  3224. if ( FAILED( hr ) )
  3225. {
  3226. goto Cleanup;
  3227. }
  3228. continue; // skip this node
  3229. } // if: no manageable resources for the node are available
  3230. else if ( FAILED( hr ) )
  3231. {
  3232. SSR_ANALYSIS_FAILED( TASKID_Minor_Compare_Resources, TASKID_Minor_Compare_Resources_Enum_Nodes_Find_Object, hr );
  3233. goto Cleanup;
  3234. } // else if: error finding manageable resources for the node
  3235. hr = THR( punk->TypeSafeQI( IEnumClusCfgManagedResources, &peccmr ) );
  3236. if ( FAILED( hr ) )
  3237. {
  3238. SSR_ANALYSIS_FAILED( TASKID_Minor_Compare_Resources, TASKID_Minor_Compare_Resources_Enum_Nodes_Find_Object_QI, hr );
  3239. goto Cleanup;
  3240. }
  3241. punk->Release();
  3242. punk = NULL;
  3243. //
  3244. // Loop thru the managed resources that the node has.
  3245. //
  3246. for ( ; m_fStop == FALSE; )
  3247. {
  3248. //
  3249. // Cleanup
  3250. //
  3251. if ( pccmri != NULL )
  3252. {
  3253. pccmri->Release();
  3254. pccmri = NULL;
  3255. }
  3256. if ( peccmrCluster != NULL )
  3257. {
  3258. peccmrCluster->Release();
  3259. peccmrCluster = NULL;
  3260. }
  3261. TraceSysFreeString( bstrNodeResUID );
  3262. TraceSysFreeString( bstrNodeResName );
  3263. bstrNodeResUID = NULL;
  3264. bstrNodeResName = NULL;
  3265. //
  3266. // Get next resource
  3267. //
  3268. hr = STHR( peccmr->Next( 1, &pccmri, &celtDummy ) );
  3269. if ( FAILED( hr ) )
  3270. {
  3271. SSR_ANALYSIS_FAILED( TASKID_Minor_Compare_Resources, TASKID_Minor_Compare_Resources_Enum_Nodes_Enum_Resources_Next, hr );
  3272. goto Cleanup;
  3273. }
  3274. if ( hr == S_FALSE )
  3275. {
  3276. break; // exit condition
  3277. }
  3278. pccmri = TraceInterface( L"CTaskAnalyzeClusterBase!IClusCfgManagedResourceInfo", IClusCfgManagedResourceInfo, pccmri, 1 );
  3279. //
  3280. // Get the resource's UID and name.
  3281. //
  3282. hr = THR( pccmri->GetUID( &bstrNodeResUID ) );
  3283. if ( FAILED( hr ) )
  3284. {
  3285. SSR_ANALYSIS_FAILED( TASKID_Minor_Compare_Resources, TASKID_Minor_Compare_Resources_Enum_Nodes_Enum_Resources_GetUID, hr );
  3286. goto Cleanup;
  3287. }
  3288. TraceMemoryAddBSTR( bstrNodeResUID );
  3289. hr = THR( pccmri->GetName( &bstrNodeResName ) );
  3290. if ( FAILED( hr ) )
  3291. {
  3292. SSR_ANALYSIS_FAILED( TASKID_Minor_Compare_Resources, TASKID_Minor_Compare_Resources_Enum_Nodes_Enum_Resources_GetName, hr );
  3293. goto Cleanup;
  3294. }
  3295. TraceMemoryAddBSTR( bstrNodeResName );
  3296. //
  3297. // See if it matches a resource already in the cluster configuration.
  3298. //
  3299. hr = THR( m_pom->FindObject( CLSID_ManagedResourceType, m_cookieCluster, NULL, DFGUID_EnumManageableResources, &cookieDummy, &punk ) );
  3300. if ( hr == HRESULT_FROM_WIN32( ERROR_NOT_FOUND ) )
  3301. {
  3302. hr = S_FALSE; // create a new object.
  3303. // fall thru
  3304. } // if: no cluster manageable resources found
  3305. else if ( FAILED( hr ) )
  3306. {
  3307. SSR_ANALYSIS_FAILED( TASKID_Minor_Compare_Resources, TASKID_Minor_Compare_Resources_Enum_Nodes_Enum_Resources_Enum_Cluster_Find_Object, hr );
  3308. goto Cleanup;
  3309. } // else if: error finding manageable resources for the cluster
  3310. else
  3311. {
  3312. hr = THR( punk->TypeSafeQI( IEnumClusCfgManagedResources, &peccmrCluster ) );
  3313. if ( FAILED( hr ) )
  3314. {
  3315. SSR_ANALYSIS_FAILED( TASKID_Minor_Compare_Resources, TASKID_Minor_Compare_Resources_Enum_Nodes_Enum_Resources_Enum_Cluster_Find_Object_QI, hr );
  3316. goto Cleanup;
  3317. }
  3318. punk->Release();
  3319. punk = NULL;
  3320. } // else: found manageable resources for the cluster
  3321. //
  3322. // Loop thru the configured cluster resources to see what matches.
  3323. //
  3324. while ( ( hr == S_OK ) && ( m_fStop == FALSE ) )
  3325. {
  3326. BOOL fMatch;
  3327. //
  3328. // Cleanup
  3329. //
  3330. if ( pccmriCluster != NULL )
  3331. {
  3332. pccmriCluster->Release();
  3333. pccmriCluster = NULL;
  3334. }
  3335. TraceSysFreeString( bstrClusterResUID );
  3336. TraceSysFreeString( bstrClusterResName );
  3337. bstrClusterResUID = NULL;
  3338. bstrClusterResName = NULL;
  3339. hr = STHR( peccmrCluster->Next( 1, &pccmriCluster, &celtDummy ) );
  3340. if ( FAILED( hr ) )
  3341. {
  3342. SSR_ANALYSIS_FAILED( TASKID_Minor_Compare_Resources, TASKID_Minor_Compare_Resources_Enum_Nodes_Enum_Resources_Enum_Cluster_Next, hr );
  3343. goto Cleanup;
  3344. }
  3345. if ( hr == S_FALSE )
  3346. {
  3347. break; // exit condition
  3348. }
  3349. //
  3350. // Get the resource's UID and name.
  3351. //
  3352. hr = THR( pccmriCluster->GetUID( &bstrClusterResUID ) );
  3353. if ( FAILED( hr ) )
  3354. {
  3355. SSR_ANALYSIS_FAILED( TASKID_Minor_Compare_Resources, TASKID_Minor_Compare_Resources_Enum_Nodes_Enum_Resources_Enum_Cluster_GetUID, hr );
  3356. goto Cleanup;
  3357. }
  3358. TraceMemoryAddBSTR( bstrClusterResUID );
  3359. hr = THR( pccmriCluster->GetName( &bstrClusterResName ) );
  3360. if ( FAILED( hr ) )
  3361. {
  3362. SSR_ANALYSIS_FAILED( TASKID_Minor_Compare_Resources, TASKID_Minor_Compare_Resources_Enum_Nodes_Enum_Resources_Enum_Cluster_GetName, hr );
  3363. goto Cleanup;
  3364. }
  3365. TraceMemoryAddBSTR( bstrClusterResName );
  3366. fMatch = ( NBSTRCompareCase( bstrNodeResUID, bstrClusterResUID ) == 0 );
  3367. if ( fMatch == FALSE )
  3368. {
  3369. continue; // keep looping
  3370. }
  3371. //
  3372. // A resource is already in the database. See if it is the
  3373. // same from the POV of management.
  3374. //
  3375. //
  3376. // If we made it here then we think it truly is the same
  3377. // resource. The rest is stuff we need to fixup during the
  3378. // commit phase.
  3379. //
  3380. //
  3381. // If this node wants its resources managed, mark it as
  3382. // being managed in the cluster configuration as well.
  3383. // THIS IS NOT VALID WHEN JUST ADDING NODES.
  3384. //
  3385. //
  3386. // BUGBUG: 09-APR-2002 GalenB
  3387. //
  3388. // I cannot see how this code is ever executed! You must have more than one node in the nodes
  3389. // list to get down here. However, you can only have more than one node in the node list when
  3390. // adding nodes...
  3391. //
  3392. if ( m_fJoiningMode == FALSE )
  3393. {
  3394. //
  3395. // Want to alert someone if we ever get in here...
  3396. //
  3397. Assert( FALSE );
  3398. hr = STHR( pccmri->IsManagedByDefault() );
  3399. if ( FAILED( hr ) )
  3400. {
  3401. SSR_ANALYSIS_FAILED( TASKID_Minor_Compare_Resources, TASKID_Minor_Compare_Resources_Enum_Nodes_Enum_Resources_Enum_Cluster_IsManageable, hr );
  3402. goto Cleanup;
  3403. }
  3404. if ( hr == S_OK )
  3405. {
  3406. hr = THR( pccmriCluster->SetManaged( TRUE ) );
  3407. if ( FAILED( hr ) )
  3408. {
  3409. SSR_ANALYSIS_FAILED( TASKID_Minor_Compare_Resources, TASKID_Minor_Compare_Resources_Enum_Nodes_Enum_Resources_Enum_Cluster_SetManaged, hr );
  3410. goto Cleanup;
  3411. }
  3412. //
  3413. // Since this node manages this resource, it should be
  3414. // able to provide us with a name. We will use this
  3415. // name to overwrite whatever we currently have,
  3416. // except for the quorum resource, which already has
  3417. // the correct name.
  3418. //
  3419. hr = STHR( pccmri->IsQuorumResource() );
  3420. if ( hr == S_FALSE )
  3421. {
  3422. hr = THR( pccmriCluster->SetName( bstrNodeResName ) );
  3423. if ( FAILED( hr ) )
  3424. {
  3425. SSR_ANALYSIS_FAILED( TASKID_Minor_Compare_Resources, TASKID_Minor_Compare_Resources_Enum_Nodes_Enum_Resources_Enum_Cluster_SetResName, hr );
  3426. goto Cleanup;
  3427. }
  3428. } // if: is not quorum device
  3429. } // if: is managed
  3430. } // if: creating a new cluster
  3431. else
  3432. {
  3433. //
  3434. // Since we have a match and we are adding nodes to the cluster we need to perform a
  3435. // private data exchange if the server objects supported it.
  3436. //
  3437. hr = THR( HrResourcePrivateDataExchange( pccmriCluster, pccmri ) );
  3438. if ( FAILED( hr ) )
  3439. {
  3440. goto Cleanup;
  3441. } // if:
  3442. } // else:
  3443. //
  3444. // Check to see if the resource is the quorum resource. If so, mark that
  3445. // we found a common quorum resource.
  3446. //
  3447. if ( m_bstrQuorumUID == NULL )
  3448. {
  3449. //
  3450. // No previous quorum has been set. See if this is the quorum resource.
  3451. //
  3452. // There is already a quorum resource when adding nodes to
  3453. // the cluster, so this string better already be set.
  3454. Assert( m_fJoiningMode == FALSE );
  3455. hr = STHR( pccmri->IsQuorumResource() );
  3456. if ( hr == S_OK )
  3457. {
  3458. //
  3459. // Yes it is. Then mark it in the configuration as such.
  3460. //
  3461. hr = THR( pccmriCluster->SetQuorumResource( TRUE ) );
  3462. if ( FAILED( hr ) )
  3463. {
  3464. SSR_ANALYSIS_FAILED( TASKID_Minor_Compare_Resources, TASKID_Minor_Compare_Resources_Enum_Nodes_Enum_Resources_Enum_Cluster_SetQuorumDevice_Cluster, hr );
  3465. goto Cleanup;
  3466. }
  3467. //
  3468. // Remember that this resource is the quorum.
  3469. //
  3470. hr = THR( pccmriCluster->GetUID( &m_bstrQuorumUID ) );
  3471. if ( FAILED( hr ) )
  3472. {
  3473. SSR_ANALYSIS_FAILED( TASKID_Minor_Compare_Resources, TASKID_Minor_Compare_Resources_Enum_Nodes_Enum_Resources_Enum_Cluster_SetQuorumDevice_GetUID, hr );
  3474. goto Cleanup;
  3475. }
  3476. TraceMemoryAddBSTR( m_bstrQuorumUID );
  3477. LogMsg( L"[MT][2] Found the quorum resource '%ws' on node '%ws' and setting it as the quorum resource.", m_bstrQuorumUID, bstrNodeName );
  3478. } // if: node resource says its the quorum resource
  3479. } // if: haven't found the quorum resource yet
  3480. else if ( NBSTRCompareCase( m_bstrQuorumUID, bstrNodeResUID ) == 0 )
  3481. {
  3482. //
  3483. // Check to ensure that the resource on the new node can
  3484. // really host the quorum resource.
  3485. //
  3486. LogMsg( L"[MT] Checking quorum capabilities (PrepareToHostQuorum) for node '%ws.' for quorum resource '%ws'", bstrNodeName, m_bstrQuorumUID );
  3487. hr = STHR( HrCheckQuorumCapabilities( pccmri, cookieNode ) );
  3488. if ( FAILED( hr ) )
  3489. {
  3490. goto Cleanup;
  3491. } // if:
  3492. //
  3493. // This is the same quorum. Mark the Node's configuration.
  3494. //
  3495. hr = THR( pccmri->SetQuorumResource( TRUE ) );
  3496. if ( FAILED( hr ) )
  3497. {
  3498. SSR_ANALYSIS_FAILED( TASKID_Minor_Compare_Resources, TASKID_Minor_Compare_Resources_Enum_Nodes_Enum_Resources_Enum_Cluster_SetQuorumDevice_Node_True, hr );
  3499. goto Cleanup;
  3500. }
  3501. } // else if: node's resource matches the quorum resource
  3502. else
  3503. {
  3504. //
  3505. // Otherwise, make sure that the device isn't marked as quorum. (paranoid)
  3506. //
  3507. hr = THR( pccmri->SetQuorumResource( FALSE ) );
  3508. if ( FAILED( hr ) )
  3509. {
  3510. SSR_ANALYSIS_FAILED( TASKID_Minor_Compare_Resources, TASKID_Minor_Compare_Resources_Enum_Nodes_Enum_Resources_Enum_Cluster_SetQuorumDevice_Node_False, hr );
  3511. goto Cleanup;
  3512. }
  3513. } // else: quorum already found and this is not it
  3514. //
  3515. // Display the names of the cluster resource and the node's
  3516. // resource in the log.
  3517. //
  3518. LogMsg(
  3519. L"[MT] Matched resource '%ws' ('%ws') from node '%ws' with '%ws' ('%ws') on cluster node '%ws'."
  3520. , bstrNodeResName
  3521. , bstrNodeResUID
  3522. , bstrNodeName
  3523. , bstrClusterResName
  3524. , bstrClusterResUID
  3525. , bstrClusterNodeName
  3526. );
  3527. //
  3528. // Exit the loop with S_OK so we don't create a new resource.
  3529. //
  3530. hr = S_OK;
  3531. break; // exit loop
  3532. } // while: S_OK
  3533. if ( hr == S_FALSE )
  3534. {
  3535. hr = THR( HrCreateNewResourceInCluster( pccmri, bstrNodeResName, &bstrNodeResUID, bstrNodeName ) );
  3536. if ( FAILED( hr ) )
  3537. {
  3538. goto Cleanup;
  3539. } // if:
  3540. } // if: node's resource not matched to a cluster resource
  3541. } // for: each resource on the node
  3542. } // for: each node
  3543. hr = S_OK;
  3544. Cleanup:
  3545. THR( HrSendStatusReport(
  3546. m_bstrClusterName
  3547. , TASKID_Major_Check_Cluster_Feasibility
  3548. , TASKID_Minor_Compare_Resources
  3549. , 0
  3550. , 1
  3551. , 1
  3552. , hr
  3553. , IDS_TASKID_MINOR_COMPARE_RESOURCES
  3554. ) );
  3555. TraceSysFreeString( bstrNotification );
  3556. TraceSysFreeString( bstrClusterNodeName );
  3557. TraceSysFreeString( bstrClusterResUID );
  3558. TraceSysFreeString( bstrClusterResName );
  3559. TraceSysFreeString( bstrNodeName );
  3560. TraceSysFreeString( bstrNodeResUID );
  3561. TraceSysFreeString( bstrNodeResName );
  3562. TraceSysFreeString( bstrQuorumName );
  3563. if ( piccvq != NULL )
  3564. {
  3565. piccvq->Release();
  3566. } // if:
  3567. if ( pccmriNew != NULL )
  3568. {
  3569. pccmriNew->Release();
  3570. } // if:
  3571. if ( punk != NULL )
  3572. {
  3573. punk->Release();
  3574. }
  3575. if ( pecNodes != NULL )
  3576. {
  3577. pecNodes->Release();
  3578. }
  3579. if ( peccmr != NULL )
  3580. {
  3581. peccmr->Release();
  3582. }
  3583. if ( peccmrCluster != NULL )
  3584. {
  3585. peccmrCluster->Release();
  3586. }
  3587. if ( pccmri != NULL )
  3588. {
  3589. pccmri->Release();
  3590. }
  3591. if ( pccmriCluster != NULL )
  3592. {
  3593. pccmriCluster->Release();
  3594. }
  3595. HRETURN( hr );
  3596. } //*** CTaskAnalyzeClusterBase::HrCompareResources
  3597. //////////////////////////////////////////////////////////////////////////////
  3598. //++
  3599. //
  3600. // CTaskAnalyzeClusterBase::HrCreateNewManagedResourceInClusterConfiguration
  3601. //
  3602. // Description:
  3603. //
  3604. // Arguments:
  3605. //
  3606. // Return Value:
  3607. // S_OK
  3608. // Success
  3609. //
  3610. // HRESULT failure.
  3611. //
  3612. //--
  3613. //////////////////////////////////////////////////////////////////////////////
  3614. HRESULT
  3615. CTaskAnalyzeClusterBase::HrCreateNewManagedResourceInClusterConfiguration(
  3616. IClusCfgManagedResourceInfo * pccmriIn
  3617. , IClusCfgManagedResourceInfo ** ppccmriNewOut
  3618. )
  3619. {
  3620. TraceFunc( "" );
  3621. Assert( pccmriIn != NULL );
  3622. Assert( ppccmriNewOut != NULL );
  3623. HRESULT hr;
  3624. OBJECTCOOKIE cookieDummy;
  3625. BSTR bstrUID = NULL;
  3626. IUnknown * punk = NULL;
  3627. IGatherData * pgd = NULL;
  3628. IClusCfgManagedResourceInfo * pccmri = NULL;
  3629. TraceFlow1( "[MT] CTaskAnalyzeClusterBase::HrCreateNewManagedResourceInClusterConfiguration() Thread id %d", GetCurrentThreadId() );
  3630. //
  3631. // TODO: gpease 28-JUN-2000
  3632. // Make this dynamic - for now we'll just create a "managed device."
  3633. //
  3634. // grab the name
  3635. hr = THR( pccmriIn->GetUID( &bstrUID ) );
  3636. if ( FAILED( hr ) )
  3637. {
  3638. SSR_ANALYSIS_FAILED( TASKID_Major_Find_Devices, TASKID_Minor_Create_Resource_GetUID, hr );
  3639. goto Cleanup;
  3640. }
  3641. TraceMemoryAddBSTR( bstrUID );
  3642. #ifdef DEBUG
  3643. BSTR _bstr_ = NULL;
  3644. THR( pccmriIn->GetName( &_bstr_ ) );
  3645. LogMsg( L"[MT] [HrCreateNewManagedResourceInClusterConfiguration] The UID for the new object is \"%ws\" and it has the name \"%ws\".", bstrUID, _bstr_ );
  3646. SysFreeString( _bstr_ );
  3647. #endif
  3648. // create an object in the object manager.
  3649. hr = THR( m_pom->FindObject( CLSID_ManagedResourceType,
  3650. m_cookieCluster,
  3651. bstrUID,
  3652. DFGUID_ManagedResource,
  3653. &cookieDummy,
  3654. &punk
  3655. ) );
  3656. if ( FAILED( hr ) )
  3657. {
  3658. SSR_ANALYSIS_FAILED( TASKID_Major_Find_Devices, TASKID_Minor_Create_Resource_FindObject, hr );
  3659. goto Cleanup;
  3660. }
  3661. // find the IGatherData interface
  3662. hr = THR( punk->TypeSafeQI( IGatherData, &pgd ) );
  3663. if ( FAILED( hr ) )
  3664. {
  3665. SSR_ANALYSIS_FAILED( TASKID_Major_Find_Devices, TASKID_Minor_Create_Resource_FindObject_QI, hr );
  3666. goto Cleanup;
  3667. }
  3668. // have the new object gather all information it needs
  3669. hr = THR( pgd->Gather( m_cookieCluster, pccmriIn ) );
  3670. if ( FAILED( hr ) )
  3671. {
  3672. SSR_ANALYSIS_FAILED( TASKID_Major_Find_Devices, TASKID_Minor_Create_Resource_Gather, hr );
  3673. goto Cleanup;
  3674. }
  3675. // hand the object out if requested
  3676. if ( ppccmriNewOut != NULL )
  3677. {
  3678. // find the IClusCfgManagedResourceInfo
  3679. hr = THR( punk->TypeSafeQI( IClusCfgManagedResourceInfo, &pccmri ) );
  3680. if ( FAILED( hr ) )
  3681. {
  3682. SSR_ANALYSIS_FAILED( TASKID_Major_Find_Devices, TASKID_Minor_Create_Resource_QI, hr );
  3683. goto Cleanup;
  3684. }
  3685. *ppccmriNewOut = TraceInterface( L"ManagedResource!ICCMRI", IClusCfgManagedResourceInfo, pccmri, 0 );
  3686. (*ppccmriNewOut)->AddRef();
  3687. }
  3688. Cleanup:
  3689. TraceSysFreeString( bstrUID );
  3690. if ( pccmri != NULL )
  3691. {
  3692. pccmri->Release();
  3693. }
  3694. if ( pgd != NULL )
  3695. {
  3696. pgd->Release();
  3697. }
  3698. if ( punk != NULL )
  3699. {
  3700. punk->Release();
  3701. }
  3702. HRETURN( hr );
  3703. } //*** CTaskAnalyzeClusterBase::HrCreateNewManagedResourceInClusterConfiguration
  3704. //////////////////////////////////////////////////////////////////////////////
  3705. //++
  3706. //
  3707. // CTaskAnalyzeClusterBase::HrCheckForCommonQuorumResource
  3708. //
  3709. // Description:
  3710. //
  3711. // Arguments:
  3712. //
  3713. // Return Value:
  3714. // S_OK
  3715. // Success
  3716. //
  3717. // HRESULT failure.
  3718. //
  3719. //--
  3720. //////////////////////////////////////////////////////////////////////////////
  3721. HRESULT
  3722. CTaskAnalyzeClusterBase::HrCheckForCommonQuorumResource( void )
  3723. {
  3724. TraceFunc( "" );
  3725. HRESULT hr;
  3726. OBJECTCOOKIE cookie;
  3727. OBJECTCOOKIE cookieDummy;
  3728. ULONG cMatchedNodes = 0;
  3729. ULONG cAnalyzedNodes = 0;
  3730. BOOL fNodeCanAccess = FALSE;
  3731. BSTR bstrUID = NULL;
  3732. BSTR bstrNotification = NULL;
  3733. BSTR bstrNodeName = NULL;
  3734. BSTR bstrMessage = NULL;
  3735. IUnknown * punk = NULL;
  3736. IEnumCookies * pecNodes = NULL;
  3737. IEnumClusCfgManagedResources * peccmr = NULL;
  3738. IClusCfgManagedResourceInfo * pccmri = NULL;
  3739. IClusCfgNodeInfo * piccni = NULL;
  3740. TraceFlow1( "[MT] CTaskAnalyzeClusterBase::HrCheckForCommonQuorumResource() Thread id %d", GetCurrentThreadId() );
  3741. hr = THR( HrSendStatusReport(
  3742. m_bstrClusterName
  3743. , TASKID_Major_Check_Cluster_Feasibility
  3744. , TASKID_Minor_Finding_Common_Quorum_Device
  3745. , 0
  3746. , m_cNodes + 1
  3747. , 0
  3748. , S_OK
  3749. , IDS_TASKID_MINOR_FINDING_COMMON_QUORUM_DEVICE
  3750. ) );
  3751. if ( FAILED( hr ) )
  3752. {
  3753. goto Cleanup;
  3754. } // if:
  3755. if ( m_bstrQuorumUID != NULL )
  3756. {
  3757. //
  3758. // Grab the cookie enumer for nodes in our cluster configuration.
  3759. //
  3760. hr = THR( m_pom->FindObject( CLSID_NodeType, m_cookieCluster, NULL, DFGUID_EnumCookies, &cookieDummy, &punk ) );
  3761. if ( FAILED( hr ) )
  3762. {
  3763. SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_Check_Common_FindObject, hr );
  3764. goto Cleanup;
  3765. }
  3766. hr = THR( punk->TypeSafeQI( IEnumCookies, &pecNodes ) );
  3767. if ( FAILED( hr ) )
  3768. {
  3769. SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_Check_Common_FindObject_QI, hr );
  3770. goto Cleanup;
  3771. }
  3772. //pecNodes = TraceInterface( L"CTaskAnalyzeClusterBase!IEnumCookies", IEnumCookies, pecNodes, 1 );
  3773. punk->Release();
  3774. punk = NULL;
  3775. //
  3776. // Scan the cluster configurations looking for the quorum resource.
  3777. //
  3778. for ( ;; )
  3779. {
  3780. ULONG celtDummy;
  3781. if ( peccmr != NULL )
  3782. {
  3783. peccmr->Release();
  3784. peccmr = NULL;
  3785. } // if:
  3786. hr = STHR( pecNodes->Next( 1, &cookie, &celtDummy ) );
  3787. if ( FAILED( hr ) )
  3788. {
  3789. SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_Check_Common_Enum_Nodes_Next, hr );
  3790. goto Cleanup;
  3791. } // if:
  3792. if ( hr == S_FALSE )
  3793. {
  3794. break; // exit condition
  3795. }
  3796. hr = THR( m_pom->GetObject( DFGUID_NodeInformation, cookie, &punk ) );
  3797. if ( FAILED( hr ) )
  3798. {
  3799. goto Cleanup;
  3800. }
  3801. hr = THR( punk->TypeSafeQI( IClusCfgNodeInfo, &piccni ) );
  3802. if ( FAILED( hr ) )
  3803. {
  3804. goto Cleanup;
  3805. }
  3806. punk->Release();
  3807. punk = NULL;
  3808. TraceSysFreeString( bstrNodeName );
  3809. bstrNodeName = NULL;
  3810. hr = THR( piccni->GetName( &bstrNodeName ) );
  3811. if ( FAILED( hr ) )
  3812. {
  3813. goto Cleanup;
  3814. }
  3815. TraceMemoryAddBSTR( bstrNodeName );
  3816. //
  3817. // increment counter for a "nice" progress bar
  3818. //
  3819. cAnalyzedNodes ++;
  3820. hr = THR( HrSendStatusReport(
  3821. m_bstrClusterName
  3822. , TASKID_Major_Check_Cluster_Feasibility
  3823. , TASKID_Minor_Finding_Common_Quorum_Device
  3824. , 0
  3825. , m_cNodes + 1
  3826. , cAnalyzedNodes
  3827. , S_OK
  3828. , IDS_TASKID_MINOR_FINDING_COMMON_QUORUM_DEVICE
  3829. ) );
  3830. if ( FAILED( hr ) )
  3831. {
  3832. goto Cleanup;
  3833. } // if:
  3834. //
  3835. // Grab the managed resource enumer for resources that our node has.
  3836. //
  3837. hr = THR( m_pom->FindObject( CLSID_ManagedResourceType, cookie, NULL, DFGUID_EnumManageableResources, &cookieDummy, &punk ) );
  3838. if ( hr == HRESULT_FROM_WIN32( ERROR_NOT_FOUND ) )
  3839. {
  3840. continue; // ignore and continue
  3841. }
  3842. else if ( FAILED( hr ) )
  3843. {
  3844. THR( hr );
  3845. SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_Check_Common_Enum_Nodes_FindObject, hr );
  3846. goto Cleanup;
  3847. }
  3848. hr = THR( punk->TypeSafeQI( IEnumClusCfgManagedResources, &peccmr ) );
  3849. if ( FAILED( hr ) )
  3850. {
  3851. SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_Check_Common_Enum_Nodes_FindObject_QI, hr );
  3852. goto Cleanup;
  3853. }
  3854. //peccmr = TraceInterface( L"CTaskAnalyzeClusterBase!IEnumClusCfgManagedResources", IEnumClusCfgManagedResources, peccmr, 1 );
  3855. punk->Release();
  3856. punk = NULL;
  3857. fNodeCanAccess = FALSE;
  3858. //
  3859. // Loop thru the resources trying to match the UID of the quorum resource.
  3860. //
  3861. for ( ; m_fStop == FALSE; )
  3862. {
  3863. TraceSysFreeString( bstrUID );
  3864. bstrUID = NULL;
  3865. if ( pccmri != NULL )
  3866. {
  3867. pccmri->Release();
  3868. pccmri = NULL;
  3869. }
  3870. hr = STHR( peccmr->Next( 1, &pccmri, &celtDummy ) );
  3871. if ( FAILED( hr ) )
  3872. {
  3873. SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_Check_Common_Enum_Nodes_Enum_Resources_Next, hr );
  3874. goto Cleanup;
  3875. }
  3876. if ( hr == S_FALSE )
  3877. {
  3878. break; // exit condition
  3879. }
  3880. pccmri = TraceInterface( L"CTaskAnalyzeClusterBase!IClusCfgManagedResourceInfo", IClusCfgManagedResourceInfo, pccmri, 1 );
  3881. hr = THR( pccmri->GetUID( &bstrUID ) );
  3882. if ( FAILED( hr ) )
  3883. {
  3884. SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_Check_Common_Enum_Nodes_Enum_Resources_GetUID, hr );
  3885. goto Cleanup;
  3886. }
  3887. TraceMemoryAddBSTR( bstrUID );
  3888. if ( NBSTRCompareCase( bstrUID, m_bstrQuorumUID ) != 0 )
  3889. {
  3890. continue; // doesn't match - keep going
  3891. }
  3892. cMatchedNodes ++;
  3893. fNodeCanAccess = TRUE;
  3894. break; // exit condition
  3895. } // for: ( ; m_fStop == FALSE; )
  3896. //
  3897. // Give the UI feedback if this node has no access to the quorum
  3898. //
  3899. if ( fNodeCanAccess == FALSE )
  3900. {
  3901. HRESULT hrTemp;
  3902. DWORD dwRefId;
  3903. CLSID clsidMinorId;
  3904. hr = THR( CoCreateGuid( &clsidMinorId ) );
  3905. if ( FAILED( hr ) )
  3906. {
  3907. clsidMinorId = IID_NULL;
  3908. } // if:
  3909. //
  3910. // Ensure that the parent item is in the tree control.
  3911. //
  3912. hr = THR( ::HrSendStatusReport(
  3913. m_pcccb
  3914. , m_bstrClusterName
  3915. , TASKID_Minor_Finding_Common_Quorum_Device
  3916. , TASKID_Minor_Nodes_Cannot_Access_Quorum
  3917. , 1
  3918. , 1
  3919. , 1
  3920. , S_OK
  3921. , IDS_TASKID_MINOR_NODES_CANNOT_ACCESS_QUORUM
  3922. ) );
  3923. if ( FAILED( hr ) )
  3924. {
  3925. goto Cleanup;
  3926. } // if:
  3927. hr = HrFixupErrorCode( HRESULT_FROM_WIN32( ERROR_QUORUM_DISK_NOT_FOUND ) ); // don't THR this!
  3928. GetNodeCannotVerifyQuorumStringRefId( &dwRefId );
  3929. //
  3930. // Cleanup.
  3931. //
  3932. TraceSysFreeString( bstrMessage );
  3933. bstrMessage = NULL;
  3934. Assert( bstrNodeName != NULL );
  3935. hrTemp = THR( HrFormatStringIntoBSTR( g_hInstance, IDS_TASKID_MINOR_NODE_CANNOT_ACCESS_QUORUM_ERROR, &bstrMessage, bstrNodeName ) );
  3936. if ( FAILED( hrTemp ) )
  3937. {
  3938. hr = hrTemp;
  3939. goto Cleanup;
  3940. } // if:
  3941. hrTemp = THR( ::HrSendStatusReport(
  3942. m_pcccb
  3943. , m_bstrClusterName
  3944. , TASKID_Minor_Nodes_Cannot_Access_Quorum
  3945. , clsidMinorId
  3946. , 1
  3947. , 1
  3948. , 1
  3949. , hr
  3950. , bstrMessage
  3951. , dwRefId
  3952. ) );
  3953. if ( FAILED( hrTemp ) )
  3954. {
  3955. hr = hrTemp;
  3956. goto Cleanup;
  3957. } // if:
  3958. } // if ( fNodeCanAccess == FALSE )
  3959. } // for: ever
  3960. } // if: m_bstrQuorumUID != NULL
  3961. if ( m_fStop == TRUE )
  3962. {
  3963. goto Cleanup;
  3964. } // if:
  3965. //
  3966. // Figure out if we ended up with a common quorum device.
  3967. //
  3968. if ( cMatchedNodes == m_cNodes )
  3969. {
  3970. //
  3971. // We found a device that can be used as a common quorum device.
  3972. //
  3973. hr = THR( HrSendStatusReport(
  3974. m_bstrClusterName
  3975. , TASKID_Minor_Finding_Common_Quorum_Device
  3976. , TASKID_Minor_Found_Common_Quorum_Resource
  3977. , 1
  3978. , 1
  3979. , 1
  3980. , S_OK
  3981. , IDS_TASKID_MINOR_FOUND_COMMON_QUORUM_RESOURCE
  3982. ) );
  3983. // error checked outside if/else statement
  3984. }
  3985. else
  3986. {
  3987. if ( ( m_cNodes == 1 ) && ( m_fJoiningMode == FALSE ) )
  3988. {
  3989. //
  3990. // We didn't find a common quorum device, but we're only forming. We can
  3991. // create the cluster with a local quorum. Just put up a warning.
  3992. //
  3993. hr = THR( HrShowLocalQuorumWarning() );
  3994. // error checked outside if/else statement
  3995. }
  3996. else
  3997. {
  3998. HRESULT hrTemp;
  3999. DWORD dwMessageId;
  4000. DWORD dwRefId;
  4001. //
  4002. // We didn't find a common quorum device.
  4003. //
  4004. hr = HrFixupErrorCode( HRESULT_FROM_WIN32( ERROR_QUORUM_DISK_NOT_FOUND ) ); // don't THR this!
  4005. GetNoCommonQuorumToAllNodesStringIds( &dwMessageId, &dwRefId );
  4006. hrTemp = THR( ::HrSendStatusReport(
  4007. m_pcccb
  4008. , m_bstrClusterName
  4009. , TASKID_Minor_Finding_Common_Quorum_Device
  4010. , TASKID_Minor_Missing_Common_Quorum_Resource
  4011. , 0
  4012. , 1
  4013. , 1
  4014. , hr
  4015. , dwMessageId
  4016. , dwRefId
  4017. ) );
  4018. //
  4019. // Should we bail out and return an error to the client?
  4020. //
  4021. if ( FAILED( hr ) )
  4022. {
  4023. goto Cleanup;
  4024. } // if:
  4025. //
  4026. // If the SSR failed. This is a secondary failure to the one above.
  4027. //
  4028. if ( FAILED( hrTemp ) )
  4029. {
  4030. hr = hrTemp;
  4031. goto Cleanup;
  4032. } // if:
  4033. }
  4034. }
  4035. //
  4036. // Check to see if any of the SendStatusReports() returned anything
  4037. // of interest.
  4038. //
  4039. if ( FAILED( hr ) )
  4040. {
  4041. goto Cleanup;
  4042. }
  4043. hr = S_OK;
  4044. Cleanup:
  4045. THR( HrSendStatusReport(
  4046. m_bstrClusterName
  4047. , TASKID_Major_Check_Cluster_Feasibility
  4048. , TASKID_Minor_Finding_Common_Quorum_Device
  4049. , 0
  4050. , m_cNodes + 1
  4051. , m_cNodes + 1
  4052. , hr
  4053. , IDS_TASKID_MINOR_FINDING_COMMON_QUORUM_DEVICE
  4054. ) );
  4055. if ( punk != NULL )
  4056. {
  4057. punk->Release();
  4058. } // if:
  4059. if ( piccni != NULL )
  4060. {
  4061. piccni->Release();
  4062. } // if:
  4063. TraceSysFreeString( bstrNotification );
  4064. TraceSysFreeString( bstrUID );
  4065. TraceSysFreeString( bstrNodeName );
  4066. TraceSysFreeString( bstrMessage );
  4067. if ( pccmri != NULL )
  4068. {
  4069. pccmri->Release();
  4070. } // if:
  4071. if ( peccmr != NULL )
  4072. {
  4073. peccmr->Release();
  4074. } // if:
  4075. if ( pecNodes != NULL )
  4076. {
  4077. pecNodes->Release();
  4078. } // if:
  4079. HRETURN( hr );
  4080. } //*** CTaskAnalyzeClusterBase::HrCheckForCommonQuorumResource
  4081. //////////////////////////////////////////////////////////////////////////////
  4082. //++
  4083. //
  4084. // CTaskAnalyzeClusterBase::HrCompareNetworks
  4085. //
  4086. // Description:
  4087. //
  4088. // Arguments:
  4089. //
  4090. // Return Value:
  4091. // S_OK
  4092. // Success
  4093. //
  4094. // HRESULT failure.
  4095. //
  4096. //--
  4097. //////////////////////////////////////////////////////////////////////////////
  4098. HRESULT
  4099. CTaskAnalyzeClusterBase::HrCompareNetworks( void )
  4100. {
  4101. TraceFunc( "" );
  4102. HRESULT hr = S_OK;
  4103. HRESULT hrError = S_OK;
  4104. BSTR bstrUID = NULL;
  4105. BSTR bstrName = NULL;
  4106. BSTR bstrUIDExisting;
  4107. BSTR bstrNotification = NULL;
  4108. ULONG celtDummy;
  4109. BOOL fIsPrivateNetworkAvailable = FALSE;
  4110. BOOL fIsPublicNetworkAvailable = FALSE;
  4111. OBJECTCOOKIE cookieNode;
  4112. OBJECTCOOKIE cookieDummy;
  4113. OBJECTCOOKIE cookieFirst;
  4114. IUnknown * punk = NULL;
  4115. IEnumCookies * pecNodes = NULL;
  4116. IEnumClusCfgNetworks * peccn = NULL;
  4117. IEnumClusCfgNetworks * peccnCluster = NULL;
  4118. IClusCfgNetworkInfo * pccni = NULL;
  4119. IClusCfgNetworkInfo * pccniCluster = NULL;
  4120. TraceFlow1( "[MT] CTaskAnalyzeClusterBase::HrCompareNetworks() Thread id %d", GetCurrentThreadId() );
  4121. hr = THR( HrSendStatusReport(
  4122. m_bstrClusterName
  4123. , TASKID_Major_Check_Cluster_Feasibility
  4124. , TASKID_Minor_Check_Compare_Networks
  4125. , 0
  4126. , 1
  4127. , 0
  4128. , hr
  4129. , IDS_TASKID_MINOR_COMPARE_NETWORKS
  4130. ) );
  4131. if ( FAILED( hr ) )
  4132. {
  4133. goto Cleanup;
  4134. } // if:
  4135. hr = THR( HrGetAClusterNodeCookie( &pecNodes, &cookieFirst ) );
  4136. if ( FAILED( hr ) )
  4137. {
  4138. goto Cleanup;
  4139. } // if:
  4140. //
  4141. // Retrieve the node name in case of errors.
  4142. //
  4143. hr = THR( HrRetrieveCookiesName( m_pom, cookieFirst, &bstrName ) );
  4144. if ( FAILED( hr ) )
  4145. {
  4146. goto Cleanup;
  4147. }
  4148. //
  4149. // Retrieve the networks enumer.
  4150. //
  4151. hr = THR( m_pom->FindObject( CLSID_NetworkType,
  4152. cookieFirst,
  4153. NULL,
  4154. DFGUID_EnumManageableNetworks,
  4155. &cookieDummy,
  4156. &punk
  4157. ) );
  4158. if ( hr == HRESULT_FROM_WIN32( ERROR_NOT_FOUND ) )
  4159. {
  4160. hr = THR( HrSendStatusReport(
  4161. bstrName
  4162. , TASKID_Minor_Check_Compare_Networks
  4163. , TASKID_Minor_No_Managed_Networks_Found
  4164. , 1
  4165. , 1
  4166. , 1
  4167. , MAKE_HRESULT( 0, FACILITY_WIN32, ERROR_NOT_FOUND )
  4168. , IDS_TASKID_MINOR_NO_MANAGED_NETWORKS_FOUND
  4169. ) );
  4170. if ( FAILED( hr ) )
  4171. {
  4172. goto Cleanup;
  4173. }
  4174. hr = HRESULT_FROM_WIN32( ERROR_NOT_FOUND );
  4175. // fall thru - the while ( hr == S_OK ) will be FALSE and keep going
  4176. }
  4177. else if ( FAILED( hr ) )
  4178. {
  4179. SSR_ANALYSIS_FAILED( TASKID_Major_Find_Devices, TASKID_Minor_CompareNetworks_EnumResources_FindObject, hr );
  4180. goto Cleanup;
  4181. }
  4182. else
  4183. {
  4184. hr = THR( punk->TypeSafeQI( IEnumClusCfgNetworks, &peccn ) );
  4185. if ( FAILED( hr ) )
  4186. {
  4187. SSR_ANALYSIS_FAILED( TASKID_Major_Find_Devices, TASKID_Minor_CompareNetworks_EnumResources_FindObject_QI, hr );
  4188. goto Cleanup;
  4189. }
  4190. //peccn = TraceInterface( L"CTaskAnalyzeClusterBase!IEnumClusCfgNetworks", IEnumClusCfgNetworks, peccn, 1 );
  4191. punk->Release();
  4192. punk = NULL;
  4193. }
  4194. //
  4195. // Loop thru the first nodes networks create an equalivant network
  4196. // under the cluster configuration object/cookie.
  4197. //
  4198. while ( ( hr == S_OK ) && ( m_fStop == FALSE ) )
  4199. {
  4200. // Cleanup
  4201. if ( pccni != NULL )
  4202. {
  4203. pccni->Release();
  4204. pccni = NULL;
  4205. }
  4206. // Get next network
  4207. hr = STHR( peccn->Next( 1, &pccni, &celtDummy ) );
  4208. if ( FAILED( hr ) )
  4209. {
  4210. SSR_ANALYSIS_FAILED( TASKID_Major_Find_Devices, TASKID_Minor_CompareNetworks_EnumNodes_EnumNetwork_Next, hr );
  4211. goto Cleanup;
  4212. }
  4213. if ( hr == S_FALSE )
  4214. {
  4215. break; // exit condition
  4216. }
  4217. pccni = TraceInterface( L"CTaskAnalyzeClusterBase!IClusCfgNetworkInfo", IClusCfgNetworkInfo, pccni, 1 );
  4218. // create a new object
  4219. hr = THR( HrCreateNewNetworkInClusterConfiguration( pccni, NULL ) );
  4220. if ( FAILED( hr ) )
  4221. {
  4222. goto Cleanup;
  4223. }
  4224. } // while: S_OK
  4225. //
  4226. // Reset the enumeration.
  4227. //
  4228. hr = THR( pecNodes->Reset() );
  4229. if ( FAILED( hr ) )
  4230. {
  4231. SSR_ANALYSIS_FAILED( TASKID_Major_Find_Devices, TASKID_Minor_CompareNetworks_EnumNodes_Reset, hr );
  4232. goto Cleanup;
  4233. }
  4234. //
  4235. // Loop thru the rest of the nodes comparing the networks.
  4236. //
  4237. do
  4238. {
  4239. //
  4240. // Cleanup
  4241. //
  4242. if ( peccn != NULL )
  4243. {
  4244. peccn->Release();
  4245. peccn = NULL;
  4246. }
  4247. TraceSysFreeString( bstrName );
  4248. bstrName = NULL;
  4249. //
  4250. // Get the next node.
  4251. //
  4252. hr = STHR( pecNodes->Next( 1, &cookieNode, &celtDummy ) );
  4253. if ( FAILED( hr ) )
  4254. {
  4255. SSR_ANALYSIS_FAILED( TASKID_Major_Find_Devices, TASKID_Minor_CompareNetworks_EnumNodes_NextNode, hr );
  4256. goto Cleanup;
  4257. }
  4258. if ( hr == S_FALSE )
  4259. {
  4260. break; // exit condition
  4261. }
  4262. if ( cookieNode == cookieFirst )
  4263. {
  4264. continue; // skip it
  4265. }
  4266. //
  4267. // Retrieve the node's name
  4268. //
  4269. hr = THR( HrRetrieveCookiesName( m_pom, cookieNode, &bstrName ) );
  4270. if ( FAILED( hr ) )
  4271. {
  4272. goto Cleanup;
  4273. }
  4274. //
  4275. // Retrieve the networks enumer.
  4276. //
  4277. hr = THR( m_pom->FindObject( CLSID_NetworkType,
  4278. cookieNode,
  4279. NULL,
  4280. DFGUID_EnumManageableNetworks,
  4281. &cookieDummy,
  4282. &punk
  4283. ) );
  4284. if ( hr == HRESULT_FROM_WIN32( ERROR_NOT_FOUND ) )
  4285. {
  4286. hr = THR( HrSendStatusReport(
  4287. bstrName
  4288. , TASKID_Minor_Check_Compare_Networks
  4289. , TASKID_Minor_No_Managed_Networks_Found
  4290. , 1
  4291. , 1
  4292. , 1
  4293. , MAKE_HRESULT( 0, FACILITY_WIN32, ERROR_NOT_FOUND )
  4294. , IDS_TASKID_MINOR_NO_MANAGED_NETWORKS_FOUND
  4295. ) );
  4296. if ( FAILED( hr ) )
  4297. {
  4298. goto Cleanup;
  4299. }
  4300. continue; // skip this node
  4301. } // if: not found
  4302. else if ( FAILED( hr ) )
  4303. {
  4304. SSR_ANALYSIS_FAILED( TASKID_Major_Find_Devices, TASKID_Minor_CompareNetworks_EnumNodes_Next_FindObject, hr );
  4305. goto Cleanup;
  4306. }
  4307. hr = THR( punk->TypeSafeQI( IEnumClusCfgNetworks, &peccn ) );
  4308. if ( FAILED( hr ) )
  4309. {
  4310. goto Cleanup;
  4311. }
  4312. //peccn = TraceInterface( L"CTaskAnalyzeClusterBase!IEnumClusCfgNetworks", IEnumClusCfgNetworks, peccn, 1 );
  4313. punk->Release();
  4314. punk = NULL;
  4315. //
  4316. // Loop thru the networks already that the node has.
  4317. //
  4318. // These are used to detect whether or not private and public communications are enabled.
  4319. fIsPrivateNetworkAvailable = FALSE;
  4320. fIsPublicNetworkAvailable = FALSE;
  4321. do
  4322. {
  4323. //
  4324. // Cleanup
  4325. //
  4326. if ( pccni != NULL )
  4327. {
  4328. pccni->Release();
  4329. pccni = NULL;
  4330. }
  4331. TraceSysFreeString( bstrUID );
  4332. bstrUID = NULL;
  4333. if ( peccnCluster != NULL )
  4334. {
  4335. peccnCluster->Release();
  4336. peccnCluster = NULL;
  4337. }
  4338. //
  4339. // Get next network
  4340. //
  4341. hr = STHR( peccn->Next( 1, &pccni, &celtDummy ) );
  4342. if ( FAILED( hr ) )
  4343. {
  4344. SSR_ANALYSIS_FAILED( TASKID_Major_Find_Devices, TASKID_Minor_CompareNetworks_EnumNodes_EnumNetworks_Next, hr );
  4345. goto Cleanup;
  4346. }
  4347. if ( hr == S_FALSE )
  4348. {
  4349. break; // exit condition
  4350. }
  4351. pccni = TraceInterface( L"CTaskAnalyzeClusterBase!IClusCfgNetworkInfo", IClusCfgNetworkInfo, pccni, 1 );
  4352. //
  4353. // Grab the network's UUID.
  4354. //
  4355. hr = THR( pccni->GetUID( &bstrUID ) );
  4356. if ( FAILED( hr ) )
  4357. {
  4358. SSR_ANALYSIS_FAILED( TASKID_Major_Find_Devices, TASKID_Minor_CompareNetworks_EnumNodes_EnumNetworks_GetUID, hr );
  4359. goto Cleanup;
  4360. }
  4361. TraceMemoryAddBSTR( bstrUID );
  4362. //
  4363. // See if it matches a network already in the cluster configuration.
  4364. //
  4365. hr = THR( m_pom->FindObject( CLSID_NetworkType,
  4366. m_cookieCluster,
  4367. NULL,
  4368. DFGUID_EnumManageableNetworks,
  4369. &cookieDummy,
  4370. &punk
  4371. ) );
  4372. if ( hr == HRESULT_FROM_WIN32( ERROR_NOT_FOUND ) )
  4373. {
  4374. hr = S_FALSE; // create a new object.
  4375. // fall thru
  4376. }
  4377. else if ( FAILED( hr ) )
  4378. {
  4379. SSR_ANALYSIS_FAILED( TASKID_Major_Find_Devices, TASKID_Minor_CompareNetworks_EnumNodes_EnumNetworks_FindObject, hr );
  4380. goto Cleanup;
  4381. }
  4382. hr = THR( punk->TypeSafeQI( IEnumClusCfgNetworks, &peccnCluster ) );
  4383. if ( FAILED( hr ) )
  4384. {
  4385. SSR_ANALYSIS_FAILED( TASKID_Major_Find_Devices, TASKID_Minor_CompareNetworks_EnumNodes_EnumNetworks_FindObject_QI, hr );
  4386. goto Cleanup;
  4387. }
  4388. //peccnCluster = TraceInterface( L"CTaskAnalyzeClusterBase!IEnumClusCfgNetworks", IEnumClusCfgNetworks, peccnCluster, 1 );
  4389. punk->Release();
  4390. punk = NULL;
  4391. //
  4392. // Loop thru the configured cluster network to see what matches.
  4393. //
  4394. while ( ( hr == S_OK ) && ( m_fStop == FALSE ) )
  4395. {
  4396. BOOL fMatch;
  4397. //
  4398. // Cleanup
  4399. //
  4400. if ( pccniCluster != NULL )
  4401. {
  4402. pccniCluster->Release();
  4403. pccniCluster = NULL;
  4404. }
  4405. hr = STHR( peccnCluster->Next( 1, &pccniCluster, &celtDummy ) );
  4406. if ( FAILED( hr ) )
  4407. {
  4408. SSR_ANALYSIS_FAILED( TASKID_Major_Find_Devices, TASKID_Minor_CompareNetworks_EnumNodes_EnumNetworks_Cluster_Next, hr );
  4409. goto Cleanup;
  4410. }
  4411. if ( hr == S_FALSE )
  4412. {
  4413. break; // exit condition
  4414. }
  4415. pccniCluster = TraceInterface( L"CTaskAnalyzeClusterBase!IClusCfgNetworkInfo", IClusCfgNetworkInfo, pccniCluster, 1 );
  4416. hr = THR( pccniCluster->GetUID( &bstrUIDExisting ) );
  4417. if ( FAILED( hr ) )
  4418. {
  4419. SSR_ANALYSIS_FAILED( TASKID_Major_Find_Devices, TASKID_Minor_CompareNetworks_EnumNodes_EnumNetworks_Cluster_GetUID, hr );
  4420. goto Cleanup;
  4421. }
  4422. TraceMemoryAddBSTR( bstrUIDExisting );
  4423. fMatch = ( NBSTRCompareCase( bstrUID, bstrUIDExisting ) == 0 );
  4424. TraceSysFreeString( bstrUIDExisting );
  4425. if ( fMatch == FALSE )
  4426. {
  4427. continue; // keep looping
  4428. }
  4429. //
  4430. //
  4431. // If we made it here then we think it TRUEly is the same network. The
  4432. // rest is stuff we need to fixup during the commit phase.
  4433. //
  4434. //
  4435. //
  4436. // Exit the loop with S_OK so we don't create a new network.
  4437. //
  4438. //
  4439. // We have a match. Now see if it's private and/or public.
  4440. //
  4441. hr = pccniCluster->IsPublic();
  4442. if ( FAILED( hr ) )
  4443. {
  4444. SSR_ANALYSIS_FAILED( TASKID_Minor_Check_Compare_Networks, TASKID_Minor_CompareNetworks_EnumNodes_EnumNetworks_IsPublic, hr );
  4445. goto Cleanup;
  4446. }
  4447. else if ( hr == S_OK )
  4448. {
  4449. fIsPublicNetworkAvailable = TRUE;
  4450. }
  4451. hr = pccniCluster->IsPrivate();
  4452. if ( FAILED( hr ) )
  4453. {
  4454. SSR_ANALYSIS_FAILED( TASKID_Minor_Check_Compare_Networks, TASKID_Minor_CompareNetworks_EnumNodes_EnumNetworks_IsPrivate, hr );
  4455. goto Cleanup;
  4456. }
  4457. else if ( hr == S_OK )
  4458. {
  4459. fIsPrivateNetworkAvailable = TRUE;
  4460. }
  4461. hr = S_OK;
  4462. break; // exit loop
  4463. } // while: S_OK
  4464. if ( hr == S_FALSE )
  4465. {
  4466. //
  4467. // Need to create a new object.
  4468. //
  4469. Assert( pccni != NULL );
  4470. hr = THR( HrCreateNewNetworkInClusterConfiguration( pccni, NULL ) );
  4471. if ( FAILED( hr ) )
  4472. {
  4473. goto Cleanup;
  4474. }
  4475. } // if: object not found
  4476. } while ( ( hr == S_OK ) && ( m_fStop == FALSE ) ); // networks
  4477. //
  4478. // If no public network is available return a warning. If no private network is available
  4479. // return an error, which supercedes the warning.
  4480. //
  4481. if ( fIsPublicNetworkAvailable == FALSE )
  4482. {
  4483. hr = THR( HrFormatMessageIntoBSTR( g_hInstance, IDS_TASKID_MINOR_NO_PUBLIC_NETWORKS_FOUND, &bstrNotification, bstrName ) );
  4484. if ( FAILED( hr ) )
  4485. {
  4486. SSR_ANALYSIS_FAILED( TASKID_Minor_Check_Compare_Networks, TASKID_Minor_CompareNetworks_IsPublic_FormatMessage, hr );
  4487. }
  4488. hr = THR( SendStatusReport(
  4489. m_bstrClusterName
  4490. , TASKID_Minor_Check_Compare_Networks
  4491. , TASKID_Minor_CompareNetworks_EnumNodes_IsPublicNetworkAvailable
  4492. , 1
  4493. , 1
  4494. , 1
  4495. , MAKE_HRESULT( SEVERITY_SUCCESS, FACILITY_WIN32, ERROR_CLUSTER_NETWORK_NOT_FOUND )
  4496. , bstrNotification
  4497. , NULL
  4498. , NULL
  4499. ) );
  4500. if ( FAILED( hr ) )
  4501. {
  4502. goto Cleanup;
  4503. }
  4504. //
  4505. // At a minimum we need to return a warning. If we have anything less than that
  4506. // then upgrade it to our warning. We don't break or goto Cleanup here so that
  4507. // we can continue evaluating any other nodes that we're trying to add.
  4508. //
  4509. if ( hrError == S_OK )
  4510. {
  4511. hrError = MAKE_HRESULT( SEVERITY_SUCCESS, FACILITY_WIN32, ERROR_CLUSTER_NETWORK_NOT_FOUND );
  4512. }
  4513. } // if: publicnetworkavailable == FALSE
  4514. if ( fIsPrivateNetworkAvailable == FALSE )
  4515. {
  4516. hr = THR( HrFormatMessageIntoBSTR( g_hInstance, IDS_TASKID_MINOR_NO_PRIVATE_NETWORKS_FOUND, &bstrNotification, bstrName ) );
  4517. if ( FAILED( hr ) )
  4518. {
  4519. SSR_ANALYSIS_FAILED( TASKID_Minor_Check_Compare_Networks, TASKID_Minor_CompareNetworks_IsPrivate_FormatMessage, hr );
  4520. }
  4521. hr = THR( SendStatusReport(
  4522. m_bstrClusterName
  4523. , TASKID_Minor_Check_Compare_Networks
  4524. , TASKID_Minor_CompareNetworks_EnumNodes_IsPrivateNetworkAvailable
  4525. , 1
  4526. , 1
  4527. , 1
  4528. , HRESULT_FROM_WIN32( ERROR_CLUSTER_NETWORK_NOT_FOUND )
  4529. , bstrNotification
  4530. , NULL
  4531. , NULL
  4532. ) );
  4533. if ( FAILED( hr ) )
  4534. {
  4535. goto Cleanup;
  4536. }
  4537. //
  4538. // We need to return an error. If we have anything less than that
  4539. // then upgrade it to our error. We don't break or goto Cleanup here so that
  4540. // we can continue evaluating any other nodes that we're trying to add.
  4541. //
  4542. if ( HRESULT_SEVERITY( hrError ) < SEVERITY_ERROR )
  4543. {
  4544. hrError = HRESULT_FROM_WIN32( ERROR_CLUSTER_NETWORK_NOT_FOUND );
  4545. }
  4546. } // if: privatenetworkavailable == FALSE
  4547. } while ( ( hr == S_OK ) && ( m_fStop == FALSE ) ); // nodes
  4548. //
  4549. // If we had an error with one of the new nodes not having both public and private
  4550. // communications enabled, then return the correct error. We do this here so that
  4551. // we can analyze all of the nodes in the enumeration to detect multiple errors at
  4552. // once. If we get here then hr is going to be S_FALSE since that is the normal
  4553. // exit condition for the loops above. Any other exit would have gone to cleanup.
  4554. //
  4555. hr = hrError;
  4556. Cleanup:
  4557. THR( HrSendStatusReport(
  4558. m_bstrClusterName
  4559. , TASKID_Major_Check_Cluster_Feasibility
  4560. , TASKID_Minor_Check_Compare_Networks
  4561. , 0
  4562. , 1
  4563. , 1
  4564. , hr
  4565. , IDS_TASKID_MINOR_COMPARE_NETWORKS
  4566. ) );
  4567. TraceSysFreeString( bstrUID );
  4568. TraceSysFreeString( bstrName );
  4569. TraceSysFreeString( bstrNotification );
  4570. if ( punk != NULL )
  4571. {
  4572. punk->Release();
  4573. }
  4574. if ( pecNodes != NULL )
  4575. {
  4576. pecNodes->Release();
  4577. }
  4578. if ( peccn != NULL )
  4579. {
  4580. peccn->Release();
  4581. }
  4582. if ( peccnCluster != NULL )
  4583. {
  4584. peccnCluster->Release();
  4585. }
  4586. if ( pccni != NULL )
  4587. {
  4588. pccni->Release();
  4589. }
  4590. if ( pccniCluster != NULL )
  4591. {
  4592. pccniCluster->Release();
  4593. }
  4594. HRETURN( hr );
  4595. } //*** CTaskAnalyzeClusterBase::HrCompareNetworks
  4596. //////////////////////////////////////////////////////////////////////////////
  4597. //++
  4598. //
  4599. // CTaskAnalyzeClusterBase::HrCreateNewNetworkInClusterConfiguration
  4600. //
  4601. // Description:
  4602. //
  4603. // Arguments:
  4604. //
  4605. // Return Value:
  4606. // S_OK
  4607. // Success
  4608. //
  4609. // HRESULT failure.
  4610. //
  4611. //--
  4612. //////////////////////////////////////////////////////////////////////////////
  4613. HRESULT
  4614. CTaskAnalyzeClusterBase::HrCreateNewNetworkInClusterConfiguration(
  4615. IClusCfgNetworkInfo * pccniIn,
  4616. IClusCfgNetworkInfo ** ppccniNewOut
  4617. )
  4618. {
  4619. TraceFunc( "" );
  4620. HRESULT hr;
  4621. OBJECTCOOKIE cookieDummy;
  4622. BSTR bstrUID = NULL;
  4623. IUnknown * punk = NULL;
  4624. IGatherData * pgd = NULL;
  4625. IClusCfgNetworkInfo * pccni = NULL;
  4626. TraceFlow1( "[MT] CTaskAnalyzeClusterBase::HrCreateNewNetworkInClusterConfiguration() Thread id %d", GetCurrentThreadId() );
  4627. // grab the name
  4628. hr = THR( pccniIn->GetUID( &bstrUID ) );
  4629. if ( FAILED( hr ) )
  4630. {
  4631. SSR_ANALYSIS_FAILED( TASKID_Major_Find_Devices, TASKID_Minor_CreateNetwork_GetUID, hr );
  4632. goto Cleanup;
  4633. }
  4634. TraceMemoryAddBSTR( bstrUID );
  4635. // create an object in the object manager.
  4636. hr = THR( m_pom->FindObject( CLSID_NetworkType,
  4637. m_cookieCluster,
  4638. bstrUID,
  4639. DFGUID_NetworkResource,
  4640. &cookieDummy,
  4641. &punk
  4642. ) );
  4643. if ( FAILED( hr ) )
  4644. {
  4645. SSR_ANALYSIS_FAILED( TASKID_Major_Find_Devices, TASKID_Minor_CreateNetwork_FindObject, hr );
  4646. goto Cleanup;
  4647. }
  4648. // find the IGatherData interface
  4649. hr = THR( punk->TypeSafeQI( IGatherData, &pgd ) );
  4650. if ( FAILED( hr ) )
  4651. {
  4652. SSR_ANALYSIS_FAILED( TASKID_Major_Find_Devices, TASKID_Minor_CreateNetwork_FindObject_QI, hr );
  4653. goto Cleanup;
  4654. }
  4655. // have the new object gather all information it needs
  4656. hr = THR( pgd->Gather( m_cookieCluster, pccniIn ) );
  4657. if ( FAILED( hr ) )
  4658. {
  4659. SSR_ANALYSIS_FAILED( TASKID_Major_Find_Devices, TASKID_Minor_CreateNetwork_Gather, hr );
  4660. goto Cleanup;
  4661. }
  4662. // hand the object out if requested
  4663. if ( ppccniNewOut != NULL )
  4664. {
  4665. // find the IClusCfgManagedResourceInfo
  4666. hr = THR( punk->TypeSafeQI( IClusCfgNetworkInfo, &pccni ) );
  4667. if ( FAILED( hr ) )
  4668. {
  4669. SSR_ANALYSIS_FAILED( TASKID_Major_Find_Devices, TASKID_Minor_CreateNetwork_QI, hr );
  4670. goto Cleanup;
  4671. }
  4672. *ppccniNewOut = TraceInterface( L"ManagedResource!ICCNI", IClusCfgNetworkInfo, pccni, 0 );
  4673. (*ppccniNewOut)->AddRef();
  4674. }
  4675. Cleanup:
  4676. TraceSysFreeString( bstrUID );
  4677. if ( pccni != NULL )
  4678. {
  4679. pccni->Release();
  4680. }
  4681. if ( pgd != NULL )
  4682. {
  4683. pgd->Release();
  4684. }
  4685. if ( punk != NULL )
  4686. {
  4687. punk->Release();
  4688. }
  4689. HRETURN( hr );
  4690. } //*** CTaskAnalyzeClusterBase::HrCreateNewNetworkInClusterConfiguration
  4691. //////////////////////////////////////////////////////////////////////////////
  4692. //++
  4693. //
  4694. // CTaskAnalyzeClusterBase::HrFreeCookies
  4695. //
  4696. // Description:
  4697. //
  4698. // Arguments:
  4699. //
  4700. // Return Value:
  4701. // S_OK
  4702. // Success
  4703. //
  4704. // HRESULT failure.
  4705. //
  4706. //--
  4707. //////////////////////////////////////////////////////////////////////////////
  4708. HRESULT
  4709. CTaskAnalyzeClusterBase::HrFreeCookies( void )
  4710. {
  4711. TraceFunc( "" );
  4712. HRESULT hr;
  4713. HRESULT hrReturn = S_OK;
  4714. Assert( m_pom != NULL );
  4715. while( m_cCookies != 0 )
  4716. {
  4717. m_cCookies --;
  4718. if ( m_pcookies[ m_cCookies ] != NULL )
  4719. {
  4720. hr = THR( m_pom->RemoveObject( m_pcookies[ m_cCookies ] ) );
  4721. if ( FAILED( hr ) )
  4722. {
  4723. hrReturn = hr;
  4724. }
  4725. } // if: found cookie
  4726. } // while: more cookies
  4727. Assert( m_cCookies == 0 );
  4728. m_cSubTasksDone = 0;
  4729. TraceFree( m_pcookies );
  4730. m_pcookies = NULL;
  4731. HRETURN( hrReturn );
  4732. } //*** CTaskAnalyzeClusterBase::HrFreeCookies
  4733. //////////////////////////////////////////////////////////////////////////////
  4734. //++
  4735. //
  4736. // CTaskAnalyzeClusterBase::HrCheckInteroperability
  4737. //
  4738. // Description:
  4739. //
  4740. // Arguments:
  4741. //
  4742. // Return Value:
  4743. // S_OK
  4744. // Success
  4745. //
  4746. // HRESULT failure.
  4747. //
  4748. //--
  4749. //////////////////////////////////////////////////////////////////////////////
  4750. HRESULT
  4751. CTaskAnalyzeClusterBase::HrCheckInteroperability( void )
  4752. {
  4753. TraceFunc( "" );
  4754. Assert( m_pcm != NULL );
  4755. HRESULT hr = S_OK;
  4756. IUnknown * punk = NULL;
  4757. bool fAllNodesMatch;
  4758. DWORD dwNodeHighestVersion;
  4759. DWORD dwNodeLowestVersion;
  4760. IClusCfgServer * piccs = NULL;
  4761. IClusCfgNodeInfo * piccni = NULL;
  4762. IClusCfgClusterInfo * piccci = NULL;
  4763. IClusCfgClusterInfoEx * picccie = NULL;
  4764. TraceFlow1( "[MT] CTaskAnalyzeClusterBase::HrCheckInteroperability() Thread id %d", GetCurrentThreadId() );
  4765. //
  4766. // If were are creating a new cluster, there is no need to do this check.
  4767. //
  4768. if ( m_fJoiningMode == FALSE )
  4769. {
  4770. goto Cleanup;
  4771. } // if:
  4772. //
  4773. // Tell the UI were are starting this.
  4774. //
  4775. hr = THR( HrSendStatusReport(
  4776. m_bstrClusterName
  4777. , TASKID_Major_Check_Cluster_Feasibility
  4778. , TASKID_Minor_CheckInteroperability
  4779. , 0
  4780. , 1
  4781. , 0
  4782. , S_OK
  4783. , IDS_TASKID_MINOR_CHECKINTEROPERABILITY
  4784. ) );
  4785. if ( FAILED( hr ) )
  4786. goto Cleanup;
  4787. //
  4788. // All nodes must be at the same level diring a bulk add.
  4789. //
  4790. hr = STHR( HrEnsureAllJoiningNodesSameVersion( &dwNodeHighestVersion, &dwNodeLowestVersion, &fAllNodesMatch ) );
  4791. if ( FAILED( hr ) )
  4792. {
  4793. goto Error;
  4794. } // if:
  4795. //
  4796. // If no nodes found that are being added, then there isn't a need to do
  4797. // do this check. Just bail.
  4798. //
  4799. if ( hr == S_FALSE )
  4800. {
  4801. goto Cleanup;
  4802. } // if
  4803. if ( fAllNodesMatch == FALSE )
  4804. {
  4805. hr = THR( HRESULT_FROM_WIN32( ERROR_CLUSTER_INCOMPATIBLE_VERSIONS ) );
  4806. goto Cleanup;
  4807. } // if:
  4808. //
  4809. // Get and verify the sponsor version
  4810. //
  4811. hr = THR( m_pcm->GetConnectionToObject( m_cookieCluster, &punk ) );
  4812. if ( FAILED( hr ) )
  4813. {
  4814. SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_HrCheckInteroperability_GetConnectionObject, hr );
  4815. goto Cleanup;
  4816. } // if:
  4817. hr = THR( punk->TypeSafeQI( IClusCfgServer, &piccs ) );
  4818. if ( FAILED( hr ) )
  4819. {
  4820. SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_HrCheckInteroperability_ConfigConnection_QI, hr );
  4821. goto Cleanup;
  4822. } // if:
  4823. hr = THR( piccs->GetClusterNodeInfo( &piccni ) );
  4824. if ( FAILED( hr ) )
  4825. {
  4826. SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_HrCheckInteroperability_GetNodeInfo, hr );
  4827. goto Cleanup;
  4828. } // if:
  4829. hr = THR( piccni->GetClusterConfigInfo( &piccci ) );
  4830. if ( FAILED( hr ) )
  4831. {
  4832. SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_HrCheckInteroperability_GetClusterConfigInfo, hr );
  4833. goto Cleanup;
  4834. } // if:
  4835. hr = THR( piccci->TypeSafeQI( IClusCfgClusterInfoEx, &picccie ) );
  4836. if ( FAILED( hr ) )
  4837. {
  4838. THR( HrSendStatusReport(
  4839. m_bstrClusterName
  4840. , TASKID_Major_Check_Cluster_Feasibility
  4841. , TASKID_Minor_HrCheckInteroperability_ClusterInfoEx_QI
  4842. , 0
  4843. , 1
  4844. , 1
  4845. , hr
  4846. , IDS_ERR_NO_RC2_INTERFACE
  4847. ) );
  4848. goto Cleanup;
  4849. } // if:
  4850. hr = THR( picccie->CheckJoiningNodeVersion( dwNodeHighestVersion, dwNodeLowestVersion ) );
  4851. if ( FAILED( hr ) )
  4852. {
  4853. SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_HrCheckInteroperability_CheckJoiningNodeVersion, hr );
  4854. goto Cleanup;
  4855. } // if: CheckJoiningNodeVersion() failed
  4856. goto UpdateStatus;
  4857. Error:
  4858. UpdateStatus:
  4859. {
  4860. HRESULT hr2;
  4861. hr2 = THR( SendStatusReport( m_bstrClusterName,
  4862. TASKID_Major_Check_Cluster_Feasibility,
  4863. TASKID_Minor_CheckInteroperability,
  4864. 0,
  4865. 1,
  4866. 1,
  4867. hr,
  4868. NULL,
  4869. NULL,
  4870. NULL
  4871. ) );
  4872. if ( FAILED( hr2 ) )
  4873. {
  4874. hr = hr2;
  4875. } // if
  4876. }
  4877. Cleanup:
  4878. if ( punk != NULL )
  4879. {
  4880. punk->Release();
  4881. } // if:
  4882. if ( piccs != NULL )
  4883. {
  4884. piccs->Release();
  4885. } // if:
  4886. if ( piccni != NULL )
  4887. {
  4888. piccni->Release();
  4889. } // if:
  4890. if ( piccci != NULL )
  4891. {
  4892. piccci->Release();
  4893. } // if:
  4894. if ( picccie != NULL )
  4895. {
  4896. picccie->Release();
  4897. } // if:
  4898. HRETURN( hr );
  4899. } //*** CTaskAnalyzeClusterBase::HrCheckInteroperability
  4900. //////////////////////////////////////////////////////////////////////////////
  4901. //++
  4902. //
  4903. // CTaskAnalyzeClusterBase::HrEnsureAllJoiningNodesSameVersion
  4904. //
  4905. // Description:
  4906. //
  4907. // Arguments:
  4908. //
  4909. // Return Value:
  4910. // S_OK
  4911. // Success
  4912. //
  4913. // HRESULT failure.
  4914. //
  4915. //--
  4916. //////////////////////////////////////////////////////////////////////////////
  4917. HRESULT
  4918. CTaskAnalyzeClusterBase::HrEnsureAllJoiningNodesSameVersion(
  4919. DWORD * pdwNodeHighestVersionOut,
  4920. DWORD * pdwNodeLowestVersionOut,
  4921. bool * pfAllNodesMatchOut
  4922. )
  4923. {
  4924. TraceFunc( "" );
  4925. Assert( m_fJoiningMode );
  4926. Assert( pdwNodeHighestVersionOut != NULL );
  4927. Assert( pdwNodeLowestVersionOut != NULL );
  4928. Assert( pfAllNodesMatchOut != NULL );
  4929. HRESULT hr = S_OK;
  4930. OBJECTCOOKIE cookieDummy;
  4931. IUnknown * punk = NULL;
  4932. IEnumNodes * pen = NULL;
  4933. IClusCfgNodeInfo * pccni = NULL;
  4934. DWORD rgdwNodeHighestVersion[ 2 ];
  4935. DWORD rgdwNodeLowestVersion[ 2 ];
  4936. int idx = 0;
  4937. BSTR bstrDescription = NULL;
  4938. BSTR bstrNodeName = NULL;
  4939. BSTR bstrFirstNodeName = NULL;
  4940. BOOL fFoundAtLeastOneJoiningNode = FALSE;
  4941. TraceFlow1( "[MT] CTaskAnalyzeClusterBase::HrEnsureAllJoiningNodesSameVersion() Thread id %d", GetCurrentThreadId() );
  4942. *pfAllNodesMatchOut = TRUE;
  4943. ZeroMemory( rgdwNodeHighestVersion, sizeof( rgdwNodeHighestVersion ) );
  4944. ZeroMemory( rgdwNodeLowestVersion, sizeof( rgdwNodeLowestVersion ) );
  4945. //
  4946. // Ask the object manager for the node enumerator.
  4947. //
  4948. hr = THR( m_pom->FindObject( CLSID_NodeType,
  4949. m_cookieCluster,
  4950. NULL,
  4951. DFGUID_EnumNodes,
  4952. &cookieDummy,
  4953. &punk
  4954. ) );
  4955. if ( FAILED( hr ) )
  4956. {
  4957. SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_HrEnsureAllJoiningNodesSameVersion_FindObject, hr );
  4958. goto Cleanup;
  4959. }
  4960. hr = THR( punk->TypeSafeQI( IEnumNodes, &pen ) );
  4961. if ( FAILED( hr ) )
  4962. {
  4963. SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_HrEnsureAllJoiningNodesSameVersion_FindObject_QI, hr );
  4964. goto Cleanup;
  4965. }
  4966. //
  4967. // Look at each node and ensure that they all have the same version.
  4968. //
  4969. Assert( SUCCEEDED( hr ) );
  4970. while ( SUCCEEDED( hr ) )
  4971. {
  4972. ULONG celtDummy;
  4973. //
  4974. // Cleanup
  4975. //
  4976. if ( pccni != NULL )
  4977. {
  4978. pccni->Release();
  4979. pccni = NULL;
  4980. } // if:
  4981. //
  4982. // Get the next node.
  4983. //
  4984. hr = STHR( pen->Next( 1, &pccni, &celtDummy ) );
  4985. if ( hr == S_FALSE )
  4986. {
  4987. break; // exit condition
  4988. } // if:
  4989. if ( FAILED( hr ) )
  4990. {
  4991. SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_HrEnsureAllJoiningNodesSameVersion_EnumNode_Next, hr );
  4992. goto Cleanup;
  4993. } // if:
  4994. hr = STHR( pccni->IsMemberOfCluster() );
  4995. if ( FAILED( hr ) )
  4996. {
  4997. SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_HrEnsureAllJoiningNodesSameVersion_Node_IsMemberOfCluster, hr );
  4998. goto Cleanup;
  4999. } // if:
  5000. //
  5001. // Only want to check those nodes that are not already members of a cluster. The nodes being added.
  5002. //
  5003. if ( hr == S_FALSE )
  5004. {
  5005. fFoundAtLeastOneJoiningNode = TRUE;
  5006. hr = THR( pccni->GetClusterVersion( &rgdwNodeHighestVersion[ idx ], &rgdwNodeLowestVersion[ idx ] ) );
  5007. if ( FAILED( hr ) )
  5008. {
  5009. SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_HrEnsureAllJoiningNodesSameVersion_Node_GetClusterVersion, hr );
  5010. goto Cleanup;
  5011. } // if:
  5012. idx++;
  5013. //
  5014. // Need to get the another node's version.
  5015. //
  5016. if ( idx == 1 )
  5017. {
  5018. WCHAR * psz = NULL;
  5019. hr = THR( pccni->GetName( &bstrFirstNodeName ) );
  5020. if ( FAILED( hr ) )
  5021. {
  5022. SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_HrEnsureAllJoiningNodesSameVersion_GetName, hr );
  5023. goto Cleanup;
  5024. } // if:
  5025. TraceMemoryAddBSTR( bstrFirstNodeName );
  5026. psz = wcschr( bstrFirstNodeName, L'.' );
  5027. if ( psz != NULL )
  5028. {
  5029. *psz = L'\0'; // change from an FQDN to a simple node name.
  5030. } // if:
  5031. continue;
  5032. } // if:
  5033. //
  5034. // Let's compare two nodes at a time...
  5035. //
  5036. if ( idx == 2 )
  5037. {
  5038. if ( ( rgdwNodeHighestVersion[ 0 ] == rgdwNodeHighestVersion[ 1 ] )
  5039. && ( rgdwNodeLowestVersion[ 1 ] == rgdwNodeLowestVersion[ 1 ] ) )
  5040. {
  5041. idx = 1; // reset to put the next node's version values at the second position...
  5042. continue;
  5043. } // if:
  5044. else
  5045. {
  5046. *pfAllNodesMatchOut = FALSE;
  5047. hr = THR( pccni->GetName( &bstrNodeName ) );
  5048. if ( FAILED( hr ) )
  5049. {
  5050. SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_HrEnsureAllJoiningNodesSameVersion_GetName, hr );
  5051. goto Cleanup;
  5052. } // if:
  5053. TraceMemoryAddBSTR( bstrNodeName );
  5054. hr = THR( HrFormatStringIntoBSTR( g_hInstance, IDS_TASKID_MINOR_NODES_VERSION_MISMATCH, &bstrDescription, bstrFirstNodeName ) );
  5055. if ( FAILED( hr ) )
  5056. {
  5057. SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_HrEnsureAllJoiningNodesSameVersion_FormatString, hr );
  5058. goto Cleanup;
  5059. } // if:
  5060. THR( SendStatusReport(
  5061. m_bstrClusterName
  5062. , TASKID_Minor_CheckInteroperability
  5063. , TASKID_Minor_Incompatible_Versions
  5064. , 1
  5065. , 1
  5066. , 1
  5067. , HRESULT_FROM_WIN32( ERROR_CLUSTER_INCOMPATIBLE_VERSIONS )
  5068. , bstrDescription
  5069. , NULL
  5070. , NULL
  5071. ) );
  5072. goto Cleanup;
  5073. } // else:
  5074. } // if:
  5075. } // if:
  5076. } // while: hr
  5077. if ( fFoundAtLeastOneJoiningNode == FALSE )
  5078. {
  5079. THR( HrSendStatusReport(
  5080. m_bstrClusterName
  5081. , TASKID_Minor_CheckInteroperability
  5082. , TASKID_Minor_No_Joining_Nodes_Found_For_Version_Check
  5083. , 1
  5084. , 1
  5085. , 1
  5086. , S_FALSE
  5087. , IDS_TASKID_MINOR_NO_JOINING_NODES_FOUND_FOR_VERSION_CHECK
  5088. ) );
  5089. hr = S_FALSE;
  5090. goto Cleanup;
  5091. }
  5092. //
  5093. // Fill in the out args...
  5094. //
  5095. *pdwNodeHighestVersionOut = rgdwNodeHighestVersion[ 0 ];
  5096. *pdwNodeLowestVersionOut = rgdwNodeLowestVersion[ 0 ];
  5097. hr = S_OK;
  5098. Cleanup:
  5099. if ( pccni != NULL )
  5100. {
  5101. pccni->Release();
  5102. } // if:
  5103. if ( pen != NULL )
  5104. {
  5105. pen->Release();
  5106. } // if:
  5107. if ( punk != NULL )
  5108. {
  5109. punk->Release();
  5110. } // if:
  5111. TraceSysFreeString( bstrNodeName );
  5112. TraceSysFreeString( bstrFirstNodeName );
  5113. TraceSysFreeString( bstrDescription );
  5114. HRETURN( hr );
  5115. } //*** CTaskAnalyzeClusterBase::HrEnsureAllJoiningNodesSameVersion
  5116. //////////////////////////////////////////////////////////////////////////////
  5117. //++
  5118. //
  5119. // CTaskAnalyzeClusterBase::HrGetUsersNodesCookies
  5120. //
  5121. // Description:
  5122. //
  5123. // Arguments:
  5124. //
  5125. // Return Value:
  5126. // S_OK
  5127. // Success
  5128. //
  5129. // HRESULT failure.
  5130. //
  5131. //--
  5132. //////////////////////////////////////////////////////////////////////////////
  5133. HRESULT
  5134. CTaskAnalyzeClusterBase::HrGetUsersNodesCookies( void )
  5135. {
  5136. TraceFunc( "" );
  5137. HRESULT hr;
  5138. ULONG cElememtsReturned;
  5139. OBJECTCOOKIE cookieDummy;
  5140. ULONG cNode;
  5141. IUnknown * punk = NULL;
  5142. IEnumCookies * pec = NULL;
  5143. BSTR bstrName = NULL;
  5144. //
  5145. // Get the cookie enumerator.
  5146. //
  5147. hr = THR( m_pom->FindObject( CLSID_NodeType, m_cookieCluster, NULL, DFGUID_EnumCookies, &cookieDummy, &punk ) );
  5148. if ( FAILED( hr ) )
  5149. {
  5150. SSR_ANALYSIS_FAILED( TASKID_Major_Establish_Connection, TASKID_Minor_GetUsersNodesCookies_FindObject, hr );
  5151. goto Cleanup;
  5152. } // if:
  5153. hr = THR( punk->TypeSafeQI( IEnumCookies, &pec ) );
  5154. if ( FAILED( hr ) )
  5155. {
  5156. SSR_ANALYSIS_FAILED( TASKID_Major_Establish_Connection, TASKID_Minor_GetUsersNodesCookies_FindObject_QI, hr );
  5157. goto Cleanup;
  5158. } // if:
  5159. punk->Release();
  5160. punk = NULL;
  5161. //
  5162. // Get the number of nodes entered by the user.
  5163. //
  5164. hr = THR( pec->Count( &m_cUserNodes ) );
  5165. if ( FAILED( hr ) )
  5166. {
  5167. SSR_ANALYSIS_FAILED( TASKID_Major_Establish_Connection, TASKID_Minor_GetUsersNodesCookies_EnumCookies_Count, hr );
  5168. goto Cleanup;
  5169. } // if: error getting count of nodes entered by user
  5170. Assert( hr == S_OK );
  5171. //
  5172. // Allocate a buffer for the cookies.
  5173. //
  5174. m_pcookiesUser = (OBJECTCOOKIE *) TraceAlloc( 0, sizeof( OBJECTCOOKIE ) * m_cUserNodes );
  5175. if ( m_pcookiesUser == NULL )
  5176. {
  5177. hr = THR( E_OUTOFMEMORY );
  5178. SSR_ANALYSIS_FAILED( TASKID_Major_Establish_Connection, TASKID_Minor_GetUsersNodesCookies_OutOfMemory, hr );
  5179. goto Cleanup;
  5180. } // if:
  5181. //
  5182. // Reset the enumerator.
  5183. //
  5184. hr = THR( pec->Reset() );
  5185. if ( FAILED( hr ) )
  5186. {
  5187. SSR_ANALYSIS_FAILED( TASKID_Major_Establish_Connection, TASKID_Minor_GetUsersNodesCookies_EnumCookies_Reset, hr );
  5188. goto Cleanup;
  5189. } // if:
  5190. //
  5191. // Enumerate them again this time putting the cookies into the buffer.
  5192. //
  5193. for ( cNode = 0 ; cNode < m_cUserNodes ; cNode ++ )
  5194. {
  5195. //
  5196. // Cleanup
  5197. //
  5198. TraceSysFreeString( bstrName );
  5199. bstrName = NULL;
  5200. //
  5201. // Get each user-added node cookie in turn and add it to the array...
  5202. //
  5203. hr = THR( pec->Next( 1, &m_pcookiesUser[ cNode ], &cElememtsReturned ) );
  5204. AssertMsg( hr != S_FALSE, "We should never hit this because the count of nodes should not change!" );
  5205. if ( hr != S_OK )
  5206. {
  5207. SSR_ANALYSIS_FAILED( TASKID_Major_Establish_Connection, TASKID_Minor_GetUsersNodesCookies_EnumCookies_Next, hr );
  5208. goto Cleanup;
  5209. } // if:
  5210. //
  5211. // Log the node name as a user-added node.
  5212. //
  5213. hr = THR( HrRetrieveCookiesName( m_pom, m_pcookiesUser[ cNode ], &bstrName ) );
  5214. if ( FAILED( hr ) )
  5215. {
  5216. goto Cleanup;
  5217. } // if:
  5218. LogMsg( L"[MT] Adding node '%ws' to the list of user-added nodes.", bstrName );
  5219. } // for: each user-entered node
  5220. Assert( cNode == m_cUserNodes );
  5221. #ifdef DEBUG
  5222. {
  5223. OBJECTCOOKIE cookie;
  5224. hr = STHR( pec->Next( 1, &cookie, &cElememtsReturned ) );
  5225. Assert( hr == S_FALSE );
  5226. }
  5227. #endif
  5228. hr = S_OK;
  5229. Cleanup:
  5230. TraceSysFreeString( bstrName );
  5231. if ( punk != NULL )
  5232. {
  5233. punk->Release();
  5234. } // if:
  5235. if ( pec != NULL )
  5236. {
  5237. pec->Release();
  5238. } // if:
  5239. HRETURN( hr );
  5240. } //*** CTaskAnalyzeClusterBase::HrGetUsersNodesCookies
  5241. //////////////////////////////////////////////////////////////////////////////
  5242. //++
  5243. //
  5244. // CTaskAnalyzeClusterBase::HrIsUserAddedNode
  5245. //
  5246. // Description:
  5247. //
  5248. // Arguments:
  5249. //
  5250. // Return Value:
  5251. // S_OK
  5252. // Success
  5253. //
  5254. // HRESULT failure.
  5255. //
  5256. //--
  5257. //////////////////////////////////////////////////////////////////////////////
  5258. HRESULT
  5259. CTaskAnalyzeClusterBase::HrIsUserAddedNode(
  5260. BSTR bstrNodeNameIn
  5261. )
  5262. {
  5263. TraceFunc( "" );
  5264. HRESULT hr = S_FALSE;
  5265. ULONG cNode;
  5266. IUnknown * punk = NULL;
  5267. IClusCfgNodeInfo * pccni = NULL;
  5268. BSTR bstrNodeName = NULL;
  5269. for ( cNode = 0 ; cNode < m_cUserNodes ; cNode ++ )
  5270. {
  5271. hr = m_pom->GetObject( DFGUID_NodeInformation, m_pcookiesUser[ cNode ], &punk );
  5272. if ( hr == HRESULT_FROM_WIN32( ERROR_NOT_FOUND ) )
  5273. {
  5274. ULONG idx;
  5275. //
  5276. // The cookie at cNode was removed from the object manager since it was gathered before the nodes
  5277. // were connected to. This typically means that the user added node was removed form the list
  5278. // of nodes to work on. We need to remove this cookie from the list.
  5279. //
  5280. //
  5281. // Shift the cookies to the left by one index.
  5282. //
  5283. for ( idx = cNode; idx < m_cUserNodes - 1; idx++ )
  5284. {
  5285. m_pcookiesUser[ idx ] = m_pcookiesUser[ idx + 1 ];
  5286. } // for:
  5287. m_cUserNodes -= 1;
  5288. hr = S_FALSE;
  5289. continue;
  5290. }
  5291. else if ( FAILED( hr ) )
  5292. {
  5293. THR( hr );
  5294. SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_HrIsUserAddedNode_GetObject, hr );
  5295. goto Cleanup;
  5296. } // else if:
  5297. hr = THR( punk->TypeSafeQI( IClusCfgNodeInfo, &pccni ) );
  5298. if ( FAILED( hr ) )
  5299. {
  5300. SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_HrIsUserAddedNode_GetObject_QI, hr );
  5301. goto Cleanup;
  5302. } // if:
  5303. punk->Release();
  5304. punk = NULL;
  5305. hr = THR( pccni->GetName( &bstrNodeName ) );
  5306. if ( FAILED( hr ) )
  5307. {
  5308. SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_HrIsUserAddedNode_GetName, hr );
  5309. goto Cleanup;
  5310. } // if:
  5311. TraceMemoryAddBSTR( bstrNodeName );
  5312. pccni->Release();
  5313. pccni = NULL;
  5314. if ( NBSTRCompareCase( bstrNodeNameIn, bstrNodeName ) == 0 )
  5315. {
  5316. hr = S_OK;
  5317. break;
  5318. } // if:
  5319. TraceSysFreeString( bstrNodeName );
  5320. bstrNodeName = NULL;
  5321. hr = S_FALSE;
  5322. } // for:
  5323. Cleanup:
  5324. if ( pccni != NULL )
  5325. {
  5326. pccni->Release();
  5327. } // if:
  5328. if ( punk != NULL )
  5329. {
  5330. punk->Release();
  5331. } // if:
  5332. TraceSysFreeString( bstrNodeName );
  5333. HRETURN( hr );
  5334. } //*** CTaskAnalyzeClusterBase::HrIsUserAddedNode
  5335. //////////////////////////////////////////////////////////////////////////////
  5336. //++
  5337. //
  5338. // CTaskAnalyzeClusterBase::HrSendStatusReport
  5339. //
  5340. // Description:
  5341. //
  5342. // Arguments:
  5343. //
  5344. //
  5345. // Return Value:
  5346. // S_OK
  5347. // Success.
  5348. //
  5349. // Other HRESULT error.
  5350. // Remarks:
  5351. //
  5352. //--
  5353. //////////////////////////////////////////////////////////////////////////////
  5354. HRESULT
  5355. CTaskAnalyzeClusterBase::HrSendStatusReport(
  5356. LPCWSTR pcszNodeNameIn
  5357. , CLSID clsidMajorIn
  5358. , CLSID clsidMinorIn
  5359. , ULONG ulMinIn
  5360. , ULONG ulMaxIn
  5361. , ULONG ulCurrentIn
  5362. , HRESULT hrIn
  5363. , int nDescriptionIdIn
  5364. )
  5365. {
  5366. TraceFunc( "" );
  5367. HRESULT hr = S_OK;
  5368. BSTR bstr = NULL;
  5369. hr = THR( HrLoadStringIntoBSTR( g_hInstance, nDescriptionIdIn, &bstr ) );
  5370. if ( FAILED( hr ) )
  5371. {
  5372. goto Cleanup;
  5373. } // if:
  5374. hr = THR( SendStatusReport(
  5375. pcszNodeNameIn == NULL ? m_bstrClusterName : pcszNodeNameIn
  5376. , clsidMajorIn
  5377. , clsidMinorIn
  5378. , ulMinIn
  5379. , ulMaxIn
  5380. , ulCurrentIn
  5381. , hrIn
  5382. , bstr
  5383. , NULL
  5384. , NULL
  5385. ) );
  5386. Cleanup:
  5387. TraceSysFreeString( bstr );
  5388. HRETURN( hr );
  5389. } //*** CTaskAnalyzeClusterBase::HrSendStatusReport
  5390. //////////////////////////////////////////////////////////////////////////////
  5391. //++
  5392. //
  5393. // CTaskAnalyzeClusterBase::HrResourcePrivateDataExchange
  5394. //
  5395. // Description:
  5396. // The two passed in managed resources are a match between the one in
  5397. // the cluster and one on a node. If they both support the
  5398. // IClusCfgManagedResourceData interface then the private data from
  5399. // the resource in the cluster will be handed to the resource on the
  5400. // node.
  5401. //
  5402. // Arguments:
  5403. // pccmriClusterIn
  5404. // The mananged resource in the cluster.
  5405. //
  5406. // pccmriNodeIn
  5407. // The managed resource from the node.
  5408. //
  5409. // Return Value:
  5410. // S_OK
  5411. // Success.
  5412. //
  5413. // Other HRESULT error.
  5414. //
  5415. // Remarks:
  5416. // This function will return S_OK unless there is a good reason to stop
  5417. // the caller from continuing. Just because one, or both, of these
  5418. // objects does not support the IClusCfgManagedResourceData interface
  5419. // is not a good reason to stop.
  5420. //
  5421. //--
  5422. //////////////////////////////////////////////////////////////////////////////
  5423. HRESULT
  5424. CTaskAnalyzeClusterBase::HrResourcePrivateDataExchange(
  5425. IClusCfgManagedResourceInfo * pccmriClusterIn
  5426. , IClusCfgManagedResourceInfo * pccmriNodeIn
  5427. )
  5428. {
  5429. TraceFunc( "" );
  5430. Assert( pccmriClusterIn != NULL );
  5431. Assert( pccmriNodeIn != NULL );
  5432. HRESULT hr = S_OK;
  5433. HRESULT hrClusterQI = S_OK;
  5434. HRESULT hrNodeQI = S_OK;
  5435. IClusCfgManagedResourceData * pccmrdCluster = NULL;
  5436. IClusCfgManagedResourceData * pccmrdNode = NULL;
  5437. BYTE * pbPrivateData = NULL;
  5438. DWORD cbPrivateData = 0;
  5439. hrClusterQI = pccmriClusterIn->TypeSafeQI( IClusCfgManagedResourceData, &pccmrdCluster );
  5440. if ( hrClusterQI == E_NOINTERFACE )
  5441. {
  5442. LogMsg( L"[MT] The cluster managed resource has no support for IClusCfgManagedResourceData." );
  5443. goto Cleanup;
  5444. } // if:
  5445. else if ( FAILED( hrClusterQI ) )
  5446. {
  5447. hr = THR( hrClusterQI );
  5448. SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_HrResourcePrivateDataExchange_ClusterResource_QI, hr );
  5449. goto Cleanup;
  5450. } // if:
  5451. hrNodeQI = pccmriNodeIn->TypeSafeQI( IClusCfgManagedResourceData, &pccmrdNode );
  5452. if ( hrNodeQI == E_NOINTERFACE )
  5453. {
  5454. LogMsg( L"[MT] The new node resource has no support for IClusCfgManagedResourceData." );
  5455. goto Cleanup;
  5456. } // if:
  5457. else if ( FAILED( hrNodeQI ) )
  5458. {
  5459. hr = THR( hrNodeQI );
  5460. SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_HrResourcePrivateDataExchange_NodeResource_QI, hr );
  5461. goto Cleanup;
  5462. } // if:
  5463. Assert( ( hrClusterQI == S_OK ) && ( pccmrdCluster != NULL ) );
  5464. Assert( ( hrNodeQI == S_OK ) && ( pccmrdNode != NULL ) );
  5465. cbPrivateData = 512; // start with a reasonable amout
  5466. pbPrivateData = (BYTE *) TraceAlloc( 0, cbPrivateData );
  5467. if ( pbPrivateData == NULL )
  5468. {
  5469. hr = THR( E_OUTOFMEMORY );
  5470. SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_HrResourcePrivateDataExchange_Out_Of_Memory1, hr );
  5471. goto Cleanup;
  5472. } // if:
  5473. hr = pccmrdCluster->GetResourcePrivateData( pbPrivateData, &cbPrivateData );
  5474. if ( hr == HR_RPC_INSUFFICIENT_BUFFER )
  5475. {
  5476. TraceFree( pbPrivateData );
  5477. pbPrivateData = NULL;
  5478. pbPrivateData = (BYTE *) TraceAlloc( 0, cbPrivateData );
  5479. if ( pbPrivateData == NULL )
  5480. {
  5481. hr = THR( E_OUTOFMEMORY );
  5482. SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_HrResourcePrivateDataExchange_Out_Of_Memory2, hr );
  5483. goto Cleanup;
  5484. } // if:
  5485. hr = pccmrdCluster->GetResourcePrivateData( pbPrivateData, &cbPrivateData );
  5486. } // if:
  5487. if ( hr == S_OK )
  5488. {
  5489. hr = THR( pccmrdNode->SetResourcePrivateData( pbPrivateData, cbPrivateData ) );
  5490. if ( FAILED( hr ) )
  5491. {
  5492. SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_HrResourcePrivateDataExchange_SetResourcePrivateData, hr );
  5493. goto Cleanup;
  5494. } // if:
  5495. } // if:
  5496. else if ( hr == S_FALSE )
  5497. {
  5498. hr = S_OK;
  5499. } // else if:
  5500. else
  5501. {
  5502. THR( hr );
  5503. SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_HrResourcePrivateDataExchange_GetResourcePrivateData, hr );
  5504. goto Cleanup;
  5505. } // if:
  5506. Cleanup:
  5507. if ( pccmrdCluster != NULL )
  5508. {
  5509. pccmrdCluster->Release();
  5510. } // if:
  5511. if ( pccmrdNode != NULL )
  5512. {
  5513. pccmrdNode->Release();
  5514. } // if:
  5515. TraceFree( pbPrivateData );
  5516. HRETURN( hr );
  5517. } //*** CTaskAnalyzeClusterBase::HrResourcePrivateDataExchange
  5518. //////////////////////////////////////////////////////////////////////////////
  5519. //++
  5520. //
  5521. // CTaskAnalyzeClusterBase::HrCheckQuorumCapabilities
  5522. //
  5523. // Description:
  5524. // Call through the CManagedResource proxy object to the server side
  5525. // object and ensure that it can indeed host the quorum resource.
  5526. //
  5527. // Arguments:
  5528. // pccmriNodeResourceIn
  5529. // The managed resource from the node.
  5530. //
  5531. // cookieNodeIn
  5532. // The cookie for the node that the passed in resource belongs to.
  5533. //
  5534. // Return Value:
  5535. // S_OK
  5536. // Success.
  5537. //
  5538. // Other HRESULT error.
  5539. //
  5540. // Remarks:
  5541. // This function will return S_OK unless there is a good reason to stop
  5542. // the caller from continuing.
  5543. //
  5544. //--
  5545. //////////////////////////////////////////////////////////////////////////////
  5546. HRESULT
  5547. CTaskAnalyzeClusterBase::HrCheckQuorumCapabilities(
  5548. IClusCfgManagedResourceInfo * pccmriNodeResourceIn
  5549. , OBJECTCOOKIE cookieNodeIn
  5550. )
  5551. {
  5552. TraceFunc( "" );
  5553. Assert( pccmriNodeResourceIn != NULL );
  5554. HRESULT hr = S_OK;
  5555. IClusCfgVerifyQuorum * piccvq = NULL;
  5556. IClusCfgNodeInfo * pcni = NULL;
  5557. //
  5558. // Get a node info object for the passed in node cookie.
  5559. //
  5560. hr = THR( m_pom->GetObject( DFGUID_NodeInformation, cookieNodeIn, reinterpret_cast< IUnknown ** >( &pcni ) ) );
  5561. if ( FAILED( hr ) )
  5562. {
  5563. goto Cleanup;
  5564. } // if:
  5565. Assert( pcni != NULL );
  5566. //
  5567. // If this node is already a member of the cluster, or an error occurs,
  5568. // then we should not call PrepareToHostQuorum() on that node.
  5569. //
  5570. hr = STHR( pcni->IsMemberOfCluster() );
  5571. if ( hr != S_FALSE )
  5572. {
  5573. BSTR bstr = NULL;
  5574. THR( pcni->GetName( &bstr ) );
  5575. if ( hr == S_OK )
  5576. {
  5577. LogMsg( L"[MT] Skipping quorum capabilities check for node \"%ws\" because the node is already clustered.", bstr != NULL ? bstr : L"<unknown>" );
  5578. } // if:
  5579. else
  5580. {
  5581. LogMsg( L"[MT] Skipping quorum capabilities check for node \"%ws\". (hr = %#08x)", bstr != NULL ? bstr : L"<unknown>", hr );
  5582. } // else:
  5583. SysFreeString( bstr ); // do not make TraceSysFreeString because it hasn't been tracked!!
  5584. goto Cleanup;
  5585. } // if:
  5586. hr = pccmriNodeResourceIn->TypeSafeQI( IClusCfgVerifyQuorum, &piccvq );
  5587. if ( hr == E_NOINTERFACE )
  5588. {
  5589. hr = S_OK;
  5590. goto Cleanup;
  5591. } // if:
  5592. else if ( FAILED( hr ) )
  5593. {
  5594. SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_HrCheckQuorumCapabilities_QI, hr );
  5595. goto Cleanup;
  5596. } // else if:
  5597. Assert( (hr == S_OK ) && ( piccvq != NULL ) );
  5598. hr = THR( HrAddResurceToCleanupList( piccvq ) );
  5599. if ( FAILED( hr ) )
  5600. {
  5601. SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_HrCheckQuorumCapabilities_HrAddResurceToCleanupList, hr );
  5602. goto Cleanup;
  5603. } // if:
  5604. hr = STHR( piccvq->PrepareToHostQuorumResource() );
  5605. if ( FAILED( hr ) )
  5606. {
  5607. SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_HrCheckQuorumCapabilities_PrepareToHostQuorumResource, hr );
  5608. goto Cleanup;
  5609. } // if:
  5610. Cleanup:
  5611. if ( pcni != NULL )
  5612. {
  5613. pcni->Release();
  5614. } // if:
  5615. if ( piccvq != NULL )
  5616. {
  5617. piccvq->Release();
  5618. } // if:
  5619. HRETURN( hr );
  5620. } //*** CTaskAnalyzeClusterBase::HrCheckQuorumCapabilities
  5621. //////////////////////////////////////////////////////////////////////////////
  5622. //++
  5623. //
  5624. // CTaskAnalyzeClusterBase::HrCleanupTask
  5625. //
  5626. // Description:
  5627. // Call through the CManagedResource proxy objects to the server side
  5628. // objects and give them a chance to cleanup anything they might need
  5629. // to.
  5630. //
  5631. // Arguments:
  5632. // hrCompletionStatusIn
  5633. // The completion status of this task.
  5634. //
  5635. // Return Value:
  5636. // S_OK
  5637. // Success.
  5638. //
  5639. // Other HRESULT error.
  5640. //
  5641. //--
  5642. //////////////////////////////////////////////////////////////////////////////
  5643. HRESULT
  5644. CTaskAnalyzeClusterBase::HrCleanupTask(
  5645. HRESULT hrCompletionStatusIn
  5646. )
  5647. {
  5648. TraceFunc( "" );
  5649. HRESULT hr = S_OK;
  5650. ULONG idx;
  5651. EClusCfgCleanupReason ecccr = crSUCCESS;
  5652. //
  5653. // Figure out what the cleanup reason should be.
  5654. //
  5655. if ( hrCompletionStatusIn == E_ABORT )
  5656. {
  5657. ecccr = crCANCELLED;
  5658. } // if:
  5659. else if ( FAILED( hrCompletionStatusIn ) )
  5660. {
  5661. ecccr = crERROR;
  5662. } // else if:
  5663. for ( idx = 0; idx < m_idxQuorumToCleanupNext; idx++ )
  5664. {
  5665. hr = STHR( ((*m_prgQuorumsToCleanup)[ idx ])->Cleanup( ecccr ) );
  5666. if ( FAILED( hr ) )
  5667. {
  5668. SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_HrCleanupTask_Cleanup, hr );
  5669. } // if:
  5670. } // for:
  5671. HRETURN( hr );
  5672. } //*** CTaskAnalyzeClusterBase::HrCleanupTask
  5673. //////////////////////////////////////////////////////////////////////////////
  5674. //++
  5675. //
  5676. // CTaskAnalyzeClusterBase::HrAddResurceToCleanupList
  5677. //
  5678. // Description:
  5679. // Add the passed in object to the side list of objects that need
  5680. // to be called for cleanup when the task exits.
  5681. //
  5682. // Arguments:
  5683. // piccvqIn
  5684. // The object to add to the list.
  5685. //
  5686. // Return Value:
  5687. // S_OK
  5688. // Success.
  5689. //
  5690. // Other HRESULT error.
  5691. //
  5692. //--
  5693. //////////////////////////////////////////////////////////////////////////////
  5694. HRESULT
  5695. CTaskAnalyzeClusterBase::HrAddResurceToCleanupList(
  5696. IClusCfgVerifyQuorum * piccvqIn
  5697. )
  5698. {
  5699. TraceFunc( "" );
  5700. Assert( piccvqIn != NULL );
  5701. HRESULT hr = S_OK;
  5702. IClusCfgVerifyQuorum * ((*prgTemp)[]) = NULL;
  5703. prgTemp = (IClusCfgVerifyQuorum *((*)[])) TraceReAlloc(
  5704. m_prgQuorumsToCleanup
  5705. , sizeof( IClusCfgVerifyQuorum * ) * ( m_idxQuorumToCleanupNext + 1 )
  5706. , HEAP_ZERO_MEMORY
  5707. );
  5708. if ( prgTemp == NULL )
  5709. {
  5710. hr = THR( E_OUTOFMEMORY );
  5711. SSR_ANALYSIS_FAILED( TASKID_Major_Find_Devices, TASKID_Minor_HrAddResurceToCleanupList_Memory, hr );
  5712. goto Cleanup;
  5713. } // if:
  5714. m_prgQuorumsToCleanup = prgTemp;
  5715. (*m_prgQuorumsToCleanup)[ m_idxQuorumToCleanupNext++ ] = piccvqIn;
  5716. piccvqIn->AddRef();
  5717. Cleanup:
  5718. HRETURN( hr );
  5719. } //*** CTaskAnalyzeClusterBase::HrAddResurceToCleanupList
  5720. //////////////////////////////////////////////////////////////////////////////
  5721. //++
  5722. //
  5723. // CTaskAnalyzeClusterBase::HrCheckPlatformInteroperability
  5724. //
  5725. // Description:
  5726. // Check each node's platform specs, processor architecture against
  5727. // the cluster's plaform specs.
  5728. //
  5729. // Arguments:
  5730. // None.
  5731. //
  5732. // Return Value:
  5733. // S_OK
  5734. // Success.
  5735. //
  5736. // Other HRESULT error.
  5737. //
  5738. //--
  5739. //////////////////////////////////////////////////////////////////////////////
  5740. HRESULT
  5741. CTaskAnalyzeClusterBase::HrCheckPlatformInteroperability( void )
  5742. {
  5743. TraceFunc( "" );
  5744. HRESULT hr = S_OK;
  5745. DWORD cookieClusterNode;
  5746. DWORD cookieNode;
  5747. IEnumCookies * pecNodes = NULL;
  5748. IUnknown * punk = NULL;
  5749. IClusCfgNodeInfo * piccni = NULL;
  5750. WORD wClusterProcArch;
  5751. WORD wNodeProcArch;
  5752. WORD wClusterProcLevel;
  5753. WORD wNodeProcLevel;
  5754. BSTR bstrNodeName = NULL;
  5755. ULONG celtDummy;
  5756. BSTR bstrDescription = NULL;
  5757. BSTR bstrReference = NULL;
  5758. hr = THR( HrSendStatusReport(
  5759. m_bstrClusterName
  5760. , TASKID_Major_Check_Cluster_Feasibility
  5761. , TASKID_Minor_Check_processor_Architecture
  5762. , 0
  5763. , 1
  5764. , 0
  5765. , hr
  5766. , IDS_TASKID_MINOR_CHECK_PROCESSOR_ARCHITECTURE
  5767. ) );
  5768. if ( FAILED( hr ) )
  5769. {
  5770. goto Cleanup;
  5771. } // if:
  5772. //
  5773. // Get a node that is already in the cluster.
  5774. //
  5775. hr = THR( HrGetAClusterNodeCookie( &pecNodes, &cookieClusterNode ) );
  5776. if ( FAILED( hr ) )
  5777. {
  5778. goto Cleanup;
  5779. } // if:
  5780. //
  5781. // Retrieve the node information.
  5782. //
  5783. hr = THR( m_pom->GetObject( DFGUID_NodeInformation, cookieClusterNode, &punk ) );
  5784. if ( FAILED( hr ) )
  5785. {
  5786. SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_CheckPlatformInteroperability_NodeInfo_FindObject, hr );
  5787. goto Cleanup;
  5788. } // if:
  5789. hr = THR( punk->TypeSafeQI( IClusCfgNodeInfo, &piccni ) );
  5790. if ( FAILED( hr ) )
  5791. {
  5792. SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_CheckPlatformInteroperability_NodeInfo_FindObject_QI, hr );
  5793. goto Cleanup;
  5794. } // if:
  5795. piccni = TraceInterface( L"CTaskAnalyzeClusterBase!HrCheckPlatformInteroperability", IClusCfgNodeInfo, piccni, 1 );
  5796. punk->Release();
  5797. punk = NULL;
  5798. //
  5799. // Now get that node's processor architecture values.
  5800. //
  5801. hr = THR( piccni->GetProcessorInfo( &wClusterProcArch, &wClusterProcLevel ) );
  5802. if ( FAILED( hr ) )
  5803. {
  5804. SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_CheckPlatformInteroperability_Get_Proc_info, hr );
  5805. goto Cleanup;
  5806. } // if:
  5807. //
  5808. // Cleanup since we now have the processor info for the cluster.
  5809. //
  5810. piccni->Release();
  5811. piccni = NULL;
  5812. hr = THR( pecNodes->Reset() );
  5813. if ( FAILED( hr ) )
  5814. {
  5815. SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_CheckPlatformInteroperability_Enum_Reset, hr );
  5816. goto Cleanup;
  5817. } // if:
  5818. //
  5819. // Loop thru the rest of the nodes comparing the resources.
  5820. //
  5821. for ( ; m_fStop == FALSE; )
  5822. {
  5823. //
  5824. // Cleanup
  5825. //
  5826. TraceSysFreeString( bstrNodeName );
  5827. bstrNodeName = NULL;
  5828. if ( piccni != NULL )
  5829. {
  5830. piccni->Release();
  5831. piccni = NULL;
  5832. } // if:
  5833. //
  5834. // Get the next node.
  5835. //
  5836. hr = STHR( pecNodes->Next( 1, &cookieNode, &celtDummy ) );
  5837. if ( FAILED( hr ) )
  5838. {
  5839. SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_CheckPlatformInteroperability_Enum_Nodes_Next, hr );
  5840. goto Cleanup;
  5841. } // if:
  5842. if ( hr == S_FALSE )
  5843. {
  5844. hr = S_OK;
  5845. break; // exit condition
  5846. } // if:
  5847. //
  5848. // Skip the selected cluster node since we already have its
  5849. // configuration.
  5850. //
  5851. if ( cookieClusterNode == cookieNode )
  5852. {
  5853. continue;
  5854. } // if:
  5855. //
  5856. // Retrieve the node's name for error messages.
  5857. //
  5858. hr = THR( HrRetrieveCookiesName( m_pom, cookieNode, &bstrNodeName ) );
  5859. if ( FAILED( hr ) )
  5860. {
  5861. goto Cleanup;
  5862. } // if:
  5863. //
  5864. // Retrieve the node information.
  5865. //
  5866. hr = THR( m_pom->GetObject( DFGUID_NodeInformation, cookieNode, &punk ) );
  5867. if ( FAILED( hr ) )
  5868. {
  5869. SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_CheckPlatformInteroperability_NodeInfo_FindObject_1, hr );
  5870. goto Cleanup;
  5871. } // if:
  5872. hr = THR( punk->TypeSafeQI( IClusCfgNodeInfo, &piccni ) );
  5873. if ( FAILED( hr ) )
  5874. {
  5875. SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_CheckPlatformInteroperability_NodeInfo_FindObject_QI_1, hr );
  5876. goto Cleanup;
  5877. } // if:
  5878. piccni = TraceInterface( L"CTaskAnalyzeClusterBase!HrCheckPlatformInteroperability", IClusCfgNodeInfo, piccni, 1 );
  5879. punk->Release();
  5880. punk = NULL;
  5881. hr = THR( piccni->GetProcessorInfo( &wNodeProcArch, &wNodeProcLevel ) );
  5882. if ( FAILED( hr ) )
  5883. {
  5884. SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_CheckPlatformInteroperability_Get_Proc_info_1, hr );
  5885. goto Cleanup;
  5886. } // if:
  5887. //
  5888. // If either the processor architecture is not the same between the node and the cluster
  5889. // then inform the user and fail.
  5890. //
  5891. if ( wClusterProcArch != wNodeProcArch )
  5892. {
  5893. THR( HrFormatStringIntoBSTR(
  5894. g_hInstance
  5895. , IDS_TASKID_MINOR_PROCESSOR_ARCHITECTURE_MISMATCH
  5896. , &bstrDescription
  5897. , bstrNodeName
  5898. ) );
  5899. THR( HrFormatProcessorArchitectureRef( wClusterProcArch, wNodeProcArch, bstrNodeName, &bstrReference ) );
  5900. hr = HRESULT_FROM_WIN32( TW32( ERROR_NODE_CANNOT_BE_CLUSTERED ) );
  5901. THR( SendStatusReport(
  5902. m_bstrClusterName
  5903. , TASKID_Minor_Check_processor_Architecture
  5904. , TASKID_Minor_Processor_Architecture_Mismatch
  5905. , 1
  5906. , 1
  5907. , 1
  5908. , hr
  5909. , bstrDescription != NULL ? bstrDescription : L"A node was found that was not the same processor architecture as the cluster."
  5910. , NULL
  5911. , bstrReference
  5912. ) );
  5913. goto Cleanup;
  5914. } // if:
  5915. } // for:
  5916. Cleanup:
  5917. THR( HrSendStatusReport(
  5918. m_bstrClusterName
  5919. , TASKID_Major_Check_Cluster_Feasibility
  5920. , TASKID_Minor_Check_processor_Architecture
  5921. , 0
  5922. , 1
  5923. , 1
  5924. , hr
  5925. , IDS_TASKID_MINOR_CHECK_PROCESSOR_ARCHITECTURE
  5926. ) );
  5927. if ( punk != NULL )
  5928. {
  5929. punk->Release();
  5930. } // if:
  5931. if ( piccni != NULL )
  5932. {
  5933. piccni->Release();
  5934. } // if:
  5935. if ( pecNodes != NULL )
  5936. {
  5937. pecNodes->Release();
  5938. } // if :
  5939. TraceSysFreeString( bstrNodeName );
  5940. TraceSysFreeString( bstrDescription );
  5941. TraceSysFreeString( bstrReference );
  5942. HRETURN( hr );
  5943. } //*** CTaskAnalyzeClusterBase::HrCheckPlatformInteroperability
  5944. //////////////////////////////////////////////////////////////////////////////
  5945. //++
  5946. //
  5947. // CTaskAnalyzeClusterBase::HrGetAClusterNodeCookie
  5948. //
  5949. // Description:
  5950. // Check each node's platform specs, processor architecture against
  5951. // the cluster's plaform specs.
  5952. //
  5953. // Arguments:
  5954. // None.
  5955. //
  5956. // Return Value:
  5957. // S_OK
  5958. // Success.
  5959. //
  5960. // Other HRESULT error.
  5961. //
  5962. //--
  5963. //////////////////////////////////////////////////////////////////////////////
  5964. HRESULT
  5965. CTaskAnalyzeClusterBase::HrGetAClusterNodeCookie(
  5966. IEnumCookies ** ppecNodesOut
  5967. , DWORD * pdwClusterNodeCookieOut
  5968. )
  5969. {
  5970. TraceFunc( "" );
  5971. Assert( ppecNodesOut != NULL );
  5972. Assert( pdwClusterNodeCookieOut != NULL );
  5973. HRESULT hr = S_OK;
  5974. DWORD cookieDummy;
  5975. DWORD cookieClusterNode;
  5976. ULONG celtDummy;
  5977. IUnknown * punk = NULL;
  5978. IClusCfgNodeInfo * pccni = NULL;
  5979. //
  5980. // Get the node cookie enumerator.
  5981. //
  5982. hr = THR( m_pom->FindObject( CLSID_NodeType, m_cookieCluster, NULL, DFGUID_EnumCookies, &cookieDummy, &punk ) );
  5983. if ( FAILED( hr ) )
  5984. {
  5985. SSR_ANALYSIS_FAILED( TASKID_Major_Find_Devices, TASKID_Minor_GetAClusterNodeCookie_Find_Object, hr );
  5986. goto Cleanup;
  5987. }
  5988. hr = THR( punk->TypeSafeQI( IEnumCookies, ppecNodesOut ) );
  5989. if ( FAILED( hr ) )
  5990. {
  5991. SSR_ANALYSIS_FAILED( TASKID_Major_Find_Devices, TASKID_Minor_GetAClusterNodeCookie_Find_Object_QI, hr );
  5992. goto Cleanup;
  5993. }
  5994. *ppecNodesOut = TraceInterface( L"CTaskAnalyzeClusterBase!IEnumCookies", IEnumCookies, *ppecNodesOut, 1 );
  5995. punk->Release();
  5996. punk = NULL;
  5997. //
  5998. // If creating a cluster, it doesn't matter who we pick to prime the cluster configuration
  5999. //
  6000. if ( m_fJoiningMode == FALSE )
  6001. {
  6002. //
  6003. // The first guy thru, we just copy his resources under the cluster
  6004. // configuration.
  6005. //
  6006. hr = THR( (*ppecNodesOut)->Next( 1, &cookieClusterNode, &celtDummy ) );
  6007. if ( FAILED( hr ) )
  6008. {
  6009. SSR_ANALYSIS_FAILED( TASKID_Major_Find_Devices, TASKID_Minor_GetAClusterNodeCookie_Next, hr );
  6010. goto Cleanup;
  6011. }
  6012. } // if: not adding
  6013. else
  6014. {
  6015. //
  6016. // We are adding nodes to the cluster. Find a node that is ta member
  6017. // of the cluster and use it to prime the new configuration.
  6018. //
  6019. for ( ;; )
  6020. {
  6021. //
  6022. // Cleanup
  6023. //
  6024. if ( pccni != NULL )
  6025. {
  6026. pccni->Release();
  6027. pccni = NULL;
  6028. }
  6029. hr = STHR( (*ppecNodesOut)->Next( 1, &cookieClusterNode, &celtDummy ) );
  6030. if ( hr == S_FALSE )
  6031. {
  6032. //
  6033. // We shouldn't make it here. There should be at least one node
  6034. // in the cluster that we are adding.
  6035. //
  6036. hr = THR( HRESULT_FROM_WIN32( ERROR_NOT_FOUND ) );
  6037. SSR_ANALYSIS_FAILED( TASKID_Major_Find_Devices, TASKID_Minor_GetAClusterNodeCookie_Find_Formed_Node_Next, hr );
  6038. goto Cleanup;
  6039. }
  6040. if ( FAILED( hr ) )
  6041. {
  6042. SSR_ANALYSIS_FAILED( TASKID_Major_Find_Devices, TASKID_Minor_GetAClusterNodeCookie_Find_Formed_Node_Next1, hr );
  6043. goto Cleanup;
  6044. }
  6045. //
  6046. // Retrieve the node information.
  6047. //
  6048. hr = THR( m_pom->GetObject( DFGUID_NodeInformation, cookieClusterNode, &punk ) );
  6049. if ( FAILED( hr ) )
  6050. {
  6051. SSR_ANALYSIS_FAILED( TASKID_Major_Find_Devices, TASKID_Minor_CompareResources_NodeInfo_FindObject, hr );
  6052. goto Cleanup;
  6053. }
  6054. hr = THR( punk->TypeSafeQI( IClusCfgNodeInfo, &pccni ) );
  6055. if ( FAILED( hr ) )
  6056. {
  6057. SSR_ANALYSIS_FAILED( TASKID_Major_Find_Devices, TASKID_Minor_CompareResources_NodeInfo_FindObject_QI, hr );
  6058. goto Cleanup;
  6059. }
  6060. pccni = TraceInterface( L"CTaskAnalyzeClusterBase!IClusCfgNodeInfo", IClusCfgNodeInfo, pccni, 1 );
  6061. punk->Release();
  6062. punk = NULL;
  6063. hr = STHR( pccni->IsMemberOfCluster() );
  6064. if ( hr == S_OK )
  6065. {
  6066. break; // exit condition
  6067. }
  6068. } // for: ever
  6069. } // else: adding
  6070. *pdwClusterNodeCookieOut = cookieClusterNode;
  6071. hr = S_OK;
  6072. Cleanup:
  6073. if ( punk != NULL )
  6074. {
  6075. punk->Release();
  6076. } // if:
  6077. if ( pccni != NULL )
  6078. {
  6079. pccni->Release();
  6080. } // if:
  6081. HRETURN( hr );
  6082. } //*** CTaskAnalyzeClusterBase::HrGetAClusterNodeCookie
  6083. //////////////////////////////////////////////////////////////////////////////
  6084. //++
  6085. //
  6086. // CTaskAnalyzeClusterBase::HrFormatProcessorArchitectureRef(
  6087. //
  6088. // Description:
  6089. // Format a reference string with the processor architecture types in
  6090. // it.
  6091. //
  6092. // Arguments:
  6093. // wClusterProcArchIn
  6094. // wNodeProcArchIn
  6095. // pcszNodeNameIn
  6096. // pbstrReferenceOut
  6097. //
  6098. // Return Value:
  6099. // S_OK
  6100. // Success.
  6101. //
  6102. // Other HRESULT error.
  6103. //
  6104. //--
  6105. //////////////////////////////////////////////////////////////////////////////
  6106. HRESULT
  6107. CTaskAnalyzeClusterBase::HrFormatProcessorArchitectureRef(
  6108. WORD wClusterProcArchIn
  6109. , WORD wNodeProcArchIn
  6110. , LPCWSTR pcszNodeNameIn
  6111. , BSTR * pbstrReferenceOut
  6112. )
  6113. {
  6114. TraceFunc( "" );
  6115. Assert( pcszNodeNameIn != NULL );
  6116. Assert( pbstrReferenceOut != NULL );
  6117. HRESULT hr = S_OK;
  6118. BSTR bstrClusterArch = NULL;
  6119. BSTR bstrNodeArch = NULL;
  6120. hr = THR( HrGetProcessorArchitectureString( wClusterProcArchIn, &bstrClusterArch ) );
  6121. if ( FAILED( hr ) )
  6122. {
  6123. goto Cleanup;
  6124. } // if:
  6125. hr = THR( HrGetProcessorArchitectureString( wNodeProcArchIn, &bstrNodeArch ) );
  6126. if ( FAILED( hr ) )
  6127. {
  6128. goto Cleanup;
  6129. } // if:
  6130. hr = THR( HrFormatStringIntoBSTR(
  6131. g_hInstance
  6132. , IDS_TASKID_MINOR_PROCESSOR_ARCHITECTURE_MISMATCH_REF
  6133. , pbstrReferenceOut
  6134. , bstrClusterArch
  6135. , bstrNodeArch
  6136. , pcszNodeNameIn
  6137. ) );
  6138. Cleanup:
  6139. TraceSysFreeString( bstrClusterArch );
  6140. TraceSysFreeString( bstrNodeArch );
  6141. HRETURN( hr );
  6142. } //*** CTaskAnalyzeClusterBase::HrFormatProcessorArchitectureRef
  6143. //////////////////////////////////////////////////////////////////////////////
  6144. //++
  6145. //
  6146. // CTaskAnalyzeClusterBase::HrGetProcessorArchitectureString
  6147. //
  6148. // Description:
  6149. // Get the description string for the passed in architecture.
  6150. // it.
  6151. //
  6152. // Arguments:
  6153. // wProcessorArchitectureIn
  6154. //
  6155. // pbstrProcessorArchitectureOut
  6156. //
  6157. // Return Value:
  6158. // S_OK
  6159. // Success.
  6160. //
  6161. // Other HRESULT error.
  6162. //
  6163. //--
  6164. //////////////////////////////////////////////////////////////////////////////
  6165. HRESULT
  6166. CTaskAnalyzeClusterBase::HrGetProcessorArchitectureString(
  6167. WORD wProcessorArchitectureIn
  6168. , BSTR * pbstrProcessorArchitectureOut
  6169. )
  6170. {
  6171. TraceFunc( "" );
  6172. Assert( pbstrProcessorArchitectureOut != NULL );
  6173. HRESULT hr = S_OK;
  6174. int id;
  6175. switch ( wProcessorArchitectureIn )
  6176. {
  6177. case PROCESSOR_ARCHITECTURE_INTEL :
  6178. id = IDS_PROCESSOR_ARCHITECTURE_INTEL;
  6179. break;
  6180. case PROCESSOR_ARCHITECTURE_IA64 :
  6181. id = IDS_PROCESSOR_ARCHITECTURE_IA64;
  6182. break;
  6183. case PROCESSOR_ARCHITECTURE_AMD64 :
  6184. id = IDS_PROCESSOR_ARCHITECTURE_AMD64;
  6185. break;
  6186. case PROCESSOR_ARCHITECTURE_UNKNOWN :
  6187. default:
  6188. id = IDS_PROCESSOR_ARCHITECTURE_UNKNOWN;
  6189. break;
  6190. } // switch:
  6191. hr = THR( HrLoadStringIntoBSTR( g_hInstance, id, pbstrProcessorArchitectureOut ) );
  6192. HRETURN( hr );
  6193. } //*** CTaskAnalyzeClusterBase::HrGetProcessorArchitectureString