Source code of Windows XP (NT5)
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.

817 lines
22 KiB

  1. //////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) 1999-2000 Microsoft Corporation
  4. //
  5. // Module Name:
  6. // ClusterGroup.cpp
  7. //
  8. // Description:
  9. // Implementation of CClusterGroup class
  10. //
  11. // Author:
  12. // Henry Wang (HenryWa) 24-AUG-1999
  13. //
  14. //////////////////////////////////////////////////////////////////////////////
  15. #include "Pch.h"
  16. #include "ClusterGroup.h"
  17. #include "ClusterGroup.tmh"
  18. //****************************************************************************
  19. //
  20. // CClusterGroup
  21. //
  22. //****************************************************************************
  23. //////////////////////////////////////////////////////////////////////////////
  24. //++
  25. //
  26. // CClusterGroup::CClusterGroup(
  27. // LPCWSTR pwszNameIn,
  28. // CWbemServices * pNamespaceIn
  29. // )
  30. //
  31. // Description:
  32. // Constructor.
  33. //
  34. // Arguments:
  35. // pwszNameIn -- Class name
  36. // pNamespaceIn -- Namespace
  37. //
  38. // Return Values:
  39. // None.
  40. //
  41. //--
  42. //////////////////////////////////////////////////////////////////////////////
  43. CClusterGroup::CClusterGroup(
  44. LPCWSTR pwszNameIn,
  45. CWbemServices * pNamespaceIn
  46. )
  47. : CProvBase( pwszNameIn, pNamespaceIn )
  48. {
  49. } //*** CClusterGroup::CClusterGroup()
  50. //////////////////////////////////////////////////////////////////////////////
  51. //++
  52. //
  53. // static
  54. // CProvBase *
  55. // CClusterGroup::S_CreateThis(
  56. // LPCWSTR pwszNameIn,
  57. // CWbemServices * pNamespaceIn,
  58. // DWORD // dwEnumTypeIn
  59. // )
  60. //
  61. // Description:
  62. // Create a CClusterGroup object.
  63. //
  64. // Arguments:
  65. // pwszNameIn -- Class name
  66. // pNamespaceIn -- Namespace
  67. // dwEnumTypeIn -- Type id
  68. //
  69. // Return Values:
  70. // pointer to the CProvBase
  71. //
  72. //--
  73. //////////////////////////////////////////////////////////////////////////////
  74. CProvBase *
  75. CClusterGroup::S_CreateThis(
  76. LPCWSTR pwszNameIn,
  77. CWbemServices * pNamespaceIn,
  78. DWORD dwEnumTypeIn
  79. )
  80. {
  81. TracePrint(("CClusterGroup::S_CreatThis for Name = %ws, EnumType %u\n", pwszNameIn, dwEnumTypeIn ));
  82. return new CClusterGroup( pwszNameIn, pNamespaceIn );
  83. } //*** CClusterGroup::S_CreateThis()
  84. //////////////////////////////////////////////////////////////////////////////
  85. //++
  86. //
  87. // const SPropMapEntryArray *
  88. // CClusterGroup::GetPropMap( void )
  89. //
  90. // Description:
  91. // Retrieve the property maping table of the cluster group.
  92. //
  93. // Arguments:
  94. // None.
  95. //
  96. // Return Values:
  97. // Reference to the array of property maping table.
  98. //
  99. //--
  100. //////////////////////////////////////////////////////////////////////////////
  101. const SPropMapEntryArray *
  102. CClusterGroup::RgGetPropMap( void )
  103. {
  104. static SPropMapEntry s_rgpm[] =
  105. {
  106. {
  107. NULL,
  108. CLUSREG_NAME_GRP_LOADBAL_STATE,
  109. DWORD_TYPE,
  110. READWRITE
  111. }
  112. };
  113. static SPropMapEntryArray s_pamea(
  114. sizeof( s_rgpm ) / sizeof( SPropMapEntry ),
  115. s_rgpm
  116. );
  117. return &s_pamea;
  118. } //*** CClusterGroup::GetPropMap()
  119. //////////////////////////////////////////////////////////////////////////////
  120. //++
  121. //
  122. // SCODE
  123. // CClusterGroup::EnumInstance(
  124. // long lFlagsIn,
  125. // IWbemContext * pCtxIn,
  126. // IWbemObjectSink * pHandlerIn
  127. // )
  128. //
  129. // Description:
  130. // Enum cluster instance.
  131. //
  132. // Arguments:
  133. // lFlagsIn -- WMI flag
  134. // pCtxIn -- WMI context
  135. // pHandlerIn -- WMI sink pointer
  136. //
  137. // Return Values:
  138. // WBEM_S_NO_ERROR
  139. //
  140. //--
  141. //////////////////////////////////////////////////////////////////////////////
  142. SCODE
  143. CClusterGroup::EnumInstance(
  144. long lFlagsIn,
  145. IWbemContext * pCtxIn,
  146. IWbemObjectSink * pHandlerIn
  147. )
  148. {
  149. SAFECLUSTER shCluster;
  150. SAFEGROUP shGroup;
  151. LPCWSTR pwszGroup;
  152. TracePrint(( "CClusterGroup::EnumInstance, pHandlerIn = %p\n", pHandlerIn ));
  153. shCluster = OpenCluster( NULL );
  154. CClusterEnum cluEnum( shCluster, CLUSTER_ENUM_GROUP );
  155. while ( ( pwszGroup = cluEnum.GetNext() ) != NULL )
  156. {
  157. shGroup = OpenClusterGroup( shCluster, pwszGroup );
  158. ClusterToWMI( shGroup, pHandlerIn );
  159. } // while: more groups
  160. return WBEM_S_NO_ERROR;
  161. } //*** CClusterGroup::EnumInstance()
  162. //////////////////////////////////////////////////////////////////////////////
  163. //++
  164. //
  165. // void
  166. // CClusterGroup::ClusterToWMI(
  167. // HGROUP hGroupIn,
  168. // IWbemObjectSink * pHandlerIn
  169. // )
  170. //
  171. // Description:
  172. // Translate a cluster group object to WMI object.
  173. //
  174. // Arguments:
  175. // hGroupIn -- Handle to group
  176. // pHandlerIn -- Handler
  177. //
  178. // Return Values:
  179. // None.
  180. //
  181. //--
  182. //////////////////////////////////////////////////////////////////////////////
  183. void
  184. CClusterGroup::ClusterToWMI(
  185. HGROUP hGroupIn,
  186. IWbemObjectSink * pHandlerIn
  187. )
  188. {
  189. static SGetControl s_rgControl[] =
  190. {
  191. { CLUSCTL_GROUP_GET_RO_COMMON_PROPERTIES, FALSE },
  192. { CLUSCTL_GROUP_GET_COMMON_PROPERTIES, FALSE },
  193. { CLUSCTL_GROUP_GET_RO_PRIVATE_PROPERTIES, TRUE },
  194. { CLUSCTL_GROUP_GET_PRIVATE_PROPERTIES, TRUE }
  195. };
  196. static UINT s_cControl = sizeof( s_rgControl ) / sizeof( SGetControl );
  197. CError er;
  198. UINT idx;
  199. CWbemClassObject wco;
  200. m_pClass->SpawnInstance( 0, &wco );
  201. for ( idx = 0 ; idx < s_cControl ; idx++ )
  202. {
  203. CClusPropList pl;
  204. er = pl.ScGetGroupProperties(
  205. hGroupIn,
  206. s_rgControl[ idx ].dwControl,
  207. NULL,
  208. 0
  209. );
  210. CClusterApi::GetObjectProperties(
  211. RgGetPropMap(),
  212. pl,
  213. wco,
  214. s_rgControl[ idx ].fPrivate
  215. );
  216. } // for: each common property type
  217. //
  218. // set prefered nodelist
  219. //
  220. {
  221. SAFEGROUPENUM shGroupEnum;
  222. DWORD dwIndex = 0;
  223. DWORD dwType;
  224. DWORD cchName = MAX_PATH ;
  225. CWstrBuf wsbName;
  226. DWORD dwError;
  227. BSTR rgbstrNode[MAX_PATH];
  228. DWORD cbstrNode = 0;
  229. wsbName.SetSize( cchName );
  230. shGroupEnum = ClusterGroupOpenEnum(
  231. hGroupIn,
  232. CLUSTER_GROUP_ENUM_NODES
  233. );
  234. for( ; ; )
  235. {
  236. DWORD cch = cchName;
  237. dwError = ClusterGroupEnum(
  238. shGroupEnum,
  239. dwIndex,
  240. &dwType,
  241. wsbName,
  242. &cch
  243. );
  244. if ( dwError == ERROR_MORE_DATA )
  245. {
  246. cchName = ++cch;
  247. wsbName.SetSize( cch );
  248. dwError = ClusterGroupEnum(
  249. shGroupEnum,
  250. dwIndex,
  251. &dwType,
  252. wsbName,
  253. &cch
  254. );
  255. } // if: more data
  256. if ( dwError == ERROR_SUCCESS )
  257. {
  258. rgbstrNode[ dwIndex ] = SysAllocString ( wsbName );
  259. if ( rgbstrNode[ dwIndex ] == NULL )
  260. {
  261. for( dwIndex = 0 ; dwIndex < cbstrNode ; dwIndex++ )
  262. {
  263. SysFreeString( rgbstrNode[ dwIndex ] );
  264. }
  265. CProvException( static_cast< HRESULT >( WBEM_E_OUT_OF_MEMORY ) );
  266. }
  267. dwIndex++;
  268. cbstrNode = dwIndex;
  269. } // if: success
  270. else
  271. {
  272. break;
  273. } // else
  274. } // for: cluster group
  275. if( cbstrNode > 0 )
  276. {
  277. wco.SetProperty(
  278. cbstrNode,
  279. rgbstrNode,
  280. PVD_PROP_NODELIST
  281. );
  282. // bugbug, how to clean up when exception occured
  283. for ( dwIndex = 0 ; dwIndex < cbstrNode ; dwIndex++ )
  284. {
  285. SysFreeString( rgbstrNode[ dwIndex ] );
  286. }
  287. } // if: has valid group
  288. }
  289. //
  290. // flags and characteristics
  291. //
  292. {
  293. DWORD cbReturned;
  294. DWORD dwOut;
  295. er = ClusterGroupControl(
  296. hGroupIn,
  297. NULL,
  298. CLUSCTL_GROUP_GET_CHARACTERISTICS,
  299. NULL,
  300. 0,
  301. &dwOut,
  302. sizeof( DWORD ),
  303. &cbReturned
  304. );
  305. wco.SetProperty(
  306. dwOut,
  307. PVD_PROP_CHARACTERISTIC
  308. );
  309. }
  310. pHandlerIn->Indicate( 1, &wco );
  311. return;
  312. } //*** CClusterGroup::ClusterToWMI()
  313. //////////////////////////////////////////////////////////////////////////////
  314. //++
  315. //
  316. // SCODE
  317. // CClusterGroup::GetObject(
  318. // CObjPath & rObjPathIn,
  319. // long lFlagsIn,
  320. // IWbemContext * pCtxIn,
  321. // IWbemObjectSink * pHandlerIn
  322. // )
  323. //
  324. // Description:
  325. // Retrieve cluster group object based given object path.
  326. //
  327. // Arguments:
  328. // rObjPathIn -- Object path to cluster object
  329. // lFlagsIn -- WMI flag
  330. // pCtxIn -- WMI context
  331. // pHandlerIn -- WMI sink pointer
  332. //
  333. // Return Values:
  334. // WBEM_S_NO_ERROR
  335. //
  336. //--
  337. //////////////////////////////////////////////////////////////////////////////
  338. SCODE
  339. CClusterGroup::GetObject(
  340. CObjPath & rObjPathIn,
  341. long lFlagsIn,
  342. IWbemContext * pCtxIn,
  343. IWbemObjectSink * pHandlerIn
  344. )
  345. {
  346. SAFECLUSTER shCluster;
  347. SAFEGROUP shGroup;
  348. shCluster = OpenCluster( NULL );
  349. shGroup = OpenClusterGroup(
  350. shCluster,
  351. rObjPathIn.GetStringValueForProperty( PVD_PROP_NAME )
  352. );
  353. ClusterToWMI( shGroup, pHandlerIn );
  354. return WBEM_S_NO_ERROR;
  355. } //*** CClusterGroup::GetObject()
  356. //////////////////////////////////////////////////////////////////////////////
  357. //++
  358. //
  359. // SCODE
  360. // CClusterGroup::ExecuteMethod(
  361. // CObjPath & rObjPathIn,
  362. // WCHAR * pwszMethodNameIn,
  363. // long lFlagIn,
  364. // IWbemClassObject * pParamsIn,
  365. // IWbemObjectSink * pHandlerIn
  366. // )
  367. //
  368. // Description:
  369. // Execute methods defined in the mof for cluster node.
  370. //
  371. // Arguments:
  372. // rObjPathIn -- Object path to cluster object
  373. // pwszMethodNameIn -- Name of the method to be invoked
  374. // lFlagIn -- WMI flag
  375. // pParamsIn -- Input parameters for the method
  376. // pHandlerIn -- WMI sink pointer
  377. //
  378. // Return Values:
  379. // WBEM_S_NO_ERROR
  380. //
  381. //--
  382. //////////////////////////////////////////////////////////////////////////////
  383. SCODE
  384. CClusterGroup::ExecuteMethod(
  385. CObjPath & rObjPathIn,
  386. WCHAR * pwszMethodNameIn,
  387. long lFlagIn,
  388. IWbemClassObject * pParamsIn,
  389. IWbemObjectSink * pHandlerIn
  390. )
  391. {
  392. SAFECLUSTER shCluster;
  393. SAFEGROUP shGroup;
  394. CWbemClassObject InArgs( pParamsIn );
  395. CError er;
  396. shCluster = OpenCluster( NULL );
  397. //
  398. // static method
  399. //
  400. if ( _wcsicmp( pwszMethodNameIn, PVD_MTH_GROUP_CREATEGROUP ) == 0 )
  401. {
  402. _bstr_t bstrNewGroup;
  403. InArgs.GetProperty( bstrNewGroup, PVD_MTH_GROUP_PARM_GROUPNAME );
  404. shGroup = CreateClusterGroup( shCluster, bstrNewGroup );
  405. er = OnlineClusterGroup( shGroup, NULL );
  406. } // if: CREATEGROUP
  407. else
  408. {
  409. shGroup = OpenClusterGroup(
  410. shCluster,
  411. rObjPathIn.GetStringValueForProperty( PVD_PROP_GROUP_NAME )
  412. );
  413. if ( _wcsicmp( pwszMethodNameIn, PVD_MTH_GROUP_TAKEOFFLINE ) == 0 )
  414. {
  415. er = OfflineClusterGroup( shGroup );
  416. } // if: TAKEOFFLINE
  417. else if ( _wcsicmp( pwszMethodNameIn, PVD_MTH_GROUP_BRINGONLINE ) == 0 )
  418. {
  419. er = OnlineClusterGroup( shGroup, NULL );
  420. } // else if: BRINGONLINE
  421. else if ( _wcsicmp( pwszMethodNameIn, PVD_MTH_GROUP_MOVETONEWNODE ) == 0 )
  422. {
  423. _bstr_t bstrNewNode;
  424. SAFENODE shNode;
  425. InArgs.GetProperty( bstrNewNode, PVD_MTH_GROUP_PARM_NODENAME );
  426. shNode = OpenClusterNode( shCluster, bstrNewNode );
  427. er = MoveClusterGroup( shGroup, shNode );
  428. } // else if: MOVETONEWNODE
  429. else if ( _wcsicmp( pwszMethodNameIn, PVD_MTH_GROUP_RENAME ) == 0 )
  430. {
  431. _bstr_t bstrNewName;
  432. InArgs.GetProperty( bstrNewName, PVD_MTH_GROUP_PARM_NEWNAME );
  433. er = SetClusterGroupName( shGroup, bstrNewName );
  434. } // else if: RENAME
  435. else
  436. {
  437. er = static_cast< HRESULT >( WBEM_E_INVALID_PARAMETER );
  438. }
  439. } // else: not create new group
  440. return WBEM_S_NO_ERROR;
  441. } //*** CClusterGroup::ExecuteMethod()
  442. //////////////////////////////////////////////////////////////////////////////
  443. //++
  444. //
  445. // SCODE
  446. // CClusterGroup::PutInstance(
  447. // CWbemClassObject & rInstToPutIn,
  448. // long lFlagIn,
  449. // IWbemContext * pCtxIn,
  450. // IWbemObjectSink * pHandlerIn
  451. // )
  452. //
  453. // Description:
  454. // Save this instance.
  455. //
  456. // Arguments:
  457. // rInstToPutIn -- WMI object to be saved
  458. // lFlagIn -- WMI flag
  459. // pCtxIn -- WMI context
  460. // pHandlerIn -- WMI sink pointer
  461. //
  462. // Return Values:
  463. // WBEM_S_NO_ERROR
  464. //
  465. //--
  466. //////////////////////////////////////////////////////////////////////////////
  467. SCODE
  468. CClusterGroup::PutInstance(
  469. CWbemClassObject & rInstToPutIn,
  470. long lFlagIn,
  471. IWbemContext * pCtxIn,
  472. IWbemObjectSink * pHandlerIn
  473. )
  474. {
  475. static SGetSetControl s_rgControl[] =
  476. {
  477. {
  478. CLUSCTL_GROUP_GET_COMMON_PROPERTIES,
  479. CLUSCTL_GROUP_SET_COMMON_PROPERTIES,
  480. FALSE
  481. },
  482. {
  483. CLUSCTL_GROUP_GET_PRIVATE_PROPERTIES,
  484. CLUSCTL_GROUP_SET_PRIVATE_PROPERTIES,
  485. TRUE
  486. }
  487. };
  488. static DWORD s_cControl = sizeof( s_rgControl ) / sizeof( SGetSetControl );
  489. _bstr_t bstrName;
  490. SAFECLUSTER shCluster;
  491. SAFEGROUP shGroup;
  492. CError er;
  493. UINT idx;
  494. rInstToPutIn.GetProperty( bstrName, PVD_PROP_NAME );
  495. shCluster = OpenCluster( NULL );
  496. shGroup = OpenClusterGroup( shCluster, bstrName );
  497. for ( idx = 0 ; idx < s_cControl ; idx++ )
  498. {
  499. CClusPropList plOld;
  500. CClusPropList plNew;
  501. er = plOld.ScGetGroupProperties(
  502. shGroup,
  503. s_rgControl[ idx ].dwGetControl,
  504. NULL,
  505. NULL,
  506. 0
  507. );
  508. CClusterApi::SetObjectProperties(
  509. NULL,
  510. plNew,
  511. plOld,
  512. rInstToPutIn,
  513. s_rgControl[ idx ].fPrivate
  514. );
  515. if ( plNew.Cprops() > 0 )
  516. {
  517. er = ClusterGroupControl(
  518. shGroup,
  519. NULL,
  520. s_rgControl[ idx ].dwSetControl,
  521. plNew.PbPropList(),
  522. plNew.CbPropList(),
  523. NULL,
  524. 0,
  525. NULL
  526. );
  527. }
  528. } // for: each control code
  529. return WBEM_S_NO_ERROR;
  530. } //*** CClusterGroup::PutInstance()
  531. //////////////////////////////////////////////////////////////////////////////
  532. //++
  533. //
  534. // SCODE
  535. // CClusterGroup::DeleteInstance(
  536. // CObjPath & rObjPathIn,
  537. // long lFlagIn,
  538. // IWbemContext * pCtxIn,
  539. // IWbemObjectSink * pHandlerIn
  540. // )
  541. //
  542. // Description:
  543. // Delete the object specified in rObjPathIn.
  544. //
  545. // Arguments:
  546. // rObjPathIn -- ObjPath for the instance to be deleted
  547. // lFlagIn -- WMI flag
  548. // pCtxIn -- WMI context
  549. // pHandlerIn -- WMI sink pointer
  550. //
  551. // Return Values:
  552. // WBEM_S_NO_ERROR
  553. //
  554. //--
  555. //////////////////////////////////////////////////////////////////////////////
  556. SCODE
  557. CClusterGroup::DeleteInstance(
  558. CObjPath & rObjPathIn,
  559. long lFlagIn,
  560. IWbemContext * pCtxIn,
  561. IWbemObjectSink * pHandlerIn
  562. )
  563. {
  564. SAFECLUSTER shCluster;
  565. SAFEGROUP shGroup;
  566. CError er;
  567. shCluster = OpenCluster( NULL );
  568. shGroup = OpenClusterGroup(
  569. shCluster,
  570. rObjPathIn.GetStringValueForProperty( PVD_PROP_NAME )
  571. );
  572. er = DeleteClusterGroup( shGroup );
  573. return WBEM_S_NO_ERROR;
  574. } //*** CClusterGroup::DeleteInstance()
  575. //****************************************************************************
  576. //
  577. // CClusterGroupRes
  578. //
  579. //****************************************************************************
  580. //////////////////////////////////////////////////////////////////////////////
  581. //++
  582. //
  583. // CClusterGroupRes::CClusterGroupRes(
  584. // LPCWSTR pwszNameIn,
  585. // CWbemServices * pNamespaceIn,
  586. // DWORD dwEnumTypeIn
  587. // )
  588. //
  589. // Description:
  590. // Constructor.
  591. //
  592. // Arguments:
  593. // pwszNameIn -- Class name
  594. // pNamespaceIn -- Namespace
  595. // dwEnumTypeIn -- Type id
  596. //
  597. // Return Values:
  598. // None.
  599. //
  600. //--
  601. //////////////////////////////////////////////////////////////////////////////
  602. CClusterGroupRes::CClusterGroupRes(
  603. LPCWSTR pwszNameIn,
  604. CWbemServices * pNamespaceIn,
  605. DWORD dwEnumTypeIn
  606. )
  607. : CClusterObjAssoc( pwszNameIn, pNamespaceIn, dwEnumTypeIn )
  608. {
  609. } //*** CClusterGroupRes::CClusterGroupRes()
  610. //////////////////////////////////////////////////////////////////////////////
  611. //++
  612. //
  613. // static
  614. // CProvBase *
  615. // CClusterGroupRes::S_CreateThis(
  616. // LPCWSTR pwszNameIn,
  617. // CWbemServices * pNamespaceIn,
  618. // DWORD dwEnumTypeIn
  619. // )
  620. //
  621. // Description:
  622. // Create a cluster node object
  623. //
  624. // Arguments:
  625. // pwszNameIn -- Class name
  626. // pNamespaceIn -- Namespace
  627. // dwEnumTypeIn -- Type id
  628. //
  629. // Return Values:
  630. // pointer to the CProvBase
  631. //
  632. //--
  633. //////////////////////////////////////////////////////////////////////////////
  634. CProvBase *
  635. CClusterGroupRes::S_CreateThis(
  636. LPCWSTR pwszNameIn,
  637. CWbemServices * pNamespaceIn,
  638. DWORD dwEnumTypeIn
  639. )
  640. {
  641. return new CClusterGroupRes(
  642. pwszNameIn,
  643. pNamespaceIn,
  644. dwEnumTypeIn
  645. );
  646. } //*** CClusterGroupRes::S_CreateThis()
  647. //////////////////////////////////////////////////////////////////////////////
  648. //++
  649. //
  650. // SCODE
  651. // CClusterGroupRes::EnumInstance(
  652. // long lFlagsIn,
  653. // IWbemContext * pCtxIn,
  654. // IWbemObjectSink * pHandlerIn
  655. // )
  656. //
  657. // Description:
  658. // Retrieve the property maping table of the cluster node active resource.
  659. //
  660. // Arguments:
  661. // lFlagsIn --
  662. // pCtxIn --
  663. // pHandlerIn --
  664. //
  665. // Return Values:
  666. // SCODE
  667. //
  668. //--
  669. //////////////////////////////////////////////////////////////////////////////
  670. SCODE
  671. CClusterGroupRes::EnumInstance(
  672. long lFlagsIn,
  673. IWbemContext * pCtxIn,
  674. IWbemObjectSink * pHandlerIn
  675. )
  676. {
  677. SAFECLUSTER shCluster;
  678. SAFEGROUP shGroup;
  679. SAFERESOURCE shResource;
  680. LPCWSTR pwszName = NULL;
  681. DWORD cchGroupName = MAX_PATH;
  682. CWstrBuf wsbGroupName;
  683. DWORD cch;
  684. CError er;
  685. DWORD dwError;
  686. CWbemClassObject wcoGroup;
  687. CWbemClassObject wcoPart;
  688. _bstr_t bstrGroup;
  689. _bstr_t bstrPart;
  690. wsbGroupName.SetSize( cchGroupName );
  691. shCluster = OpenCluster( NULL );
  692. CClusterEnum clusEnum( shCluster, m_dwEnumType );
  693. m_wcoGroup.SpawnInstance( 0, &wcoGroup );
  694. m_wcoPart.SpawnInstance( 0, &wcoPart );
  695. while ( ( pwszName = clusEnum.GetNext() ) != NULL )
  696. {
  697. CWbemClassObject wco;
  698. DWORD dwState;
  699. cch = cchGroupName;
  700. wcoPart.SetProperty( pwszName, PVD_PROP_RES_NAME );
  701. wcoPart.GetProperty( bstrPart, PVD_WBEM_RELPATH );
  702. shResource = OpenClusterResource( shCluster, pwszName );
  703. dwState = GetClusterResourceState(
  704. shResource,
  705. NULL,
  706. 0,
  707. wsbGroupName,
  708. &cch
  709. );
  710. if ( dwState == ClusterResourceStateUnknown )
  711. {
  712. dwError = GetLastError();
  713. if ( dwError == ERROR_MORE_DATA )
  714. {
  715. cchGroupName = ++cch;
  716. wsbGroupName.SetSize( cch );
  717. dwState = GetClusterResourceState(
  718. shResource,
  719. NULL,
  720. 0,
  721. wsbGroupName,
  722. &cch
  723. );
  724. } // if: more data
  725. else
  726. {
  727. er = dwError;
  728. }
  729. } // if: state unknown
  730. wcoGroup.SetProperty( wsbGroupName, CLUSREG_NAME_GRP_NAME );
  731. wcoGroup.GetProperty( bstrGroup, PVD_WBEM_RELPATH );
  732. m_pClass->SpawnInstance( 0, &wco );
  733. wco.SetProperty( (LPWSTR) bstrGroup, PVD_PROP_GROUPCOMPONENT );
  734. wco.SetProperty( (LPWSTR) bstrPart, PVD_PROP_PARTCOMPONENT );
  735. pHandlerIn->Indicate( 1, &wco );
  736. } // while: more resources
  737. return WBEM_S_NO_ERROR;
  738. } //*** CClusterGroupRes::EnumInstance()