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.

2967 lines
80 KiB

  1. /////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) 1997-2002 Microsoft Corporation
  4. //
  5. // Module Name:
  6. // ClusNode.cpp
  7. //
  8. // Description:
  9. // Implementation of the node classes for the MSCLUS automation classes.
  10. //
  11. // Author:
  12. // Charles Stacy Harris (stacyh) 28-Feb-1997
  13. // Galen Barbee (galenb) July 1998
  14. //
  15. // Revision History:
  16. // July 1998 GalenB Maaaaaajjjjjjjjjoooooorrrr clean up
  17. //
  18. // Notes:
  19. //
  20. /////////////////////////////////////////////////////////////////////////////
  21. #include "stdafx.h"
  22. #include "ClusterObject.h"
  23. #include "property.h"
  24. #include "clusres.h"
  25. #include "clusresg.h"
  26. #include "clusneti.h"
  27. #include "clusnode.h"
  28. /////////////////////////////////////////////////////////////////////////////
  29. // Global variables
  30. /////////////////////////////////////////////////////////////////////////////
  31. static const IID * iidCClusNode[] =
  32. {
  33. &IID_ISClusNode
  34. };
  35. static const IID * iidCClusNodes[] =
  36. {
  37. &IID_ISClusNodes
  38. };
  39. static const IID * iidCClusResGroupPreferredOwnerNodes[] =
  40. {
  41. &IID_ISClusResGroupPreferredOwnerNodes
  42. };
  43. static const IID * iidCClusResPossibleOwnerNodes[] =
  44. {
  45. &IID_ISClusResPossibleOwnerNodes
  46. };
  47. static const IID * iidCClusResTypePossibleOwnerNodes[] =
  48. {
  49. &IID_ISClusResTypePossibleOwnerNodes
  50. };
  51. //*************************************************************************//
  52. /////////////////////////////////////////////////////////////////////////////
  53. // CClusNode class
  54. /////////////////////////////////////////////////////////////////////////////
  55. /////////////////////////////////////////////////////////////////////////////
  56. //++
  57. //
  58. // CClusNode::CClusNode
  59. //
  60. // Description:
  61. // Constructor.
  62. //
  63. // Arguments:
  64. // None.
  65. //
  66. // Return Value:
  67. // None.
  68. //
  69. //--
  70. /////////////////////////////////////////////////////////////////////////////
  71. CClusNode::CClusNode( void )
  72. {
  73. m_hNode = NULL;
  74. m_pClusRefObject = NULL;
  75. m_pResourceGroups = NULL;
  76. m_pCommonProperties = NULL;
  77. m_pPrivateProperties = NULL;
  78. m_pCommonROProperties = NULL;
  79. m_pPrivateROProperties = NULL;
  80. m_pNetInterfaces = NULL;
  81. m_piids = (const IID *) iidCClusNode;
  82. m_piidsSize = ARRAYSIZE( iidCClusNode );
  83. } //*** CClusNode::CClusNode()
  84. /////////////////////////////////////////////////////////////////////////////
  85. //++
  86. //
  87. // CClusNode::~CClusNode
  88. //
  89. // Description:
  90. // Destructor.
  91. //
  92. // Arguments:
  93. // None.
  94. //
  95. // Return Value:
  96. // None.
  97. //
  98. //--
  99. /////////////////////////////////////////////////////////////////////////////
  100. CClusNode::~CClusNode( void )
  101. {
  102. if ( m_hNode != NULL )
  103. {
  104. ::CloseClusterNode( m_hNode );
  105. m_hNode = NULL;
  106. } // if:
  107. if ( m_pResourceGroups != NULL )
  108. {
  109. m_pResourceGroups->Release();
  110. m_pResourceGroups = NULL;
  111. } // if:
  112. if ( m_pCommonProperties != NULL )
  113. {
  114. m_pCommonProperties->Release();
  115. m_pCommonProperties = NULL;
  116. } // if: release the property collection
  117. if ( m_pPrivateProperties != NULL )
  118. {
  119. m_pPrivateProperties->Release();
  120. m_pPrivateProperties = NULL;
  121. } // if: release the property collection
  122. if ( m_pCommonROProperties != NULL )
  123. {
  124. m_pCommonROProperties->Release();
  125. m_pCommonROProperties = NULL;
  126. } // if: release the property collection
  127. if ( m_pPrivateROProperties != NULL )
  128. {
  129. m_pPrivateROProperties->Release();
  130. m_pPrivateROProperties = NULL;
  131. } // if: release the property collection
  132. if ( m_pNetInterfaces != NULL )
  133. {
  134. m_pNetInterfaces->Release();
  135. m_pNetInterfaces = NULL;
  136. } // if:
  137. if ( m_pClusRefObject != NULL )
  138. {
  139. m_pClusRefObject->Release();
  140. m_pClusRefObject = NULL;
  141. } // if:
  142. } //*** CClusNode::~CClusNode()
  143. /////////////////////////////////////////////////////////////////////////////
  144. //++
  145. //
  146. // CClusNode::Open
  147. //
  148. // Description:
  149. // Retrieve this object's (Node) data from the cluster.
  150. //
  151. // Arguments:
  152. // pClusRefObject [IN] - Wraps the cluster handle.
  153. // bstrNodeName [IN] - The name of the node to open.
  154. //
  155. // Return Value:
  156. // S_OK if successful, E_POINTER, or other Win32 error as HRESULT.
  157. //
  158. //--
  159. /////////////////////////////////////////////////////////////////////////////
  160. HRESULT CClusNode::Open(
  161. IN ISClusRefObject * pClusRefObject,
  162. IN BSTR bstrNodeName
  163. )
  164. {
  165. ASSERT( pClusRefObject != NULL );
  166. ASSERT( bstrNodeName != NULL);
  167. HRESULT _hr = E_POINTER;
  168. if ( ( pClusRefObject != NULL ) && ( bstrNodeName != NULL ) )
  169. {
  170. m_pClusRefObject = pClusRefObject;
  171. m_pClusRefObject->AddRef();
  172. HCLUSTER hCluster = NULL;
  173. _hr = m_pClusRefObject->get_Handle( (ULONG_PTR *) &hCluster );
  174. if ( SUCCEEDED( _hr ) )
  175. {
  176. m_hNode = ::OpenClusterNode( hCluster, bstrNodeName );
  177. if ( m_hNode == 0 )
  178. {
  179. DWORD _sc = GetLastError();
  180. _hr = HRESULT_FROM_WIN32( _sc );
  181. } // if: the node failed to open
  182. else
  183. {
  184. m_bstrNodeName = bstrNodeName;
  185. _hr = S_OK;
  186. } // else: we opened the node
  187. } // if: we have a cluster handle
  188. } // if: non NULL args
  189. return _hr;
  190. } //*** CClusNode::Open()
  191. /////////////////////////////////////////////////////////////////////////////
  192. //++
  193. //
  194. // CClusNode::GetProperties
  195. //
  196. // Description:
  197. // Creates a property collection for this object type (Node).
  198. //
  199. // Arguments:
  200. // ppProperties [OUT] - Catches the newly created collection.
  201. // bPrivate [IN] - Are these private properties? Or Common?
  202. // bReadOnly [IN] - Are these read only properties?
  203. //
  204. // Return Value:
  205. // S_OK if successful, or other HRESULT error.
  206. //
  207. //--
  208. /////////////////////////////////////////////////////////////////////////////
  209. HRESULT CClusNode::GetProperties(
  210. ISClusProperties ** ppProperties,
  211. BOOL bPrivate,
  212. BOOL bReadOnly
  213. )
  214. {
  215. //ASSERT( ppProperties != NULL );
  216. HRESULT _hr = E_POINTER;
  217. if ( ppProperties != NULL )
  218. {
  219. CComObject< CClusProperties > * pProperties = NULL;
  220. *ppProperties = NULL;
  221. _hr = CComObject< CClusProperties >::CreateInstance( &pProperties );
  222. if ( SUCCEEDED( _hr ) )
  223. {
  224. CSmartPtr< CComObject< CClusProperties > > ptrProperties( pProperties );
  225. _hr = ptrProperties->Create( this, bPrivate, bReadOnly );
  226. if ( SUCCEEDED( _hr ) )
  227. {
  228. _hr = ptrProperties->Refresh();
  229. if ( SUCCEEDED( _hr ) )
  230. {
  231. _hr = ptrProperties->QueryInterface( IID_ISClusProperties, (void **) ppProperties );
  232. if ( SUCCEEDED( _hr ) )
  233. {
  234. ptrProperties->AddRef();
  235. if ( bPrivate )
  236. {
  237. if ( bReadOnly )
  238. {
  239. m_pPrivateROProperties = ptrProperties;
  240. }
  241. else
  242. {
  243. m_pPrivateProperties = ptrProperties;
  244. }
  245. }
  246. else
  247. {
  248. if ( bReadOnly )
  249. {
  250. m_pCommonROProperties = ptrProperties;
  251. }
  252. else
  253. {
  254. m_pCommonProperties = ptrProperties;
  255. }
  256. }
  257. }
  258. }
  259. }
  260. }
  261. } // if: non NULL args
  262. return _hr;
  263. } //*** CClusNode::GetProperties()
  264. /////////////////////////////////////////////////////////////////////////////
  265. //++
  266. //
  267. // CClusNode::get_Handle
  268. //
  269. // Description:
  270. // Get the native handle for this object (Node).
  271. //
  272. // Arguments:
  273. // phandle [OUT] - Catches the handle.
  274. //
  275. // Return Value:
  276. // S_OK if successful, or E_POINTER.
  277. //
  278. //--
  279. /////////////////////////////////////////////////////////////////////////////
  280. STDMETHODIMP CClusNode::get_Handle( OUT ULONG_PTR * phandle )
  281. {
  282. //ASSERT( phandle != NULL );
  283. ASSERT( m_hNode != NULL );
  284. HRESULT _hr = E_POINTER;
  285. if ( phandle != NULL )
  286. {
  287. if ( m_hNode != NULL )
  288. {
  289. *phandle = (ULONG_PTR) m_hNode;
  290. _hr = S_OK;
  291. } // if: node handle not NULL
  292. } // if: argument no NULL
  293. return _hr;
  294. } //*** CClusNode::get_Handle()
  295. /////////////////////////////////////////////////////////////////////////////
  296. //++
  297. //
  298. // CClusNode::Close
  299. //
  300. // Description:
  301. // Close this object (Node).
  302. //
  303. // Arguments:
  304. // None.
  305. //
  306. // Return Value:
  307. // S_OK if successful, or other Win32 error as HRESULT.
  308. //
  309. //--
  310. /////////////////////////////////////////////////////////////////////////////
  311. HRESULT CClusNode::Close( void )
  312. {
  313. HRESULT _hr = S_FALSE;
  314. if ( m_hNode != NULL )
  315. {
  316. if ( ::CloseClusterNode( m_hNode ) )
  317. {
  318. m_hNode = NULL;
  319. _hr = S_OK;
  320. }
  321. else
  322. {
  323. DWORD _sc = GetLastError();
  324. _hr = HRESULT_FROM_WIN32( _sc );
  325. }
  326. }
  327. return _hr;
  328. } //*** CClusNode::Close()
  329. /////////////////////////////////////////////////////////////////////////////
  330. //++
  331. //
  332. // CClusNode::get_Name
  333. //
  334. // Description:
  335. // Return the name of this object (Node).
  336. //
  337. // Arguments:
  338. // pbstrNodeName [OUT] - Catches the name of this object.
  339. //
  340. // Return Value:
  341. // S_OK if successful, E_POINTER, or other HRESULT error.
  342. //
  343. //--
  344. /////////////////////////////////////////////////////////////////////////////
  345. STDMETHODIMP CClusNode::get_Name( BSTR * pbstrNodeName )
  346. {
  347. //ASSERT( pbstrNodeName != NULL );
  348. HRESULT _hr = E_POINTER;
  349. if ( pbstrNodeName != NULL )
  350. {
  351. *pbstrNodeName = m_bstrNodeName.Copy();
  352. _hr = S_OK;
  353. }
  354. return _hr;
  355. } //*** CClusNode::get_Name()
  356. /////////////////////////////////////////////////////////////////////////////
  357. //++
  358. //
  359. // CClusNode::get_NodeID
  360. //
  361. // Description:
  362. // Get the ID of this node.
  363. //
  364. // Arguments:
  365. // pbstrNodeID [OUT] - Catches the node id.
  366. //
  367. // Return Value:
  368. // S_OK if successful, E_POINTER, or other Win32 error as HRESULT.
  369. //
  370. //--
  371. /////////////////////////////////////////////////////////////////////////////
  372. STDMETHODIMP CClusNode::get_NodeID( OUT BSTR * pbstrNodeID )
  373. {
  374. //ASSERT( pbstrNodeID != NULL );
  375. HRESULT _hr = E_POINTER;
  376. if ( pbstrNodeID != NULL )
  377. {
  378. LPWSTR pwszNodeID;
  379. DWORD dwRet = ERROR_SUCCESS;
  380. dwRet = ::WrapGetClusterNodeId( m_hNode, &pwszNodeID );
  381. if ( dwRet == ERROR_SUCCESS )
  382. {
  383. *pbstrNodeID = ::SysAllocString( pwszNodeID );
  384. if ( *pbstrNodeID == NULL )
  385. {
  386. _hr = E_OUTOFMEMORY;
  387. }
  388. ::LocalFree( pwszNodeID );
  389. } // if: got node ID...
  390. _hr = HRESULT_FROM_WIN32( dwRet );
  391. }
  392. return _hr;
  393. } //*** CClusNode::get_NodeID()
  394. /////////////////////////////////////////////////////////////////////////////
  395. //++
  396. //
  397. // CClusNode::get_State
  398. //
  399. // Description:
  400. // Get the current state of the cluster node. Up/down/paused, etc.
  401. //
  402. // Arguments:
  403. // pState [OUT] - Catches the node state.
  404. //
  405. // Return Value:
  406. // S_OK if successful, E_POINTER, or other Win32 error as HRESULT.
  407. //
  408. //--
  409. /////////////////////////////////////////////////////////////////////////////
  410. STDMETHODIMP CClusNode::get_State( OUT CLUSTER_NODE_STATE * pState )
  411. {
  412. //ASSERT( pState != NULL );
  413. HRESULT _hr = E_POINTER;
  414. if ( pState != NULL )
  415. {
  416. CLUSTER_NODE_STATE cns;
  417. cns = ::GetClusterNodeState( m_hNode );
  418. if ( cns == ClusterNodeStateUnknown )
  419. {
  420. DWORD _sc = GetLastError();
  421. _hr = HRESULT_FROM_WIN32( _sc );
  422. }
  423. else
  424. {
  425. *pState = cns;
  426. _hr = S_OK;
  427. }
  428. }
  429. return _hr;
  430. } //*** CClusNode::get_State()
  431. /////////////////////////////////////////////////////////////////////////////
  432. //++
  433. //
  434. // CClusNode::Pause
  435. //
  436. // Description:
  437. // Pause this cluster node.
  438. //
  439. // Arguments:
  440. // None.
  441. //
  442. // Return Value:
  443. // S_OK if successful, E_POINTER, or other Win32 error as HRESULT.
  444. //
  445. //--
  446. /////////////////////////////////////////////////////////////////////////////
  447. STDMETHODIMP CClusNode::Pause( void )
  448. {
  449. HRESULT _hr = E_POINTER;
  450. if ( m_hNode != NULL )
  451. {
  452. DWORD _sc = ::PauseClusterNode( m_hNode );
  453. _hr = HRESULT_FROM_WIN32( _sc );
  454. }
  455. return _hr;
  456. } //*** CClusNode::Pause()
  457. /////////////////////////////////////////////////////////////////////////////
  458. //++
  459. //
  460. // CClusNode::Resume
  461. //
  462. // Description:
  463. // Resume this paused cluster node.
  464. //
  465. // Arguments:
  466. // None.
  467. //
  468. // Return Value:
  469. // S_OK if successful, E_POINTER, or other Win32 error as HRESULT.
  470. //
  471. //--
  472. /////////////////////////////////////////////////////////////////////////////
  473. STDMETHODIMP CClusNode::Resume( void )
  474. {
  475. HRESULT _hr = E_POINTER;
  476. if ( m_hNode != NULL )
  477. {
  478. DWORD _sc = ::ResumeClusterNode( m_hNode );
  479. _hr = HRESULT_FROM_WIN32( _sc );
  480. }
  481. return _hr;
  482. } //*** CClusNode::Resume()
  483. /////////////////////////////////////////////////////////////////////////////
  484. //++
  485. //
  486. // CClusNode::Evict
  487. //
  488. // Description:
  489. // Evict this node from the cluster.
  490. //
  491. // Arguments:
  492. // None.
  493. //
  494. // Return Value:
  495. // S_OK if successful, E_POINTER, or other Win32 error as HRESULT.
  496. //
  497. //--
  498. /////////////////////////////////////////////////////////////////////////////
  499. STDMETHODIMP CClusNode::Evict( void )
  500. {
  501. HRESULT _hr = E_POINTER;
  502. if ( m_hNode != NULL )
  503. {
  504. DWORD _sc = ::EvictClusterNode( m_hNode );
  505. _hr = HRESULT_FROM_WIN32( _sc );
  506. }
  507. return _hr;
  508. } //*** CClusNode::Evict()
  509. /////////////////////////////////////////////////////////////////////////////
  510. //++
  511. //
  512. // CClusNode::get_ResourceGroups
  513. //
  514. // Description:
  515. // Get the collection of groups that are active on this node.
  516. //
  517. // Arguments:
  518. // ppResourceGroups [OUT] - Catches the collection of groups.
  519. //
  520. // Return Value:
  521. // S_OK if successful, E_POINTER, or other Win32 error as HRESULT.
  522. //
  523. //--
  524. /////////////////////////////////////////////////////////////////////////////
  525. STDMETHODIMP CClusNode::get_ResourceGroups(
  526. OUT ISClusResGroups ** ppResourceGroups
  527. )
  528. {
  529. return ::HrCreateResourceCollection< CClusResGroups, ISClusResGroups, CComBSTR >(
  530. &m_pResourceGroups,
  531. m_bstrNodeName,
  532. ppResourceGroups,
  533. IID_ISClusResGroups,
  534. m_pClusRefObject
  535. );
  536. } //*** CClusNode::get_ResourceGroups()
  537. /////////////////////////////////////////////////////////////////////////////
  538. //++
  539. //
  540. // CClusNode::get_CommonProperties
  541. //
  542. // Description:
  543. // Get this object's (Node) common properties collection.
  544. //
  545. // Arguments:
  546. // ppProperties [OUT] - Catches the properties collection.
  547. //
  548. // Return Value:
  549. // S_OK if successful, or other HRESULT error.
  550. //
  551. //--
  552. /////////////////////////////////////////////////////////////////////////////
  553. STDMETHODIMP CClusNode::get_CommonProperties(
  554. OUT ISClusProperties ** ppProperties
  555. )
  556. {
  557. //ASSERT( ppProperties != NULL );
  558. HRESULT _hr = E_POINTER;
  559. if ( ppProperties != NULL )
  560. {
  561. if ( m_pCommonProperties )
  562. {
  563. _hr = m_pCommonProperties->QueryInterface( IID_ISClusProperties, (void **) ppProperties );
  564. }
  565. else
  566. {
  567. _hr = GetProperties( ppProperties, FALSE, FALSE );
  568. }
  569. }
  570. return _hr;
  571. } //*** CClusNode::get_CommonProperties()
  572. /////////////////////////////////////////////////////////////////////////////
  573. //++
  574. //
  575. // CClusNode::get_PrivateProperties
  576. //
  577. // Description:
  578. // Get this object's (Node) private properties collection.
  579. //
  580. // Arguments:
  581. // ppProperties [OUT] - Catches the properties collection.
  582. //
  583. // Return Value:
  584. // S_OK if successful, or other HRESULT error.
  585. //
  586. //--
  587. /////////////////////////////////////////////////////////////////////////////
  588. STDMETHODIMP CClusNode::get_PrivateProperties(
  589. OUT ISClusProperties ** ppProperties
  590. )
  591. {
  592. //ASSERT( ppProperties != NULL );
  593. HRESULT _hr = E_POINTER;
  594. if ( ppProperties != NULL )
  595. {
  596. if ( m_pPrivateProperties )
  597. {
  598. _hr = m_pPrivateProperties->QueryInterface( IID_ISClusProperties, (void **) ppProperties );
  599. }
  600. else
  601. {
  602. _hr = GetProperties( ppProperties, TRUE, FALSE );
  603. }
  604. }
  605. return _hr;
  606. } //*** CClusNode::get_PrivateProperties()
  607. /////////////////////////////////////////////////////////////////////////////
  608. //++
  609. //
  610. // CClusNode::get_CommonROProperties
  611. //
  612. // Description:
  613. // Get this object's (Node) common read only properties collection.
  614. //
  615. // Arguments:
  616. // ppProperties [OUT] - Catches the properties collection.
  617. //
  618. // Return Value:
  619. // S_OK if successful, or other HRESULT error.
  620. //
  621. //--
  622. /////////////////////////////////////////////////////////////////////////////
  623. STDMETHODIMP CClusNode::get_CommonROProperties(
  624. OUT ISClusProperties ** ppProperties
  625. )
  626. {
  627. //ASSERT( ppProperties != NULL );
  628. HRESULT _hr = E_POINTER;
  629. if ( ppProperties != NULL )
  630. {
  631. if ( m_pCommonROProperties )
  632. {
  633. _hr = m_pCommonROProperties->QueryInterface( IID_ISClusProperties, (void **) ppProperties );
  634. }
  635. else
  636. {
  637. _hr = GetProperties( ppProperties, FALSE, TRUE );
  638. }
  639. }
  640. return _hr;
  641. } //*** CClusNode::get_CommonROProperties()
  642. /////////////////////////////////////////////////////////////////////////////
  643. //++
  644. //
  645. // CClusNode::get_PrivateROProperties
  646. //
  647. // Description:
  648. // Get this object's (Node) private read only properties collection.
  649. //
  650. // Arguments:
  651. // ppProperties [OUT] - Catches the properties collection.
  652. //
  653. // Return Value:
  654. // S_OK if successful, or other HRESULT error.
  655. //
  656. //--
  657. /////////////////////////////////////////////////////////////////////////////
  658. STDMETHODIMP CClusNode::get_PrivateROProperties(
  659. OUT ISClusProperties ** ppProperties
  660. )
  661. {
  662. //ASSERT( ppProperties != NULL );
  663. HRESULT _hr = E_POINTER;
  664. if ( ppProperties != NULL )
  665. {
  666. if ( m_pPrivateROProperties )
  667. {
  668. _hr = m_pPrivateROProperties->QueryInterface( IID_ISClusProperties, (void **) ppProperties );
  669. }
  670. else
  671. {
  672. _hr = GetProperties( ppProperties, TRUE, TRUE );
  673. }
  674. }
  675. return _hr;
  676. } //*** CClusNode::get_PrivateROProperties()
  677. /////////////////////////////////////////////////////////////////////////////
  678. //++
  679. //
  680. // CClusNode::get_NetInterfaces
  681. //
  682. // Description:
  683. // Get this object's (Node) network interfaces collection.
  684. //
  685. // Arguments:
  686. // ppNetInterfaces [OUT] - Catches the network interfaces collection.
  687. //
  688. // Return Value:
  689. // S_OK if successful, E_POINTER, or other HRESULT error.
  690. //
  691. //--
  692. /////////////////////////////////////////////////////////////////////////////
  693. STDMETHODIMP CClusNode::get_NetInterfaces(
  694. OUT ISClusNodeNetInterfaces ** ppNetInterfaces
  695. )
  696. {
  697. return ::HrCreateResourceCollection< CClusNodeNetInterfaces, ISClusNodeNetInterfaces, HNODE >(
  698. &m_pNetInterfaces,
  699. m_hNode,
  700. ppNetInterfaces,
  701. IID_ISClusNodeNetInterfaces,
  702. m_pClusRefObject
  703. );
  704. } //*** CClusNode::get_NetInterfaces()
  705. /////////////////////////////////////////////////////////////////////////////
  706. //++
  707. //
  708. // CClusNode::get_Cluster
  709. //
  710. // Description:
  711. // Returns the parent cluster of this node.
  712. //
  713. // Arguments:
  714. // ppCluster [OUT] - Catches the cluster parent.
  715. //
  716. // Return Value:
  717. // S_OK if successful, E_POINTER, or other Win32 error as HRESULT.
  718. //
  719. //--
  720. /////////////////////////////////////////////////////////////////////////////
  721. STDMETHODIMP CClusNode::get_Cluster( OUT ISCluster ** ppCluster )
  722. {
  723. return ::HrGetCluster( ppCluster, m_pClusRefObject );
  724. } //*** CClusNode::get_Cluster()
  725. /////////////////////////////////////////////////////////////////////////////
  726. //++
  727. //
  728. // CClusNode::HrLoadProperties
  729. //
  730. // Description:
  731. // This virtual function does the actual load of the property list from
  732. // the cluster.
  733. //
  734. // Arguments:
  735. // rcplPropList [IN OUT] - The property list to load.
  736. // bReadOnly [IN] - Load the read only properties?
  737. // bPrivate [IN] - Load the common or the private properties?
  738. //
  739. // Return Value:
  740. // S_OK if successful, or other Win32 error as HRESULT error.
  741. //
  742. //--
  743. /////////////////////////////////////////////////////////////////////////////
  744. HRESULT CClusNode::HrLoadProperties(
  745. IN OUT CClusPropList & rcplPropList,
  746. IN BOOL bReadOnly,
  747. IN BOOL bPrivate
  748. )
  749. {
  750. HRESULT _hr = S_FALSE;
  751. DWORD _dwControlCode = 0;
  752. DWORD _sc = ERROR_SUCCESS;
  753. if ( bReadOnly )
  754. {
  755. _dwControlCode = bPrivate
  756. ? CLUSCTL_NODE_GET_RO_PRIVATE_PROPERTIES
  757. : CLUSCTL_NODE_GET_RO_COMMON_PROPERTIES;
  758. }
  759. else
  760. {
  761. _dwControlCode = bPrivate
  762. ? CLUSCTL_NODE_GET_PRIVATE_PROPERTIES
  763. : CLUSCTL_NODE_GET_COMMON_PROPERTIES;
  764. }
  765. _sc = rcplPropList.ScGetNodeProperties( m_hNode, _dwControlCode );
  766. _hr = HRESULT_FROM_WIN32( _sc );
  767. return _hr;
  768. } //*** CClusNode::HrLoadProperties()
  769. /////////////////////////////////////////////////////////////////////////////
  770. //++
  771. //
  772. // CClusNode::ScWriteProperties
  773. //
  774. // Description:
  775. // This virtual function does the actual saving of the property list to
  776. // the cluster.
  777. //
  778. // Arguments:
  779. // rcplPropList [IN] - The property list to save.
  780. // bPrivate [IN] - Save the common or the private properties?
  781. //
  782. // Return Value:
  783. // ERROR_SUCCESS if successful, or other Win32 error if not.
  784. //
  785. //--
  786. /////////////////////////////////////////////////////////////////////////////
  787. DWORD CClusNode::ScWriteProperties(
  788. const CClusPropList & rcplPropList,
  789. BOOL bPrivate
  790. )
  791. {
  792. DWORD dwControlCode = bPrivate ? CLUSCTL_NODE_SET_PRIVATE_PROPERTIES : CLUSCTL_NODE_SET_COMMON_PROPERTIES;
  793. DWORD nBytesReturned = 0;
  794. DWORD _sc = ERROR_SUCCESS;
  795. _sc = ClusterNodeControl(
  796. m_hNode,
  797. NULL,
  798. dwControlCode,
  799. rcplPropList,
  800. rcplPropList.CbBufferSize(),
  801. 0,
  802. 0,
  803. &nBytesReturned
  804. );
  805. return _sc;
  806. } //*** CClusNode::ScWriteProperties()
  807. //*************************************************************************//
  808. /////////////////////////////////////////////////////////////////////////////
  809. // CNodes class
  810. /////////////////////////////////////////////////////////////////////////////
  811. /////////////////////////////////////////////////////////////////////////////
  812. //++
  813. //
  814. // CNodes::CNodes
  815. //
  816. // Description:
  817. // Constructor. This class implements functionality common to all node
  818. // collections.
  819. //
  820. // Arguments:
  821. // None.
  822. //
  823. // Return Value:
  824. // None.
  825. //
  826. //--
  827. /////////////////////////////////////////////////////////////////////////////
  828. CNodes::CNodes( void )
  829. {
  830. m_pClusRefObject = NULL;
  831. } //*** CNodes::CNodes()
  832. /////////////////////////////////////////////////////////////////////////////
  833. //++
  834. //
  835. // CNodes::~CNodes
  836. //
  837. // Description:
  838. // Desctructor.
  839. //
  840. // Arguments:
  841. // None.
  842. //
  843. // Return Value:
  844. // None.
  845. //
  846. //--
  847. /////////////////////////////////////////////////////////////////////////////
  848. CNodes::~CNodes( void )
  849. {
  850. Clear();
  851. if ( m_pClusRefObject != NULL )
  852. {
  853. m_pClusRefObject->Release();
  854. m_pClusRefObject = NULL;
  855. } // if:
  856. } //*** CNodes::~CNodes()
  857. /////////////////////////////////////////////////////////////////////////////
  858. //++
  859. //
  860. // CNodes::Create
  861. //
  862. // Description:
  863. // Finish creating the object by doing things that cannot be done in
  864. // a light weight constructor.
  865. //
  866. // Arguments:
  867. // pClusRefObject [IN] - Wraps the cluster handle.
  868. //
  869. // Return Value:
  870. // S_OK if successful or E_POINTER if not.
  871. //
  872. //--
  873. /////////////////////////////////////////////////////////////////////////////
  874. HRESULT CNodes::Create( IN ISClusRefObject * pClusRefObject )
  875. {
  876. ASSERT( pClusRefObject != NULL );
  877. HRESULT _hr = E_POINTER;
  878. if ( pClusRefObject != NULL )
  879. {
  880. m_pClusRefObject = pClusRefObject;
  881. m_pClusRefObject->AddRef();
  882. _hr = S_OK;
  883. }
  884. return _hr;
  885. } //*** CNodes::Create()
  886. /////////////////////////////////////////////////////////////////////////////
  887. //++
  888. //
  889. // CNodes::Clear
  890. //
  891. // Description:
  892. // Release the objects in the vector and clean up the vector.
  893. //
  894. // Arguments:
  895. // None.
  896. //
  897. // Return Value:
  898. // None.
  899. //
  900. //--
  901. /////////////////////////////////////////////////////////////////////////////
  902. void CNodes::Clear( void )
  903. {
  904. ::ReleaseAndEmptyCollection< NodeList, CComObject< CClusNode > >( m_Nodes );
  905. } //*** CNodes::Clear()
  906. /////////////////////////////////////////////////////////////////////////////
  907. //++
  908. //
  909. // CNodes::FindItem
  910. //
  911. // Description:
  912. // Find the passed in node in the vector and return its index.
  913. //
  914. // Arguments:
  915. // pwszNodeName [IN] - The node to find.
  916. // pnIndex [OUT] - Catches the node's index.
  917. //
  918. // Return Value:
  919. // S_OK if successful, E_POINTER, or E_INVALIDARG.
  920. //
  921. //--
  922. /////////////////////////////////////////////////////////////////////////////
  923. HRESULT CNodes::FindItem(
  924. IN LPWSTR pwszNodeName,
  925. OUT UINT * pnIndex
  926. )
  927. {
  928. //ASSERT( pwszNodeName != NULL );
  929. //ASSERT( pnIndex != NULL );
  930. HRESULT _hr = E_POINTER;
  931. if ( ( pwszNodeName != NULL ) && ( pnIndex != NULL ) )
  932. {
  933. _hr = E_INVALIDARG;
  934. if ( ! m_Nodes.empty() )
  935. {
  936. CComObject< CClusNode > * pNode = NULL;
  937. NodeList::iterator first = m_Nodes.begin();
  938. NodeList::iterator last = m_Nodes.end();
  939. UINT _iIndex;
  940. for ( _iIndex = 0; first != last; first++, _iIndex++ )
  941. {
  942. pNode = *first;
  943. if ( pNode && ( lstrcmpi( pwszNodeName, pNode->Name() ) == 0 ) )
  944. {
  945. *pnIndex = _iIndex;
  946. _hr = S_OK;
  947. break;
  948. }
  949. }
  950. } // if:
  951. }
  952. return _hr;
  953. } //*** CNodes::FindItem( pwszNodeName )
  954. /////////////////////////////////////////////////////////////////////////////
  955. //++
  956. //
  957. // CNodes::FindItem
  958. //
  959. // Description:
  960. // Find the passed in node in the vector and return its index.
  961. //
  962. // Arguments:
  963. // pClusterNode [IN] - The node to find.
  964. // pnIndex [OUT] - Catches the node's index.
  965. //
  966. // Return Value:
  967. // S_OK if successful, E_POINTER, or E_INVALIDARG.
  968. //
  969. //--
  970. /////////////////////////////////////////////////////////////////////////////
  971. HRESULT CNodes::FindItem(
  972. IN ISClusNode * pClusterNode,
  973. OUT UINT * pnIndex
  974. )
  975. {
  976. //ASSERT( pClusterNode != NULL );
  977. //ASSERT( pnIndex != NULL );
  978. HRESULT _hr = E_POINTER;
  979. if ( ( pClusterNode != NULL ) && ( pnIndex != NULL ) )
  980. {
  981. CComBSTR bstrName;
  982. _hr = pClusterNode->get_Name( &bstrName );
  983. if ( SUCCEEDED( _hr ) )
  984. {
  985. _hr = FindItem( bstrName, pnIndex );
  986. }
  987. }
  988. return _hr;
  989. } //*** CNodes::FindItem( pClusterNode )
  990. /////////////////////////////////////////////////////////////////////////////
  991. //++
  992. //
  993. // CNodes::GetIndex
  994. //
  995. // Description:
  996. // Convert the passed in variant index into the real index in the
  997. // collection.
  998. //
  999. // Arguments:
  1000. // varIndex [IN] - The index to convert.
  1001. // pnIndex [OUT] - Catches the index.
  1002. //
  1003. // Return Value:
  1004. // S_OK if successful, E_POINTER, or E_INVALIDARG.
  1005. //
  1006. //--
  1007. /////////////////////////////////////////////////////////////////////////////
  1008. HRESULT CNodes::GetIndex(
  1009. IN VARIANT varIndex,
  1010. OUT UINT * pnIndex
  1011. )
  1012. {
  1013. //ASSERT( pnIndex != NULL );
  1014. HRESULT _hr = E_POINTER;
  1015. if ( pnIndex != NULL )
  1016. {
  1017. UINT nIndex = 0;
  1018. CComVariant v;
  1019. *pnIndex = 0;
  1020. v.Copy( &varIndex );
  1021. // Check to see if the index is a number.
  1022. _hr = v.ChangeType( VT_I4 );
  1023. if ( SUCCEEDED( _hr ) )
  1024. {
  1025. nIndex = v.lVal;
  1026. nIndex--; // Adjust index to be 0 relative instead of 1 relative
  1027. }
  1028. else
  1029. {
  1030. // Check to see if the index is a string.
  1031. _hr = v.ChangeType( VT_BSTR );
  1032. if ( SUCCEEDED( _hr ) )
  1033. {
  1034. // Search for the string.
  1035. _hr = FindItem( v.bstrVal, &nIndex );
  1036. }
  1037. }
  1038. // We found an index, now check the range.
  1039. if ( SUCCEEDED( _hr ) )
  1040. {
  1041. if ( nIndex < m_Nodes.size() )
  1042. {
  1043. *pnIndex = nIndex;
  1044. }
  1045. else
  1046. {
  1047. _hr = E_INVALIDARG;
  1048. }
  1049. }
  1050. }
  1051. return _hr;
  1052. } //*** CNodes::GetIndex()
  1053. /////////////////////////////////////////////////////////////////////////////
  1054. //++
  1055. //
  1056. // CNodes::GetItem
  1057. //
  1058. // Description:
  1059. // Return the item (Node) by name.
  1060. //
  1061. // Arguments:
  1062. // pwszNodeName [IN] - The name of the item requested.
  1063. // ppClusterNode [OUT] - Catches the item.
  1064. //
  1065. // Return Value:
  1066. // S_OK if successful, E_POINTER, or E_INVALIDARG.
  1067. //
  1068. //--
  1069. /////////////////////////////////////////////////////////////////////////////
  1070. HRESULT CNodes::GetItem(
  1071. IN LPWSTR pwszNodeName,
  1072. OUT ISClusNode ** ppClusterNode
  1073. )
  1074. {
  1075. //ASSERT( pwszNodeName != NULL );
  1076. //ASSERT( ppClusterNode != NULL );
  1077. HRESULT _hr = E_POINTER;
  1078. if ( ( pwszNodeName != NULL ) && ( ppClusterNode != NULL ) )
  1079. {
  1080. CComObject< CClusNode > * pNode = NULL;
  1081. NodeList::iterator first = m_Nodes.begin();
  1082. NodeList::iterator last = m_Nodes.end();
  1083. _hr = E_INVALIDARG;
  1084. for ( ; first != last; first++ )
  1085. {
  1086. pNode = *first;
  1087. if ( pNode && ( lstrcmpi( pwszNodeName, pNode->Name() ) == 0 ) )
  1088. {
  1089. _hr = pNode->QueryInterface( IID_ISClusNode, (void **) ppClusterNode );
  1090. break;
  1091. }
  1092. }
  1093. }
  1094. return _hr;
  1095. } //*** CNodes::GetItem()
  1096. /////////////////////////////////////////////////////////////////////////////
  1097. //++
  1098. //
  1099. // CNodes::GetItem
  1100. //
  1101. // Description:
  1102. // Return the item (Node) by index.
  1103. //
  1104. // Arguments:
  1105. // nIndex [IN] - The name of the item requested.
  1106. // ppClusterNode [OUT] - Catches the item.
  1107. //
  1108. // Return Value:
  1109. // S_OK if successful, E_POINTER, or E_INVALIDARG.
  1110. //
  1111. //--
  1112. /////////////////////////////////////////////////////////////////////////////
  1113. HRESULT CNodes::GetItem( IN UINT nIndex, OUT ISClusNode ** ppClusterNode )
  1114. {
  1115. //ASSERT( ppClusterNode != NULL );
  1116. HRESULT _hr = E_POINTER;
  1117. if ( ppClusterNode != NULL )
  1118. {
  1119. //
  1120. // Automation collections are 1-relative for languages like VB.
  1121. // We are 0-relative internally.
  1122. //
  1123. if ( ( --nIndex ) < m_Nodes.size() )
  1124. {
  1125. CComObject< CClusNode > * pNode = m_Nodes[ nIndex ];
  1126. _hr = pNode->QueryInterface( IID_ISClusNode, (void **) ppClusterNode );
  1127. }
  1128. else
  1129. {
  1130. _hr = E_INVALIDARG;
  1131. }
  1132. }
  1133. return _hr;
  1134. } //*** CNodes::GetItem()
  1135. /////////////////////////////////////////////////////////////////////////////
  1136. //++
  1137. //
  1138. // CNodes::GetNodeItem
  1139. //
  1140. // Description:
  1141. // Return the object (Node) at the passed in index.
  1142. //
  1143. // Arguments:
  1144. // varIndex [IN] - Contains the index requested.
  1145. // ppClusterNode [OUT] - Catches the item.
  1146. //
  1147. // Return Value:
  1148. // S_OK if successful, E_POINTER, or E_INVALIDARG.
  1149. //
  1150. //--
  1151. /////////////////////////////////////////////////////////////////////////////
  1152. HRESULT CNodes::GetNodeItem(
  1153. IN VARIANT varIndex,
  1154. OUT ISClusNode ** ppClusterNode
  1155. )
  1156. {
  1157. //ASSERT( ppClusterNode != NULL );
  1158. HRESULT _hr = E_POINTER;
  1159. if ( ppClusterNode != NULL )
  1160. {
  1161. CComObject<CClusNode> * pNode = NULL;
  1162. UINT nIndex = 0;
  1163. *ppClusterNode = NULL;
  1164. _hr = GetIndex( varIndex, &nIndex );
  1165. if ( SUCCEEDED( _hr ) )
  1166. {
  1167. pNode = m_Nodes[ nIndex ];
  1168. _hr = pNode->QueryInterface( IID_ISClusNode, (void **) ppClusterNode );
  1169. }
  1170. }
  1171. return _hr;
  1172. } //*** CNodes::GetNodeItem()
  1173. /////////////////////////////////////////////////////////////////////////////
  1174. //++
  1175. //
  1176. // CNodes::InsertAt
  1177. //
  1178. // Description:
  1179. // Insert the passed in node into the node list.
  1180. //
  1181. // Arguments:
  1182. // pClusNode [IN] - The node to add.
  1183. // pos [IN] - The position to insert the node at.
  1184. //
  1185. // Return Value:
  1186. // E_POINTER, E_INVALIDARG, or S_OK if successful.
  1187. //
  1188. //--
  1189. /////////////////////////////////////////////////////////////////////////////
  1190. HRESULT CNodes::InsertAt(
  1191. CComObject< CClusNode > * pClusNode,
  1192. size_t pos
  1193. )
  1194. {
  1195. //ASSERT( pClusNode != NULL );
  1196. HRESULT _hr = E_POINTER;
  1197. if ( pClusNode != NULL )
  1198. {
  1199. if ( pos < m_Nodes.size() )
  1200. {
  1201. NodeList::iterator first = m_Nodes.begin();
  1202. NodeList::iterator last = m_Nodes.end();
  1203. size_t _iIndex;
  1204. for ( _iIndex = 0; ( _iIndex < pos ) && ( first != last ); _iIndex++, first++ )
  1205. {
  1206. } // for:
  1207. m_Nodes.insert( first, pClusNode );
  1208. pClusNode->AddRef();
  1209. _hr = S_OK;
  1210. }
  1211. else
  1212. {
  1213. _hr = E_INVALIDARG;
  1214. }
  1215. }
  1216. return _hr;
  1217. } //*** CNodes::InsertAt()
  1218. /////////////////////////////////////////////////////////////////////////////
  1219. //++
  1220. //
  1221. // CNodes::RemoveAt
  1222. //
  1223. // Description:
  1224. // Remove the object from the vector at the passed in position.
  1225. //
  1226. // Arguments:
  1227. // pos [IN] - the position of the object to remove.
  1228. //
  1229. // Return Value:
  1230. // S_OK if successful, or E_INVALIDARG if the position is out of range.
  1231. //
  1232. //--
  1233. /////////////////////////////////////////////////////////////////////////////
  1234. HRESULT CNodes::RemoveAt( size_t pos )
  1235. {
  1236. CComObject<CClusNode> * pNode = NULL;
  1237. NodeList::iterator first = m_Nodes.begin();
  1238. NodeList::const_iterator last = m_Nodes.end();
  1239. HRESULT _hr = E_INVALIDARG;
  1240. size_t _iIndex;
  1241. for ( _iIndex = 0; ( _iIndex < pos ) && ( first != last ); _iIndex++, first++ )
  1242. {
  1243. } // for:
  1244. if ( first != last )
  1245. {
  1246. pNode = *first;
  1247. if ( pNode )
  1248. {
  1249. pNode->Release();
  1250. }
  1251. m_Nodes.erase( first );
  1252. _hr = S_OK;
  1253. }
  1254. return _hr;
  1255. } //*** CNodes::RemoveAt()
  1256. //*************************************************************************//
  1257. /////////////////////////////////////////////////////////////////////////////
  1258. // CClusNodes class
  1259. /////////////////////////////////////////////////////////////////////////////
  1260. /////////////////////////////////////////////////////////////////////////////
  1261. //++
  1262. //
  1263. // CClusNodes::CClusNodes
  1264. //
  1265. // Description:
  1266. // Constructor.
  1267. //
  1268. // Arguments:
  1269. // None.
  1270. //
  1271. // Return Value:
  1272. // None.
  1273. //
  1274. //--
  1275. /////////////////////////////////////////////////////////////////////////////
  1276. CClusNodes::CClusNodes( void )
  1277. {
  1278. m_piids = (const IID *) iidCClusNodes;
  1279. m_piidsSize = ARRAYSIZE( iidCClusNodes );
  1280. } //*** CClusNodes::CClusNodes()
  1281. /////////////////////////////////////////////////////////////////////////////
  1282. //++
  1283. //
  1284. // CClusNodes::~CClusNodes
  1285. //
  1286. // Description:
  1287. // destructor.
  1288. //
  1289. // Arguments:
  1290. // None.
  1291. //
  1292. // Return Value:
  1293. // None.
  1294. //
  1295. //--
  1296. /////////////////////////////////////////////////////////////////////////////
  1297. CClusNodes::~CClusNodes( void )
  1298. {
  1299. Clear();
  1300. } //*** CClusNodes::~CClusNodes()
  1301. /////////////////////////////////////////////////////////////////////////////
  1302. //++
  1303. //
  1304. // CClusNodes::get_Count
  1305. //
  1306. // Description:
  1307. // Return the count of objects (Nodes) in the collection.
  1308. //
  1309. // Arguments:
  1310. // plCount [OUT] - Catches the count.
  1311. //
  1312. // Return Value:
  1313. // S_OK if successful, or E_POINTER.
  1314. //
  1315. //--
  1316. /////////////////////////////////////////////////////////////////////////////
  1317. STDMETHODIMP CClusNodes::get_Count( OUT long * plCount )
  1318. {
  1319. //ASSERT( plCount != NULL );
  1320. HRESULT _hr = E_POINTER;
  1321. if ( plCount != NULL )
  1322. {
  1323. *plCount = m_Nodes.size();
  1324. _hr = S_OK;
  1325. }
  1326. return _hr;
  1327. } //*** CClusNodes::get_Count()
  1328. /////////////////////////////////////////////////////////////////////////////
  1329. //++
  1330. //
  1331. // CClusNodes::get_Item
  1332. //
  1333. // Description:
  1334. // Return the object (Node) at the passed in index.
  1335. //
  1336. // Arguments:
  1337. // varIndex [IN] - Contains the index requested.
  1338. // ppClusterNode [OUT] - Catches the item.
  1339. //
  1340. // Return Value:
  1341. // S_OK if successful, E_POINTER, or E_INVALIDARG.
  1342. //
  1343. //--
  1344. /////////////////////////////////////////////////////////////////////////////
  1345. STDMETHODIMP CClusNodes::get_Item(
  1346. IN VARIANT varIndex,
  1347. OUT ISClusNode ** ppClusterNode
  1348. )
  1349. {
  1350. //ASSERT( ppClusterNode != NULL );
  1351. HRESULT _hr = E_POINTER;
  1352. if ( ppClusterNode != NULL )
  1353. {
  1354. _hr = GetNodeItem(varIndex, ppClusterNode);
  1355. } // if: args are not NULL
  1356. return _hr;
  1357. } //*** CClusNodes::get_Item()
  1358. /////////////////////////////////////////////////////////////////////////////
  1359. //++
  1360. //
  1361. // CClusNodes::get__NewEnum
  1362. //
  1363. // Description:
  1364. // Create and return a new enumeration for this collection.
  1365. //
  1366. // Arguments:
  1367. // ppunk [OUT] - Catches the new enumeration.
  1368. //
  1369. // Return Value:
  1370. // S_OK if successful, E_POINTER, or other HRESULT error.
  1371. //
  1372. //--
  1373. /////////////////////////////////////////////////////////////////////////////
  1374. STDMETHODIMP CClusNodes::get__NewEnum( IUnknown ** ppunk )
  1375. {
  1376. return ::HrNewIDispatchEnum< NodeList, CComObject< CClusNode > >( ppunk, m_Nodes );
  1377. } //*** CClusNodes::get__NewEnum()
  1378. /////////////////////////////////////////////////////////////////////////////
  1379. //++
  1380. //
  1381. // CClusNodes::Refresh
  1382. //
  1383. // Description:
  1384. // Load the collection from the cluster database.
  1385. //
  1386. // Arguments:
  1387. // None.
  1388. //
  1389. // Return Value:
  1390. // S_OK if successful, E_POINTER, or Win32 error as HRESULT.
  1391. //
  1392. //--
  1393. /////////////////////////////////////////////////////////////////////////////
  1394. STDMETHODIMP CClusNodes::Refresh( void )
  1395. {
  1396. HCLUSENUM hEnum = NULL;
  1397. HCLUSTER hCluster = NULL;
  1398. DWORD _sc = ERROR_SUCCESS;
  1399. HRESULT _hr = S_OK;
  1400. ASSERT( m_pClusRefObject != NULL );
  1401. _hr = m_pClusRefObject->get_Handle( (ULONG_PTR *) &hCluster );
  1402. if ( SUCCEEDED( _hr ) )
  1403. {
  1404. hEnum = ::ClusterOpenEnum( hCluster, CLUSTER_ENUM_NODE );
  1405. if ( hEnum != NULL )
  1406. {
  1407. int _nIndex = 0;
  1408. DWORD dwType;
  1409. LPWSTR pszName = NULL;
  1410. CComObject< CClusNode > * pNode = NULL;
  1411. Clear();
  1412. for( _nIndex = 0, _hr = S_OK; SUCCEEDED( _hr ); _nIndex++ )
  1413. {
  1414. _sc = ::WrapClusterEnum( hEnum, _nIndex, &dwType, &pszName );
  1415. if ( _sc == ERROR_NO_MORE_ITEMS )
  1416. {
  1417. _hr = S_OK;
  1418. break;
  1419. }
  1420. else if ( _sc == ERROR_SUCCESS )
  1421. {
  1422. _hr = CComObject< CClusNode >::CreateInstance( &pNode );
  1423. if ( SUCCEEDED( _hr ) )
  1424. {
  1425. CSmartPtr< ISClusRefObject > ptrRefObject( m_pClusRefObject );
  1426. CSmartPtr< CComObject< CClusNode > > ptrNode( pNode );
  1427. BSTR bstr = NULL;
  1428. bstr = SysAllocString( pszName );
  1429. if ( bstr == NULL )
  1430. {
  1431. _hr = E_OUTOFMEMORY;
  1432. }
  1433. else
  1434. {
  1435. _hr = ptrNode->Open( ptrRefObject, bstr );
  1436. if ( SUCCEEDED( _hr ) )
  1437. {
  1438. ptrNode->AddRef();
  1439. m_Nodes.insert( m_Nodes.end(), ptrNode );
  1440. }
  1441. else if ( HRESULT_CODE( _hr ) == ERROR_CLUSTER_NODE_NOT_FOUND )
  1442. {
  1443. //
  1444. // It is possible for the node to have been deleted from the cluster
  1445. // in the time between creating the enum and opening the node. When
  1446. // that happens we need to simply skip that node and continue
  1447. // enumerating.
  1448. //
  1449. _hr = S_FALSE; // success code to keep us in the loop
  1450. } // else if: the cluster node was not found
  1451. SysFreeString( bstr );
  1452. }
  1453. }
  1454. ::LocalFree( pszName );
  1455. pszName = NULL;
  1456. }
  1457. else
  1458. {
  1459. _hr = HRESULT_FROM_WIN32( _sc );
  1460. }
  1461. }
  1462. ::ClusterCloseEnum( hEnum );
  1463. }
  1464. else
  1465. {
  1466. _sc = GetLastError();
  1467. _hr = HRESULT_FROM_WIN32( _sc );
  1468. }
  1469. }
  1470. return _hr;
  1471. } //*** CClusNodes::Refresh()
  1472. //*************************************************************************//
  1473. /////////////////////////////////////////////////////////////////////////////
  1474. // CClusResGroupPreferredOwnerNodes class
  1475. /////////////////////////////////////////////////////////////////////////////
  1476. /////////////////////////////////////////////////////////////////////////////
  1477. //++
  1478. //
  1479. // CClusResGroupPreferredOwnerNodes::CClusResGroupPreferredOwnerNodes
  1480. //
  1481. // Description:
  1482. // Constructor.
  1483. //
  1484. // Arguments:
  1485. // None.
  1486. //
  1487. // Return Value:
  1488. // None.
  1489. //
  1490. //--
  1491. /////////////////////////////////////////////////////////////////////////////
  1492. CClusResGroupPreferredOwnerNodes::CClusResGroupPreferredOwnerNodes( void )
  1493. {
  1494. m_bModified = FALSE;
  1495. m_piids = (const IID *) iidCClusResGroupPreferredOwnerNodes;
  1496. m_piidsSize = ARRAYSIZE( iidCClusResGroupPreferredOwnerNodes );
  1497. } //*** CClusResGroupPreferredOwnerNodes::CClusResGroupPreferredOwnerNodes()
  1498. /////////////////////////////////////////////////////////////////////////////
  1499. //++
  1500. //
  1501. // CClusResGroupPreferredOwnerNodes::~CClusResGroupPreferredOwnerNodes
  1502. //
  1503. // Description:
  1504. // destructor.
  1505. //
  1506. // Arguments:
  1507. // None.
  1508. //
  1509. // Return Value:
  1510. // None.
  1511. //
  1512. //--
  1513. /////////////////////////////////////////////////////////////////////////////
  1514. CClusResGroupPreferredOwnerNodes::~CClusResGroupPreferredOwnerNodes( void )
  1515. {
  1516. Clear();
  1517. } //*** CClusResGroupPreferredOwnerNodes::~CClusResGroupPreferredOwnerNodes()
  1518. /////////////////////////////////////////////////////////////////////////////
  1519. //++
  1520. //
  1521. // CClusResGroupPreferredOwnerNodes::Create
  1522. //
  1523. // Description:
  1524. // Finish creating the object by doing things that cannot be done in
  1525. // a light weight constructor.
  1526. //
  1527. // Arguments:
  1528. // pClusRefObject [IN] - Wraps the cluster handle.
  1529. // hGroup [IN] - Group the collection belongs to.
  1530. //
  1531. // Return Value:
  1532. // S_OK if successful or E_POINTER if not.
  1533. //
  1534. //--
  1535. /////////////////////////////////////////////////////////////////////////////
  1536. HRESULT CClusResGroupPreferredOwnerNodes::Create(
  1537. IN ISClusRefObject * pClusRefObject,
  1538. IN CRefcountedHGROUP hGroup
  1539. )
  1540. {
  1541. HRESULT _hr = E_POINTER;
  1542. _hr = CNodes::Create( pClusRefObject );
  1543. if ( SUCCEEDED( _hr ) )
  1544. {
  1545. m_hGroup = hGroup;
  1546. } // if:
  1547. return _hr;
  1548. } //*** CClusResGroupPreferredOwnerNodes::Create()
  1549. /////////////////////////////////////////////////////////////////////////////
  1550. //++
  1551. //
  1552. // CClusResGroupPreferredOwnerNodes::get_Count
  1553. //
  1554. // Description:
  1555. // Return the count of objects (Nodes) in the collection.
  1556. //
  1557. // Arguments:
  1558. // plCount [OUT] - Catches the count.
  1559. //
  1560. // Return Value:
  1561. // S_OK if successful, or E_POINTER.
  1562. //
  1563. //--
  1564. /////////////////////////////////////////////////////////////////////////////
  1565. STDMETHODIMP CClusResGroupPreferredOwnerNodes::get_Count(
  1566. OUT long * plCount
  1567. )
  1568. {
  1569. //ASSERT( plCount != NULL );
  1570. HRESULT _hr = E_POINTER;
  1571. if ( plCount != NULL )
  1572. {
  1573. *plCount = m_Nodes.size();
  1574. _hr = S_OK;
  1575. }
  1576. return _hr;
  1577. } //*** CClusResGroupPreferredOwnerNodes::get_Count()
  1578. /////////////////////////////////////////////////////////////////////////////
  1579. //++
  1580. //
  1581. // CClusResGroupPreferredOwnerNodes::get_Item
  1582. //
  1583. // Description:
  1584. // Return the object (Node) at the passed in index.
  1585. //
  1586. // Arguments:
  1587. // varIndex [IN] - Contains the index requested.
  1588. // ppClusterNode [OUT] - Catches the item.
  1589. //
  1590. // Return Value:
  1591. // S_OK if successful, E_POINTER, or E_INVALIDARG.
  1592. //
  1593. //--
  1594. /////////////////////////////////////////////////////////////////////////////
  1595. STDMETHODIMP CClusResGroupPreferredOwnerNodes::get_Item(
  1596. IN VARIANT varIndex,
  1597. OUT ISClusNode ** ppClusterNode
  1598. )
  1599. {
  1600. //ASSERT( ppClusterNode != NULL );
  1601. HRESULT _hr = E_POINTER;
  1602. if ( ppClusterNode != NULL )
  1603. {
  1604. _hr = GetNodeItem( varIndex, ppClusterNode );
  1605. }
  1606. return _hr;
  1607. } //*** CClusResGroupPreferredOwnerNodes::get_Item()
  1608. /////////////////////////////////////////////////////////////////////////////
  1609. //++
  1610. //
  1611. // CClusResGroupPreferredOwnerNodes::get__NewEnum
  1612. //
  1613. // Description:
  1614. // Create and return a new enumeration for this collection.
  1615. //
  1616. // Arguments:
  1617. // ppunk [OUT] - Catches the new enumeration.
  1618. //
  1619. // Return Value:
  1620. // S_OK if successful, E_POINTER, or other HRESULT error.
  1621. //
  1622. //--
  1623. /////////////////////////////////////////////////////////////////////////////
  1624. STDMETHODIMP CClusResGroupPreferredOwnerNodes::get__NewEnum(
  1625. IUnknown ** ppunk
  1626. )
  1627. {
  1628. return ::HrNewIDispatchEnum< NodeList, CComObject< CClusNode > >( ppunk, m_Nodes );
  1629. } //*** CClusResGroupPreferredOwnerNodes::get__NewEnum()
  1630. /////////////////////////////////////////////////////////////////////////////
  1631. //++
  1632. //
  1633. // CClusResGroupPreferredOwnerNodes::Refresh
  1634. //
  1635. // Description:
  1636. // Loads the resource group preferred owner node collection from the
  1637. // cluster.
  1638. //
  1639. // Arguments:
  1640. // None.
  1641. //
  1642. // Return Value:
  1643. // S_OK if successful, or other HRESULT error.
  1644. //
  1645. //--
  1646. /////////////////////////////////////////////////////////////////////////////
  1647. STDMETHODIMP CClusResGroupPreferredOwnerNodes::Refresh( void )
  1648. {
  1649. HRESULT _hr = S_OK;
  1650. HGROUPENUM hEnum = NULL;
  1651. DWORD _sc = ERROR_SUCCESS;
  1652. hEnum = ::ClusterGroupOpenEnum( m_hGroup->get_Handle(), CLUSTER_GROUP_ENUM_NODES );
  1653. if ( hEnum != NULL )
  1654. {
  1655. int _nIndex = 0;
  1656. DWORD dwType = 0;
  1657. LPWSTR pszName = NULL;
  1658. CComObject< CClusNode > * pNode = NULL;
  1659. Clear();
  1660. m_bModified = FALSE;
  1661. for( _nIndex = 0, _hr = S_OK; SUCCEEDED( _hr ); _nIndex++ )
  1662. {
  1663. _sc = WrapClusterGroupEnum( hEnum, _nIndex, &dwType, &pszName );
  1664. if ( _sc == ERROR_NO_MORE_ITEMS )
  1665. {
  1666. _hr = S_OK;
  1667. break;
  1668. }
  1669. else if ( _sc == ERROR_SUCCESS )
  1670. {
  1671. _hr = CComObject< CClusNode >::CreateInstance( &pNode );
  1672. if ( SUCCEEDED( _hr ) )
  1673. {
  1674. CSmartPtr< ISClusRefObject > ptrRefObject( m_pClusRefObject );
  1675. CSmartPtr< CComObject< CClusNode > > ptrNode( pNode );
  1676. BSTR bstr = NULL;
  1677. bstr = SysAllocString( pszName );
  1678. if ( bstr == NULL )
  1679. {
  1680. _hr = E_OUTOFMEMORY;
  1681. }
  1682. else
  1683. {
  1684. _hr = ptrNode->Open( ptrRefObject, bstr );
  1685. if ( SUCCEEDED( _hr ) )
  1686. {
  1687. ptrNode->AddRef();
  1688. m_Nodes.insert( m_Nodes.end(), ptrNode );
  1689. }
  1690. else if ( HRESULT_CODE( _hr ) == ERROR_CLUSTER_NODE_NOT_FOUND )
  1691. {
  1692. //
  1693. // It is possible for the node to have been deleted from the cluster
  1694. // in the time between creating the enum and opening the node. When
  1695. // that happens we need to simply skip that node and continue
  1696. // enumerating.
  1697. //
  1698. _hr = S_FALSE; // success code to keep us in the loop
  1699. } // else if: the cluster node was not found
  1700. SysFreeString( bstr );
  1701. }
  1702. }
  1703. ::LocalFree( pszName );
  1704. pszName = NULL;
  1705. }
  1706. else
  1707. {
  1708. _hr = HRESULT_FROM_WIN32( _sc );
  1709. }
  1710. }
  1711. ::ClusterGroupCloseEnum( hEnum );
  1712. }
  1713. else
  1714. {
  1715. _sc = GetLastError();
  1716. _hr = HRESULT_FROM_WIN32( _sc );
  1717. }
  1718. return _hr;
  1719. } //*** CClusResGroupPreferredOwnerNodes::Refresh()
  1720. /////////////////////////////////////////////////////////////////////////////
  1721. //++
  1722. //
  1723. // CClusResGroupPreferredOwnerNodes::InsertItem
  1724. //
  1725. // Description:
  1726. // Insert the node into the groups preferred owners list.
  1727. //
  1728. // Arguments:
  1729. // pNode [IN] - Node to add to the preferred owners list.
  1730. // nPosition [IN] - Where in the list to insert the node.
  1731. //
  1732. // Return Value:
  1733. // S_OK if successful, or other HRESULT error.
  1734. //
  1735. //--
  1736. /////////////////////////////////////////////////////////////////////////////
  1737. STDMETHODIMP CClusResGroupPreferredOwnerNodes::InsertItem(
  1738. IN ISClusNode * pNode,
  1739. IN long nPosition
  1740. )
  1741. {
  1742. //ASSERT( pNode != NULL );
  1743. HRESULT _hr = E_POINTER;
  1744. if ( pNode != NULL )
  1745. {
  1746. UINT _nIndex = 0;
  1747. _hr = FindItem( pNode, &_nIndex );
  1748. if ( FAILED( _hr ) )
  1749. {
  1750. _hr = E_INVALIDARG;
  1751. if ( nPosition > 0 )
  1752. {
  1753. SSIZE_T pos = (SSIZE_T) nPosition - 1; // convert to zero base
  1754. if ( pos >= 0 )
  1755. {
  1756. CComObject< CClusNode > * _pNode = NULL;
  1757. _hr = pNode->QueryInterface( IID_CClusNode, (void **) &_pNode );
  1758. if ( SUCCEEDED( _hr ) )
  1759. {
  1760. if ( ( m_Nodes.empty() ) || ( pos == 0 ) )
  1761. {
  1762. _pNode->AddRef();
  1763. m_Nodes.insert( m_Nodes.begin(), _pNode );
  1764. } // if: list is empty or the insert index is zero then insert at the beginning
  1765. else if ( pos >= m_Nodes.size() )
  1766. {
  1767. _pNode->AddRef();
  1768. m_Nodes.insert( m_Nodes.end(), _pNode );
  1769. } // else if: pos equals the end, append
  1770. else
  1771. {
  1772. _hr = InsertAt( _pNode, pos );
  1773. } // else: try to insert it where is belongs
  1774. m_bModified = TRUE;
  1775. pNode->Release();
  1776. } // if:
  1777. } // if: index is greater than zero
  1778. } // if: nPosition must be greater than zero!
  1779. } // if: node was not already in the collection
  1780. else
  1781. {
  1782. _hr = E_INVALIDARG;
  1783. } // else: node was already in the collectoin
  1784. }
  1785. return _hr;
  1786. } //*** CClusResGroupPreferredOwnerNodes::InsertItem()
  1787. /////////////////////////////////////////////////////////////////////////////
  1788. //++
  1789. //
  1790. // CClusResGroupPreferredOwnerNodes::AddItem
  1791. //
  1792. // Description:
  1793. // Add the node into the groups preferred owners list.
  1794. //
  1795. // Arguments:
  1796. // pNode [IN] - Node to add to the preferred owners list.
  1797. //
  1798. // Return Value:
  1799. // S_OK if successful, or other HRESULT error.
  1800. //
  1801. //--
  1802. /////////////////////////////////////////////////////////////////////////////
  1803. STDMETHODIMP CClusResGroupPreferredOwnerNodes::AddItem(
  1804. IN ISClusNode * pNode
  1805. )
  1806. {
  1807. //ASSERT( pNode != NULL );
  1808. HRESULT _hr = E_POINTER;
  1809. if ( pNode != NULL )
  1810. {
  1811. UINT _nIndex = 0;
  1812. _hr = FindItem( pNode, &_nIndex );
  1813. if ( FAILED( _hr ) )
  1814. {
  1815. CComObject< CClusNode > * _pNode = NULL;
  1816. _hr = pNode->QueryInterface( IID_CClusNode, (void **) &_pNode );
  1817. if ( SUCCEEDED( _hr ) )
  1818. {
  1819. m_Nodes.insert( m_Nodes.end(), _pNode );
  1820. m_bModified = TRUE;
  1821. } // if:
  1822. } // if: node was not found in the collection already
  1823. else
  1824. {
  1825. _hr = E_INVALIDARG;
  1826. } // esle: node was found
  1827. }
  1828. return _hr;
  1829. } //*** CClusResGroupPreferredOwnerNodes::AddItem()
  1830. /////////////////////////////////////////////////////////////////////////////
  1831. //++
  1832. //
  1833. // CClusResGroupPreferredOwnerNodes::RemoveItem
  1834. //
  1835. // Description:
  1836. // Remove the item at the passed in index.
  1837. //
  1838. // Arguments:
  1839. // varIndex [IN] - The index of the item to remove.
  1840. //
  1841. // Return Value:
  1842. // S_OK if successful, E_POINTER, or E_INVALIDARG.
  1843. //
  1844. //--
  1845. /////////////////////////////////////////////////////////////////////////////
  1846. STDMETHODIMP CClusResGroupPreferredOwnerNodes::RemoveItem(
  1847. IN VARIANT varIndex
  1848. )
  1849. {
  1850. HRESULT _hr = S_OK;
  1851. UINT _nIndex = 0;
  1852. _hr = GetIndex( varIndex, &_nIndex );
  1853. if ( SUCCEEDED( _hr ) )
  1854. {
  1855. _hr = RemoveAt( _nIndex );
  1856. if ( SUCCEEDED( _hr ) )
  1857. {
  1858. m_bModified = TRUE;
  1859. } // if:
  1860. } // if:
  1861. return _hr;
  1862. } //*** CClusResGroupPreferredOwnerNodes::RemoveItem()
  1863. /////////////////////////////////////////////////////////////////////////////
  1864. //++
  1865. //
  1866. // CClusResGroupPreferredOwnerNodes::get_Modified
  1867. //
  1868. // Description:
  1869. // Has this collection been modified?
  1870. //
  1871. // Arguments:
  1872. // pvarModified [OUT] - Catches the modified state.
  1873. //
  1874. // Return Value:
  1875. // S_OK if successful, or E_POINTER.
  1876. //
  1877. //--
  1878. /////////////////////////////////////////////////////////////////////////////
  1879. STDMETHODIMP CClusResGroupPreferredOwnerNodes::get_Modified(
  1880. OUT VARIANT * pvarModified
  1881. )
  1882. {
  1883. //ASSERT( pvarModified != NULL );
  1884. HRESULT _hr = E_POINTER;
  1885. if ( pvarModified != NULL )
  1886. {
  1887. pvarModified->vt = VT_BOOL;
  1888. if ( m_bModified )
  1889. {
  1890. pvarModified->boolVal = VARIANT_TRUE;
  1891. } // if: the collection has been modified.
  1892. else
  1893. {
  1894. pvarModified->boolVal = VARIANT_FALSE;
  1895. } // else: the collection has not been modified.
  1896. _hr = S_OK;
  1897. }
  1898. return _hr;
  1899. } //*** CClusResGroupPreferredOwnerNodes::get_Modified()
  1900. /////////////////////////////////////////////////////////////////////////////
  1901. //++
  1902. //
  1903. // CClusResGroupPreferredOwnerNodes::SaveChanges
  1904. //
  1905. // Description:
  1906. // Saves the changes to this collection of preferred owner nodes to
  1907. // the cluster database.
  1908. //
  1909. // Arguments:
  1910. // None.
  1911. //
  1912. // Return Value:
  1913. // S_OK if successful, or other HRESULT error.
  1914. //
  1915. //--
  1916. /////////////////////////////////////////////////////////////////////////////
  1917. STDMETHODIMP CClusResGroupPreferredOwnerNodes::SaveChanges( void )
  1918. {
  1919. HRESULT _hr = S_OK;
  1920. if ( m_bModified )
  1921. {
  1922. size_t _cNodes;
  1923. HNODE * _phNodes = NULL;
  1924. _cNodes = m_Nodes.size();
  1925. _phNodes = new HNODE [ _cNodes ];
  1926. if ( _phNodes != NULL )
  1927. {
  1928. NodeList::const_iterator _itCurrent = m_Nodes.begin();
  1929. NodeList::const_iterator _itLast = m_Nodes.end();
  1930. size_t _iIndex;
  1931. DWORD _sc = ERROR_SUCCESS;
  1932. CComObject< CClusNode > * _pOwnerNode = NULL;
  1933. ZeroMemory( _phNodes, _cNodes * sizeof( HNODE ) );
  1934. for ( _iIndex = 0; _itCurrent != _itLast; _itCurrent++, _iIndex++ )
  1935. {
  1936. _pOwnerNode = *_itCurrent;
  1937. _phNodes[ _iIndex ] = _pOwnerNode->RhNode();
  1938. } // for:
  1939. _sc = ::SetClusterGroupNodeList( m_hGroup->get_Handle(), _cNodes, _phNodes );
  1940. _hr = HRESULT_FROM_WIN32( _sc );
  1941. if ( SUCCEEDED( _hr ) )
  1942. {
  1943. m_bModified = FALSE;
  1944. } // if:
  1945. delete [] _phNodes;
  1946. }
  1947. else
  1948. {
  1949. _hr = E_OUTOFMEMORY;
  1950. }
  1951. }
  1952. return _hr;
  1953. } //*** CClusResGroupPreferredOwnerNodes::SaveChanges()
  1954. //*************************************************************************//
  1955. /////////////////////////////////////////////////////////////////////////////
  1956. // CClusResPossibleOwnerNodes class
  1957. /////////////////////////////////////////////////////////////////////////////
  1958. /////////////////////////////////////////////////////////////////////////////
  1959. //++
  1960. //
  1961. // CClusResPossibleOwnerNodes::CClusResPossibleOwnerNodes
  1962. //
  1963. // Description:
  1964. // Constructor.
  1965. //
  1966. // Arguments:
  1967. // None.
  1968. //
  1969. // Return Value:
  1970. // None.
  1971. //
  1972. //--
  1973. /////////////////////////////////////////////////////////////////////////////
  1974. CClusResPossibleOwnerNodes::CClusResPossibleOwnerNodes( void )
  1975. {
  1976. m_piids = (const IID *) iidCClusResPossibleOwnerNodes;
  1977. m_piidsSize = ARRAYSIZE( iidCClusResPossibleOwnerNodes );
  1978. } //*** CClusResPossibleOwnerNodes::CClusResPossibleOwnerNodes()
  1979. /////////////////////////////////////////////////////////////////////////////
  1980. //++
  1981. //
  1982. // CClusResPossibleOwnerNodes::~CClusResPossibleOwnerNodes
  1983. //
  1984. // Description:
  1985. // destructor.
  1986. //
  1987. // Arguments:
  1988. // None.
  1989. //
  1990. // Return Value:
  1991. // None.
  1992. //
  1993. //--
  1994. /////////////////////////////////////////////////////////////////////////////
  1995. CClusResPossibleOwnerNodes::~CClusResPossibleOwnerNodes( void )
  1996. {
  1997. Clear();
  1998. } //*** CClusResPossibleOwnerNodes::~CClusResPossibleOwnerNodes()
  1999. /////////////////////////////////////////////////////////////////////////////
  2000. //++
  2001. //
  2002. // CClusResPossibleOwnerNodes::Create
  2003. //
  2004. // Description:
  2005. // Finish creating the object by doing things that cannot be done in
  2006. // a light weight constructor.
  2007. //
  2008. // Arguments:
  2009. // pClusRefObject [IN] - Wraps the cluster handle.
  2010. // hResource [IN] - Resource the collection belongs to.
  2011. //
  2012. // Return Value:
  2013. // S_OK if successful or E_POINTER if not.
  2014. //
  2015. //--
  2016. /////////////////////////////////////////////////////////////////////////////
  2017. HRESULT CClusResPossibleOwnerNodes::Create(
  2018. IN ISClusRefObject * pClusRefObject,
  2019. IN HRESOURCE hResource
  2020. )
  2021. {
  2022. HRESULT _hr = E_POINTER;
  2023. _hr = CNodes::Create( pClusRefObject );
  2024. if ( SUCCEEDED( _hr ) )
  2025. {
  2026. m_hResource = hResource;
  2027. } // if:
  2028. return _hr;
  2029. } //*** CClusResPossibleOwnerNodes::Create()
  2030. /////////////////////////////////////////////////////////////////////////////
  2031. //++
  2032. //
  2033. // CClusResPossibleOwnerNodes::get_Count
  2034. //
  2035. // Description:
  2036. // Return the count of objects (Nodes) in the collection.
  2037. //
  2038. // Arguments:
  2039. // plCount [OUT] - Catches the count.
  2040. //
  2041. // Return Value:
  2042. // S_OK if successful, or E_POINTER.
  2043. //
  2044. //--
  2045. /////////////////////////////////////////////////////////////////////////////
  2046. STDMETHODIMP CClusResPossibleOwnerNodes::get_Count( OUT long * plCount )
  2047. {
  2048. //ASSERT( plCount != NULL );
  2049. HRESULT _hr = E_POINTER;
  2050. if ( plCount != NULL )
  2051. {
  2052. *plCount = m_Nodes.size();
  2053. _hr = S_OK;
  2054. }
  2055. return _hr;
  2056. } //*** CClusResPossibleOwnerNodes::get_Count()
  2057. /////////////////////////////////////////////////////////////////////////////
  2058. //++
  2059. //
  2060. // CClusResPossibleOwnerNodes::get_Item
  2061. //
  2062. // Description:
  2063. // Return the object (Node) at the passed in index.
  2064. //
  2065. // Arguments:
  2066. // varIndex [IN] - Contains the index requested.
  2067. // ppClusterNode [OUT] - Catches the item.
  2068. //
  2069. // Return Value:
  2070. // S_OK if successful, E_POINTER, or E_INVALIDARG.
  2071. //
  2072. //--
  2073. /////////////////////////////////////////////////////////////////////////////
  2074. STDMETHODIMP CClusResPossibleOwnerNodes::get_Item(
  2075. IN VARIANT varIndex,
  2076. OUT ISClusNode ** ppClusterNode
  2077. )
  2078. {
  2079. //ASSERT( ppClusterNode != NULL );
  2080. HRESULT _hr = E_POINTER;
  2081. if ( ppClusterNode != NULL )
  2082. {
  2083. _hr = GetNodeItem( varIndex, ppClusterNode );
  2084. }
  2085. return _hr;
  2086. } //*** CClusResPossibleOwnerNodes::get_Item()
  2087. /////////////////////////////////////////////////////////////////////////////
  2088. //++
  2089. //
  2090. // CClusResPossibleOwnerNodes::get__NewEnum
  2091. //
  2092. // Description:
  2093. // Create and return a new enumeration for this collection.
  2094. //
  2095. // Arguments:
  2096. // ppunk [OUT] - Catches the new enumeration.
  2097. //
  2098. // Return Value:
  2099. // S_OK if successful, E_POINTER, or other HRESULT error.
  2100. //
  2101. //--
  2102. /////////////////////////////////////////////////////////////////////////////
  2103. STDMETHODIMP CClusResPossibleOwnerNodes::get__NewEnum( IUnknown ** ppunk )
  2104. {
  2105. return ::HrNewIDispatchEnum< NodeList, CComObject< CClusNode > >( ppunk, m_Nodes );
  2106. } //*** CClusResPossibleOwnerNodes::get__NewEnum()
  2107. /////////////////////////////////////////////////////////////////////////////
  2108. //++
  2109. //
  2110. // CClusResPossibleOwnerNodes::Refresh
  2111. //
  2112. // Description:
  2113. // Load the collection from the cluster database.
  2114. //
  2115. // Arguments:
  2116. // None.
  2117. //
  2118. // Return Value:
  2119. // S_OK if successful, E_POINTER, or Win32 error as HRESULT.
  2120. //
  2121. //--
  2122. /////////////////////////////////////////////////////////////////////////////
  2123. STDMETHODIMP CClusResPossibleOwnerNodes::Refresh( void )
  2124. {
  2125. HRESULT _hr = S_OK;
  2126. HRESENUM hEnum = NULL;
  2127. DWORD _sc = ERROR_SUCCESS;
  2128. hEnum = ::ClusterResourceOpenEnum( m_hResource, CLUSTER_RESOURCE_ENUM_NODES );
  2129. if ( hEnum != NULL )
  2130. {
  2131. int _nIndex = 0;
  2132. DWORD dwType;
  2133. LPWSTR pszName = NULL;
  2134. CComObject< CClusNode > * pNode = NULL;
  2135. Clear();
  2136. m_bModified = FALSE;
  2137. for( _nIndex = 0, _hr = S_OK; SUCCEEDED( _hr ); _nIndex++ )
  2138. {
  2139. _sc = ::WrapClusterResourceEnum( hEnum, _nIndex, &dwType, &pszName );
  2140. if ( _sc == ERROR_NO_MORE_ITEMS )
  2141. {
  2142. _hr = S_OK;
  2143. break;
  2144. }
  2145. else if ( _sc == ERROR_SUCCESS )
  2146. {
  2147. _hr = CComObject< CClusNode >::CreateInstance( &pNode );
  2148. if ( SUCCEEDED( _hr ) )
  2149. {
  2150. CSmartPtr< ISClusRefObject > ptrRefObject( m_pClusRefObject );
  2151. CSmartPtr< CComObject< CClusNode > > ptrNode( pNode );
  2152. BSTR bstr = NULL;
  2153. bstr = SysAllocString( pszName );
  2154. if ( bstr == NULL )
  2155. {
  2156. _hr = E_OUTOFMEMORY;
  2157. }
  2158. else
  2159. {
  2160. _hr = ptrNode->Open( ptrRefObject, bstr );
  2161. if ( SUCCEEDED( _hr ) )
  2162. {
  2163. ptrNode->AddRef();
  2164. m_Nodes.insert( m_Nodes.end(), ptrNode );
  2165. }
  2166. else if ( HRESULT_CODE( _hr ) == ERROR_CLUSTER_NODE_NOT_FOUND )
  2167. {
  2168. //
  2169. // It is possible for the node to have been deleted from the cluster
  2170. // in the time between creating the enum and opening the node. When
  2171. // that happens we need to simply skip that node and continue
  2172. // enumerating.
  2173. //
  2174. _hr = S_FALSE; // success code to keep us in the loop
  2175. } // else if: the cluster node was not found
  2176. SysFreeString( bstr );
  2177. }
  2178. }
  2179. ::LocalFree( pszName );
  2180. pszName = NULL;
  2181. }
  2182. else
  2183. {
  2184. _hr = HRESULT_FROM_WIN32( _sc );
  2185. }
  2186. }
  2187. ::ClusterResourceCloseEnum( hEnum );
  2188. }
  2189. else
  2190. {
  2191. _sc = GetLastError();
  2192. _hr = HRESULT_FROM_WIN32( _sc );
  2193. }
  2194. return _hr;
  2195. } //*** CClusResPossibleOwnerNodes::Refresh()
  2196. /////////////////////////////////////////////////////////////////////////////
  2197. //++
  2198. //
  2199. // CClusResPossibleOwnerNodes::AddItem
  2200. //
  2201. // Description:
  2202. // Add the passed in node to this resource's list of possible owners.
  2203. //
  2204. // Arguments:
  2205. // pNode [IN] - The node to add to the list.
  2206. //
  2207. // Return Value:
  2208. // S_OK if successful, E_POINTER, or other HRESULT error.
  2209. //
  2210. //--
  2211. /////////////////////////////////////////////////////////////////////////////
  2212. STDMETHODIMP CClusResPossibleOwnerNodes::AddItem( ISClusNode * pNode )
  2213. {
  2214. //ASSERT( pNode != NULL );
  2215. HRESULT _hr = E_POINTER;
  2216. if ( pNode != NULL )
  2217. {
  2218. // Fail if duplicate
  2219. UINT _nIndex = 0;
  2220. _hr = FindItem( pNode, &_nIndex );
  2221. if ( SUCCEEDED( _hr ) )
  2222. {
  2223. _hr = E_INVALIDARG;
  2224. }
  2225. else
  2226. {
  2227. CComObject< CClusNode > * _pNode = NULL;
  2228. _hr = pNode->QueryInterface( IID_CClusNode, (void **) &_pNode );
  2229. if ( SUCCEEDED( _hr ) )
  2230. {
  2231. DWORD _sc = ERROR_SUCCESS;
  2232. _sc = ::AddClusterResourceNode( m_hResource, _pNode->RhNode() );
  2233. if ( _sc == ERROR_SUCCESS )
  2234. {
  2235. _pNode->AddRef();
  2236. m_Nodes.insert( m_Nodes.end(), _pNode );
  2237. m_bModified = TRUE;
  2238. } // if:
  2239. _hr = HRESULT_FROM_WIN32( _sc );
  2240. pNode->Release();
  2241. } // if:
  2242. }
  2243. }
  2244. return _hr;
  2245. } //*** CClusResPossibleOwnerNodes::AddItem()
  2246. /////////////////////////////////////////////////////////////////////////////
  2247. //++
  2248. //
  2249. // CClusResPossibleOwnerNodes::RemoveItem
  2250. //
  2251. // Description:
  2252. // Remove the node at the passed in index from this resource's list of
  2253. // possible owners.
  2254. //
  2255. // Arguments:
  2256. // varIndex [IN] - holds the index of the node to remove.
  2257. //
  2258. // Return Value:
  2259. // S_OK if successful, or other HRESULT error.
  2260. //
  2261. //--
  2262. /////////////////////////////////////////////////////////////////////////////
  2263. STDMETHODIMP CClusResPossibleOwnerNodes::RemoveItem( VARIANT varIndex )
  2264. {
  2265. HRESULT _hr = S_OK;
  2266. UINT _nIndex = 0;
  2267. _hr = GetIndex( varIndex, &_nIndex );
  2268. if ( SUCCEEDED( _hr ) )
  2269. {
  2270. CComObject< CClusNode> * _pNode = m_Nodes[ _nIndex ];
  2271. DWORD _sc = ERROR_SUCCESS;
  2272. _sc = ::RemoveClusterResourceNode( m_hResource, _pNode->RhNode() );
  2273. _hr = HRESULT_FROM_WIN32( _sc );
  2274. if ( SUCCEEDED( _hr ) )
  2275. {
  2276. RemoveAt( _nIndex );
  2277. m_bModified = TRUE;
  2278. } // if:
  2279. } // if:
  2280. return _hr;
  2281. } //*** CClusResPossibleOwnerNodes::RemoveItem()
  2282. /////////////////////////////////////////////////////////////////////////////
  2283. //++
  2284. //
  2285. // CClusResPossibleOwnerNodes::get_Modified
  2286. //
  2287. // Description:
  2288. // Has this collection been modified?
  2289. //
  2290. // Arguments:
  2291. // pvarModified [OUT] - Catches the modified state.
  2292. //
  2293. // Return Value:
  2294. // S_OK if successful, or E_POINTER.
  2295. //
  2296. //--
  2297. /////////////////////////////////////////////////////////////////////////////
  2298. STDMETHODIMP CClusResPossibleOwnerNodes::get_Modified(
  2299. OUT VARIANT * pvarModified
  2300. )
  2301. {
  2302. //ASSERT( pvarModified != NULL );
  2303. HRESULT _hr = E_POINTER;
  2304. if ( pvarModified != NULL )
  2305. {
  2306. pvarModified->vt = VT_BOOL;
  2307. if ( m_bModified )
  2308. {
  2309. pvarModified->boolVal = VARIANT_TRUE;
  2310. } // if: the collection has been modified.
  2311. else
  2312. {
  2313. pvarModified->boolVal = VARIANT_FALSE;
  2314. } // else: the collection has not been modified.
  2315. _hr = S_OK;
  2316. }
  2317. return _hr;
  2318. } //*** CClusResPossibleOwnerNodes::get_Modified()
  2319. //*************************************************************************//
  2320. /////////////////////////////////////////////////////////////////////////////
  2321. // CClusResTypePossibleOwnerNodes class
  2322. /////////////////////////////////////////////////////////////////////////////
  2323. #if CLUSAPI_VERSION >= 0x0500
  2324. /////////////////////////////////////////////////////////////////////////////
  2325. //++
  2326. //
  2327. // CClusResTypePossibleOwnerNodes::CClusResTypePossibleOwnerNodes
  2328. //
  2329. // Description:
  2330. // Constructor.
  2331. //
  2332. // Arguments:
  2333. // None.
  2334. //
  2335. // Return Value:
  2336. // None.
  2337. //
  2338. //--
  2339. /////////////////////////////////////////////////////////////////////////////
  2340. CClusResTypePossibleOwnerNodes::CClusResTypePossibleOwnerNodes( void )
  2341. {
  2342. m_piids = (const IID *) iidCClusResTypePossibleOwnerNodes;
  2343. m_piidsSize = ARRAYSIZE( iidCClusResTypePossibleOwnerNodes );
  2344. } //*** CClusResTypePossibleOwnerNodes::CClusResTypePossibleOwnerNodes()
  2345. /////////////////////////////////////////////////////////////////////////////
  2346. //++
  2347. //
  2348. // CClusResTypePossibleOwnerNodes::~CClusResTypePossibleOwnerNodes
  2349. //
  2350. // Description:
  2351. // destructor.
  2352. //
  2353. // Arguments:
  2354. // None.
  2355. //
  2356. // Return Value:
  2357. // None.
  2358. //
  2359. //--
  2360. /////////////////////////////////////////////////////////////////////////////
  2361. CClusResTypePossibleOwnerNodes::~CClusResTypePossibleOwnerNodes( void )
  2362. {
  2363. Clear();
  2364. } //*** CClusResTypePossibleOwnerNodes::~CClusResTypePossibleOwnerNodes()
  2365. /////////////////////////////////////////////////////////////////////////////
  2366. //++
  2367. //
  2368. // CClusResTypePossibleOwnerNodes::Create
  2369. //
  2370. // Description:
  2371. // Finish creating the object by doing things that cannot be done in
  2372. // a light weight constructor.
  2373. //
  2374. // Arguments:
  2375. // pClusRefObject [IN] - Wraps the cluster handle.
  2376. // bstrResTypeName [IN] - Resource type name the collection belongs to.
  2377. //
  2378. // Return Value:
  2379. // S_OK if successful or E_POINTER if not.
  2380. //
  2381. //--
  2382. /////////////////////////////////////////////////////////////////////////////
  2383. HRESULT CClusResTypePossibleOwnerNodes::Create(
  2384. IN ISClusRefObject * pClusRefObject,
  2385. IN BSTR bstrResTypeName
  2386. )
  2387. {
  2388. HRESULT _hr = E_POINTER;
  2389. _hr = CNodes::Create( pClusRefObject );
  2390. if ( SUCCEEDED( _hr ) )
  2391. {
  2392. m_bstrResTypeName = bstrResTypeName;
  2393. } // if:
  2394. return _hr;
  2395. } //*** CClusResTypePossibleOwnerNodes::Create()
  2396. /////////////////////////////////////////////////////////////////////////////
  2397. //++
  2398. //
  2399. // CClusResTypePossibleOwnerNodes::get_Count
  2400. //
  2401. // Description:
  2402. // Return the count of objects (Nodes) in the collection.
  2403. //
  2404. // Arguments:
  2405. // plCount [OUT] - Catches the count.
  2406. //
  2407. // Return Value:
  2408. // S_OK if successful, or E_POINTER.
  2409. //
  2410. //--
  2411. /////////////////////////////////////////////////////////////////////////////
  2412. STDMETHODIMP CClusResTypePossibleOwnerNodes::get_Count( OUT long * plCount )
  2413. {
  2414. //ASSERT( plCount != NULL );
  2415. HRESULT _hr = E_POINTER;
  2416. if ( plCount != NULL )
  2417. {
  2418. *plCount = m_Nodes.size();
  2419. _hr = S_OK;
  2420. }
  2421. return _hr;
  2422. } //*** CClusResTypePossibleOwnerNodes::get_Count()
  2423. /////////////////////////////////////////////////////////////////////////////
  2424. //++
  2425. //
  2426. // CClusResTypePossibleOwnerNodes::get_Item
  2427. //
  2428. // Description:
  2429. // Return the object (Node) at the passed in index.
  2430. //
  2431. // Arguments:
  2432. // varIndex [IN] - Contains the index requested.
  2433. // ppClusterNode [OUT] - Catches the item.
  2434. //
  2435. // Return Value:
  2436. // S_OK if successful, E_POINTER, or E_INVALIDARG.
  2437. //
  2438. //--
  2439. /////////////////////////////////////////////////////////////////////////////
  2440. STDMETHODIMP CClusResTypePossibleOwnerNodes::get_Item(
  2441. IN VARIANT varIndex,
  2442. OUT ISClusNode ** ppClusterNode
  2443. )
  2444. {
  2445. //ASSERT( ppClusterNode != NULL );
  2446. HRESULT _hr = E_POINTER;
  2447. if ( ppClusterNode != NULL )
  2448. {
  2449. _hr = GetNodeItem( varIndex, ppClusterNode );
  2450. }
  2451. return _hr;
  2452. } //*** CClusResTypePossibleOwnerNodes::get_Item()
  2453. /////////////////////////////////////////////////////////////////////////////
  2454. //++
  2455. //
  2456. // CClusResTypePossibleOwnerNodes::get__NewEnum
  2457. //
  2458. // Description:
  2459. // Create and return a new enumeration for this collection.
  2460. //
  2461. // Arguments:
  2462. // ppunk [OUT] - Catches the new enumeration.
  2463. //
  2464. // Return Value:
  2465. // S_OK if successful, E_POINTER, or other HRESULT error.
  2466. //
  2467. //--
  2468. /////////////////////////////////////////////////////////////////////////////
  2469. STDMETHODIMP CClusResTypePossibleOwnerNodes::get__NewEnum(
  2470. OUT IUnknown ** ppunk
  2471. )
  2472. {
  2473. return ::HrNewIDispatchEnum< NodeList, CComObject< CClusNode > >( ppunk, m_Nodes );
  2474. } //*** CClusResTypePossibleOwnerNodes::get__NewEnum()
  2475. /////////////////////////////////////////////////////////////////////////////
  2476. //++
  2477. //
  2478. // CClusResTypePossibleOwnerNodes::Refresh
  2479. //
  2480. // Description:
  2481. // Load the resource type possible owner nodes collection from the
  2482. // cluster.
  2483. //
  2484. // Arguments:
  2485. // None.
  2486. //
  2487. // Return Value:
  2488. // S_OK if successful, or Win32 error ad HRESULT.
  2489. //
  2490. //--
  2491. /////////////////////////////////////////////////////////////////////////////
  2492. STDMETHODIMP CClusResTypePossibleOwnerNodes::Refresh( void )
  2493. {
  2494. HRESULT _hr = S_OK;
  2495. HRESTYPEENUM hEnum = NULL;
  2496. DWORD _sc = ERROR_SUCCESS;
  2497. HCLUSTER hCluster = NULL;
  2498. _hr = m_pClusRefObject->get_Handle( (ULONG_PTR *) &hCluster );
  2499. if ( SUCCEEDED( _hr ) )
  2500. {
  2501. hEnum = ::ClusterResourceTypeOpenEnum( hCluster, m_bstrResTypeName, CLUSTER_RESOURCE_TYPE_ENUM_NODES );
  2502. if ( hEnum != NULL )
  2503. {
  2504. int _nIndex = 0;
  2505. DWORD dwType;
  2506. LPWSTR pszName = NULL;
  2507. CComObject< CClusNode > * pNode = NULL;
  2508. Clear();
  2509. for ( _nIndex = 0, _hr = S_OK; SUCCEEDED( _hr ); _nIndex++ )
  2510. {
  2511. _sc = ::WrapClusterResourceTypeEnum( hEnum, _nIndex, &dwType, &pszName );
  2512. if ( _sc == ERROR_NO_MORE_ITEMS )
  2513. {
  2514. _hr = S_OK;
  2515. break;
  2516. }
  2517. else if ( _sc == ERROR_SUCCESS )
  2518. {
  2519. _hr = CComObject< CClusNode >::CreateInstance( &pNode );
  2520. if ( SUCCEEDED( _hr ) )
  2521. {
  2522. CSmartPtr< ISClusRefObject > ptrRefObject( m_pClusRefObject );
  2523. CSmartPtr< CComObject< CClusNode > > ptrNode( pNode );
  2524. BSTR bstr = NULL;
  2525. bstr = SysAllocString( pszName );
  2526. if ( bstr == NULL )
  2527. {
  2528. _hr = E_OUTOFMEMORY;
  2529. }
  2530. else
  2531. {
  2532. _hr = ptrNode->Open( ptrRefObject, bstr );
  2533. if ( SUCCEEDED( _hr ) )
  2534. {
  2535. ptrNode->AddRef();
  2536. m_Nodes.insert( m_Nodes.end(), ptrNode );
  2537. }
  2538. else if ( HRESULT_CODE( _hr ) == ERROR_CLUSTER_NODE_NOT_FOUND )
  2539. {
  2540. //
  2541. // It is possible for the node to have been deleted from the cluster
  2542. // in the time between creating the enum and opening the node. When
  2543. // that happens we need to simply skip that node and continue
  2544. // enumerating.
  2545. //
  2546. _hr = S_FALSE; // success code to keep us in the loop
  2547. } // else if: the cluster node was not found
  2548. SysFreeString( bstr );
  2549. }
  2550. }
  2551. ::LocalFree( pszName );
  2552. pszName = NULL;
  2553. } // else if: no error
  2554. else
  2555. {
  2556. _hr = HRESULT_FROM_WIN32( _sc );
  2557. } // else: error from WrapClusterResourceTypeEnum
  2558. } // for: repeat until error
  2559. ::ClusterResourceTypeCloseEnum( hEnum );
  2560. }
  2561. else
  2562. {
  2563. _sc = GetLastError();
  2564. _hr = HRESULT_FROM_WIN32( _sc );
  2565. }
  2566. } // if: we have a cluster handle
  2567. return _hr;
  2568. } //*** CClusResTypePossibleOwnerNodes::Refresh()
  2569. #endif // CLUSAPI_VERSION >= 0x0500