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.

2301 lines
56 KiB

  1. //////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) 2000-2002 Microsoft Corporation
  4. //
  5. // Module Name:
  6. // TaskCommitClusterChanges.cpp
  7. //
  8. // Description:
  9. // CTaskCommitClusterChanges implementation.
  10. //
  11. // Maintained By:
  12. // Galen Barbee (GalenB) 02-FEB-2000
  13. //
  14. //////////////////////////////////////////////////////////////////////////////
  15. #include "Pch.h"
  16. #include "TaskCommitClusterChanges.h"
  17. DEFINE_THISCLASS("CTaskCommitClusterChanges")
  18. // ************************************************************************
  19. //
  20. // Constructor / Destructor
  21. //
  22. // ************************************************************************
  23. //////////////////////////////////////////////////////////////////////////////
  24. //
  25. // HRESULT
  26. // CTaskCommitClusterChanges::S_HrCreateInstance(
  27. // IUnknown ** ppunkOut
  28. // )
  29. //
  30. //////////////////////////////////////////////////////////////////////////////
  31. HRESULT
  32. CTaskCommitClusterChanges::S_HrCreateInstance(
  33. IUnknown ** ppunkOut
  34. )
  35. {
  36. TraceFunc( "" );
  37. HRESULT hr = S_OK;
  38. CTaskCommitClusterChanges * ptccc = NULL;
  39. Assert( ppunkOut != NULL );
  40. if ( ppunkOut == NULL )
  41. {
  42. hr = THR( E_POINTER );
  43. goto Cleanup;
  44. }
  45. ptccc = new CTaskCommitClusterChanges;
  46. if ( ptccc == NULL )
  47. {
  48. hr = THR( E_OUTOFMEMORY );
  49. goto Cleanup;
  50. }
  51. hr = THR( ptccc->HrInit() );
  52. if ( FAILED( hr ) )
  53. {
  54. goto Cleanup;
  55. }
  56. hr = THR( ptccc->TypeSafeQI( IUnknown, ppunkOut ) );
  57. if ( FAILED( hr ) )
  58. {
  59. goto Cleanup;
  60. }
  61. Cleanup:
  62. if ( ptccc != NULL )
  63. {
  64. ptccc->Release();
  65. }
  66. HRETURN( hr );
  67. } //*** CTaskCommitClusterChanges::S_HrCreateInstance
  68. //////////////////////////////////////////////////////////////////////////////
  69. //
  70. // CTaskCommitClusterChanges::CTaskCommitClusterChanges
  71. //
  72. //////////////////////////////////////////////////////////////////////////////
  73. CTaskCommitClusterChanges::CTaskCommitClusterChanges( void )
  74. : m_cRef( 1 )
  75. {
  76. TraceFunc( "" );
  77. InterlockedIncrement( &g_cObjects );
  78. TraceFuncExit();
  79. } //*** CTaskCommitClusterChanges::CTaskCommitClusterChanges
  80. //////////////////////////////////////////////////////////////////////////////
  81. //++
  82. //
  83. // CTaskCommitClusterChanges::HrInit
  84. //
  85. // Description:
  86. // Initialize the object.
  87. //
  88. // Arguments:
  89. // None.
  90. //
  91. // Return Values:
  92. // S_OK - Success.
  93. // Other HRESULTs.
  94. //
  95. //////////////////////////////////////////////////////////////////////////////
  96. STDMETHODIMP
  97. CTaskCommitClusterChanges::HrInit( void )
  98. {
  99. TraceFunc( "" );
  100. HRESULT hr = S_OK;
  101. // IUnknown stuff
  102. Assert( m_cRef == 1 );
  103. // IDoTask / ITaskCommitClusterChanges
  104. Assert( m_cookie == 0 );
  105. Assert( m_pcccb == NULL );
  106. Assert( m_pcookies == NULL );
  107. Assert( m_cNodes == 0 );
  108. Assert( m_event == NULL );
  109. Assert( m_cookieCluster == NULL );
  110. Assert( m_cookieFormingNode == NULL );
  111. Assert( m_punkFormingNode == NULL );
  112. Assert( m_bstrClusterName == NULL );
  113. Assert( m_bstrClusterBindingString == NULL );
  114. Assert( m_pccc == NULL );
  115. Assert( m_ulIPAddress == 0 );
  116. Assert( m_ulSubnetMask == 0 );
  117. Assert( m_bstrNetworkUID == 0 );
  118. Assert( m_fStop == FALSE );
  119. Assert( m_pen == NULL );
  120. Assert( m_pnui == NULL );
  121. Assert( m_pom == NULL );
  122. Assert( m_ptm == NULL );
  123. Assert( m_pcm == NULL );
  124. // INotifyUI
  125. Assert( m_cNodes == 0 );
  126. Assert( m_hrStatus == S_OK );
  127. hr = THR( HrCoCreateInternalInstance(
  128. CLSID_ClusCfgCredentials
  129. , NULL
  130. , CLSCTX_INPROC_SERVER
  131. , IID_IClusCfgCredentials
  132. , reinterpret_cast< void ** >( &m_pccc )
  133. ) );
  134. if ( FAILED( hr ) )
  135. {
  136. goto Cleanup;
  137. }
  138. hr = THR( HrGetComputerName(
  139. ComputerNameDnsHostname
  140. , &m_bstrNodeName
  141. , TRUE // fBestFitIn
  142. ) );
  143. if ( FAILED( hr ) )
  144. {
  145. goto Cleanup;
  146. }
  147. Cleanup:
  148. HRETURN( hr );
  149. } //*** CTaskCommitClusterChanges::HrInit
  150. //////////////////////////////////////////////////////////////////////////////
  151. //
  152. // CTaskCommitClusterChanges::~CTaskCommitClusterChanges
  153. //
  154. //////////////////////////////////////////////////////////////////////////////
  155. CTaskCommitClusterChanges::~CTaskCommitClusterChanges( void )
  156. {
  157. TraceFunc( "" );
  158. // m_cRef
  159. // m_cookie
  160. if ( m_pcccb != NULL )
  161. {
  162. m_pcccb->Release();
  163. }
  164. if ( m_pcookies != NULL )
  165. {
  166. TraceFree( m_pcookies );
  167. }
  168. // m_cNodes
  169. if ( m_event != NULL )
  170. {
  171. CloseHandle( m_event );
  172. }
  173. // m_cookieCluster
  174. // m_cookieFormingNode
  175. if ( m_punkFormingNode != NULL )
  176. {
  177. m_punkFormingNode->Release();
  178. }
  179. TraceSysFreeString( m_bstrClusterName );
  180. TraceSysFreeString( m_bstrClusterBindingString );
  181. // m_ulIPAddress
  182. // m_ulSubnetMask
  183. TraceSysFreeString( m_bstrNetworkUID );
  184. TraceSysFreeString( m_bstrNodeName );
  185. if ( m_pen != NULL )
  186. {
  187. m_pen->Release();
  188. }
  189. if ( m_pccc != NULL )
  190. {
  191. m_pccc->Release();
  192. }
  193. if ( m_pnui != NULL )
  194. {
  195. m_pnui->Release();
  196. }
  197. if ( m_pom != NULL )
  198. {
  199. m_pom->Release();
  200. }
  201. if ( m_ptm != NULL )
  202. {
  203. m_ptm->Release();
  204. }
  205. if ( m_pcm != NULL )
  206. {
  207. m_pcm->Release();
  208. }
  209. // m_cSubTasksDone
  210. // m_hrStatus
  211. // m_lLockCallback
  212. InterlockedDecrement( &g_cObjects );
  213. TraceFuncExit();
  214. } //*** CTaskCommitClusterChanges::~CTaskCommitClusterChanges
  215. // ************************************************************************
  216. //
  217. // IUnknown
  218. //
  219. // ************************************************************************
  220. //////////////////////////////////////////////////////////////////////////////
  221. //++
  222. //
  223. // CTaskCommitClusterChanges::QueryInterface
  224. //
  225. // Description:
  226. // Query this object for the passed in interface.
  227. //
  228. // Arguments:
  229. // riidIn
  230. // Id of interface requested.
  231. //
  232. // ppvOut
  233. // Pointer to the requested interface.
  234. //
  235. // Return Value:
  236. // S_OK
  237. // If the interface is available on this object.
  238. //
  239. // E_NOINTERFACE
  240. // If the interface is not available.
  241. //
  242. // E_POINTER
  243. // ppvOut was NULL.
  244. //
  245. // Remarks:
  246. // None.
  247. //
  248. //--
  249. //////////////////////////////////////////////////////////////////////////////
  250. STDMETHODIMP
  251. CTaskCommitClusterChanges::QueryInterface(
  252. REFIID riidIn
  253. , LPVOID * ppvOut
  254. )
  255. {
  256. TraceQIFunc( riidIn, ppvOut );
  257. HRESULT hr = S_OK;
  258. //
  259. // Validate arguments.
  260. //
  261. Assert( ppvOut != NULL );
  262. if ( ppvOut == NULL )
  263. {
  264. hr = THR( E_POINTER );
  265. goto Cleanup;
  266. }
  267. //
  268. // Handle known interfaces.
  269. //
  270. if ( IsEqualIID( riidIn, IID_IUnknown ) )
  271. {
  272. *ppvOut = static_cast< ITaskCommitClusterChanges * >( this );
  273. } // if: IUnknown
  274. else if ( IsEqualIID( riidIn, IID_ITaskCommitClusterChanges ) )
  275. {
  276. *ppvOut = TraceInterface( __THISCLASS__, ITaskCommitClusterChanges, this, 0 );
  277. } // else if: ITaskCommitClusterChanges
  278. else if ( IsEqualIID( riidIn, IID_IDoTask ) )
  279. {
  280. *ppvOut = TraceInterface( __THISCLASS__, IDoTask, this, 0 );
  281. } // else if: IDoTask
  282. else if ( IsEqualIID( riidIn, IID_INotifyUI ) )
  283. {
  284. *ppvOut = TraceInterface( __THISCLASS__, INotifyUI, this, 0 );
  285. } // else if: INotifyUI
  286. else if ( IsEqualIID( riidIn, IID_IClusCfgCallback ) )
  287. {
  288. *ppvOut = TraceInterface( __THISCLASS__, IClusCfgCallback, this, 0 );
  289. } // else if: IClusCfgCallback
  290. else
  291. {
  292. *ppvOut = NULL;
  293. hr = E_NOINTERFACE;
  294. }
  295. //
  296. // Add a reference to the interface if successful.
  297. //
  298. if ( SUCCEEDED( hr ) )
  299. {
  300. ((IUnknown *) *ppvOut)->AddRef();
  301. } // if: success
  302. Cleanup:
  303. QIRETURN_IGNORESTDMARSHALLING( hr, riidIn );
  304. } //*** CTaskCommitClusterChanges::QueryInterface
  305. //////////////////////////////////////////////////////////////////////////////
  306. //
  307. // STDMETHODIMP_(ULONG)
  308. // CTaskCommitClusterChanges::AddRef
  309. //
  310. //////////////////////////////////////////////////////////////////////////////
  311. STDMETHODIMP_( ULONG )
  312. CTaskCommitClusterChanges::AddRef( void )
  313. {
  314. TraceFunc( "[IUnknown]" );
  315. InterlockedIncrement( &m_cRef );
  316. CRETURN( m_cRef );
  317. } //*** CTaskCommitClusterChanges::AddRef
  318. //////////////////////////////////////////////////////////////////////////////
  319. //
  320. // STDMETHODIMP_(ULONG)
  321. // CTaskCommitClusterChanges::Release
  322. //
  323. //////////////////////////////////////////////////////////////////////////////
  324. STDMETHODIMP_( ULONG )
  325. CTaskCommitClusterChanges::Release( void )
  326. {
  327. TraceFunc( "[IUnknown]" );
  328. LONG cRef;
  329. cRef = InterlockedDecrement( &m_cRef );
  330. if ( cRef == 0 )
  331. {
  332. TraceDo( delete this );
  333. }
  334. CRETURN( cRef );
  335. } //*** CTaskCommitClusterChanges::Release
  336. // ************************************************************************
  337. //
  338. // IDoTask / ITaskCommitClusterChanges
  339. //
  340. // ************************************************************************
  341. //////////////////////////////////////////////////////////////////////////////
  342. //
  343. // STDMETHODIMP
  344. // CTaskCommitClusterChanges::BeginTask
  345. //
  346. //////////////////////////////////////////////////////////////////////////////
  347. STDMETHODIMP
  348. CTaskCommitClusterChanges::BeginTask( void )
  349. {
  350. TraceFunc( "[IDoTask]" );
  351. HRESULT hr;
  352. OBJECTCOOKIE cookieDummy;
  353. IServiceProvider * psp = NULL;
  354. IUnknown * punk = NULL;
  355. IConnectionPointContainer * pcpc = NULL;
  356. IConnectionPoint * pcp = NULL;
  357. TraceInitializeThread( L"TaskCommitClusterChanges" );
  358. LogMsg( L"[MT] [CTaskCommitClusterChanges] Beginning task..." );
  359. //
  360. // Gather the managers we need to complete the task.
  361. //
  362. hr = THR( CoCreateInstance( CLSID_ServiceManager,
  363. NULL,
  364. CLSCTX_INPROC_SERVER,
  365. TypeSafeParams( IServiceProvider, &psp )
  366. ) );
  367. if ( FAILED( hr ) )
  368. {
  369. goto Cleanup;
  370. }
  371. hr = THR( psp->TypeSafeQS( CLSID_NotificationManager, IConnectionPointContainer, &pcpc ) );
  372. if ( FAILED( hr ) )
  373. {
  374. goto Cleanup;
  375. }
  376. pcpc = TraceInterface( L"CTaskCommitClusterChanges!IConnectionPointContainer", IConnectionPointContainer, pcpc, 1 );
  377. hr = THR( pcpc->FindConnectionPoint( IID_INotifyUI, &pcp ) );
  378. if ( FAILED( hr ) )
  379. {
  380. goto Cleanup;
  381. }
  382. pcp = TraceInterface( L"CTaskCommitClusterChanges!IConnectionPoint", IConnectionPoint, pcp, 1 );
  383. hr = THR( pcp->TypeSafeQI( INotifyUI, &m_pnui ) );
  384. if ( FAILED( hr ) )
  385. {
  386. goto Cleanup;
  387. }
  388. // TraceMoveFromMemoryList( m_pnui, g_GlobalMemoryList );
  389. m_pnui = TraceInterface( L"CTaskCommitClusterChanges!INotifyUI", INotifyUI, m_pnui, 1 );
  390. hr = THR( psp->TypeSafeQS( CLSID_TaskManager, ITaskManager, &m_ptm ) );
  391. if ( FAILED( hr ) )
  392. {
  393. goto Cleanup;
  394. }
  395. hr = THR( psp->TypeSafeQS( CLSID_ObjectManager, IObjectManager, &m_pom ) );
  396. if ( FAILED( hr ) )
  397. {
  398. goto Cleanup;
  399. }
  400. hr = THR( psp->TypeSafeQS( CLSID_ClusterConnectionManager, IConnectionManager, &m_pcm ) );
  401. if ( FAILED( hr ) )
  402. {
  403. goto Cleanup;
  404. }
  405. //
  406. // Release the service manager.
  407. //
  408. psp->Release();
  409. psp = NULL;
  410. //
  411. // Get the enum of the nodes.
  412. //
  413. hr = THR( m_pom->FindObject( CLSID_NodeType,
  414. m_cookieCluster,
  415. NULL,
  416. DFGUID_EnumCookies,
  417. &cookieDummy,
  418. &punk
  419. ) );
  420. if ( FAILED( hr ) )
  421. {
  422. goto Cleanup;
  423. }
  424. Assert( m_pen == NULL );
  425. hr = THR( punk->TypeSafeQI( IEnumCookies, &m_pen ) );
  426. if ( FAILED( hr ) )
  427. {
  428. goto Cleanup;
  429. }
  430. //
  431. // Compare and push information to the nodes.
  432. //
  433. hr = THR( HrCompareAndPushInformationToNodes() );
  434. if ( FAILED( hr ) )
  435. {
  436. goto Cleanup;
  437. }
  438. //
  439. // Gather information about the cluster we are to form/join.
  440. //
  441. hr = THR( HrGatherClusterInformation() );
  442. if ( FAILED( hr ) )
  443. {
  444. goto Cleanup;
  445. }
  446. //
  447. // Check to see if we need to "form" a cluster first.
  448. //
  449. if ( m_punkFormingNode != NULL )
  450. {
  451. hr = THR( HrFormFirstNode() );
  452. if ( FAILED( hr ) )
  453. {
  454. goto Cleanup;
  455. }
  456. } // if: m_punkFormingNode
  457. //
  458. // Join the additional nodes.
  459. //
  460. hr = THR( HrAddJoiningNodes() );
  461. if ( FAILED( hr ) )
  462. {
  463. goto Cleanup;
  464. }
  465. Cleanup:
  466. if ( m_cookie != 0 )
  467. {
  468. if ( m_pom != NULL )
  469. {
  470. HRESULT hr2;
  471. IUnknown * punkTemp = NULL;
  472. hr2 = THR( m_pom->GetObject( DFGUID_StandardInfo,
  473. m_cookie,
  474. &punkTemp
  475. ) );
  476. if ( SUCCEEDED( hr2 ) )
  477. {
  478. IStandardInfo * psi;
  479. hr2 = THR( punkTemp->TypeSafeQI( IStandardInfo, &psi ) );
  480. punkTemp->Release();
  481. punkTemp = NULL;
  482. if ( SUCCEEDED( hr2 ) )
  483. {
  484. hr2 = THR( psi->SetStatus( hr ) );
  485. psi->Release();
  486. }
  487. } // if: ( SUCCEEDED( hr2 ) )
  488. } // if: ( m_pom != NULL )
  489. if ( m_pnui != NULL )
  490. {
  491. // Signal that the task completed.
  492. THR( m_pnui->ObjectChanged( m_cookie ) );
  493. }
  494. } // if: ( m_cookie != 0 )
  495. if ( punk != NULL )
  496. {
  497. punk->Release();
  498. }
  499. if ( psp != NULL )
  500. {
  501. psp->Release();
  502. }
  503. if ( pcpc != NULL )
  504. {
  505. pcpc->Release();
  506. }
  507. if ( pcp != NULL )
  508. {
  509. pcp->Release();
  510. }
  511. LogMsg( L"[MT] [CTaskCommitClusterChanges] Exiting task. The task was%ws cancelled. (hr = %#08x)", m_fStop == FALSE ? L" not" : L"", hr );
  512. HRETURN( hr );
  513. } //*** CTaskCommitClusterChanges::BeginTask
  514. //////////////////////////////////////////////////////////////////////////////
  515. //
  516. // STDMETHODIMP
  517. // CTaskCommitClusterChanges::StopTask
  518. //
  519. //////////////////////////////////////////////////////////////////////////////
  520. STDMETHODIMP
  521. CTaskCommitClusterChanges::StopTask( void )
  522. {
  523. TraceFunc( "[IDoTask]" );
  524. HRESULT hr = S_OK;
  525. m_fStop = TRUE;
  526. LogMsg( L"[MT] [CTaskCommitClusterChanges] Calling StopTask() on all remaining sub-tasks." );
  527. THR( HrNotifyAllTasksToStop() );
  528. HRETURN( hr );
  529. } //*** CTaskCommitClusterChanges::StopTask
  530. //////////////////////////////////////////////////////////////////////////////
  531. //
  532. // STDMETHODIMP
  533. // CTaskCommitClusterChanges::SetCookie(
  534. // OBJECTCOOKIE cookieIn
  535. // )
  536. //
  537. //////////////////////////////////////////////////////////////////////////////
  538. STDMETHODIMP
  539. CTaskCommitClusterChanges::SetCookie(
  540. OBJECTCOOKIE cookieIn
  541. )
  542. {
  543. TraceFunc( "[ITaskCommitClusterChanges]" );
  544. HRESULT hr = S_OK;
  545. m_cookie = cookieIn;
  546. HRETURN( hr );
  547. } //*** CTaskCommitClusterChanges::SetCookie
  548. //////////////////////////////////////////////////////////////////////////////
  549. //
  550. // STDMETHODIMP
  551. // CTaskCommitClusterChanges::SetClusterCookie(
  552. // OBJECTCOOKIE cookieClusterIn
  553. // )
  554. //
  555. //////////////////////////////////////////////////////////////////////////////
  556. STDMETHODIMP
  557. CTaskCommitClusterChanges::SetClusterCookie(
  558. OBJECTCOOKIE cookieClusterIn
  559. )
  560. {
  561. TraceFunc( "[ITaskCommitClusterChanges]" );
  562. HRESULT hr = S_OK;
  563. m_cookieCluster = cookieClusterIn;
  564. HRETURN( hr );
  565. } //*** CTaskCommitClusterChanges::SetClusterCookie
  566. //////////////////////////////////////////////////////////////////////////////
  567. //
  568. // STDMETHODIMP
  569. // CTaskCommitClusterChanges::SetJoining
  570. //
  571. //////////////////////////////////////////////////////////////////////////////
  572. STDMETHODIMP
  573. CTaskCommitClusterChanges::SetJoining( void )
  574. {
  575. TraceFunc( "[ITaskCommitClusterChanges]" );
  576. HRESULT hr = S_OK;
  577. m_fJoining = TRUE;
  578. HRETURN( hr );
  579. } //*** CTaskCommitClusterChanges::SetJoining
  580. //****************************************************************************
  581. //
  582. // IClusCfgCallback
  583. //
  584. //****************************************************************************
  585. //////////////////////////////////////////////////////////////////////////////
  586. //
  587. // STDMETHODIMP
  588. // CTaskCommitClusterChanges::SendStatusReport(
  589. // LPCWSTR pcszNodeNameIn
  590. // , CLSID clsidTaskMajorIn
  591. // , CLSID clsidTaskMinorIn
  592. // , ULONG ulMinIn
  593. // , ULONG ulMaxIn
  594. // , ULONG ulCurrentIn
  595. // , HRESULT hrStatusIn
  596. // , LPCWSTR pcszDescriptionIn
  597. // , FILETIME * pftTimeIn
  598. // , LPCWSTR pcszReferenceIn
  599. // )
  600. //
  601. //////////////////////////////////////////////////////////////////////////////
  602. STDMETHODIMP
  603. CTaskCommitClusterChanges::SendStatusReport(
  604. LPCWSTR pcszNodeNameIn
  605. , CLSID clsidTaskMajorIn
  606. , CLSID clsidTaskMinorIn
  607. , ULONG ulMinIn
  608. , ULONG ulMaxIn
  609. , ULONG ulCurrentIn
  610. , HRESULT hrStatusIn
  611. , LPCWSTR pcszDescriptionIn
  612. , FILETIME * pftTimeIn
  613. , LPCWSTR pcszReferenceIn
  614. )
  615. {
  616. TraceFunc( "[IClusCfgCallback]" );
  617. Assert( pcszNodeNameIn != NULL );
  618. HRESULT hr = S_OK;
  619. IServiceProvider * psp = NULL;
  620. IConnectionPointContainer * pcpc = NULL;
  621. IConnectionPoint * pcp = NULL;
  622. FILETIME ft;
  623. if ( m_pcccb == NULL )
  624. {
  625. //
  626. // Collect the manager we need to complete this task.
  627. //
  628. hr = THR( CoCreateInstance( CLSID_ServiceManager, NULL, CLSCTX_INPROC_SERVER, TypeSafeParams( IServiceProvider, &psp ) ) );
  629. if ( FAILED( hr ) )
  630. {
  631. goto Cleanup;
  632. }
  633. hr = THR( psp->TypeSafeQS( CLSID_NotificationManager, IConnectionPointContainer, &pcpc ) );
  634. if ( FAILED( hr ) )
  635. {
  636. goto Cleanup;
  637. }
  638. hr = THR( pcpc->FindConnectionPoint( IID_IClusCfgCallback, &pcp ) );
  639. if ( FAILED( hr ) )
  640. {
  641. goto Cleanup;
  642. }
  643. pcp = TraceInterface( L"CConfigurationConnection!IConnectionPoint", IConnectionPoint, pcp, 1 );
  644. hr = THR( pcp->TypeSafeQI( IClusCfgCallback, &m_pcccb ) );
  645. if ( FAILED( hr ) )
  646. {
  647. goto Cleanup;
  648. }
  649. m_pcccb = TraceInterface( L"CConfigurationConnection!IClusCfgCallback", IClusCfgCallback, m_pcccb, 1 );
  650. psp->Release();
  651. psp = NULL;
  652. }
  653. if ( pftTimeIn == NULL )
  654. {
  655. GetSystemTimeAsFileTime( &ft );
  656. pftTimeIn = &ft;
  657. } // if:
  658. //
  659. // Send the message!
  660. //
  661. hr = THR( m_pcccb->SendStatusReport(
  662. pcszNodeNameIn != NULL ? pcszNodeNameIn : m_bstrNodeName
  663. , clsidTaskMajorIn
  664. , clsidTaskMinorIn
  665. , ulMinIn
  666. , ulMaxIn
  667. , ulCurrentIn
  668. , hrStatusIn
  669. , pcszDescriptionIn
  670. , pftTimeIn
  671. , pcszReferenceIn
  672. ) );
  673. if ( m_fStop == TRUE )
  674. {
  675. hr = E_ABORT;
  676. } // if:
  677. Cleanup:
  678. if ( psp != NULL )
  679. {
  680. psp->Release();
  681. }
  682. if ( pcpc != NULL )
  683. {
  684. pcpc->Release();
  685. }
  686. if ( pcp != NULL )
  687. {
  688. pcp->Release();
  689. }
  690. HRETURN( hr );
  691. } //*** CTaskCommitClusterChanges::SendStatusReport
  692. //****************************************************************************
  693. //
  694. // INotifyUI
  695. //
  696. //****************************************************************************
  697. //////////////////////////////////////////////////////////////////////////////
  698. //
  699. // STDMETHODIMP
  700. // CTaskCommitClusterChanges::ObjectChanged(
  701. // OBJECTCOOKIE cookieIn
  702. // )
  703. //
  704. //////////////////////////////////////////////////////////////////////////////
  705. STDMETHODIMP
  706. CTaskCommitClusterChanges::ObjectChanged(
  707. OBJECTCOOKIE cookieIn
  708. )
  709. {
  710. TraceFunc( "[INotifyUI]" );
  711. BOOL fSuccess;
  712. ULONG idx;
  713. HRESULT hr = S_OK;
  714. LogMsg( L"[TaskCommitClusterChanges] Looking for the completion cookie %u.", cookieIn );
  715. for ( idx = 0; idx < m_cNodes; idx ++ )
  716. {
  717. if ( cookieIn == m_pcookies[ idx ] )
  718. {
  719. LogMsg( L"[TaskCommitClusterChanges] Clearing completion cookie %u at array index %u", cookieIn, idx );
  720. // don't care if this fails, but it really shouldn't
  721. THR( HrRemoveTaskFromTrackingList( cookieIn ) );
  722. //
  723. // Make sure it won't be signalled twice.
  724. //
  725. m_pcookies[ idx ] = NULL;
  726. InterlockedIncrement( reinterpret_cast< long * >( &m_cSubTasksDone ) );
  727. if ( m_cSubTasksDone == m_cNodes )
  728. {
  729. //
  730. // Signal the event if all the nodes are done.
  731. //
  732. fSuccess = SetEvent( m_event );
  733. if ( ! fSuccess )
  734. {
  735. hr = HRESULT_FROM_WIN32( TW32( GetLastError() ) );
  736. goto Cleanup;
  737. } // if:
  738. } // if: all done
  739. break;
  740. } // if: matched cookie
  741. } // for: each cookie in the list
  742. goto Cleanup;
  743. Cleanup:
  744. HRETURN( hr );
  745. } //*** CTaskCommitClusterChanges::ObjectChanged
  746. //****************************************************************************
  747. //
  748. // Private
  749. //
  750. //****************************************************************************
  751. //////////////////////////////////////////////////////////////////////////////
  752. //
  753. // HRESULT
  754. // CTaskCommitClusterChanges::HrCompareAndPushInformationToNodes
  755. //
  756. //////////////////////////////////////////////////////////////////////////////
  757. HRESULT
  758. CTaskCommitClusterChanges::HrCompareAndPushInformationToNodes( void )
  759. {
  760. TraceFunc( "" );
  761. HRESULT hr = S_OK;
  762. DWORD dwCookie = 0;
  763. DWORD sc;
  764. ULONG cNodes;
  765. ULONG celtDummy;
  766. OBJECTCOOKIE cookieNode;
  767. OBJECTCOOKIE * pcookies = NULL;
  768. BOOL fDeterminedForming = FALSE;
  769. BSTR bstrNodeName = NULL;
  770. BSTR bstrNotification = NULL;
  771. IUnknown * punk = NULL;
  772. IClusCfgNodeInfo * pccni = NULL;
  773. IConnectionPoint * pcp = NULL;
  774. IStandardInfo * psi = NULL;
  775. ITaskCompareAndPushInformation * ptcapi = NULL;
  776. //
  777. // Tell the UI layer that we are starting to connect to the nodes.
  778. //
  779. hr = THR( SendStatusReport( m_bstrNodeName,
  780. TASKID_Major_Update_Progress, // just twiddle the icon
  781. TASKID_Major_Reanalyze,
  782. 1,
  783. 1,
  784. 1,
  785. S_OK,
  786. NULL,
  787. NULL,
  788. NULL
  789. ) );
  790. if ( FAILED( hr ) )
  791. {
  792. goto Cleanup;
  793. }
  794. //
  795. // Count the number of nodes.
  796. //
  797. hr = THR( m_pen->Count( &m_cNodes ) );
  798. if ( FAILED( hr ) )
  799. {
  800. goto Error;
  801. }
  802. //
  803. // Create an event to signal when all the "push" tasks have been
  804. // completed.
  805. //
  806. m_event = CreateEvent( NULL, TRUE, FALSE, NULL );
  807. if ( m_event == NULL )
  808. {
  809. hr = THR( HRESULT_FROM_WIN32( GetLastError() ) );
  810. goto Error;
  811. }
  812. //
  813. // Register with the Notification Manager to get notified.
  814. //
  815. hr = THR( m_pnui->TypeSafeQI( IConnectionPoint, &pcp ) );
  816. if ( FAILED( hr ) )
  817. {
  818. goto Error;
  819. }
  820. hr = THR( pcp->Advise( static_cast< INotifyUI * >( this ), &dwCookie ) );
  821. if ( FAILED( hr ) )
  822. {
  823. goto Error;
  824. }
  825. //
  826. // Allocate a buffer to collect cookies
  827. //
  828. m_pcookies = reinterpret_cast< OBJECTCOOKIE * >( TraceAlloc( HEAP_ZERO_MEMORY, m_cNodes * sizeof( OBJECTCOOKIE ) ) );
  829. if ( m_pcookies == NULL )
  830. {
  831. hr = THR( E_OUTOFMEMORY );
  832. goto Cleanup;
  833. }
  834. //
  835. // This copy is to find out the status of the subtasks.
  836. //
  837. pcookies = reinterpret_cast< OBJECTCOOKIE * >( TraceAlloc( HEAP_ZERO_MEMORY, m_cNodes * sizeof( OBJECTCOOKIE ) ) );
  838. if ( pcookies == NULL )
  839. {
  840. hr = THR( E_OUTOFMEMORY );
  841. goto Cleanup;
  842. }
  843. //
  844. // Loop thru the nodes, creating cookies and compare data for that node.
  845. //
  846. Assert( hr == S_OK );
  847. for ( cNodes = 0; ( ( hr == S_OK ) && ( m_fStop == FALSE ) ); cNodes ++ )
  848. {
  849. //
  850. // Grab the next node.
  851. //
  852. hr = STHR( m_pen->Next( 1, &cookieNode, &celtDummy ) );
  853. if ( hr == S_FALSE )
  854. {
  855. break;
  856. } // if:
  857. if ( FAILED( hr ) )
  858. {
  859. goto Error;
  860. } // if:
  861. //
  862. // Get the object for this node cookie.
  863. //
  864. hr = THR( m_pom->GetObject( DFGUID_NodeInformation, cookieNode, &punk ) );
  865. if ( FAILED( hr ) )
  866. {
  867. goto Cleanup;
  868. } // if:
  869. hr = THR( punk->TypeSafeQI( IClusCfgNodeInfo, &pccni ) );
  870. if ( FAILED( hr ) )
  871. {
  872. goto Cleanup;
  873. } // if:
  874. punk->Release();
  875. punk = NULL;
  876. //
  877. // Get the nodes name. We are using this to distinguish one nodes
  878. // completion cookie from another. It might also make debugging
  879. // easier (??).
  880. //
  881. hr = THR( HrRetrieveCookiesName( m_pom, cookieNode, &bstrNodeName ) );
  882. if ( FAILED( hr ) )
  883. {
  884. goto Cleanup;
  885. } // if:
  886. //
  887. // Update the notification in case something goes wrong.
  888. //
  889. hr = THR( HrFormatMessageIntoBSTR( g_hInstance, IDS_TASKID_MINOR_CONNECTING_TO_NODES, &bstrNotification, bstrNodeName ) );
  890. if ( FAILED( hr ) )
  891. {
  892. goto Cleanup;
  893. }
  894. //
  895. // Create a completion cookie.
  896. //
  897. // KB: These will probably be the same cookie from TaskAnalyzeCluster.
  898. //
  899. // Wrap this because we're just generating a cookie
  900. hr = THR( m_pom->FindObject( IID_NULL, m_cookieCluster, bstrNodeName, IID_NULL, &m_pcookies[ cNodes ], &punk ) );
  901. Assert( punk == NULL );
  902. if ( FAILED( hr ) )
  903. {
  904. goto Error;
  905. }
  906. //
  907. // This copy is for determining the status of the sub-tasks.
  908. //
  909. pcookies[ cNodes ] = m_pcookies[ cNodes ];
  910. //
  911. // Figure out if this node is already part of a cluster.
  912. //
  913. hr = STHR( pccni->IsMemberOfCluster() );
  914. if ( FAILED( hr ) )
  915. {
  916. goto Error;
  917. }
  918. //
  919. // Figure out the forming node.
  920. //
  921. if ( ( m_punkFormingNode == NULL ) // no forming node selected
  922. && ( fDeterminedForming == FALSE ) // no forming node determined
  923. && ( hr == S_FALSE ) // node isn't a member of a cluster
  924. )
  925. {
  926. //
  927. // If it isn't a member of a cluster, select it as the forming node.
  928. //
  929. Assert( m_punkFormingNode == NULL );
  930. hr = THR( pccni->TypeSafeQI( IUnknown, &m_punkFormingNode ) );
  931. if ( FAILED( hr ) )
  932. {
  933. goto Error;
  934. }
  935. //
  936. // Retrieve the cookie for the forming node.
  937. //
  938. // Wrap this because all Nodes should be in the database by now.
  939. hr = THR( m_pom->FindObject( CLSID_NodeType,
  940. m_cookieCluster,
  941. bstrNodeName,
  942. IID_NULL,
  943. &m_cookieFormingNode,
  944. &punk // dummy
  945. ) );
  946. Assert( punk == NULL );
  947. if ( FAILED( hr ) )
  948. {
  949. goto Error;
  950. }
  951. //
  952. // Set this flag to once a node has been determined to be the
  953. // forming node to keep other nodes from being selected.
  954. //
  955. fDeterminedForming = TRUE;
  956. } // if: forming node not found yet
  957. else if ( hr == S_OK ) // node is a member of a cluster
  958. {
  959. //
  960. // Figured out that this node has already formed therefore there
  961. // shouldn't be a "forming node." "Unselect" the forming node by
  962. // releasing the punk and setting it to NULL.
  963. //
  964. if ( m_punkFormingNode != NULL )
  965. {
  966. m_punkFormingNode->Release();
  967. m_punkFormingNode = NULL;
  968. }
  969. //
  970. // Set this flag to once a node has been determined to be the
  971. // forming node to keep other nodes from being selected.
  972. //
  973. fDeterminedForming = TRUE;
  974. } // else:
  975. //
  976. // Create a task to gather this nodes information.
  977. //
  978. hr = THR( m_ptm->CreateTask( TASK_CompareAndPushInformation, &punk ) );
  979. if ( FAILED( hr ) )
  980. {
  981. goto Error;
  982. }
  983. hr = THR( punk->TypeSafeQI( ITaskCompareAndPushInformation, &ptcapi ) );
  984. if ( FAILED( hr ) )
  985. {
  986. goto Cleanup;
  987. }
  988. //
  989. // Set the tasks completion cookie.
  990. //
  991. LogMsg( L"[TaskCommitClusterChanges] Setting completion cookie %u at array index %u into the compare and push information task for node %ws", m_pcookies[ cNodes ], cNodes, bstrNodeName );
  992. hr = THR( ptcapi->SetCompletionCookie( m_pcookies[ cNodes ] ) );
  993. if ( FAILED( hr ) )
  994. {
  995. goto Error;
  996. }
  997. //
  998. // Tell it what node it is suppose to gather information from.
  999. //
  1000. hr = THR( ptcapi->SetNodeCookie( cookieNode ) );
  1001. if ( FAILED( hr ) )
  1002. {
  1003. goto Error;
  1004. }
  1005. //
  1006. // Submit the task.
  1007. //
  1008. hr = THR( m_ptm->SubmitTask( ptcapi ) );
  1009. if ( FAILED( hr ) )
  1010. {
  1011. goto Error;
  1012. }
  1013. hr = THR( HrAddTaskToTrackingList( punk, m_pcookies[ cNodes ] ) );
  1014. if ( FAILED( hr ) )
  1015. {
  1016. goto Cleanup;
  1017. } // if:
  1018. punk->Release();
  1019. punk = NULL;
  1020. //
  1021. // Cleanup for the next node.
  1022. //
  1023. pccni->Release();
  1024. pccni = NULL;
  1025. TraceSysFreeString( bstrNodeName );
  1026. bstrNodeName = NULL;
  1027. ptcapi->Release();
  1028. ptcapi = NULL;
  1029. } // for: looping thru nodes
  1030. Assert( cNodes == m_cNodes );
  1031. if ( m_fStop == TRUE )
  1032. {
  1033. goto Cleanup;
  1034. } // if:
  1035. //
  1036. // Now wait for the work to be done.
  1037. //
  1038. sc = (DWORD) -1;
  1039. Assert( sc != WAIT_OBJECT_0 );
  1040. while ( ( sc != WAIT_OBJECT_0 ) && ( m_fStop == FALSE ) )
  1041. {
  1042. MSG msg;
  1043. while( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )
  1044. {
  1045. TranslateMessage( &msg );
  1046. DispatchMessage( &msg );
  1047. }
  1048. sc = MsgWaitForMultipleObjectsEx( 1,
  1049. &m_event,
  1050. INFINITE,
  1051. QS_ALLEVENTS | QS_ALLINPUT | QS_ALLPOSTMESSAGE,
  1052. 0
  1053. );
  1054. } // while: sc == WAIT_OBJECT_0
  1055. //
  1056. // Check the status to make sure everyone was happy, if not abort the task.
  1057. //
  1058. for( cNodes = 0; cNodes < m_cNodes; cNodes ++ )
  1059. {
  1060. HRESULT hrStatus;
  1061. hr = THR( m_pom->GetObject( DFGUID_StandardInfo, pcookies[ cNodes ], &punk ) );
  1062. if ( FAILED( hr ) )
  1063. {
  1064. goto Error;
  1065. }
  1066. hr = THR( punk->TypeSafeQI( IStandardInfo, &psi ) );
  1067. punk->Release();
  1068. punk = NULL;
  1069. if ( FAILED( hr ) )
  1070. {
  1071. goto Error;
  1072. }
  1073. hr = THR( psi->GetStatus( &hrStatus ) );
  1074. if ( FAILED( hr ) )
  1075. {
  1076. goto Error;
  1077. }
  1078. if ( hrStatus != S_OK )
  1079. {
  1080. hr = hrStatus;
  1081. goto Cleanup;
  1082. }
  1083. } // for: each node
  1084. hr = S_OK;
  1085. Cleanup:
  1086. Assert( punk == NULL );
  1087. if ( pcookies != NULL )
  1088. {
  1089. for ( cNodes = 0; cNodes < m_cNodes; cNodes++ )
  1090. {
  1091. if ( pcookies[ cNodes ] != NULL )
  1092. {
  1093. THR( m_pom->RemoveObject( pcookies[ cNodes ] ) );
  1094. }
  1095. } // for: each node
  1096. TraceFree( pcookies );
  1097. } // if: cookiees were allocated
  1098. TraceSysFreeString( bstrNodeName );
  1099. TraceSysFreeString( bstrNotification );
  1100. if ( ptcapi != NULL )
  1101. {
  1102. ptcapi->Release();
  1103. }
  1104. if ( pcp != NULL )
  1105. {
  1106. if ( dwCookie != 0 )
  1107. {
  1108. THR( pcp->Unadvise( dwCookie ) );
  1109. }
  1110. pcp->Release();
  1111. }
  1112. if ( pccni != NULL )
  1113. {
  1114. pccni->Release();
  1115. }
  1116. if ( psi != NULL )
  1117. {
  1118. psi->Release();
  1119. }
  1120. HRETURN( hr );
  1121. Error:
  1122. //
  1123. // Tell the UI layer about the failure.
  1124. //
  1125. THR( HrSendStatusReport(
  1126. m_bstrNodeName
  1127. , TASKID_Major_Reanalyze
  1128. , TASKID_Minor_Inconsistant_MiddleTier_Database
  1129. , 0
  1130. , 1
  1131. , 1
  1132. , hr
  1133. , IDS_TASKID_MINOR_INCONSISTANT_MIDDLETIER_DATABASE
  1134. ) );
  1135. goto Cleanup;
  1136. } //*** CTaskCommitClusterChanges::HrCompareAndPushInformationToNodes
  1137. //////////////////////////////////////////////////////////////////////////////
  1138. //
  1139. // HRESULT
  1140. // CTaskCommitClusterChanges::HrGatherClusterInformation
  1141. //
  1142. //////////////////////////////////////////////////////////////////////////////
  1143. HRESULT
  1144. CTaskCommitClusterChanges::HrGatherClusterInformation( void )
  1145. {
  1146. TraceFunc( "" );
  1147. HRESULT hr;
  1148. IUnknown * punk = NULL;
  1149. IClusCfgClusterInfo * pccci = NULL;
  1150. IClusCfgCredentials * piccc = NULL;
  1151. IClusCfgNetworkInfo * pccni = NULL;
  1152. //
  1153. // Ask the object manager for the cluster configuration object.
  1154. //
  1155. hr = THR( m_pom->GetObject( DFGUID_ClusterConfigurationInfo, m_cookieCluster, &punk ) );
  1156. if ( FAILED( hr ) )
  1157. {
  1158. goto Error;
  1159. }
  1160. hr = THR( punk->TypeSafeQI( IClusCfgClusterInfo, &pccci ) );
  1161. if ( FAILED( hr ) )
  1162. {
  1163. goto Error;
  1164. }
  1165. //
  1166. // Gather common properties.
  1167. //
  1168. hr = THR( pccci->GetName( &m_bstrClusterName ) );
  1169. if ( FAILED( hr ) )
  1170. {
  1171. goto Error;
  1172. }
  1173. TraceMemoryAddBSTR( m_bstrClusterName );
  1174. hr = STHR( pccci->GetBindingString( &m_bstrClusterBindingString ) );
  1175. if ( FAILED( hr ) )
  1176. {
  1177. goto Error;
  1178. } // if:
  1179. TraceMemoryAddBSTR( m_bstrClusterBindingString );
  1180. LogMsg( L"[MT] Cluster binding string is {%ws}.", m_bstrClusterBindingString );
  1181. hr = THR( pccci->GetClusterServiceAccountCredentials( &piccc ) );
  1182. if ( FAILED( hr ) )
  1183. {
  1184. goto Error;
  1185. }
  1186. hr = THR( m_pccc->AssignFrom( piccc ) );
  1187. if ( FAILED( hr ) )
  1188. {
  1189. goto Error;
  1190. }
  1191. hr = THR( pccci->GetIPAddress( &m_ulIPAddress ) );
  1192. if ( FAILED( hr ) )
  1193. {
  1194. goto Error;
  1195. }
  1196. hr = THR( pccci->GetSubnetMask( &m_ulSubnetMask ) );
  1197. if ( FAILED( hr ) )
  1198. {
  1199. goto Error;
  1200. }
  1201. hr = THR( pccci->GetNetworkInfo( &pccni ) );
  1202. if ( FAILED( hr ) )
  1203. {
  1204. goto Error;
  1205. }
  1206. hr = THR( pccni->GetUID( &m_bstrNetworkUID ) );
  1207. if ( FAILED( hr ) )
  1208. {
  1209. goto Error;
  1210. }
  1211. TraceMemoryAddBSTR( m_bstrNetworkUID );
  1212. Cleanup:
  1213. if ( punk != NULL )
  1214. {
  1215. punk->Release();
  1216. }
  1217. if ( pccni != NULL )
  1218. {
  1219. pccni->Release();
  1220. }
  1221. if ( piccc != NULL )
  1222. {
  1223. piccc->Release();
  1224. }
  1225. if ( pccci != NULL )
  1226. {
  1227. pccci->Release();
  1228. }
  1229. HRETURN( hr );
  1230. Error:
  1231. //
  1232. // Tell the UI layer about the failure.
  1233. //
  1234. THR( HrSendStatusReport(
  1235. m_bstrClusterName
  1236. , TASKID_Major_Reanalyze
  1237. , TASKID_Minor_Inconsistant_MiddleTier_Database
  1238. , 0
  1239. , 1
  1240. , 1
  1241. , hr
  1242. , IDS_TASKID_MINOR_INCONSISTANT_MIDDLETIER_DATABASE
  1243. ) );
  1244. goto Cleanup;
  1245. } //*** CTaskCommitClusterChanges::HrGatherClusterInformation
  1246. //////////////////////////////////////////////////////////////////////////////
  1247. //
  1248. // HRESULT
  1249. // CTaskCommitClusterChanges::HrFormFirstNode
  1250. //
  1251. //////////////////////////////////////////////////////////////////////////////
  1252. HRESULT
  1253. CTaskCommitClusterChanges::HrFormFirstNode( void )
  1254. {
  1255. TraceFunc( "" );
  1256. HRESULT hr = S_OK;
  1257. ULONG celtDummy;
  1258. BSTR bstrNodeName = NULL;
  1259. BSTR bstrUID = NULL;
  1260. IUnknown * punk = NULL;
  1261. IClusCfgCredentials * piccc = NULL;
  1262. IClusCfgNodeInfo * pccni = NULL;
  1263. IClusCfgClusterInfo * pccci = NULL;
  1264. IClusCfgServer * pccs = NULL;
  1265. IEnumClusCfgNetworks * peccn = NULL;
  1266. IClusCfgNetworkInfo * pccneti = NULL;
  1267. //
  1268. // TODO: gpease 25-MAR-2000
  1269. // Figure out what additional work to do here.
  1270. //
  1271. //
  1272. // Get the name of the node.
  1273. //
  1274. hr = THR( m_pom->GetObject( DFGUID_NodeInformation, m_cookieFormingNode, &punk ) );
  1275. if ( FAILED( hr ) )
  1276. {
  1277. goto Cleanup;
  1278. }
  1279. hr = THR( punk->TypeSafeQI( IClusCfgNodeInfo, &pccni ) );
  1280. if ( FAILED( hr ) )
  1281. {
  1282. goto Cleanup;
  1283. }
  1284. punk->Release();
  1285. punk = NULL;
  1286. hr = THR( pccni->GetName( &bstrNodeName ) );
  1287. if ( FAILED( hr ) )
  1288. {
  1289. goto Cleanup;
  1290. }
  1291. TraceMemoryAddBSTR( bstrNodeName );
  1292. pccni->Release();
  1293. pccni = NULL;
  1294. //
  1295. // Create notification string.
  1296. //
  1297. //
  1298. // Update the UI layer telling it that we are about to start.
  1299. //
  1300. hr = THR( HrSendStatusReport(
  1301. bstrNodeName
  1302. , TASKID_Major_Configure_Cluster_Services
  1303. , TASKID_Minor_Forming_Node
  1304. , 0
  1305. , 2
  1306. , 0
  1307. , S_OK
  1308. , IDS_TASKID_MINOR_FORMING_NODE
  1309. ) );
  1310. if ( FAILED( hr ) )
  1311. {
  1312. goto Cleanup;
  1313. }
  1314. //
  1315. // Ask the Connection Manager for a connection to the node.
  1316. //
  1317. hr = THR( m_pcm->GetConnectionToObject( m_cookieFormingNode, &punk ) );
  1318. if ( FAILED( hr ) )
  1319. {
  1320. goto Error;
  1321. }
  1322. hr = THR( punk->TypeSafeQI( IClusCfgServer, &pccs ) );
  1323. if ( FAILED( hr ) )
  1324. {
  1325. goto Error;
  1326. }
  1327. punk->Release();
  1328. punk = NULL;
  1329. //
  1330. // Get the node info interface.
  1331. //
  1332. hr = THR( pccs->GetClusterNodeInfo( &pccni ) );
  1333. if ( FAILED( hr ) )
  1334. {
  1335. goto Error;
  1336. }
  1337. //
  1338. // Retrieve the server's Cluster Configuration Object..
  1339. //
  1340. hr = THR( pccni->GetClusterConfigInfo( &pccci ) );
  1341. if ( FAILED( hr ) )
  1342. {
  1343. goto Error;
  1344. }
  1345. //
  1346. // Put the properties into the remoted object.
  1347. //
  1348. hr = THR( pccci->SetName( m_bstrClusterName ) );
  1349. if ( FAILED( hr ) )
  1350. {
  1351. goto Error;
  1352. }
  1353. hr = STHR( pccci->SetBindingString( m_bstrClusterBindingString ) );
  1354. if ( FAILED( hr ) )
  1355. {
  1356. goto Error;
  1357. }
  1358. hr = THR( pccci->GetClusterServiceAccountCredentials( &piccc ) );
  1359. if ( FAILED( hr ) )
  1360. {
  1361. goto Error;
  1362. }
  1363. hr = THR( m_pccc->AssignTo( piccc ) );
  1364. if( FAILED( hr ) )
  1365. {
  1366. goto Error;
  1367. }
  1368. hr = THR( pccci->SetIPAddress( m_ulIPAddress ) );
  1369. if ( FAILED( hr ) )
  1370. {
  1371. goto Error;
  1372. }
  1373. hr = THR( pccci->SetSubnetMask( m_ulSubnetMask ) );
  1374. if ( FAILED( hr ) )
  1375. {
  1376. goto Error;
  1377. }
  1378. //
  1379. // Find the network that matches the UID of network to host the
  1380. // IP address.
  1381. //
  1382. hr = THR( pccs->GetNetworksEnum( &peccn ) );
  1383. if ( FAILED( hr ) )
  1384. {
  1385. goto Error;
  1386. }
  1387. Assert( hr == S_OK );
  1388. while ( hr == S_OK )
  1389. {
  1390. hr = STHR( peccn->Next( 1, &pccneti, &celtDummy ) );
  1391. if ( hr == S_FALSE )
  1392. {
  1393. //
  1394. // Somehow, there isn't a network that matches the UID of the
  1395. // network. How did we get this far?
  1396. //
  1397. hr = THR( E_UNEXPECTED );
  1398. goto Error;
  1399. }
  1400. if ( FAILED( hr ) )
  1401. {
  1402. goto Error;
  1403. }
  1404. hr = THR( pccneti->GetUID( &bstrUID ) );
  1405. if ( FAILED( hr ) )
  1406. {
  1407. goto Error;
  1408. }
  1409. TraceMemoryAddBSTR( bstrUID );
  1410. if ( NBSTRCompareCase( bstrUID, m_bstrNetworkUID ) == 0 )
  1411. {
  1412. //
  1413. // Found the network!
  1414. //
  1415. break;
  1416. }
  1417. TraceSysFreeString( bstrUID );
  1418. bstrUID = NULL;
  1419. pccneti->Release();
  1420. pccneti = NULL;
  1421. } // while: hr == S_OK
  1422. hr = THR( pccci->SetNetworkInfo( pccneti ) );
  1423. if ( FAILED( hr ) )
  1424. {
  1425. goto Error;
  1426. }
  1427. //
  1428. // Configure that node to create a cluster
  1429. //
  1430. hr = THR( pccci->SetCommitMode( cmCREATE_CLUSTER ) );
  1431. if ( FAILED( hr ) )
  1432. {
  1433. goto Error;
  1434. }
  1435. //
  1436. // Update the UI layer telling it that we are making progress.
  1437. //
  1438. hr = THR( SendStatusReport( bstrNodeName,
  1439. TASKID_Major_Configure_Cluster_Services,
  1440. TASKID_Minor_Forming_Node,
  1441. 0,
  1442. 2,
  1443. 1,
  1444. hr,
  1445. NULL, // don't need to update string
  1446. NULL,
  1447. NULL
  1448. ) );
  1449. if ( FAILED( hr ) )
  1450. {
  1451. goto Cleanup;
  1452. }
  1453. //
  1454. // Commit this node!
  1455. //
  1456. hr = THR( pccs->CommitChanges() );
  1457. if ( FAILED( hr ) )
  1458. {
  1459. goto Error;
  1460. }
  1461. Cleanup:
  1462. //
  1463. // Update the UI layer telling it that we are finished.
  1464. //
  1465. THR( SendStatusReport( bstrNodeName,
  1466. TASKID_Major_Configure_Cluster_Services,
  1467. TASKID_Minor_Forming_Node,
  1468. 0,
  1469. 2,
  1470. 2,
  1471. hr,
  1472. NULL, // don't need to update string
  1473. NULL,
  1474. NULL
  1475. ) );
  1476. if ( punk != NULL )
  1477. {
  1478. punk->Release();
  1479. }
  1480. TraceSysFreeString( bstrNodeName );
  1481. TraceSysFreeString( bstrUID );
  1482. if ( pccneti != NULL )
  1483. {
  1484. pccneti->Release();
  1485. }
  1486. if ( peccn != NULL )
  1487. {
  1488. peccn->Release();
  1489. }
  1490. if ( piccc != NULL )
  1491. {
  1492. piccc->Release();
  1493. }
  1494. if ( pccni != NULL )
  1495. {
  1496. pccni->Release();
  1497. }
  1498. if ( pccci != NULL )
  1499. {
  1500. pccci->Release();
  1501. }
  1502. if ( pccs != NULL )
  1503. {
  1504. pccs->Release();
  1505. }
  1506. HRETURN( hr );
  1507. Error:
  1508. //
  1509. // Tell the UI layer about the failure.
  1510. //
  1511. THR( SendStatusReport( bstrNodeName,
  1512. TASKID_Major_Configure_Cluster_Services,
  1513. TASKID_Minor_Forming_Node,
  1514. 0,
  1515. 2,
  1516. 2,
  1517. hr,
  1518. NULL, // don't need to update string
  1519. NULL,
  1520. NULL
  1521. ) );
  1522. goto Cleanup;
  1523. } //*** CTaskCommitClusterChanges::HrFormFirstNode
  1524. //////////////////////////////////////////////////////////////////////////////
  1525. //
  1526. // HRESULT
  1527. // CTaskCommitClusterChanges::HrAddJoiningNodes
  1528. //
  1529. //////////////////////////////////////////////////////////////////////////////
  1530. HRESULT
  1531. CTaskCommitClusterChanges::HrAddJoiningNodes( void )
  1532. {
  1533. TraceFunc( "" );
  1534. HRESULT hr = S_OK;
  1535. ULONG cNodes;
  1536. ULONG celtDummy;
  1537. OBJECTCOOKIE cookieNode;
  1538. BSTR bstrNodeName = NULL;
  1539. IClusCfgNodeInfo * pccni = NULL;
  1540. IUnknown * punkNode = NULL;
  1541. //
  1542. // Reset the enum to use again.
  1543. //
  1544. hr = THR( m_pen->Reset() );
  1545. if ( FAILED( hr ) )
  1546. {
  1547. goto Cleanup;
  1548. }
  1549. //
  1550. // Loop thru the nodes, adding all joining nodes, skipping the forming node (if any).
  1551. //
  1552. Assert( hr == S_OK );
  1553. for( cNodes = 0; ( ( hr == S_OK ) && ( m_fStop == FALSE ) ); cNodes ++ )
  1554. {
  1555. //
  1556. // Cleanup
  1557. //
  1558. if ( punkNode != NULL )
  1559. {
  1560. punkNode->Release();
  1561. punkNode = NULL;
  1562. } // if:
  1563. if ( pccni != NULL )
  1564. {
  1565. pccni->Release();
  1566. pccni = NULL;
  1567. } // if:
  1568. TraceSysFreeString( bstrNodeName );
  1569. bstrNodeName = NULL;
  1570. //
  1571. // Grab the next node.
  1572. //
  1573. hr = STHR( m_pen->Next( 1, &cookieNode, &celtDummy ) );
  1574. if ( hr == S_FALSE )
  1575. {
  1576. break;
  1577. }
  1578. if ( FAILED( hr ) )
  1579. {
  1580. goto Cleanup;
  1581. }
  1582. //
  1583. // Get the name of the node ffrom the cookies standard info, Once we have a node
  1584. // name it's okay to goto error instead of cleanup.
  1585. //
  1586. hr = THR( HrRetrieveCookiesName( m_pom, cookieNode, &bstrNodeName ) );
  1587. if ( FAILED( hr ) )
  1588. {
  1589. goto Cleanup;
  1590. } // if:
  1591. //
  1592. // Get the node object for the cookie.
  1593. //
  1594. // While the argument list says it returns an IUnknown pointer, it
  1595. // actually calls into QueryInterface requesting an IClusCfgNodeInfo
  1596. // interface.
  1597. hr = THR( m_pom->GetObject(
  1598. DFGUID_NodeInformation
  1599. , cookieNode
  1600. , reinterpret_cast< IUnknown ** >( &pccni )
  1601. ) );
  1602. if ( FAILED( hr ) )
  1603. {
  1604. goto Cleanup;
  1605. }
  1606. // Get an IUnknown pointer for use in the comparison to determine
  1607. // whether this is the forming node or not. This is necessary because
  1608. // in the comparison below, we need to compare the exact same
  1609. // interface that was set into m_punkFormingNode, which was an
  1610. // IUnknown interface.
  1611. hr = THR( pccni->TypeSafeQI( IUnknown, &punkNode ) );
  1612. if ( FAILED( hr ) )
  1613. {
  1614. goto Cleanup;
  1615. }
  1616. //
  1617. // Check cluster membership.
  1618. //
  1619. hr = STHR( pccni->IsMemberOfCluster() );
  1620. if ( FAILED( hr ) )
  1621. {
  1622. goto Cleanup;
  1623. }
  1624. //
  1625. // If the node is already clustered then skip it.
  1626. //
  1627. if ( hr == S_OK )
  1628. {
  1629. continue;
  1630. }
  1631. //
  1632. // KB: We only need the punk's address to see if the objects are the
  1633. // same COM object by comparing the IUnknown interfaces.
  1634. //
  1635. // If the addresses are the same then skip it since we already "formed" in
  1636. // HrCompareAndPushInformationToNodes() above.
  1637. //
  1638. if ( m_punkFormingNode == punkNode )
  1639. {
  1640. continue;
  1641. }
  1642. hr = THR( HrAddAJoiningNode( bstrNodeName, cookieNode ) );
  1643. if ( FAILED( hr ) )
  1644. {
  1645. goto Cleanup;
  1646. }
  1647. } // for: looping thru nodes a second time.
  1648. Assert( cNodes == m_cNodes );
  1649. hr = S_OK;
  1650. Cleanup:
  1651. TraceSysFreeString( bstrNodeName );
  1652. if ( pccni != NULL )
  1653. {
  1654. pccni->Release();
  1655. }
  1656. if ( punkNode != NULL )
  1657. {
  1658. punkNode->Release();
  1659. }
  1660. HRETURN( hr );
  1661. } //*** CTaskCommitClusterChanges::HrAddJoiningNodes
  1662. //////////////////////////////////////////////////////////////////////////////
  1663. //
  1664. // HRESULT
  1665. // CTaskCommitClusterChanges::HrAddAJoiningNode(
  1666. // BSTR bstrNameIn,
  1667. // OBJECTCOOKIE cookieIn
  1668. // )
  1669. //
  1670. //////////////////////////////////////////////////////////////////////////////
  1671. HRESULT
  1672. CTaskCommitClusterChanges::HrAddAJoiningNode(
  1673. BSTR bstrNameIn,
  1674. OBJECTCOOKIE cookieIn
  1675. )
  1676. {
  1677. TraceFunc( "" );
  1678. HRESULT hr;
  1679. IUnknown * punk = NULL;
  1680. IClusCfgCredentials * piccc = NULL;
  1681. IClusCfgNodeInfo * pccni = NULL;
  1682. IClusCfgClusterInfo * pccci = NULL;
  1683. IClusCfgServer * pccs = NULL;
  1684. //
  1685. // Create the notification string
  1686. //
  1687. //
  1688. // Tell UI layer we are about to start this.
  1689. //
  1690. hr = THR( HrSendStatusReport(
  1691. bstrNameIn
  1692. , TASKID_Major_Configure_Cluster_Services
  1693. , TASKID_Minor_Joining_Node
  1694. , 0
  1695. , 2
  1696. , 0
  1697. , S_OK
  1698. , IDS_TASKID_MINOR_JOINING_NODE
  1699. ) );
  1700. if ( FAILED( hr ) )
  1701. {
  1702. goto Cleanup;
  1703. }
  1704. //
  1705. // Connect to the node.
  1706. //
  1707. hr = THR( m_pcm->GetConnectionToObject( cookieIn,
  1708. &punk
  1709. ) );
  1710. if ( FAILED( hr ) )
  1711. {
  1712. goto Cleanup;
  1713. }
  1714. hr = THR( punk->TypeSafeQI( IClusCfgServer, &pccs ) );
  1715. if ( FAILED( hr ) )
  1716. {
  1717. goto Cleanup;
  1718. }
  1719. //
  1720. // Get the node info interface.
  1721. //
  1722. hr = THR( pccs->GetClusterNodeInfo( &pccni ) );
  1723. if ( FAILED( hr ) )
  1724. {
  1725. goto Cleanup;
  1726. }
  1727. //
  1728. // Retrieve the server's Cluster Configuration Object..
  1729. //
  1730. hr = THR( pccni->GetClusterConfigInfo( &pccci ) );
  1731. if ( FAILED( hr ) )
  1732. {
  1733. goto Cleanup;
  1734. }
  1735. //
  1736. // Put the properties into the remoted object.
  1737. //
  1738. hr = THR( pccci->SetName( m_bstrClusterName ) );
  1739. if ( FAILED( hr ) )
  1740. {
  1741. goto Cleanup;
  1742. }
  1743. hr = THR( pccci->SetBindingString( m_bstrClusterBindingString ) );
  1744. if ( FAILED( hr ) )
  1745. {
  1746. goto Cleanup;
  1747. }
  1748. hr = THR( pccci->GetClusterServiceAccountCredentials( &piccc ) );
  1749. if ( FAILED( hr ) )
  1750. {
  1751. goto Cleanup;
  1752. }
  1753. hr = THR( m_pccc->AssignTo( piccc ) );
  1754. if ( FAILED( hr ) )
  1755. {
  1756. goto Cleanup;
  1757. }
  1758. hr = THR( pccci->SetIPAddress( m_ulIPAddress ) );
  1759. if ( FAILED( hr ) )
  1760. {
  1761. goto Cleanup;
  1762. }
  1763. hr = THR( pccci->SetSubnetMask( m_ulSubnetMask ) );
  1764. if ( FAILED( hr ) )
  1765. {
  1766. goto Cleanup;
  1767. }
  1768. //
  1769. // Set this node to add itself to a cluster
  1770. //
  1771. hr = THR( pccci->SetCommitMode( cmADD_NODE_TO_CLUSTER ) );
  1772. if ( FAILED( hr ) )
  1773. {
  1774. goto Cleanup;
  1775. }
  1776. //
  1777. // Tell the UI layer we are making progess.... the server will then send messages
  1778. // indicating what it is doing.
  1779. //
  1780. hr = THR( SendStatusReport( bstrNameIn,
  1781. TASKID_Major_Configure_Cluster_Services,
  1782. TASKID_Minor_Joining_Node,
  1783. 0,
  1784. 2,
  1785. 1,
  1786. S_OK,
  1787. NULL, // don't need to update string
  1788. NULL,
  1789. NULL
  1790. ) );
  1791. if ( FAILED( hr ) )
  1792. {
  1793. goto Cleanup;
  1794. }
  1795. //
  1796. // Commit this node!
  1797. //
  1798. hr = THR( pccs->CommitChanges() );
  1799. if ( FAILED( hr ) )
  1800. {
  1801. goto Cleanup;
  1802. }
  1803. Cleanup:
  1804. THR( SendStatusReport( bstrNameIn,
  1805. TASKID_Major_Configure_Cluster_Services,
  1806. TASKID_Minor_Joining_Node,
  1807. 0,
  1808. 2,
  1809. 2,
  1810. hr,
  1811. NULL, // don't need to update string
  1812. NULL,
  1813. NULL
  1814. ) );
  1815. if ( punk != NULL )
  1816. {
  1817. punk->Release();
  1818. }
  1819. if ( piccc != NULL )
  1820. {
  1821. piccc->Release();
  1822. }
  1823. if ( pccci != NULL )
  1824. {
  1825. pccci->Release();
  1826. }
  1827. if ( pccs != NULL )
  1828. {
  1829. pccs->Release();
  1830. }
  1831. if ( pccni != NULL )
  1832. {
  1833. pccni->Release();
  1834. }
  1835. HRETURN( hr );
  1836. } //*** CTaskCommitClusterChanges::HrAddAJoiningNode
  1837. //////////////////////////////////////////////////////////////////////////////
  1838. //
  1839. // HRESULT
  1840. // CTaskCommitClusterChanges::HrSendStatusReport(
  1841. // LPCWSTR pcsNodeNameIn
  1842. // , CLSID clsidMajorIn
  1843. // , CLSID clsidMinorIn
  1844. // , ULONG ulMinIn
  1845. // , ULONG ulMaxIn
  1846. // , ULONG ulCurrentIn
  1847. // , HRESULT hrIn
  1848. // , int nDescriptionIdIn
  1849. // )
  1850. //
  1851. //////////////////////////////////////////////////////////////////////////////
  1852. HRESULT
  1853. CTaskCommitClusterChanges::HrSendStatusReport(
  1854. LPCWSTR pcszNodeNameIn
  1855. , CLSID clsidMajorIn
  1856. , CLSID clsidMinorIn
  1857. , ULONG ulMinIn
  1858. , ULONG ulMaxIn
  1859. , ULONG ulCurrentIn
  1860. , HRESULT hrIn
  1861. , int nDescriptionIdIn
  1862. )
  1863. {
  1864. TraceFunc( "" );
  1865. HRESULT hr = S_OK;
  1866. BSTR bstr = NULL;
  1867. hr = THR( HrLoadStringIntoBSTR( g_hInstance, nDescriptionIdIn, &bstr ) );
  1868. if ( FAILED( hr ) )
  1869. {
  1870. goto Cleanup;
  1871. } // if:
  1872. hr = THR( SendStatusReport( pcszNodeNameIn, clsidMajorIn, clsidMinorIn, ulMinIn, ulMaxIn, ulCurrentIn, hrIn, bstr, NULL, NULL ) );
  1873. Cleanup:
  1874. TraceSysFreeString( bstr );
  1875. HRETURN( hr );
  1876. } //*** CTaskCommitClusterChanges::HrSendStatusReport