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.

3058 lines
82 KiB

  1. //////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) 2000-2002 Microsoft Corporation
  4. //
  5. // Module Name:
  6. // CClusCfgServer.cpp
  7. //
  8. // Description:
  9. // This file contains the definition of the CClusCfgServer class.
  10. //
  11. // The class CClusCfgServer is the implementations of the
  12. // IClusCfgServer interface.
  13. //
  14. // Maintained By:
  15. // Galen Barbee (GalenB) 03-FEB-2000
  16. //
  17. //////////////////////////////////////////////////////////////////////////////
  18. //////////////////////////////////////////////////////////////////////////////
  19. // Include Files
  20. //////////////////////////////////////////////////////////////////////////////
  21. #include "Pch.h"
  22. #include <ClusRTL.h>
  23. #include "CClusCfgServer.h"
  24. #include "PrivateInterfaces.h"
  25. #include "CClusCfgNodeInfo.h"
  26. #include "CEnumClusCfgManagedResources.h"
  27. #include "CClusCfgCallback.h"
  28. #include "EventName.h"
  29. #include <ClusRtl.h>
  30. #include <windns.h>
  31. #include <ClusterUtils.h>
  32. #include <clusudef.h>
  33. //////////////////////////////////////////////////////////////////////////////
  34. // Constant Definitions
  35. //////////////////////////////////////////////////////////////////////////////
  36. DEFINE_THISCLASS( "CClusCfgServer" );
  37. #define CLEANUP_LOCK_NAME L"Global\\Microsoft Cluster Configuration Cleanup Lock"
  38. //*************************************************************************//
  39. /////////////////////////////////////////////////////////////////////////////
  40. // CClusCfgServer class
  41. /////////////////////////////////////////////////////////////////////////////
  42. //////////////////////////////////////////////////////////////////////////////
  43. //++
  44. //
  45. // CClusCfgServer::S_HrCreateInstance
  46. //
  47. // Description:
  48. // Create a CClusCfgServer instance.
  49. //
  50. // Arguments:
  51. // ppunkOut -
  52. //
  53. // Return Values:
  54. // Pointer to CClusCfgServer instance.
  55. //
  56. //--
  57. //////////////////////////////////////////////////////////////////////////////
  58. HRESULT
  59. CClusCfgServer::S_HrCreateInstance( IUnknown ** ppunkOut )
  60. {
  61. TraceFunc( "" );
  62. HRESULT hr = S_OK;
  63. CClusCfgServer * pccs = NULL;
  64. if ( ppunkOut == NULL )
  65. {
  66. hr = THR( E_POINTER );
  67. goto Cleanup;
  68. } // if:
  69. //
  70. // KB: Since this is usually the start of the "server" thread,
  71. // we will cause it to read its thread settings here.
  72. //
  73. TraceInitializeThread( L"ServerThread" );
  74. pccs = new CClusCfgServer();
  75. if ( pccs == NULL )
  76. {
  77. hr = THR( E_OUTOFMEMORY );
  78. goto Cleanup;
  79. } // if: error allocating object
  80. hr = THR( pccs->HrInit() );
  81. if ( FAILED( hr ) )
  82. {
  83. goto Cleanup;
  84. } // if: HrInit() failed
  85. hr = THR( pccs->TypeSafeQI( IUnknown, ppunkOut ) );
  86. if ( FAILED( hr ) )
  87. {
  88. goto Cleanup;
  89. } // if: QI failed
  90. Cleanup:
  91. if ( FAILED( hr ) )
  92. {
  93. LogMsg( L"[SRV] CClusCfgServer::S_HrCreateInstance() failed. (hr = %#08x)", hr );
  94. } // if:
  95. if ( pccs != NULL )
  96. {
  97. pccs->Release();
  98. } // if:
  99. HRETURN( hr );
  100. } //*** CClusCfgServer::S_HrCreateInstance
  101. //////////////////////////////////////////////////////////////////////////////
  102. //++
  103. //
  104. // CClusCfgServer::CClusCfgServer
  105. //
  106. // Description:
  107. // Constructor of the CClusCfgServer class. This initializes
  108. // the m_cRef variable to 1 instead of 0 to account of possible
  109. // QueryInterface failure in DllGetClassObject.
  110. //
  111. // Arguments:
  112. // None.
  113. //
  114. // Return Value:
  115. // None.
  116. //
  117. // Remarks:
  118. // None.
  119. //
  120. //--
  121. //////////////////////////////////////////////////////////////////////////////
  122. CClusCfgServer::CClusCfgServer( void )
  123. : m_cRef( 1 )
  124. , m_pIWbemServices( NULL )
  125. , m_lcid( LOCALE_NEUTRAL )
  126. , m_fCanBeClustered( TRUE )
  127. {
  128. TraceFunc( "" );
  129. // Increment the count of components in memory so the DLL hosting this
  130. // object cannot be unloaded.
  131. InterlockedIncrement( &g_cObjects );
  132. Assert( m_picccCallback == NULL );
  133. Assert( m_punkNodeInfo == NULL );
  134. Assert( m_punkEnumResources == NULL );
  135. Assert( m_punkNetworksEnum == NULL );
  136. Assert( m_bstrNodeName == NULL );
  137. Assert( !m_fUsePolling );
  138. Assert( m_bstrBindingString == NULL );
  139. TraceFuncExit();
  140. } //*** CClusCfgServer::CClusCfgServer
  141. //////////////////////////////////////////////////////////////////////////////
  142. //++
  143. //
  144. // CClusCfgServer::~CClusCfgServer
  145. //
  146. // Description:
  147. // Destructor of the CClusCfgServer class.
  148. //
  149. // Arguments:
  150. // None.
  151. //
  152. // Return Value:
  153. // None.
  154. //
  155. // Remarks:
  156. // None.
  157. //
  158. //--
  159. //////////////////////////////////////////////////////////////////////////////
  160. CClusCfgServer::~CClusCfgServer( void )
  161. {
  162. TraceFunc( "" );
  163. TraceSysFreeString( m_bstrNodeName );
  164. TraceSysFreeString( m_bstrBindingString );
  165. if ( m_pIWbemServices != NULL )
  166. {
  167. m_pIWbemServices->Release();
  168. } // if:
  169. if ( m_punkNodeInfo != NULL )
  170. {
  171. m_punkNodeInfo->Release();
  172. } // if:
  173. if ( m_punkEnumResources != NULL )
  174. {
  175. m_punkEnumResources->Release();
  176. } // if:
  177. if ( m_punkNetworksEnum != NULL )
  178. {
  179. m_punkNetworksEnum->Release();
  180. } // if:
  181. if ( m_picccCallback != NULL )
  182. {
  183. m_picccCallback->Release();
  184. } // if:
  185. // There's going to be one less component in memory. Decrement component count.
  186. InterlockedDecrement( &g_cObjects );
  187. TraceFuncExit();
  188. } //*** CClusCfgServer::~CClusCfgServer
  189. //*************************************************************************//
  190. /////////////////////////////////////////////////////////////////////////////
  191. // CClusCfgServer -- IUknkown interface.
  192. /////////////////////////////////////////////////////////////////////////////
  193. //////////////////////////////////////////////////////////////////////////////
  194. //++
  195. //
  196. // CClusCfgServer::AddRef
  197. //
  198. // Description:
  199. // Increment the reference count of this object by one.
  200. //
  201. // Arguments:
  202. // None.
  203. //
  204. // Return Value:
  205. // The new reference count.
  206. //
  207. // Remarks:
  208. // None.
  209. //
  210. //--
  211. //////////////////////////////////////////////////////////////////////////////
  212. STDMETHODIMP_( ULONG )
  213. CClusCfgServer::AddRef( void )
  214. {
  215. TraceFunc( "[IUnknown]" );
  216. InterlockedIncrement( &m_cRef );
  217. CRETURN( m_cRef );
  218. } //*** CClusCfgServer::AddRef
  219. //////////////////////////////////////////////////////////////////////////////
  220. //++
  221. //
  222. // CClusCfgServer::Release
  223. //
  224. // Description:
  225. // Decrement the reference count of this object by one.
  226. //
  227. // Arguments:
  228. // None.
  229. //
  230. // Return Value:
  231. // The new reference count.
  232. //
  233. // Remarks:
  234. // None.
  235. //
  236. //--
  237. //////////////////////////////////////////////////////////////////////////////
  238. STDMETHODIMP_( ULONG )
  239. CClusCfgServer::Release( void )
  240. {
  241. TraceFunc( "[IUnknown]" );
  242. LONG cRef;
  243. cRef = InterlockedDecrement( &m_cRef );
  244. if ( cRef == 0 )
  245. {
  246. TraceDo( delete this );
  247. } // if: reference count equal to zero
  248. CRETURN( cRef );
  249. } //*** CClusCfgServer::Release
  250. //////////////////////////////////////////////////////////////////////////////
  251. //++
  252. //
  253. // CClusCfgServer::QueryInterface
  254. //
  255. // Description:
  256. // Query this object for the passed in interface.
  257. //
  258. // Arguments:
  259. // riidIn
  260. // Id of interface requested.
  261. //
  262. // ppvOut
  263. // Pointer to the requested interface.
  264. //
  265. // Return Value:
  266. // S_OK
  267. // If the interface is available on this object.
  268. //
  269. // E_NOINTERFACE
  270. // If the interface is not available.
  271. //
  272. // E_POINTER
  273. // ppvOut was NULL.
  274. //
  275. // Remarks:
  276. // None.
  277. //
  278. //--
  279. //////////////////////////////////////////////////////////////////////////////
  280. STDMETHODIMP
  281. CClusCfgServer::QueryInterface(
  282. REFIID riidIn
  283. , void ** ppvOut
  284. )
  285. {
  286. TraceQIFunc( riidIn, ppvOut );
  287. HRESULT hr = S_OK;
  288. //
  289. // Validate arguments.
  290. //
  291. Assert( ppvOut != NULL );
  292. if ( ppvOut == NULL )
  293. {
  294. hr = THR( E_POINTER );
  295. goto Cleanup;
  296. }
  297. //
  298. // Handle known interfaces.
  299. //
  300. if ( IsEqualIID( riidIn, IID_IUnknown ) )
  301. {
  302. *ppvOut = static_cast< IClusCfgServer * >( this );
  303. } // if: IUnknown
  304. else if ( IsEqualIID( riidIn, IID_IClusCfgServer ) )
  305. {
  306. *ppvOut = TraceInterface( __THISCLASS__, IClusCfgServer, this, 0 );
  307. } // else if: IClusCfgServer
  308. else if ( IsEqualIID( riidIn, IID_IClusCfgInitialize ) )
  309. {
  310. *ppvOut = TraceInterface( __THISCLASS__, IClusCfgInitialize, this, 0 );
  311. } // else if: IClusCfgInitialize
  312. else if ( IsEqualIID( riidIn, IID_IClusCfgCapabilities ) )
  313. {
  314. *ppvOut = TraceInterface( __THISCLASS__, IClusCfgCapabilities, this, 0 );
  315. } // else if: IClusCfgCapabilities
  316. else if ( IsEqualIID( riidIn, IID_IClusCfgPollingCallbackInfo ) )
  317. {
  318. *ppvOut = TraceInterface( __THISCLASS__, IClusCfgPollingCallbackInfo, this, 0 );
  319. } // else if: IClusCfgPollingCallbackInfo
  320. else if ( IsEqualIID( riidIn, IID_IClusCfgVerify ) )
  321. {
  322. *ppvOut = TraceInterface( __THISCLASS__, IClusCfgVerify, this, 0 );
  323. } // else if: IClusCfgVerify
  324. else
  325. {
  326. *ppvOut = NULL;
  327. hr = E_NOINTERFACE;
  328. }
  329. //
  330. // Add a reference to the interface if successful.
  331. //
  332. if ( SUCCEEDED( hr ) )
  333. {
  334. ((IUnknown *) *ppvOut)->AddRef();
  335. } // if: success
  336. Cleanup:
  337. QIRETURN_IGNORESTDMARSHALLING( hr, riidIn );
  338. } //*** CClusCfgServer::QueryInterface
  339. //*************************************************************************//
  340. /////////////////////////////////////////////////////////////////////////////
  341. // CClusCfgServer -- IClusCfgInitialize interface.
  342. /////////////////////////////////////////////////////////////////////////////
  343. //////////////////////////////////////////////////////////////////////////////
  344. //++
  345. //
  346. // CClusCfgServer::Initialize
  347. //
  348. // Description:
  349. // Initialize this component.
  350. //
  351. // Arguments:
  352. // IN IUknown * punkCallbackIn
  353. //
  354. // IN LCID lcidIn
  355. //
  356. // Return Value:
  357. // S_OK
  358. // Success
  359. //
  360. // E_POINTER
  361. // The punkCallbackIn param is NULL.
  362. //
  363. // Remarks:
  364. // None.
  365. //
  366. //--
  367. //////////////////////////////////////////////////////////////////////////////
  368. STDMETHODIMP
  369. CClusCfgServer::Initialize(
  370. IUnknown * punkCallbackIn,
  371. LCID lcidIn
  372. )
  373. {
  374. TraceFunc( "[IClusCfgInitialize]" );
  375. Assert( m_picccCallback != NULL );
  376. TraceInitializeThread( L"ClusCfgServerFlags" );
  377. HRESULT hr = S_OK;
  378. IUnknown * punk = NULL;
  379. IClusCfgCallback * piccc = NULL; // this is NULL when we are polling callback
  380. IClusCfgNodeInfo * piccni = NULL;
  381. IClusCfgClusterInfo * piccci = NULL;
  382. // hr = STHR( HrCheckSecurity() );
  383. // if ( FAILED( hr ) )
  384. // {
  385. // goto Cleanup;
  386. // } // if:
  387. m_lcid = lcidIn;
  388. //
  389. // If we are passed a callback object then we need to get its IClusCfgCallback
  390. // interface so we can pass it into our callback object when it's initialized
  391. // below.
  392. //
  393. if ( punkCallbackIn != NULL )
  394. {
  395. Assert( !m_fUsePolling );
  396. hr = THR( punkCallbackIn->TypeSafeQI( IClusCfgCallback, &piccc ) );
  397. if ( FAILED( hr ) )
  398. {
  399. goto Cleanup;
  400. } // if:
  401. } // if:
  402. else
  403. {
  404. Assert( m_fUsePolling );
  405. if ( m_fUsePolling == FALSE )
  406. {
  407. hr = THR( E_INVALIDARG );
  408. goto Cleanup;
  409. } // if:
  410. } // else:
  411. //
  412. // Initialize our internal callback object passing it either the passed in
  413. // callback object's callback interface or NULL if we are polling.
  414. //
  415. hr = THR( m_picccCallback->TypeSafeQI( IUnknown, &punk ) );
  416. if ( FAILED( hr ) )
  417. {
  418. goto Cleanup;
  419. } // if:
  420. hr = THR( HrSetInitialize( punk, piccc, m_lcid ) );
  421. if ( FAILED( hr ) )
  422. {
  423. goto Cleanup;
  424. } // if:
  425. //
  426. // KB: 24-JUL-2000 GalenB
  427. //
  428. // If we are being initialized on this interface then we are going to run this server local
  429. // to the node.
  430. //
  431. hr = THR( HrInitializeForLocalServer() );
  432. if ( FAILED( hr ) )
  433. {
  434. goto Cleanup;
  435. } // if:
  436. //
  437. // Precreate the node info so we can get the cluster info object and determine if the cluster service
  438. // is running on this node or not.
  439. //
  440. hr = THR( HrCreateClusterNodeInfo() );
  441. if ( FAILED( hr ) )
  442. {
  443. goto Cleanup;
  444. } // if:
  445. hr = THR( m_punkNodeInfo->TypeSafeQI( IClusCfgNodeInfo, &piccni ) );
  446. if ( FAILED( hr ) )
  447. {
  448. goto Cleanup;
  449. } // if:
  450. //
  451. // This could return HRESUTL_FROM_WIN32( ERROR_CLUSTER_NODE_DOWN ) and that
  452. // tells us that the cluster service is not running on this node. The
  453. // middletier needs to know this so it doesn't call us on this node
  454. // anymore.
  455. //
  456. hr = THR( piccni->GetClusterConfigInfo( &piccci ) );
  457. Cleanup:
  458. if ( m_picccCallback != NULL )
  459. {
  460. STATUS_REPORT( TASKID_Major_Establish_Connection, TASKID_Minor_Server_Initialized, IDS_NOTIFY_SERVER_INITIALIZED, hr );
  461. } // if:
  462. if ( piccci != NULL )
  463. {
  464. piccci->Release();
  465. } // if:
  466. if ( piccni != NULL )
  467. {
  468. piccni->Release();
  469. } // if:
  470. if ( piccc != NULL )
  471. {
  472. piccc->Release();
  473. } // if:
  474. if ( punk != NULL )
  475. {
  476. punk->Release();
  477. } // if:
  478. HRETURN( hr );
  479. } //*** CClusCfgServer::Initialize
  480. //*************************************************************************//
  481. /////////////////////////////////////////////////////////////////////////////
  482. // CClusCfgServer -- IClusCfgServer interface.
  483. /////////////////////////////////////////////////////////////////////////////
  484. //////////////////////////////////////////////////////////////////////////////
  485. //++
  486. //
  487. // CClusCfgServer::GetClusterNodeInfo
  488. //
  489. // Description:
  490. // Get information about the computer on which this object is present.
  491. //
  492. // Arguments:
  493. // OUT IClusCfgNodeInfo ** ppClusterNodeInfoOut
  494. // Catches the node info object.
  495. //
  496. // Return Value:
  497. // S_OK
  498. // Success
  499. //
  500. // E_POINTER
  501. // The out param was NULL.
  502. //
  503. // E_OUTOFMEMORY
  504. // The IClusCfgNodeInfo object could not be allocated.
  505. //
  506. // Remarks:
  507. // None.
  508. //
  509. //--
  510. //////////////////////////////////////////////////////////////////////////////
  511. STDMETHODIMP
  512. CClusCfgServer::GetClusterNodeInfo(
  513. IClusCfgNodeInfo ** ppClusterNodeInfoOut
  514. )
  515. {
  516. TraceFunc( "[IClusCfgServer]" );
  517. HRESULT hr = S_OK;
  518. if ( ppClusterNodeInfoOut == NULL )
  519. {
  520. hr = THR( E_POINTER );
  521. STATUS_REPORT_REF(
  522. TASKID_Major_Check_Node_Feasibility
  523. , TASKID_Minor_GetClusterNodeInfo
  524. , IDS_ERROR_NULL_POINTER
  525. , IDS_ERROR_NULL_POINTER_REF
  526. , hr
  527. );
  528. goto Cleanup;
  529. } // if:
  530. if ( m_punkNodeInfo != NULL )
  531. {
  532. hr = S_OK;
  533. goto SkipCreate;
  534. } // if:
  535. hr = THR( HrCreateClusterNodeInfo() );
  536. SkipCreate:
  537. if ( SUCCEEDED( hr ) )
  538. {
  539. Assert( m_punkNodeInfo != NULL );
  540. hr = THR( m_punkNodeInfo->TypeSafeQI( IClusCfgNodeInfo, ppClusterNodeInfoOut ) );
  541. } // if:
  542. Cleanup:
  543. if ( FAILED( hr ) )
  544. {
  545. STATUS_REPORT_REF(
  546. TASKID_Major_Check_Node_Feasibility
  547. , TASKID_Minor_Server_GetClusterNodeInfo
  548. , IDS_ERROR_NODE_INFO_CREATE
  549. , IDS_ERROR_NODE_INFO_CREATE_REF
  550. , hr
  551. );
  552. } // if:
  553. HRETURN( hr );
  554. } //*** CClusCfgServer::GetClusterNodeInfo
  555. //////////////////////////////////////////////////////////////////////////////
  556. //++
  557. //
  558. // CClusCfgServer::GetManagedResourcesEnum
  559. //
  560. // Description:
  561. // Get an enumeration of the devices on this computer that can be
  562. // managed by the cluster service.
  563. //
  564. // Arguments:
  565. // OUT IEnumClusCfgManagedResources ** ppEnumManagedResourcesOut
  566. // Catches the CEnumClusCfgManagedResources object.
  567. //
  568. // Return Value:
  569. // S_OK
  570. // Success
  571. //
  572. // E_POINTER
  573. // The out param was NULL.
  574. //
  575. // E_OUTOFMEMORY
  576. // The CEnumClusCfgManagedResources object could not be allocated.
  577. //
  578. // Remarks:
  579. // None.
  580. //
  581. //--
  582. //////////////////////////////////////////////////////////////////////////////
  583. STDMETHODIMP
  584. CClusCfgServer::GetManagedResourcesEnum(
  585. IEnumClusCfgManagedResources ** ppEnumManagedResourcesOut
  586. )
  587. {
  588. TraceFunc( "[IClusCfgServer]" );
  589. HRESULT hr = S_OK;
  590. if ( ppEnumManagedResourcesOut == NULL )
  591. {
  592. hr = THR( E_POINTER );
  593. STATUS_REPORT_REF( TASKID_Major_Find_Devices, TASKID_Minor_GetManagedResourcesEnum, IDS_ERROR_NULL_POINTER, IDS_ERROR_NULL_POINTER_REF, hr );
  594. goto Cleanup;
  595. } // if:
  596. if ( m_punkEnumResources != NULL )
  597. {
  598. m_punkEnumResources->Release();
  599. m_punkEnumResources = NULL;
  600. } // if:
  601. hr = THR( CEnumClusCfgManagedResources::S_HrCreateInstance( &m_punkEnumResources ) );
  602. if ( FAILED( hr ) )
  603. {
  604. goto Cleanup;
  605. } // if:
  606. m_punkEnumResources = TraceInterface( L"CEnumClusCfgManagedResources", IUnknown, m_punkEnumResources, 1 );
  607. hr = THR( HrSetInitialize( m_punkEnumResources, m_picccCallback, m_lcid ) );
  608. if ( FAILED( hr ) )
  609. {
  610. goto Cleanup;
  611. } // if:
  612. hr = THR( HrSetWbemServices( m_punkEnumResources, m_pIWbemServices ) );
  613. if ( FAILED( hr ) )
  614. {
  615. goto Cleanup;
  616. } // if:
  617. hr = THR( m_punkEnumResources->TypeSafeQI( IEnumClusCfgManagedResources, ppEnumManagedResourcesOut ) );
  618. Cleanup:
  619. if ( FAILED( hr ) )
  620. {
  621. STATUS_REPORT_REF(
  622. TASKID_Major_Find_Devices
  623. , TASKID_Minor_Server_GetManagedResourcesEnum
  624. , IDS_ERROR_MANAGED_RESOURCE_ENUM_CREATE
  625. , IDS_ERROR_MANAGED_RESOURCE_ENUM_CREATE_REF
  626. , hr
  627. );
  628. } // if:
  629. HRETURN( hr );
  630. } //*** CClusCfgServer::GetManagedResourcesEnum
  631. //////////////////////////////////////////////////////////////////////////////
  632. //++
  633. //
  634. // CClusCfgServer::GetNetworksEnum
  635. //
  636. // Description:
  637. // Get an enumeration of all the networks on this computer.
  638. //
  639. // Arguments:
  640. // OUT IEnumClusCfgNetworks ** ppEnumNetworksOut
  641. // Catches the CEnumClusCfgNetworks object.
  642. //
  643. // Return Value:
  644. // S_OK
  645. // Success
  646. //
  647. // E_POINTER
  648. // The out param was NULL.
  649. //
  650. // E_OUTOFMEMORY
  651. // The CEnumClusCfgNetworks object could not be allocated.
  652. //
  653. // Remarks:
  654. // None.
  655. //
  656. //--
  657. //////////////////////////////////////////////////////////////////////////////
  658. STDMETHODIMP
  659. CClusCfgServer::GetNetworksEnum(
  660. IEnumClusCfgNetworks ** ppEnumNetworksOut
  661. )
  662. {
  663. TraceFunc( "[IClusCfgServer]" );
  664. HRESULT hr = S_OK;
  665. if ( ppEnumNetworksOut == NULL )
  666. {
  667. hr = THR( E_POINTER );
  668. STATUS_REPORT_REF( TASKID_Major_Find_Devices, TASKID_Minor_GetNetworksEnum, IDS_ERROR_NULL_POINTER, IDS_ERROR_NULL_POINTER_REF, hr );
  669. goto Cleanup;
  670. } // if:
  671. if ( m_punkNetworksEnum != NULL )
  672. {
  673. m_punkNetworksEnum->Release();
  674. m_punkNetworksEnum = NULL;
  675. } // if:
  676. hr = THR( HrCreateNetworksEnum( m_picccCallback, m_lcid, m_pIWbemServices, &m_punkNetworksEnum ) );
  677. if ( FAILED( hr ) )
  678. {
  679. goto Cleanup;
  680. } // if:
  681. hr = THR( m_punkNetworksEnum->TypeSafeQI( IEnumClusCfgNetworks, ppEnumNetworksOut ) );
  682. Cleanup:
  683. if ( FAILED( hr ) )
  684. {
  685. STATUS_REPORT_REF(
  686. TASKID_Major_Find_Devices
  687. , TASKID_Minor_Server_GetNetworksEnum
  688. , IDS_ERROR_NETWORKS_ENUM_CREATE
  689. , IDS_ERROR_NETWORKS_ENUM_CREATE_REF
  690. , hr
  691. );
  692. } // if:
  693. HRETURN( hr );
  694. } //*** CClusCfgServer::GetNetworksEnum
  695. //////////////////////////////////////////////////////////////////////////////
  696. //++
  697. //
  698. // CClusCfgServer::CommitChanges
  699. //
  700. // Description:
  701. // Commit the changes to the node.
  702. //
  703. // Arguments:
  704. //
  705. //
  706. // Return Value:
  707. // S_OK
  708. // Success
  709. //
  710. // Remarks:
  711. // None.
  712. //
  713. //--
  714. //////////////////////////////////////////////////////////////////////////////
  715. STDMETHODIMP
  716. CClusCfgServer::CommitChanges( void )
  717. {
  718. TraceFunc( "[IClusCfgServer]" );
  719. HRESULT hr = S_OK;
  720. HRESULT hrTemp = S_OK;
  721. IClusCfgInitialize * pcci = NULL;
  722. IClusCfgClusterInfo * pClusCfgClusterInfo = NULL;
  723. ECommitMode ecmCommitChangesMode = cmUNKNOWN;
  724. IClusCfgNodeInfo * piccni = NULL;
  725. IPostCfgManager * ppcm = NULL;
  726. IUnknown * punkCallback = NULL;
  727. HANDLE heventPostCfgCompletion = NULL;
  728. IEnumClusCfgManagedResources * peccmr = NULL;
  729. DWORD sc = ERROR_SUCCESS;
  730. MULTI_QI mqiInterfaces[] =
  731. {
  732. { &IID_IClusCfgBaseCluster, NULL, S_OK },
  733. { &IID_IClusCfgInitialize, NULL, S_OK }
  734. };
  735. hr = THR( m_picccCallback->TypeSafeQI( IUnknown, &punkCallback ) );
  736. if ( FAILED( hr ) )
  737. {
  738. goto Cleanup;
  739. } // if:
  740. //
  741. // KB: First, get a pointer to the IClusCfgNodeInfo interface. Use this to get
  742. // a pointer to the IClusCfgClusterInfo interface to see what action needs
  743. // to be committed.
  744. //
  745. if ( m_punkNodeInfo == NULL )
  746. {
  747. hr = THR( GetClusterNodeInfo( &piccni ) );
  748. if ( FAILED( hr ) )
  749. {
  750. goto Cleanup;
  751. } // if:
  752. } // if:
  753. else
  754. {
  755. hr = THR( m_punkNodeInfo->TypeSafeQI( IClusCfgNodeInfo, &piccni ) );
  756. if ( FAILED( hr ) )
  757. {
  758. goto Cleanup;
  759. } // if: we could not get the pointer to the IClusCfgNodeInfo interface
  760. } // else:
  761. hr = THR( piccni->GetClusterConfigInfo( &pClusCfgClusterInfo ) );
  762. if ( FAILED( hr ) )
  763. {
  764. goto Cleanup;
  765. } // if: we could not get the pointer to the IClusCfgClusterInfo interface
  766. hr = STHR( pClusCfgClusterInfo->GetCommitMode( &ecmCommitChangesMode ) );
  767. if ( FAILED( hr ) )
  768. {
  769. goto Cleanup;
  770. } // if:
  771. Assert( ecmCommitChangesMode != cmUNKNOWN );
  772. //
  773. // Create and initialize the BaseClusterAction component
  774. //
  775. hr = THR( HrCoCreateInternalInstanceEx( CLSID_ClusCfgBaseCluster, NULL, CLSCTX_SERVER, NULL, ARRAYSIZE( mqiInterfaces ), mqiInterfaces ) );
  776. if ( FAILED( hr ) && ( hr != CO_S_NOTALLINTERFACES ) )
  777. {
  778. LOG_STATUS_REPORT( L"Failed to CoCreate Base Cluster Actions", hr );
  779. goto Cleanup;
  780. } // if: CoCreateInstanceEx() failed
  781. hr = THR( mqiInterfaces[ 0 ].hr );
  782. if ( FAILED( hr ) )
  783. {
  784. goto Cleanup;
  785. } // if: we could not get a pointer to the IClusCfgBaseCluster interface
  786. //
  787. // Check if we got a pointer to the IClusCfgInitialize interface
  788. hr = mqiInterfaces[ 1 ].hr;
  789. if ( hr == S_OK )
  790. {
  791. hr = THR( ((IClusCfgInitialize *) mqiInterfaces[ 1 ].pItf)->Initialize( punkCallback, m_lcid ) );
  792. if ( FAILED( hr ) )
  793. {
  794. goto Cleanup;
  795. } // if: something went wrong during initialization
  796. } // if: we got a pointer to the IClusCfgInitialize interface
  797. else
  798. {
  799. if ( hr != E_NOINTERFACE )
  800. {
  801. goto Cleanup;
  802. } // if: the interface is supported, but something else went wrong.
  803. } // if: we did not get a pointer to the IClusCfgInitialize interface
  804. //
  805. // Create and initialize the Post configuration manager
  806. //
  807. hr = THR( HrCoCreateInternalInstance( CLSID_ClusCfgPostConfigManager, NULL, CLSCTX_SERVER, TypeSafeParams( IPostCfgManager, &ppcm ) ) );
  808. if ( FAILED( hr ) )
  809. {
  810. STATUS_REPORT_REF(
  811. TASKID_Major_Configure_Cluster_Services
  812. , TASKID_Minor_Cannot_Create_PostCfg_Mgr
  813. , IDS_ERROR_CANNOT_CREATE_POSTCFG_MGR
  814. , IDS_ERROR_CANNOT_CREATE_POSTCFG_MGR_REF
  815. , hr
  816. );
  817. goto Cleanup;
  818. }
  819. // Check if this component supports the callback interface.
  820. hrTemp = THR( ppcm->TypeSafeQI( IClusCfgInitialize, &pcci ) );
  821. if ( FAILED( hrTemp ) )
  822. {
  823. LOG_STATUS_REPORT( L"Could not get a pointer to the IClusCfgInitialize interface. This post configuration manager does not support initialization", hr );
  824. } // if: the callback interface is not supported
  825. else
  826. {
  827. // Initialize this component.
  828. hr = THR( pcci->Initialize( punkCallback, m_lcid ) );
  829. if ( FAILED( hr ) )
  830. {
  831. LOG_STATUS_REPORT( L"Could not initialize the post configuration manager", hr );
  832. goto Cleanup;
  833. } // if: the initialization failed
  834. } // else: the callback interface is supported
  835. if ( m_punkEnumResources != NULL )
  836. {
  837. hr = THR( m_punkEnumResources->TypeSafeQI( IEnumClusCfgManagedResources, &peccmr ) );
  838. } // if: resource enum is not NULL
  839. else
  840. {
  841. //
  842. // If the enumerator is NULL then we are most likely cleaning up a
  843. // node. That also means that we are not creating a cluster or
  844. // adding nodes to a cluster.
  845. //
  846. Assert( ( ecmCommitChangesMode != cmCREATE_CLUSTER ) && ( ecmCommitChangesMode != cmADD_NODE_TO_CLUSTER) );
  847. hr = GetManagedResourcesEnum( &peccmr );
  848. if ( FAILED( hr ) )
  849. {
  850. //
  851. // If we are cleaning up a node then we don't really care if this
  852. // enum loads 100% correctly or not. Any resources in the enum
  853. // that fail to load will simply not participate in the clean up.
  854. //
  855. if ( ecmCommitChangesMode == cmCLEANUP_NODE_AFTER_EVICT )
  856. {
  857. hr = S_OK;
  858. } // if: cleaning up a node
  859. else
  860. {
  861. THR( hr );
  862. goto Cleanup;
  863. } // else: not cleaning up a node
  864. } // if: loading the resource enum failed
  865. } // else: resource enum is NULL
  866. //
  867. // If we are here, then the BaseCluster and Post configuration components were successfully
  868. // created and initialized. Now perform the desired action.
  869. //
  870. if ( ( ecmCommitChangesMode == cmCREATE_CLUSTER ) || ( ecmCommitChangesMode == cmADD_NODE_TO_CLUSTER ) )
  871. {
  872. if ( !m_fCanBeClustered )
  873. {
  874. //
  875. // TODO: 01-JUN-2000 GalenB
  876. //
  877. // Need better error code... What is the major and minor taskids?
  878. //
  879. hr = S_FALSE;
  880. LOG_STATUS_REPORT( L"It was previously determined that this node cannot be clustered.", hr );
  881. goto Cleanup;
  882. } // if: this node cannot be part of a cluster
  883. //
  884. // If the cluster service is being started for the first time, as a part
  885. // of adding this node to a cluster (forming or joining), then we have
  886. // to wait till the post-configuration steps are completed before we
  887. // can send out notifications. Create an event that indicates that post configuration
  888. // has completed.
  889. //
  890. TraceFlow1( "Trying to create an event named '%s'.", POSTCONFIG_COMPLETE_EVENT_NAME );
  891. //
  892. // Create an event in the unsignalled state.
  893. //
  894. heventPostCfgCompletion = CreateEvent(
  895. NULL // event security attributes
  896. , TRUE // manual-reset event
  897. , FALSE // create in unsignaled state
  898. , POSTCONFIG_COMPLETE_EVENT_NAME
  899. );
  900. if ( heventPostCfgCompletion == NULL )
  901. {
  902. hr = HRESULT_FROM_WIN32( TW32( GetLastError() ) );
  903. LogMsg( L"[SRV] Error %#08x occurred trying to create an event named '%ws'.", hr, POSTCONFIG_COMPLETE_EVENT_NAME );
  904. goto Cleanup;
  905. } // if: we could not get a handle to the event
  906. sc = TW32( ClRtlSetObjSecurityInfo(
  907. heventPostCfgCompletion
  908. , SE_KERNEL_OBJECT
  909. , EVENT_ALL_ACCESS
  910. , EVENT_ALL_ACCESS
  911. , 0
  912. ) );
  913. if ( sc != ERROR_SUCCESS )
  914. {
  915. hr = HRESULT_FROM_WIN32( sc );
  916. LogMsg( "[BC] Error %#08x occurred trying set %s event security.", sc, POSTCONFIG_COMPLETE_EVENT_NAME);
  917. goto Cleanup;
  918. } // if: ClRtlSetObjSecurityInfo failed
  919. //
  920. // Reset the event, just as a safetly measure, in case the event already existed before the call above.
  921. //
  922. if ( ResetEvent( heventPostCfgCompletion ) == 0 )
  923. {
  924. hr = HRESULT_FROM_WIN32( TW32( GetLastError() ) );
  925. LogMsg( L"[SRV] Error %#08x occurred trying to unsignal an event named '%ws'.", hr, POSTCONFIG_COMPLETE_EVENT_NAME );
  926. goto Cleanup;
  927. } // if: ResetEvent() failed()
  928. } // if: we are forming or joining
  929. if ( ecmCommitChangesMode == cmCREATE_CLUSTER )
  930. {
  931. //
  932. // Commit the base cluster
  933. //
  934. hr = THR( HrFormCluster( pClusCfgClusterInfo, (( IClusCfgBaseCluster * ) mqiInterfaces[ 0 ].pItf) ) );
  935. if ( FAILED( hr ) )
  936. {
  937. goto Cleanup;
  938. } // if:
  939. //
  940. // Point of no return: Send a special message so that CCommitPage::SendStatusReport will "display error messages as warnings".
  941. //
  942. if ( m_picccCallback != NULL )
  943. {
  944. hr = THR(
  945. m_picccCallback->SendStatusReport(
  946. NULL
  947. , TASKID_Major_Configure_Cluster_Services
  948. , TASKID_Minor_Errors_To_Warnings_Point
  949. , 0
  950. , 1
  951. , 1
  952. , hr
  953. , NULL
  954. , NULL
  955. , NULL
  956. )
  957. );
  958. } // if: the callback pointer is not NULL
  959. //
  960. // Commit the post configuration steps
  961. //
  962. hr = THR( ppcm->CommitChanges( peccmr, pClusCfgClusterInfo ) );
  963. if ( FAILED( hr ) )
  964. {
  965. goto Cleanup;
  966. } // if:
  967. //
  968. // Signal the event to indicate that post configuration is complete.
  969. //
  970. if ( SetEvent( heventPostCfgCompletion ) == 0 )
  971. {
  972. hr = HRESULT_FROM_WIN32( TW32( GetLastError() ) );
  973. LogMsg( L"[SRV] Error %#08x occurred trying to signal an event named '%ws'.", hr, POSTCONFIG_COMPLETE_EVENT_NAME );
  974. goto Cleanup;
  975. } // if: SetEvent() failed()
  976. } // if: we are forming a cluster.
  977. else if ( ecmCommitChangesMode == cmADD_NODE_TO_CLUSTER )
  978. {
  979. //
  980. // Commit the base cluster
  981. //
  982. hr = THR( HrJoinToCluster( pClusCfgClusterInfo, (( IClusCfgBaseCluster * ) mqiInterfaces[ 0 ].pItf) ) );
  983. if ( FAILED( hr ) )
  984. {
  985. goto Cleanup;
  986. } // if:
  987. //
  988. // Point of no return: Send a special message so that CCommitPage::SendStatusReport will "display error messages as warnings".
  989. //
  990. if ( m_picccCallback != NULL )
  991. {
  992. hr = THR(
  993. m_picccCallback->SendStatusReport(
  994. NULL
  995. , TASKID_Major_Configure_Cluster_Services
  996. , TASKID_Minor_Errors_To_Warnings_Point
  997. , 0
  998. , 1
  999. , 1
  1000. , hr
  1001. , NULL
  1002. , NULL
  1003. , NULL
  1004. )
  1005. );
  1006. } // if: the callback pointer is not NULL
  1007. //
  1008. // Commit the post configuration steps
  1009. //
  1010. hr = THR( ppcm->CommitChanges( peccmr, pClusCfgClusterInfo ) );
  1011. if ( FAILED( hr ) )
  1012. {
  1013. goto Cleanup;
  1014. } // if:
  1015. //
  1016. // Signal the event to indicate that post configuration is complete.
  1017. //
  1018. if ( SetEvent( heventPostCfgCompletion ) == 0 )
  1019. {
  1020. hr = HRESULT_FROM_WIN32( TW32( GetLastError() ) );
  1021. LogMsg( L"[SRV] Error %#08x occurred trying to signal an event named '%ws'.", hr, POSTCONFIG_COMPLETE_EVENT_NAME );
  1022. goto Cleanup;
  1023. } // if: SetEvent() failed()
  1024. } // else if: we are joining a cluster
  1025. else if ( ecmCommitChangesMode == cmCLEANUP_NODE_AFTER_EVICT )
  1026. {
  1027. //
  1028. // This node has been evicted - clean it up.
  1029. //
  1030. hr = THR( HrEvictedFromCluster( ppcm, peccmr, pClusCfgClusterInfo, (( IClusCfgBaseCluster * ) mqiInterfaces[ 0 ].pItf) ) );
  1031. if ( FAILED( hr ) )
  1032. {
  1033. goto Cleanup;
  1034. } // if:
  1035. } // else if: we have just been evicted from a cluster
  1036. Cleanup:
  1037. if ( punkCallback != NULL )
  1038. {
  1039. punkCallback->Release();
  1040. } // if:
  1041. if ( pcci != NULL )
  1042. {
  1043. pcci->Release();
  1044. } // if:
  1045. if ( ppcm != NULL )
  1046. {
  1047. ppcm->Release();
  1048. } // if:
  1049. if ( peccmr != NULL )
  1050. {
  1051. peccmr->Release();
  1052. } // if:
  1053. if ( mqiInterfaces[ 0 ].pItf != NULL )
  1054. {
  1055. mqiInterfaces[ 0 ].pItf->Release();
  1056. } // if:
  1057. if ( mqiInterfaces[ 1 ].pItf != NULL )
  1058. {
  1059. mqiInterfaces[ 1 ].pItf->Release();
  1060. } // if:
  1061. if ( pClusCfgClusterInfo != NULL )
  1062. {
  1063. pClusCfgClusterInfo->Release();
  1064. } // if:
  1065. if ( piccni != NULL )
  1066. {
  1067. piccni->Release();
  1068. } // if:
  1069. if ( heventPostCfgCompletion != NULL )
  1070. {
  1071. //
  1072. // If we had created this event, then signal this event to let the
  1073. // startup notification thread proceed.
  1074. //
  1075. SetEvent( heventPostCfgCompletion );
  1076. CloseHandle( heventPostCfgCompletion );
  1077. } // if:
  1078. if ( FAILED( hr ) )
  1079. {
  1080. STATUS_REPORT_REF(
  1081. TASKID_Major_Configure_Cluster_Services
  1082. , TASKID_Minor_Server_CommitChanges
  1083. , IDS_ERROR_COMMIT_CHANGES
  1084. , IDS_ERROR_COMMIT_CHANGES_REF
  1085. , hr
  1086. );
  1087. } // if:
  1088. HRETURN( hr );
  1089. } //*** CClusCfgServer::CommitChanges
  1090. //////////////////////////////////////////////////////////////////////////////
  1091. //++
  1092. //
  1093. // CClusCfgServer::GetBindingString
  1094. //
  1095. // Description:
  1096. // Get the binding string for this server.
  1097. //
  1098. // Arguments:
  1099. //
  1100. // Return Value:
  1101. //
  1102. // Remarks:
  1103. // None.
  1104. //
  1105. //--
  1106. //////////////////////////////////////////////////////////////////////////////
  1107. STDMETHODIMP
  1108. CClusCfgServer::GetBindingString( BSTR * pbstrBindingStringOut )
  1109. {
  1110. TraceFunc( "[IClusCfgServer]" );
  1111. HRESULT hr = S_OK;
  1112. if ( pbstrBindingStringOut == NULL )
  1113. {
  1114. hr = THR( E_POINTER );
  1115. STATUS_REPORT_REF( TASKID_Major_Find_Devices, TASKID_Minor_Server_GetBindingString_Pointer, IDS_ERROR_NULL_POINTER, IDS_ERROR_NULL_POINTER_REF, hr );
  1116. goto Cleanup;
  1117. } // if:
  1118. if ( m_bstrBindingString == NULL )
  1119. {
  1120. hr = S_FALSE;
  1121. LOG_STATUS_REPORT_MINOR( TASKID_Minor_Server_GetBindingString_NULL, L"Binding string is NULL. Must be a local connection.", hr );
  1122. goto Cleanup;
  1123. } // if:
  1124. *pbstrBindingStringOut = SysAllocString( m_bstrBindingString );
  1125. if ( *pbstrBindingStringOut == NULL )
  1126. {
  1127. hr = THR( E_OUTOFMEMORY );
  1128. STATUS_REPORT_REF( TASKID_Major_Find_Devices, TASKID_Minor_Server_GetBindingString_Memory, IDS_ERROR_OUTOFMEMORY, IDS_ERROR_OUTOFMEMORY_REF, hr );
  1129. } // if:
  1130. Cleanup:
  1131. HRETURN( hr );
  1132. } //*** CClusCfgServer::GetBindingString
  1133. //////////////////////////////////////////////////////////////////////////////
  1134. //++
  1135. //
  1136. // CClusCfgServer::SetBindingString
  1137. //
  1138. // Description:
  1139. // Set the binding string of this server.
  1140. //
  1141. // Arguments:
  1142. //
  1143. // Return Value:
  1144. //
  1145. // Remarks:
  1146. // None.
  1147. //
  1148. //--
  1149. //////////////////////////////////////////////////////////////////////////////
  1150. STDMETHODIMP
  1151. CClusCfgServer::SetBindingString( LPCWSTR pcszBindingStringIn )
  1152. {
  1153. TraceFunc1( "[IClusCfgServer] pcszBindingStringIn = '%ws'", pcszBindingStringIn == NULL ? L"<null>" : pcszBindingStringIn );
  1154. HRESULT hr = S_OK;
  1155. BSTR bstr = NULL;
  1156. if ( pcszBindingStringIn == NULL )
  1157. {
  1158. hr = THR( E_INVALIDARG );
  1159. goto Cleanup;
  1160. } // if:
  1161. bstr = TraceSysAllocString( pcszBindingStringIn );
  1162. if ( bstr == NULL )
  1163. {
  1164. hr = THR( E_OUTOFMEMORY );
  1165. STATUS_REPORT_REF( TASKID_Major_Find_Devices, TASKID_Minor_SetBindingString_Server, IDS_ERROR_OUTOFMEMORY, IDS_ERROR_OUTOFMEMORY_REF, hr );
  1166. goto Cleanup;
  1167. } // if:
  1168. TraceSysFreeString( m_bstrBindingString );
  1169. m_bstrBindingString = bstr;
  1170. Cleanup:
  1171. HRETURN( hr );
  1172. } //*** CClusCfgServer::SetBindingString
  1173. //*************************************************************************//
  1174. /////////////////////////////////////////////////////////////////////////////
  1175. // CClusCfgServer class -- IClusCfgCapabilities interfaces.
  1176. /////////////////////////////////////////////////////////////////////////////
  1177. //////////////////////////////////////////////////////////////////////////////
  1178. //++
  1179. //
  1180. // CClusCfgServer::CanNodeBeClustered
  1181. //
  1182. // Description:
  1183. // Can this node be added to a cluster?
  1184. //
  1185. // Arguments:
  1186. //
  1187. //
  1188. // Return Value:
  1189. // S_OK
  1190. // Node can be clustered.
  1191. //
  1192. // S_FALSE
  1193. // Node cannot be clustered.
  1194. //
  1195. // other HRESULTs
  1196. // The call failed.
  1197. //
  1198. // Remarks:
  1199. // None.
  1200. //
  1201. //--
  1202. //////////////////////////////////////////////////////////////////////////////
  1203. STDMETHODIMP
  1204. CClusCfgServer::CanNodeBeClustered( void )
  1205. {
  1206. TraceFunc( "[IClusCfgServer]" );
  1207. HRESULT hr;
  1208. ICatInformation * pici = NULL;
  1209. CATID rgCatIds[ 1 ];
  1210. IEnumCLSID * pieclsids = NULL;
  1211. IClusCfgCapabilities * piccc = NULL;
  1212. CLSID clsid;
  1213. ULONG cFetched;
  1214. IUnknown * punk = NULL;
  1215. //
  1216. // KB: 10-SEP-2000 GalenB
  1217. //
  1218. // Last ditch effort to clean up a node that is in a bad state before trying
  1219. // to add it into a cluster.
  1220. //
  1221. hr = STHR( HrHasNodeBeenEvicted() );
  1222. if ( hr == S_OK )
  1223. {
  1224. hr = THR( HrCleanUpNode() ) ;
  1225. if ( FAILED( hr ) )
  1226. {
  1227. goto Cleanup;
  1228. } // if:
  1229. } // if:
  1230. else if ( FAILED( hr ) )
  1231. {
  1232. goto Cleanup;
  1233. } // else if:
  1234. rgCatIds[ 0 ] = CATID_ClusCfgCapabilities;
  1235. hr = THR( CoCreateInstance( CLSID_StdComponentCategoriesMgr, NULL, CLSCTX_INPROC_SERVER, IID_ICatInformation, (void **) &pici ) );
  1236. if ( FAILED( hr ) )
  1237. {
  1238. LOG_STATUS_REPORT( L"Failed to CoCreate CLSID_StdComponentCategoriesMgr component", hr );
  1239. goto Cleanup;
  1240. }
  1241. hr = THR( pici->EnumClassesOfCategories( 1, rgCatIds, 0, NULL, &pieclsids ) );
  1242. if ( FAILED( hr ) )
  1243. {
  1244. LOG_STATUS_REPORT( L"Failed to get enumerator for the IClusCfgClusterCapabilites components", hr );
  1245. goto Cleanup;
  1246. } // if:
  1247. for ( ; ; )
  1248. {
  1249. hr = STHR( pieclsids->Next( 1, &clsid, &cFetched ) );
  1250. if ( FAILED( hr ) )
  1251. {
  1252. LOG_STATUS_REPORT( L"IClusCfgClusterCapabilites component enumerator failed", hr );
  1253. break;
  1254. } // if:
  1255. if ( ( hr == S_FALSE ) && ( cFetched == 0 ) )
  1256. {
  1257. hr = S_OK;
  1258. break;
  1259. } // if:
  1260. hr = THR( HrCoCreateInternalInstance( clsid, NULL, CLSCTX_ALL, IID_IClusCfgCapabilities, (void **) &piccc ) );
  1261. if ( FAILED( hr ) )
  1262. {
  1263. LOG_STATUS_REPORT( L"Failed to CoCreate IClusCfgClusterCapabilites component", hr );
  1264. continue;
  1265. } // if:
  1266. hr = THR( piccc->TypeSafeQI( IUnknown, &punk ) );
  1267. if ( FAILED( hr ) )
  1268. {
  1269. LOG_STATUS_REPORT( L"Failed to QI IClusCfgClusterCapabilites component for IUnknown", hr );
  1270. piccc->Release();
  1271. piccc = NULL;
  1272. continue;
  1273. } // if:
  1274. hr = THR( HrSetInitialize( punk, m_picccCallback, m_lcid ) );
  1275. if ( FAILED( hr ) )
  1276. {
  1277. LOG_STATUS_REPORT( L"Failed to initialize IClusCfgClusterCapabilites component", hr );
  1278. piccc->Release();
  1279. piccc = NULL;
  1280. punk->Release();
  1281. punk = NULL;
  1282. continue;
  1283. } // if:
  1284. punk->Release();
  1285. punk = NULL;
  1286. hr = STHR( piccc->CanNodeBeClustered() );
  1287. if ( FAILED( hr ) )
  1288. {
  1289. LOG_STATUS_REPORT( L"IClusCfgClusterCapabilites component failed in CanNodeBeClustered()", hr );
  1290. piccc->Release();
  1291. piccc = NULL;
  1292. continue;
  1293. } // if:
  1294. if ( hr == S_FALSE )
  1295. {
  1296. m_fCanBeClustered = false;
  1297. } // if:
  1298. piccc->Release();
  1299. piccc = NULL;
  1300. } // for:
  1301. if ( !m_fCanBeClustered )
  1302. {
  1303. hr = S_FALSE;
  1304. } // if:
  1305. Cleanup:
  1306. if ( punk != NULL )
  1307. {
  1308. punk->Release();
  1309. } // if:
  1310. if ( piccc != NULL )
  1311. {
  1312. piccc->Release();
  1313. } // if:
  1314. if ( pieclsids != NULL )
  1315. {
  1316. pieclsids->Release();
  1317. } // if:
  1318. if ( pici != NULL )
  1319. {
  1320. pici->Release();
  1321. } // if:
  1322. HRETURN( hr );
  1323. } //*** CClusCfgServer::CanNodeBeClustered
  1324. //*************************************************************************//
  1325. /////////////////////////////////////////////////////////////////////////////
  1326. // CClusCfgServer class -- IClusCfgPollingCallbackInfo interface.
  1327. /////////////////////////////////////////////////////////////////////////////
  1328. //////////////////////////////////////////////////////////////////////////////
  1329. //++
  1330. //
  1331. // CClusCfgServer::GetCallback
  1332. //
  1333. // Description:
  1334. // Return the pointer to the embedded polling callback object.
  1335. //
  1336. // Arguments:
  1337. // ppiccpcOut
  1338. //
  1339. // Return Value:
  1340. // S_OK
  1341. // Success
  1342. //
  1343. // Remarks:
  1344. // None.
  1345. //
  1346. //--
  1347. //////////////////////////////////////////////////////////////////////////////
  1348. STDMETHODIMP
  1349. CClusCfgServer::GetCallback( IClusCfgPollingCallback ** ppiccpcOut )
  1350. {
  1351. TraceFunc( "[IClusCfgServer]" );
  1352. Assert( m_picccCallback != NULL );
  1353. HRESULT hr = S_OK;
  1354. if ( ppiccpcOut == NULL )
  1355. {
  1356. hr = THR( E_POINTER );
  1357. STATUS_REPORT_REF( TASKID_Major_Establish_Connection, TASKID_Minor_GetCallback, IDS_ERROR_NULL_POINTER, IDS_ERROR_NULL_POINTER_REF, hr );
  1358. goto Cleanup;
  1359. } // if:
  1360. hr = THR( m_picccCallback->TypeSafeQI( IClusCfgPollingCallback, ppiccpcOut ) );
  1361. Cleanup:
  1362. HRETURN( hr );
  1363. } //*** CClusCfgServer::GetCallback
  1364. //////////////////////////////////////////////////////////////////////////////
  1365. //++
  1366. //
  1367. // CClusCfgServer::SetPollingMode
  1368. //
  1369. // Description:
  1370. // Set the polling mode of the callback.
  1371. //
  1372. // Arguments:
  1373. // fPollingModeIn
  1374. //
  1375. // Return Value:
  1376. // S_OK
  1377. // Success
  1378. //
  1379. // Remarks:
  1380. // None.
  1381. //
  1382. //--
  1383. //////////////////////////////////////////////////////////////////////////////
  1384. STDMETHODIMP
  1385. CClusCfgServer::SetPollingMode( BOOL fPollingModeIn )
  1386. {
  1387. TraceFunc( "[IClusCfgServer]" );
  1388. Assert( m_picccCallback != NULL );
  1389. HRESULT hr = S_OK;
  1390. IClusCfgSetPollingCallback * piccspc = NULL;
  1391. m_fUsePolling = fPollingModeIn;
  1392. hr = THR( m_picccCallback->TypeSafeQI( IClusCfgSetPollingCallback, &piccspc ) );
  1393. if ( FAILED( hr ) )
  1394. {
  1395. goto Cleanup;
  1396. } // if:
  1397. hr = THR( piccspc->SetPollingMode( m_fUsePolling ) );
  1398. Cleanup:
  1399. if ( piccspc != NULL )
  1400. {
  1401. piccspc->Release();
  1402. } // if:
  1403. HRETURN( hr );
  1404. } //*** CClusCfgServer::SetPollingMode
  1405. //*************************************************************************//
  1406. /////////////////////////////////////////////////////////////////////////////
  1407. // CClusCfgServer class -- IClusCfgVerify interface.
  1408. /////////////////////////////////////////////////////////////////////////////
  1409. //////////////////////////////////////////////////////////////////////////////
  1410. //++
  1411. //
  1412. // CClusCfgServer::VerifyCredentials
  1413. //
  1414. // Description:
  1415. // Validate the passed in credentials.
  1416. //
  1417. // Arguments:
  1418. //
  1419. // Return Value:
  1420. // S_OK
  1421. // The credentials are valid.
  1422. //
  1423. // other HRESULTs
  1424. // The call failed.
  1425. //
  1426. // Remarks:
  1427. // None.
  1428. //
  1429. //--
  1430. //////////////////////////////////////////////////////////////////////////////
  1431. STDMETHODIMP
  1432. CClusCfgServer::VerifyCredentials(
  1433. LPCWSTR pcszNameIn,
  1434. LPCWSTR pcszDomainIn,
  1435. LPCWSTR pcszPasswordIn
  1436. )
  1437. {
  1438. TraceFunc( "[IClusCfgVerify]" );
  1439. HRESULT hr = S_OK;
  1440. HANDLE hToken = NULL;
  1441. DWORD dwSidSize = 0;
  1442. DWORD dwDomainSize = 0;
  1443. SID_NAME_USE snuSidNameUse;
  1444. DWORD sc;
  1445. BSTR bstrDomainName = NULL;
  1446. //
  1447. // Try to find out how much space is required by the SID. If we don't fail with
  1448. // insufficient buffer then we know the account exists.
  1449. //
  1450. hr = THR( HrFormatStringIntoBSTR( L"%1!ws!\\%2!ws!", &bstrDomainName, pcszDomainIn, pcszNameIn ) );
  1451. if ( FAILED( hr ) )
  1452. {
  1453. goto Cleanup;
  1454. } // if:
  1455. if ( LookupAccountName( NULL, bstrDomainName, NULL, &dwSidSize, NULL, &dwDomainSize, &snuSidNameUse ) == FALSE )
  1456. {
  1457. sc = GetLastError();
  1458. if ( sc != ERROR_INSUFFICIENT_BUFFER )
  1459. {
  1460. TW32( sc );
  1461. hr = HRESULT_FROM_WIN32( sc );
  1462. STATUS_REPORT_STRING2_REF(
  1463. TASKID_Minor_Validating_Credentials
  1464. , TASKID_Minor_Invalid_Domain_User
  1465. , IDS_ERROR_INVALID_DOMAIN_USER
  1466. , pcszNameIn
  1467. , pcszDomainIn
  1468. , IDS_ERROR_INVALID_DOMAIN_USER_REF
  1469. , hr
  1470. );
  1471. goto Cleanup;
  1472. } // if:
  1473. } // if:
  1474. //
  1475. // Logon the passed in user to ensure that it is valid.
  1476. //
  1477. if ( !LogonUserW(
  1478. const_cast< LPWSTR >( pcszNameIn )
  1479. , const_cast< LPWSTR >( pcszDomainIn )
  1480. , const_cast< LPWSTR >( pcszPasswordIn )
  1481. , LOGON32_LOGON_NETWORK
  1482. , LOGON32_PROVIDER_DEFAULT
  1483. , &hToken
  1484. ) )
  1485. {
  1486. sc = TW32( GetLastError() );
  1487. hr = HRESULT_FROM_WIN32( sc );
  1488. STATUS_REPORT_STRING2_REF(
  1489. TASKID_Minor_Validating_Credentials
  1490. , TASKID_Minor_Invalid_Credentials
  1491. , IDS_ERROR_INVALID_CREDENTIALS
  1492. , pcszNameIn
  1493. , pcszDomainIn
  1494. , IDS_ERROR_INVALID_CREDENTIALS_REF
  1495. , hr
  1496. );
  1497. goto Cleanup;
  1498. } // if:
  1499. Cleanup:
  1500. TraceSysFreeString( bstrDomainName );
  1501. if ( hToken != NULL )
  1502. {
  1503. CloseHandle( hToken );
  1504. } // if:
  1505. HRETURN( hr );
  1506. } //*** CClusCfgServer::VerifyCredentials
  1507. //////////////////////////////////////////////////////////////////////////////
  1508. //++
  1509. //
  1510. // CClusCfgServer::VerifyConnectionToCluster
  1511. //
  1512. // Description:
  1513. // Verify that that this server is the same as the passed in server.
  1514. //
  1515. // Arguments:
  1516. // pcszClusterNameIn
  1517. //
  1518. // Return Value:
  1519. // S_OK
  1520. // This is the server.
  1521. //
  1522. // S_FALSE
  1523. // This is not the server.
  1524. //
  1525. // other HRESULTs
  1526. // The call failed.
  1527. //
  1528. // Remarks:
  1529. // None.
  1530. //
  1531. //--
  1532. //////////////////////////////////////////////////////////////////////////////
  1533. STDMETHODIMP
  1534. CClusCfgServer::VerifyConnectionToCluster(
  1535. LPCWSTR pcszClusterNameIn
  1536. )
  1537. {
  1538. TraceFunc1( "[IClusCfgVerify] pcszClusterNameIn = '%ws'", pcszClusterNameIn );
  1539. DWORD sc;
  1540. DWORD dwClusterState;
  1541. HRESULT hr = S_OK;
  1542. HCLUSTER hCluster = NULL;
  1543. BSTR bstrClusterName = NULL;
  1544. BSTR bstrLocalFQDN = NULL;
  1545. BSTR bstrGivenHostname = NULL;
  1546. size_t idxGivenDomain = 0;
  1547. size_t idxLocalDomain = 0;
  1548. //
  1549. // Test arguments
  1550. //
  1551. if ( pcszClusterNameIn == NULL )
  1552. {
  1553. hr = THR( E_INVALIDARG );
  1554. STATUS_REPORT_REF( TASKID_Minor_Connecting, TASKID_Minor_VerifyConnection_InvalidArg, IDS_ERROR_INVALIDARG, IDS_ERROR_INVALIDARG_REF, hr );
  1555. goto Cleanup;
  1556. } // if:
  1557. //
  1558. // Gather names necessary for informative status reports.
  1559. //
  1560. hr = THR( HrGetComputerName(
  1561. ComputerNamePhysicalDnsFullyQualified
  1562. , &bstrLocalFQDN
  1563. , FALSE // fBestEffortIn
  1564. ) );
  1565. if ( FAILED( hr ) )
  1566. {
  1567. goto Cleanup;
  1568. }
  1569. hr = THR( HrFindDomainInFQN( bstrLocalFQDN, &idxLocalDomain ) );
  1570. if ( FAILED( hr ) )
  1571. {
  1572. goto Cleanup;
  1573. }
  1574. hr = THR( HrFindDomainInFQN( pcszClusterNameIn, &idxGivenDomain ) );
  1575. if ( FAILED( hr ) )
  1576. {
  1577. goto Cleanup;
  1578. }
  1579. //
  1580. // Get the hostname label from the given name.
  1581. //
  1582. hr = THR( HrExtractPrefixFromFQN( pcszClusterNameIn, &bstrGivenHostname ) );
  1583. if ( FAILED( hr ) )
  1584. {
  1585. goto Cleanup;
  1586. }
  1587. //
  1588. // See if we are clustered.
  1589. //
  1590. sc = TW32( GetNodeClusterState( NULL, &dwClusterState ) );
  1591. if ( sc != ERROR_SUCCESS )
  1592. {
  1593. hr = HRESULT_FROM_WIN32( sc );
  1594. goto Cleanup;
  1595. } // if : GetClusterState() failed
  1596. //
  1597. // If the current cluster node state is neither "running" nor "not running,"
  1598. // then this node is not part of a cluster.
  1599. //
  1600. if ( ( dwClusterState != ClusterStateNotRunning ) && ( dwClusterState != ClusterStateRunning ) )
  1601. {
  1602. hr = S_FALSE;
  1603. STATUS_REPORT_STRING3(
  1604. TASKID_Minor_Connecting
  1605. , TASKID_Minor_VerifyConnection_MachineNotInCluster
  1606. , IDS_WARN_MACHINE_NOT_IN_CLUSTER
  1607. , bstrGivenHostname
  1608. , pcszClusterNameIn + idxGivenDomain
  1609. , bstrLocalFQDN
  1610. , hr
  1611. );
  1612. goto Cleanup;
  1613. } // if:
  1614. //
  1615. // If given name is an FQDN, its hostname label needs to match the cluster's.
  1616. //
  1617. hr = STHR( HrFQNIsFQDN( pcszClusterNameIn ) );
  1618. if ( FAILED( hr ) )
  1619. {
  1620. goto Cleanup;
  1621. } // if:
  1622. else if ( hr == S_OK )
  1623. {
  1624. //
  1625. // Open the cluster to get the cluster's name.
  1626. //
  1627. hCluster = OpenCluster( NULL );
  1628. if ( hCluster == NULL )
  1629. {
  1630. hr = HRESULT_FROM_WIN32( TW32( GetLastError() ) );
  1631. STATUS_REPORT_REF(
  1632. TASKID_Minor_Connecting
  1633. , TASKID_Minor_VerifyConnection_OpenCluster
  1634. , IDS_ERROR_OPEN_CLUSTER_FAILED
  1635. , IDS_ERROR_OPEN_CLUSTER_FAILED_REF
  1636. , hr
  1637. );
  1638. goto Cleanup;
  1639. } // if:
  1640. //
  1641. // Try to get the cluster's name.
  1642. //
  1643. hr = THR( HrGetClusterInformation( hCluster, &bstrClusterName, NULL ) );
  1644. if ( FAILED( hr ) )
  1645. {
  1646. goto Cleanup;
  1647. } // if:
  1648. //
  1649. // If they don't match, the client has connected to an unexpected place.
  1650. //
  1651. if ( NBSTRCompareNoCase( bstrGivenHostname, bstrClusterName ) != 0 )
  1652. {
  1653. hr = S_FALSE;
  1654. STATUS_REPORT_STRING3(
  1655. TASKID_Minor_Connecting
  1656. , TASKID_Minor_VerifyConnection_Cluster_Name_Mismatch
  1657. , IDS_WARN_CLUSTER_NAME_MISMATCH
  1658. , bstrGivenHostname
  1659. , pcszClusterNameIn + idxGivenDomain
  1660. , bstrClusterName
  1661. , hr
  1662. );
  1663. goto Cleanup;
  1664. }
  1665. }
  1666. else if ( hr == S_FALSE )
  1667. {
  1668. //
  1669. // pcszClusterNameIn is an FQIP. Nothing to do regarding the hostname prefix in this case,
  1670. // but reset hr to S_OK to avoid returning bogus errors.
  1671. hr = S_OK;
  1672. }
  1673. //
  1674. // Make sure we are in the expected domain.
  1675. //
  1676. if ( ClRtlStrICmp( pcszClusterNameIn + idxGivenDomain, bstrLocalFQDN + idxLocalDomain ) != 0 )
  1677. {
  1678. hr = S_FALSE;
  1679. STATUS_REPORT_NODESTRING2(
  1680. pcszClusterNameIn
  1681. , TASKID_Minor_Connecting
  1682. , TASKID_Minor_VerifyConnection_Cluster_Domain_Mismatch
  1683. , IDS_WARN_CLUSTER_DOMAIN_MISMATCH
  1684. , pcszClusterNameIn + idxGivenDomain
  1685. , bstrLocalFQDN + idxLocalDomain
  1686. , hr
  1687. );
  1688. goto Cleanup;
  1689. } // if:
  1690. Assert( hr == S_OK );
  1691. goto Cleanup;
  1692. Cleanup:
  1693. if ( hr == S_FALSE )
  1694. {
  1695. LOG_STATUS_REPORT( L"Server name does not match what client is expecting.", hr );
  1696. } // if:
  1697. else if ( hr == S_OK )
  1698. {
  1699. LOG_STATUS_REPORT( L"Server name matches what client is expecting.", hr );
  1700. } // else if:
  1701. if ( hCluster != NULL )
  1702. {
  1703. CloseCluster( hCluster );
  1704. } // if:
  1705. TraceSysFreeString( bstrClusterName );
  1706. TraceSysFreeString( bstrLocalFQDN );
  1707. TraceSysFreeString( bstrGivenHostname );
  1708. HRETURN( hr );
  1709. } // ClusCfgServer::VerifyConnection
  1710. //////////////////////////////////////////////////////////////////////////////
  1711. //++
  1712. //
  1713. // CClusCfgServer::VerifyConnectionToNode
  1714. //
  1715. // Description:
  1716. // Verify that that this server is the same as the passed in server.
  1717. //
  1718. // Arguments:
  1719. // pcszNodeNameIn
  1720. //
  1721. // Return Value:
  1722. // S_OK
  1723. // This is the server.
  1724. //
  1725. // S_FALSE
  1726. // This is not the server.
  1727. //
  1728. // other HRESULTs
  1729. // The call failed.
  1730. //
  1731. // Remarks:
  1732. // None.
  1733. //
  1734. //--
  1735. //////////////////////////////////////////////////////////////////////////////
  1736. STDMETHODIMP
  1737. CClusCfgServer::VerifyConnectionToNode(
  1738. LPCWSTR pcszNodeNameIn
  1739. )
  1740. {
  1741. TraceFunc1( "[IClusCfgVerify] pcszNodeNameIn = '%ws'", pcszNodeNameIn );
  1742. HRESULT hr = S_FALSE;
  1743. Assert( m_bstrNodeName != NULL );
  1744. //
  1745. // Test arguments
  1746. //
  1747. if ( pcszNodeNameIn == NULL )
  1748. {
  1749. hr = THR( E_INVALIDARG );
  1750. goto Cleanup;
  1751. } // if:
  1752. hr = STHR( HrFQNIsFQDN( pcszNodeNameIn ) );
  1753. if ( FAILED( hr ) )
  1754. {
  1755. goto Cleanup;
  1756. } // if:
  1757. if ( hr == S_OK )
  1758. {
  1759. if ( ClRtlStrICmp( pcszNodeNameIn, m_bstrNodeName ) != 0 )
  1760. {
  1761. hr = S_FALSE;
  1762. STATUS_REPORT_STRING2(
  1763. TASKID_Minor_Connecting
  1764. , TASKID_Minor_VerifyConnection_Node_FQDN_Mismatch
  1765. , IDS_WARN_NODE_FQDN_MISMATCH
  1766. , pcszNodeNameIn
  1767. , m_bstrNodeName
  1768. , hr
  1769. );
  1770. goto Cleanup;
  1771. }
  1772. }
  1773. else // pcszNodeNameIn is an FQIP, so compare only domains.
  1774. {
  1775. //
  1776. // pcszNodeNameIn is an FQIP, so compare only domains.
  1777. //
  1778. size_t idxGivenDomain = 0;
  1779. size_t idxThisDomain = 0;
  1780. hr = THR( HrFindDomainInFQN( pcszNodeNameIn, &idxGivenDomain ) );
  1781. if ( FAILED( hr ) )
  1782. {
  1783. goto Cleanup;
  1784. } // if:
  1785. hr = THR( HrFindDomainInFQN( m_bstrNodeName, &idxThisDomain ) );
  1786. if ( FAILED( hr ) )
  1787. {
  1788. goto Cleanup;
  1789. } // if:
  1790. if ( ClRtlStrICmp( pcszNodeNameIn + idxGivenDomain, m_bstrNodeName + idxThisDomain ) == 0 )
  1791. {
  1792. hr = S_OK;
  1793. } // if:
  1794. else
  1795. {
  1796. hr = S_FALSE;
  1797. STATUS_REPORT_NODESTRING2(
  1798. pcszNodeNameIn
  1799. , TASKID_Minor_Connecting
  1800. , TASKID_Minor_VerifyConnection_Node_Domain_Mismatch
  1801. , IDS_WARN_NODE_DOMAIN_MISMATCH
  1802. , pcszNodeNameIn + idxGivenDomain
  1803. , m_bstrNodeName
  1804. , hr
  1805. );
  1806. goto Cleanup;
  1807. }
  1808. }
  1809. Cleanup:
  1810. if ( hr == S_FALSE )
  1811. {
  1812. LogMsg( L"[SRV] VerifyConnection - Server name does not match what client is expecting." );
  1813. } // if:
  1814. else if ( hr == S_OK )
  1815. {
  1816. LogMsg( L"[SRV] VerifyConnection - Server name matches what client is expecting." );
  1817. } // else if:
  1818. HRETURN( hr );
  1819. } //*** ClusCfgServer::VerifyConnectionToNode
  1820. //*************************************************************************//
  1821. /////////////////////////////////////////////////////////////////////////////
  1822. // CClusCfgServer class -- Private Methods.
  1823. /////////////////////////////////////////////////////////////////////////////
  1824. //////////////////////////////////////////////////////////////////////////////
  1825. //++
  1826. //
  1827. // CClusCfgServer::HrInit
  1828. //
  1829. // Description:
  1830. // Initialize this component.
  1831. //
  1832. // Arguments:
  1833. //
  1834. //
  1835. // Return Value:
  1836. // S_OK
  1837. // Success
  1838. //
  1839. // Remarks:
  1840. // None.
  1841. //
  1842. //--
  1843. //////////////////////////////////////////////////////////////////////////////
  1844. HRESULT
  1845. CClusCfgServer::HrInit( void )
  1846. {
  1847. TraceFunc( "" );
  1848. HRESULT hr = S_FALSE;
  1849. IUnknown * punk = NULL;
  1850. // IUnknown
  1851. Assert( m_cRef == 1 );
  1852. hr = THR( CClusCfgCallback::S_HrCreateInstance( &punk ) );
  1853. if ( FAILED ( hr ) )
  1854. {
  1855. LogMsg( L"[SRV] Could not create CClusCfgCallback. (hr = %#08x)", hr );
  1856. goto Cleanup;
  1857. } // if:
  1858. hr = THR( punk->TypeSafeQI( IClusCfgCallback, &m_picccCallback ) );
  1859. if ( FAILED( hr ) )
  1860. {
  1861. LogMsg( L"[SRV] Could not QI callback for a punk. (hr = %#08x)", hr );
  1862. goto Cleanup;
  1863. } // if:
  1864. //
  1865. // Save off the local computer name.
  1866. // If we can't get the fully-qualified name, just get the NetBIOS name.
  1867. //
  1868. hr = THR( HrGetComputerName(
  1869. ComputerNameDnsFullyQualified
  1870. , &m_bstrNodeName
  1871. , TRUE // fBestEffortIn
  1872. ) );
  1873. if ( FAILED( hr ) )
  1874. {
  1875. THR( hr );
  1876. LogMsg( L"[SRV] An error occurred trying to get the fully-qualified Dns name for the local machine during initialization. (hr = %#08x)", hr );
  1877. goto Cleanup;
  1878. } // if: error getting computer name
  1879. Cleanup:
  1880. if ( punk != NULL )
  1881. {
  1882. punk->Release();
  1883. } // if:
  1884. HRETURN( hr );
  1885. } //*** CClusCfgServer::HrInit
  1886. //////////////////////////////////////////////////////////////////////////////
  1887. //++
  1888. //
  1889. // CClusCfgServer::HrInitializeForLocalServer
  1890. //
  1891. // Description:
  1892. // Initialize this component.
  1893. //
  1894. // Arguments:
  1895. //
  1896. //
  1897. // Return Value:
  1898. // S_OK
  1899. // Success
  1900. //
  1901. // Remarks:
  1902. // None.
  1903. //
  1904. //--
  1905. //////////////////////////////////////////////////////////////////////////////
  1906. HRESULT
  1907. CClusCfgServer::HrInitializeForLocalServer( void )
  1908. {
  1909. TraceFunc( "" );
  1910. HRESULT hr = S_OK;
  1911. IWbemLocator * pIWbemLocator = NULL;
  1912. BSTR bstrNameSpace = NULL;
  1913. hr = CoCreateInstance( CLSID_WbemLocator, NULL, CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID *) &pIWbemLocator );
  1914. if ( FAILED( hr ) )
  1915. {
  1916. STATUS_REPORT_REF(
  1917. TASKID_Major_Establish_Connection
  1918. , TASKID_Minor_HrInitializeForLocalServer_WbemLocator
  1919. , IDS_ERROR_WBEM_LOCATOR_CREATE_FAILED
  1920. , IDS_ERROR_WBEM_LOCATOR_CREATE_FAILED_REF
  1921. , hr
  1922. );
  1923. goto Cleanup;
  1924. } // if:
  1925. bstrNameSpace = TraceSysAllocString( L"\\\\.\\root\\cimv2" );
  1926. if ( bstrNameSpace == NULL )
  1927. {
  1928. hr = THR( E_OUTOFMEMORY );
  1929. STATUS_REPORT_REF(
  1930. TASKID_Major_Establish_Connection
  1931. , TASKID_Minor_HrInitializeForLocalServer_Memory
  1932. , IDS_ERROR_OUTOFMEMORY
  1933. , IDS_ERROR_OUTOFMEMORY_REF
  1934. , hr
  1935. );
  1936. goto Cleanup;
  1937. } // if:
  1938. hr = THR( pIWbemLocator->ConnectServer(
  1939. bstrNameSpace,
  1940. NULL, // using current account for simplicity
  1941. NULL, // using current password for simplicity
  1942. NULL, // locale
  1943. 0L, // securityFlags, reserved must be 0
  1944. NULL, // authority (domain for NTLM)
  1945. NULL, // context
  1946. &m_pIWbemServices
  1947. ) );
  1948. if ( FAILED( hr ) )
  1949. {
  1950. STATUS_REPORT_REF(
  1951. TASKID_Major_Establish_Connection
  1952. , TASKID_Minor_WBEM_Connection_Failure
  1953. , IDS_ERROR_WBEM_CONNECTION_FAILURE
  1954. , IDS_ERROR_WBEM_CONNECTION_FAILURE_REF
  1955. , hr
  1956. );
  1957. goto Cleanup;
  1958. } // if:
  1959. hr = THR( HrSetBlanket() );
  1960. if ( FAILED( hr ) )
  1961. {
  1962. LOG_STATUS_REPORT_MINOR(
  1963. TASKID_Minor_HrInitializeForLocalServer_Blanket
  1964. , L"[SRV] The security rights and impersonation levels cannot be set on the connection to the Windows Management Instrumentation service."
  1965. , hr
  1966. );
  1967. goto Cleanup;
  1968. } // if:
  1969. Cleanup:
  1970. TraceSysFreeString( bstrNameSpace );
  1971. if ( pIWbemLocator != NULL )
  1972. {
  1973. pIWbemLocator->Release();
  1974. } // if:
  1975. HRETURN( hr );
  1976. } //*** CClusCfgServer::HrInitializeForLocalServer
  1977. //////////////////////////////////////////////////////////////////////////////
  1978. //++
  1979. //
  1980. // CClusCfgServer::HrSetBlanket
  1981. //
  1982. // Description:
  1983. // Adjusts the security blanket on the IWbemServices pointer.
  1984. //
  1985. // Arguments:
  1986. // None.
  1987. //
  1988. // Return Value:
  1989. //
  1990. //
  1991. // Remarks:
  1992. // None.
  1993. //
  1994. //--
  1995. //////////////////////////////////////////////////////////////////////////////
  1996. HRESULT
  1997. CClusCfgServer::HrSetBlanket( void )
  1998. {
  1999. TraceFunc( "" );
  2000. Assert( m_pIWbemServices != NULL );
  2001. HRESULT hr = S_FALSE;
  2002. if ( m_pIWbemServices )
  2003. {
  2004. IClientSecurity * pCliSec;
  2005. hr = THR( m_pIWbemServices->TypeSafeQI( IClientSecurity, &pCliSec ) );
  2006. if ( SUCCEEDED( hr ) )
  2007. {
  2008. hr = THR( pCliSec->SetBlanket(
  2009. m_pIWbemServices,
  2010. RPC_C_AUTHN_WINNT,
  2011. RPC_C_AUTHZ_NONE,
  2012. NULL,
  2013. RPC_C_AUTHN_LEVEL_CONNECT,
  2014. RPC_C_IMP_LEVEL_IMPERSONATE,
  2015. NULL,
  2016. EOAC_NONE
  2017. ) );
  2018. pCliSec->Release();
  2019. } // if:
  2020. } // if:
  2021. HRETURN( hr );
  2022. } //*** CClusCfgServer::HrSetBlanket
  2023. //////////////////////////////////////////////////////////////////////////////
  2024. //++
  2025. //
  2026. // CClusCfgServer::HrFormCluster
  2027. //
  2028. // Description:
  2029. // Form a new cluster.
  2030. //
  2031. // Arguments:
  2032. // None.
  2033. //
  2034. // Return Value:
  2035. //
  2036. //
  2037. // Remarks:
  2038. // None.
  2039. //
  2040. //--
  2041. //////////////////////////////////////////////////////////////////////////////
  2042. HRESULT
  2043. CClusCfgServer::HrFormCluster(
  2044. IClusCfgClusterInfo * piccciIn,
  2045. IClusCfgBaseCluster * piccbcaIn
  2046. )
  2047. {
  2048. TraceFunc( "" );
  2049. HRESULT hr;
  2050. BSTR bstrClusterName = NULL;
  2051. BSTR bstrClusterBindingString = NULL;
  2052. BSTR bstrClusterIPNetwork = NULL;
  2053. ULONG ulClusterIPAddress = 0;
  2054. ULONG ulClusterIPSubnetMask = 0;
  2055. IClusCfgCredentials * picccServiceAccount = NULL;
  2056. IClusCfgNetworkInfo * piccni = NULL;
  2057. //
  2058. // Get the parameters required to form a cluster.
  2059. //
  2060. hr = THR( piccciIn->GetName( &bstrClusterName ) );
  2061. if ( FAILED( hr ) )
  2062. {
  2063. goto Cleanup;
  2064. } // if: we could not get the name of the cluster
  2065. TraceMemoryAddBSTR( bstrClusterName );
  2066. hr = STHR( piccciIn->GetBindingString( &bstrClusterBindingString ) );
  2067. if ( FAILED( hr ) )
  2068. {
  2069. goto Cleanup;
  2070. } // if: we could not get the binding string of the cluster.
  2071. TraceMemoryAddBSTR( bstrClusterBindingString );
  2072. hr = THR( piccciIn->GetClusterServiceAccountCredentials( &picccServiceAccount ) );
  2073. if ( FAILED( hr ) )
  2074. {
  2075. goto Cleanup;
  2076. } // if: we could not get the cluster service account credentials
  2077. hr = THR( piccciIn->GetIPAddress( &ulClusterIPAddress ) );
  2078. if ( FAILED( hr ) )
  2079. {
  2080. goto Cleanup;
  2081. } // if: we could not get the cluster IP address
  2082. hr = THR( piccciIn->GetSubnetMask( &ulClusterIPSubnetMask ) );
  2083. if ( FAILED( hr ) )
  2084. {
  2085. goto Cleanup;
  2086. } // if: we could not get the cluster subnet mask
  2087. hr = THR( piccciIn->GetNetworkInfo( &piccni ) );
  2088. if ( FAILED( hr ) )
  2089. {
  2090. goto Cleanup;
  2091. } // if: we could not get the network info of the network the cluster name should be on.
  2092. hr = THR( piccni->GetName( &bstrClusterIPNetwork ) );
  2093. if ( FAILED( hr ) )
  2094. {
  2095. goto Cleanup;
  2096. } // if: we could not get the name of the cluster name network.
  2097. TraceMemoryAddBSTR( bstrClusterIPNetwork );
  2098. //
  2099. // Indicate that a cluster should be created when Commit() is called.
  2100. //
  2101. hr = THR( piccbcaIn->SetCreate(
  2102. bstrClusterName
  2103. , bstrClusterBindingString
  2104. , picccServiceAccount
  2105. , ulClusterIPAddress
  2106. , ulClusterIPSubnetMask
  2107. , bstrClusterIPNetwork
  2108. ) );
  2109. if ( FAILED( hr ) )
  2110. {
  2111. goto Cleanup;
  2112. } // if: SetCreate() failed.
  2113. // Initiate cluster creation.
  2114. hr = THR( piccbcaIn->Commit() );
  2115. Cleanup:
  2116. TraceSysFreeString( bstrClusterName );
  2117. TraceSysFreeString( bstrClusterBindingString );
  2118. TraceSysFreeString( bstrClusterIPNetwork );
  2119. if ( piccni != NULL )
  2120. {
  2121. piccni->Release();
  2122. } // if:
  2123. if ( picccServiceAccount != NULL )
  2124. {
  2125. picccServiceAccount->Release();
  2126. } // if:
  2127. HRETURN( hr );
  2128. } //*** CClusCfgServer::HrFormCluster
  2129. //////////////////////////////////////////////////////////////////////////////
  2130. //++
  2131. //
  2132. // CClusCfgServer::HrJoinToCluster
  2133. //
  2134. // Description:
  2135. // Join a node to a cluster.
  2136. //
  2137. // Arguments:
  2138. // None.
  2139. //
  2140. // Return Value:
  2141. //
  2142. //
  2143. // Remarks:
  2144. // None.
  2145. //
  2146. //--
  2147. //////////////////////////////////////////////////////////////////////////////
  2148. HRESULT
  2149. CClusCfgServer::HrJoinToCluster(
  2150. IClusCfgClusterInfo * piccciIn,
  2151. IClusCfgBaseCluster * piccbcaIn
  2152. )
  2153. {
  2154. TraceFunc( "" );
  2155. HRESULT hr;
  2156. BSTR bstrClusterName = NULL;
  2157. BSTR bstrClusterBindingString = NULL;
  2158. IClusCfgCredentials * picccServiceAccount = NULL;
  2159. //
  2160. // Get the parameters required to form a cluster.
  2161. //
  2162. hr = THR( piccciIn->GetName( &bstrClusterName ) );
  2163. if ( FAILED( hr ) )
  2164. {
  2165. goto Cleanup;
  2166. } // if: we could not get the name of the cluster
  2167. TraceMemoryAddBSTR( bstrClusterName );
  2168. hr = THR( piccciIn->GetBindingString( &bstrClusterBindingString ) );
  2169. if ( FAILED( hr ) )
  2170. {
  2171. goto Cleanup;
  2172. } // if: we could not get the cluster binding string.
  2173. TraceMemoryAddBSTR( bstrClusterBindingString );
  2174. hr = THR( piccciIn->GetClusterServiceAccountCredentials( &picccServiceAccount ) );
  2175. if ( FAILED( hr ) )
  2176. {
  2177. goto Cleanup;
  2178. } // if: we could not get the cluster service account credentials
  2179. //
  2180. // Indicate that a cluster should be formed when Commit() is called.
  2181. //
  2182. hr = THR( piccbcaIn->SetAdd( bstrClusterName, bstrClusterBindingString, picccServiceAccount ) );
  2183. if ( FAILED( hr ) )
  2184. {
  2185. goto Cleanup;
  2186. } // if: SetAdd() failed.
  2187. // Initiate joining of the node to the cluster.
  2188. hr = THR( piccbcaIn->Commit() );
  2189. Cleanup:
  2190. TraceSysFreeString( bstrClusterName );
  2191. TraceSysFreeString( bstrClusterBindingString );
  2192. if ( picccServiceAccount != NULL )
  2193. {
  2194. picccServiceAccount->Release();
  2195. } // if:
  2196. HRETURN( hr );
  2197. } //*** CClusCfgServer::HrJoinToCluster
  2198. //////////////////////////////////////////////////////////////////////////////
  2199. //++
  2200. //
  2201. // CClusCfgServer::HrEvictedFromCluster
  2202. //
  2203. // Description:
  2204. // Cleanup after a node has been evicted from a cluster. If another cleanup
  2205. // session is in progress, wait for it to complete and then attempt cleanup.
  2206. // In this way, if the other cleanup failed, this will retry it. If it had
  2207. // suceeded, this will do nothing.
  2208. //
  2209. // This function first calls the CommitChanges() method of the PostConfigManager
  2210. // (which will inform resource types and memberset listeners that this node
  2211. // has been evicted). It then cleans up the base cluster.
  2212. //
  2213. // Arguments:
  2214. // ppcmIn
  2215. // Pointer to the IPostCfgManager interface
  2216. //
  2217. // peccmrIn
  2218. // Argument needed by the IPostCfgManager::CommitChanges()
  2219. //
  2220. // piccciIn
  2221. // Pointer to the cluster info
  2222. //
  2223. // piccbcaIn
  2224. // Pointer to the IClusCfgBaseCluster interface that is used to clean up
  2225. // the base cluster.
  2226. //
  2227. // Return Value:
  2228. // S_OK
  2229. // If everything went well
  2230. //
  2231. // other HRESULTs
  2232. // If the call failed
  2233. //
  2234. // Remarks:
  2235. // None.
  2236. //
  2237. //--
  2238. //////////////////////////////////////////////////////////////////////////////
  2239. HRESULT
  2240. CClusCfgServer::HrEvictedFromCluster(
  2241. IPostCfgManager * ppcmIn,
  2242. IEnumClusCfgManagedResources * peccmrIn,
  2243. IClusCfgClusterInfo * piccciIn,
  2244. IClusCfgBaseCluster * piccbcaIn
  2245. )
  2246. {
  2247. TraceFunc( "" );
  2248. HRESULT hr = S_OK;
  2249. DWORD dwStatus = ERROR_SUCCESS;
  2250. HANDLE hsCleanupLock = NULL;
  2251. HANDLE heventCleanupComplete = NULL;
  2252. bool fLockAcquired = false;
  2253. DWORD dwClusterState;
  2254. HKEY hNodeStateKey = NULL;
  2255. DWORD dwEvictState = 1;
  2256. LogMsg( "[SRV] Creating cleanup lock." );
  2257. // First, try and acquire a lock, so that two cleanup operations cannot overlap.
  2258. hsCleanupLock = CreateSemaphore( NULL, 1, 1, CLEANUP_LOCK_NAME );
  2259. if ( hsCleanupLock == NULL )
  2260. {
  2261. hr = HRESULT_FROM_WIN32( TW32( GetLastError() ) );
  2262. LogMsg( "[SRV] Error %#08x occurred trying to create the cleanup lock.", hr );
  2263. goto Cleanup;
  2264. } // CreateSemaphore() failed
  2265. LogMsg( "[SRV] Acquiring cleanup lock." );
  2266. do
  2267. {
  2268. // Wait for any message sent or posted to this queue
  2269. // or for our lock to be released.
  2270. dwStatus = MsgWaitForMultipleObjects( 1, &hsCleanupLock, FALSE, CC_DEFAULT_TIMEOUT, QS_ALLINPUT );
  2271. // The result tells us the type of event we have.
  2272. if ( dwStatus == ( WAIT_OBJECT_0 + 1 ) )
  2273. {
  2274. MSG msg;
  2275. // Read all of the messages in this next loop,
  2276. // removing each message as we read it.
  2277. while ( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) != 0 )
  2278. {
  2279. // If it is a quit message, we are done pumping messages.
  2280. if ( msg.message == WM_QUIT)
  2281. {
  2282. TraceFlow( "Get a WM_QUIT message. Cleanup message pump loop." );
  2283. break;
  2284. } // if: we got a WM_QUIT message
  2285. // Otherwise, dispatch the message.
  2286. DispatchMessage( &msg );
  2287. } // while: there are still messages in the window message queue
  2288. } // if: we have a message in the window message queue
  2289. else
  2290. {
  2291. if ( dwStatus == WAIT_OBJECT_0 )
  2292. {
  2293. fLockAcquired = true;
  2294. LogMsg( "[SRV] Cleanup lock acquired." );
  2295. break;
  2296. } // else if: our lock is signaled
  2297. else
  2298. {
  2299. if ( dwStatus == -1 )
  2300. {
  2301. hr = HRESULT_FROM_WIN32( TW32( GetLastError() ) );
  2302. LogMsg( "[SRV] Error %#08x occurred trying to wait for our lock to be granted.", hr );
  2303. } // if: MsgWaitForMultipleObjects() returned an error
  2304. else
  2305. {
  2306. hr = THR( HRESULT_FROM_WIN32( dwStatus ) );
  2307. LogMsg( "[SRV] An error occurred trying to wait for our lock to be granted. Status code is %#08x.", dwStatus );
  2308. } // else: an unexpected value was returned by MsgWaitForMultipleObjects()
  2309. break;
  2310. } // else: an unexpected result
  2311. } // else: MsgWaitForMultipleObjects() exited for a reason other than a waiting message
  2312. }
  2313. while( true ); // do-while: loop infinitely
  2314. if ( FAILED( hr ) )
  2315. {
  2316. goto Cleanup;
  2317. } // if: we could not acquire the cleanup lock
  2318. // Check if the install state is correct before invoking post configuration manager.
  2319. // Ignore the case where the service does not exist so that we can do our job.
  2320. dwStatus = GetNodeClusterState( NULL, &dwClusterState );
  2321. if ( dwStatus == ERROR_SERVICE_DOES_NOT_EXIST )
  2322. {
  2323. LogMsg( "[SRV] GetNodeClusterState() determined that the cluster service does not exist." );
  2324. }
  2325. else if ( dwStatus != ERROR_SUCCESS )
  2326. {
  2327. LogMsg( "[SRV] Error %#08x occurred trying to determine the installation state of this node.", dwStatus );
  2328. hr = HRESULT_FROM_WIN32( TW32( dwStatus ) );
  2329. goto Cleanup;
  2330. } // if : GetClusterState() failed
  2331. // Check if this node is part of a cluster.
  2332. if ( ( dwClusterState != ClusterStateNotRunning ) && ( dwClusterState != ClusterStateRunning ) )
  2333. {
  2334. LogMsg( "[SRV] This node is not part of a cluster - no cleanup is necessary." );
  2335. goto Cleanup;
  2336. } // if: this node is not part of a cluster
  2337. //
  2338. // Set a registry value indicating that this node has been evicted.
  2339. // If, for some reason, the cleanup could not be completed, the cluster
  2340. // service will check this flag the next time it comes up and restarts
  2341. // cleanup.
  2342. //
  2343. dwStatus = TW32(
  2344. RegOpenKeyEx(
  2345. HKEY_LOCAL_MACHINE
  2346. , CLUSREG_KEYNAME_NODE_DATA
  2347. , 0
  2348. , KEY_ALL_ACCESS
  2349. , &hNodeStateKey
  2350. )
  2351. );
  2352. if ( dwStatus != ERROR_SUCCESS )
  2353. {
  2354. hr = HRESULT_FROM_WIN32( dwStatus );
  2355. LogMsg( "[SRV] Error %#08x occurred trying to open a registry key to set a value indicating that this node has been evicted.", dwStatus );
  2356. goto Cleanup;
  2357. } // if: RegOpenKeyEx() has failed
  2358. dwStatus = TW32(
  2359. RegSetValueEx(
  2360. hNodeStateKey
  2361. , CLUSREG_NAME_EVICTION_STATE
  2362. , 0
  2363. , REG_DWORD
  2364. , reinterpret_cast< const BYTE * >( &dwEvictState )
  2365. , sizeof( dwEvictState )
  2366. )
  2367. );
  2368. if ( dwStatus != ERROR_SUCCESS )
  2369. {
  2370. hr = HRESULT_FROM_WIN32( dwStatus );
  2371. LogMsg( "[SRV] Error %#08x occurred trying to set a registry value indicating that this node has been evicted.", dwStatus );
  2372. goto Cleanup;
  2373. } // if: RegSetValueEx() has failed
  2374. // Commit the post configuration steps first
  2375. hr = THR( ppcmIn->CommitChanges( peccmrIn, piccciIn ) );
  2376. if ( FAILED( hr ) )
  2377. {
  2378. LogMsg( "[SRV] Error %#08x occurred during the post configuration step of cleanup.", hr );
  2379. goto Cleanup;
  2380. } // if: post configuration failed
  2381. TraceFlow( "IPostCfgManager::CommitChanges() completed successfully during cleanup." );
  2382. hr = THR( piccbcaIn->SetCleanup() );
  2383. if ( FAILED( hr ) )
  2384. {
  2385. LogMsg( "[SRV] Error %#08x occurred initiating cleanup of the base cluster.", hr );
  2386. goto Cleanup;
  2387. } // if: SetCleanup() failed
  2388. // Initiate the cleanup
  2389. hr = THR( piccbcaIn->Commit() );
  2390. if ( FAILED( hr ) )
  2391. {
  2392. LogMsg( "[SRV] Error %#08x occurred trying to cleanup the base cluster.", hr );
  2393. goto Cleanup;
  2394. } // if: base cluster cleanup failed
  2395. LogMsg( "[SRV] Base cluster successfully cleaned up." );
  2396. // If we are here, then cleanup has completed successfully. If some other process is waiting
  2397. // for cleanup to complete, release that process by signaling an event.
  2398. // Open the event. Note, if this event does not already exist, then it means that nobody is
  2399. // waiting on this event. So, it is ok for OpenEvent to fail.
  2400. heventCleanupComplete = OpenEvent( EVENT_ALL_ACCESS, FALSE, SUCCESSFUL_CLEANUP_EVENT_NAME );
  2401. if ( heventCleanupComplete == NULL )
  2402. {
  2403. dwStatus = GetLastError();
  2404. LogMsg( "[SRV] Status %#08x was returned trying to open the cleanup completion event. This just means that no process is waiting on this event.", dwStatus );
  2405. goto Cleanup;
  2406. } // if: OpenEvent() failed
  2407. if ( PulseEvent( heventCleanupComplete ) == FALSE )
  2408. {
  2409. // Error, but not fatal. hr should still be S_OK.
  2410. dwStatus = TW32( GetLastError() );
  2411. LogMsg( "[SRV] Error %#08x occurred trying to pulse the cleanup completion event. This is not a fatal error.", dwStatus );
  2412. goto Cleanup;
  2413. } // if: PulseEvent() failed
  2414. TraceFlow( "Cleanup completion event has been set." );
  2415. Cleanup:
  2416. if ( heventCleanupComplete == NULL )
  2417. {
  2418. CloseHandle( heventCleanupComplete );
  2419. } // if: we had opened the cleanup complete event
  2420. if ( hsCleanupLock != NULL )
  2421. {
  2422. if ( fLockAcquired )
  2423. {
  2424. ReleaseSemaphore( hsCleanupLock, 1, NULL );
  2425. LogMsg( "[SRV] Cleanup lock released." );
  2426. } // if: we have acquired the semaphore but not released it yet
  2427. CloseHandle( hsCleanupLock );
  2428. } // if: we had created a cleanup lock
  2429. if ( hNodeStateKey != NULL )
  2430. {
  2431. RegCloseKey( hNodeStateKey );
  2432. } // if: we had opened the node state registry key
  2433. HRETURN( hr );
  2434. } //*** CClusCfgServer::HrEvictedFromCluster
  2435. //////////////////////////////////////////////////////////////////////////////
  2436. //++
  2437. //
  2438. // CClusCfgServer::HrHasNodeBeenEvicted
  2439. //
  2440. // Description:
  2441. // Has this node been evicted?
  2442. //
  2443. // Arguments:
  2444. //
  2445. //
  2446. // Return Value:
  2447. // S_OK
  2448. // The node needs to be cleanedup.
  2449. //
  2450. // S_FALSE
  2451. // The node does not need to be cleanup.
  2452. //
  2453. // Win32 error as HRESULT.
  2454. //
  2455. // Remarks:
  2456. // None.
  2457. //
  2458. //--
  2459. //////////////////////////////////////////////////////////////////////////////
  2460. HRESULT
  2461. CClusCfgServer::HrHasNodeBeenEvicted( void )
  2462. {
  2463. TraceFunc( "" );
  2464. HRESULT hr = S_FALSE;
  2465. DWORD sc;
  2466. DWORD dwClusterState;
  2467. BOOL fEvicted = false;
  2468. sc = TW32( GetNodeClusterState( NULL, &dwClusterState ) );
  2469. if ( sc != ERROR_SUCCESS )
  2470. {
  2471. hr = HRESULT_FROM_WIN32( sc );
  2472. goto Cleanup;
  2473. } // if : GetClusterState() failed
  2474. //
  2475. // If the cluster service is not running then we need to check if we should
  2476. // clean it up or not.
  2477. //
  2478. if ( dwClusterState == ClusterStateNotRunning )
  2479. {
  2480. sc = TW32( ClRtlHasNodeBeenEvicted( &fEvicted ) );
  2481. if ( sc != ERROR_SUCCESS )
  2482. {
  2483. hr = HRESULT_FROM_WIN32( sc );
  2484. goto Cleanup;
  2485. } // if:
  2486. if ( fEvicted )
  2487. {
  2488. hr = S_OK;
  2489. } // if:
  2490. } // if:
  2491. Cleanup:
  2492. HRETURN( hr );
  2493. } //*** CClusCfgServer::HrHasNodeBeenEvicted
  2494. /////////////////////////////////////////////////////////////////////////////
  2495. //++
  2496. //
  2497. // CClusCfgServer::HrCleanUpNode
  2498. //
  2499. // Description:
  2500. // Cleanup this node because it was evicted.
  2501. //
  2502. // Arguments:
  2503. // None.
  2504. //
  2505. // Return Value:
  2506. // S_OK
  2507. // Success.
  2508. //
  2509. // Remarks:
  2510. // None.
  2511. //
  2512. //--
  2513. //////////////////////////////////////////////////////////////////////////////
  2514. HRESULT
  2515. CClusCfgServer::HrCleanUpNode( void )
  2516. {
  2517. TraceFunc( "" );
  2518. HRESULT hr = S_OK;
  2519. IClusCfgEvictCleanup * pcceEvict = NULL;
  2520. hr = THR(
  2521. CoCreateInstance(
  2522. CLSID_ClusCfgEvictCleanup
  2523. , NULL
  2524. , CLSCTX_LOCAL_SERVER
  2525. , __uuidof( pcceEvict )
  2526. , reinterpret_cast< void ** >( &pcceEvict )
  2527. ) );
  2528. if ( FAILED( hr ) )
  2529. {
  2530. goto Cleanup;
  2531. } // if: the ClusCfgEvictCleanup object could not be created
  2532. hr = THR( pcceEvict->CleanupLocalNode( 0 ) ); // 0 means "cleanup immediately"
  2533. if ( FAILED( hr ) )
  2534. {
  2535. goto Cleanup;
  2536. } // if: an error occurred during cleanup
  2537. Cleanup:
  2538. if ( pcceEvict != NULL )
  2539. {
  2540. pcceEvict->Release();
  2541. } // if:
  2542. HRETURN( hr );
  2543. } //*** CClusCfgServer::HrCleanUpNode
  2544. /////////////////////////////////////////////////////////////////////////////
  2545. //++
  2546. //
  2547. // CClusCfgServer::HrCreateClusterNodeInfo
  2548. //
  2549. // Description:
  2550. // Create the cluster node info object and store it in the member
  2551. // variable.
  2552. //
  2553. // Arguments:
  2554. // None.
  2555. //
  2556. // Return Value:
  2557. // S_OK
  2558. // Success.
  2559. //
  2560. // Remarks:
  2561. // None.
  2562. //
  2563. //--
  2564. //////////////////////////////////////////////////////////////////////////////
  2565. HRESULT
  2566. CClusCfgServer::HrCreateClusterNodeInfo( void )
  2567. {
  2568. TraceFunc( "" );
  2569. Assert( m_punkNodeInfo == NULL );
  2570. HRESULT hr = S_OK;
  2571. hr = THR( CClusCfgNodeInfo::S_HrCreateInstance( &m_punkNodeInfo ) );
  2572. if ( FAILED( hr ) )
  2573. {
  2574. goto Cleanup;
  2575. } // if:
  2576. m_punkNodeInfo = TraceInterface( L"CClusCfgNodeInfo", IUnknown, m_punkNodeInfo, 1 );
  2577. hr = THR( HrSetInitialize( m_punkNodeInfo, m_picccCallback, m_lcid ) );
  2578. if ( FAILED( hr ) )
  2579. {
  2580. goto Cleanup;
  2581. } // if:
  2582. hr = THR( HrSetWbemServices( m_punkNodeInfo, m_pIWbemServices ) );
  2583. Cleanup:
  2584. HRETURN( hr );
  2585. } //*** CClusCfgServer::HrCreateClusterNodeInfo