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.

2114 lines
47 KiB

  1. /////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) 1997-1999 Microsoft Corporation
  4. //
  5. // Module Name:
  6. // Property.cpp
  7. //
  8. // Description:
  9. // Implementation of the cluster property classes for the MSCLUS
  10. // automation classes.
  11. //
  12. // Author:
  13. // Charles Stacy Harris (stacyh) 28-Feb-1997
  14. // Galen Barbee (galenb) July 1998
  15. //
  16. // Revision History:
  17. // July 1998 GalenB Maaaaaajjjjjjjjjoooooorrrr clean up
  18. //
  19. // Notes:
  20. //
  21. /////////////////////////////////////////////////////////////////////////////
  22. #include "stdafx.h"
  23. #include "ClusterObject.h"
  24. #include "property.h"
  25. /////////////////////////////////////////////////////////////////////////////
  26. // Global variables
  27. /////////////////////////////////////////////////////////////////////////////
  28. static const IID * iidCClusProperty[] =
  29. {
  30. &IID_ISClusProperty
  31. };
  32. static const IID * iidCClusProperties[] =
  33. {
  34. &IID_ISClusProperties
  35. };
  36. //*************************************************************************//
  37. /////////////////////////////////////////////////////////////////////////////
  38. // CClusProperty class
  39. /////////////////////////////////////////////////////////////////////////////
  40. /////////////////////////////////////////////////////////////////////////////
  41. //++
  42. //
  43. // CClusProperty::CClusProperty
  44. //
  45. // Description:
  46. // Constructor
  47. //
  48. // Arguments:
  49. // None.
  50. //
  51. // Return Value:
  52. // None.
  53. //
  54. //--
  55. /////////////////////////////////////////////////////////////////////////////
  56. CClusProperty::CClusProperty( void )
  57. {
  58. m_dwFlags = 0;
  59. m_pValues = NULL;
  60. m_piids = (const IID *) iidCClusProperty;
  61. m_piidsSize = ARRAYSIZE( iidCClusProperty );
  62. } //*** CClusProperty::CClusProperty()
  63. /////////////////////////////////////////////////////////////////////////////
  64. //++
  65. //
  66. // CClusProperty::~CClusProperty
  67. //
  68. // Description:
  69. // Destructor
  70. //
  71. // Arguments:
  72. // None.
  73. //
  74. // Return Value:
  75. // None.
  76. //
  77. //--
  78. /////////////////////////////////////////////////////////////////////////////
  79. CClusProperty::~CClusProperty( void )
  80. {
  81. if ( m_pValues != NULL )
  82. {
  83. m_pValues->Release();
  84. } // if:
  85. } //*** CClusProperty::~CClusProperty()
  86. /////////////////////////////////////////////////////////////////////////////
  87. //++
  88. //
  89. // CClusProperty::HrCoerceVariantType
  90. //
  91. // Description:
  92. // Coerce the passed in variant to a type that matches the cluster
  93. // property type.
  94. //
  95. // Arguments:
  96. // cpfFormat [IN] - CLUSPROP_FORMAT_xxxx of the property.
  97. // rvarValue [IN] - The variant to coerce.
  98. //
  99. // Return Value:
  100. // S_OK if successful, or other HRESULT error.
  101. //
  102. //--
  103. /////////////////////////////////////////////////////////////////////////////
  104. HRESULT CClusProperty::HrCoerceVariantType(
  105. IN CLUSTER_PROPERTY_FORMAT cpfFormat,
  106. IN VARIANT & rvarValue
  107. )
  108. {
  109. HRESULT _hr = S_OK;
  110. VARIANT _var;
  111. ::VariantInit( &_var );
  112. switch ( cpfFormat )
  113. {
  114. case CLUSPROP_FORMAT_BINARY:
  115. {
  116. if ( ! ( rvarValue.vt & VT_ARRAY ) )
  117. {
  118. _hr = E_INVALIDARG;
  119. } // if:
  120. break;
  121. } // case:
  122. #if CLUSAPI_VERSION >= 0x0500
  123. case CLUSPROP_FORMAT_LONG:
  124. #endif // CLUSAPI_VERSION >= 0x0500
  125. case CLUSPROP_FORMAT_DWORD:
  126. {
  127. _hr = VariantChangeTypeEx( &_var, &rvarValue, LOCALE_SYSTEM_DEFAULT, 0, VT_I4 );
  128. break;
  129. } // case:
  130. case CLUSPROP_FORMAT_SZ:
  131. case CLUSPROP_FORMAT_EXPAND_SZ:
  132. case CLUSPROP_FORMAT_MULTI_SZ:
  133. {
  134. _hr = VariantChangeTypeEx( &_var, &rvarValue, LOCALE_SYSTEM_DEFAULT, 0, VT_BSTR );
  135. break;
  136. } // case:
  137. case CLUSPROP_FORMAT_ULARGE_INTEGER:
  138. {
  139. _hr = VariantChangeTypeEx( &_var, &rvarValue, LOCALE_SYSTEM_DEFAULT, 0, VT_I8 );
  140. break;
  141. } // case:
  142. #if CLUSAPI_VERSION >= 0x0500
  143. case CLUSPROP_FORMAT_EXPANDED_SZ:
  144. #endif // CLUSAPI_VERSION >= 0x0500
  145. case CLUSPROP_FORMAT_UNKNOWN:
  146. default:
  147. {
  148. _hr = E_INVALIDARG;
  149. break;
  150. } // default:
  151. } // switch:
  152. return _hr;
  153. } //*** CClusProperty::HrCoerceVariantType()
  154. /////////////////////////////////////////////////////////////////////////////
  155. //++
  156. //
  157. // CClusProperty::HrBinaryCompare
  158. //
  159. // Description:
  160. // Compare two SafeArrays and return whether or not they are equal.
  161. //
  162. // Arguments:
  163. // rvarOldValue [IN] - Old value
  164. // rvarValue [IN] - New value.
  165. // pbEqual [OUT] - Catches the equality state.
  166. //
  167. // Return Value:
  168. // S_OK if successful, or other HRESULT error.
  169. //
  170. //--
  171. /////////////////////////////////////////////////////////////////////////////
  172. HRESULT CClusProperty::HrBinaryCompare(
  173. IN const CComVariant rvarOldValue,
  174. IN const VARIANT & rvarValue,
  175. OUT BOOL * pbEqual
  176. )
  177. {
  178. ASSERT( pbEqual != NULL );
  179. HRESULT _hr = E_POINTER;
  180. if ( pbEqual != NULL )
  181. {
  182. PBYTE _pbOld = NULL;
  183. SAFEARRAY * _psaOld = NULL;
  184. *pbEqual = FALSE;
  185. _psaOld = rvarOldValue.parray;
  186. _hr = ::SafeArrayAccessData( _psaOld, (PVOID *) &_pbOld );
  187. if ( SUCCEEDED( _hr ) )
  188. {
  189. PBYTE _pbNew = NULL;
  190. SAFEARRAY * _psaNew = NULL;
  191. _psaNew = rvarValue.parray;
  192. _hr = ::SafeArrayAccessData( _psaNew, (PVOID *) &_pbNew );
  193. if ( SUCCEEDED( _hr ) )
  194. {
  195. if ( _psaOld->cbElements == _psaNew->cbElements )
  196. {
  197. *pbEqual = ( ::memcmp( _pbOld, _pbNew, _psaNew->cbElements ) == 0 );
  198. } // if:
  199. _hr = ::SafeArrayUnaccessData( _psaNew );
  200. } // if:
  201. _hr = ::SafeArrayUnaccessData( _psaOld );
  202. } // if:
  203. } // if:
  204. return _hr;
  205. } //*** CClusProperty::HrBinaryCompare()
  206. /////////////////////////////////////////////////////////////////////////////
  207. //++
  208. //
  209. // CClusProperty::HrConvertVariantTypeToClusterFormat
  210. //
  211. // Description:
  212. // Given a variant, pick the best CLUSPROP_FORMAT_xxx.
  213. //
  214. // Arguments:
  215. // rvar [IN] - variant to check.
  216. // varType [IN] - variant type.
  217. // pcpfFormat [OUT] - catches the cluster property format
  218. //
  219. // Return Value:
  220. // S_OK if successful, or other HRESULT error.
  221. //
  222. //--
  223. /////////////////////////////////////////////////////////////////////////////
  224. HRESULT CClusProperty::HrConvertVariantTypeToClusterFormat(
  225. IN const VARIANT & rvar,
  226. IN VARTYPE varType,
  227. OUT CLUSTER_PROPERTY_FORMAT * pcpfFormat
  228. )
  229. {
  230. HRESULT _hr = E_INVALIDARG;
  231. do
  232. {
  233. if ( ( varType & VT_ARRAY ) && ( varType & VT_UI1 ) )
  234. {
  235. *pcpfFormat = CLUSPROP_FORMAT_BINARY;
  236. _hr = S_OK;
  237. break;
  238. } // if:
  239. if ( varType & VT_VECTOR )
  240. {
  241. break;
  242. } // if: Don't know what to do with a vector...
  243. varType &= ~VT_BYREF; // mask off the by ref bit if it was set...
  244. if ( ( varType == VT_I2 ) || ( varType == VT_I4 ) || ( varType == VT_BOOL ) || ( varType == VT_R4 ) )
  245. {
  246. *pcpfFormat = CLUSPROP_FORMAT_DWORD;
  247. _hr = S_OK;
  248. break;
  249. } // if:
  250. else if ( varType == VT_BSTR )
  251. {
  252. *pcpfFormat = CLUSPROP_FORMAT_SZ;
  253. _hr = S_OK;
  254. break;
  255. } // else if:
  256. else if ( ( varType == VT_I8 ) || ( varType == VT_R8 ) )
  257. {
  258. *pcpfFormat = CLUSPROP_FORMAT_ULARGE_INTEGER;
  259. _hr = S_OK;
  260. break;
  261. } // else if:
  262. else if ( varType == VT_VARIANT )
  263. {
  264. _hr = HrConvertVariantTypeToClusterFormat( *rvar.pvarVal, rvar.pvarVal->vt, pcpfFormat );
  265. break;
  266. } // else if:
  267. }
  268. while( TRUE ); // do-while: want to avoid using a goto ;-)
  269. return _hr;
  270. } //*** CClusProperty::HrConvertVariantTypeToClusterFormat()
  271. /////////////////////////////////////////////////////////////////////////////
  272. //++
  273. //
  274. // CClusProperty::Create
  275. //
  276. // Description:
  277. // Finish creating a ClusProperty object. This is where the real
  278. // work is done -- not the ctor.
  279. //
  280. // Arguments:
  281. // bstrName [IN] - The name of the property.
  282. // varValue [IN] - The value of the property.
  283. // bPrivate [IN] - Is it a private property?
  284. // bReadOnly [IN] - Is it a read only property?
  285. //
  286. // Return Value:
  287. // S_OK if successful, or other HRESULT error.
  288. //
  289. //--
  290. /////////////////////////////////////////////////////////////////////////////
  291. HRESULT CClusProperty::Create(
  292. IN BSTR bstrName,
  293. IN VARIANT varValue,
  294. IN BOOL bPrivate,
  295. IN BOOL bReadOnly
  296. )
  297. {
  298. HRESULT _hr = S_OK;
  299. CLUSTER_PROPERTY_FORMAT _cpfFormat = CLUSPROP_FORMAT_UNKNOWN;
  300. if ( bPrivate )
  301. {
  302. m_dwFlags |= PRIVATE;
  303. } // if: set the private flag
  304. else
  305. {
  306. m_dwFlags &= ~PRIVATE;
  307. } // else: clear the private flag
  308. if ( bReadOnly )
  309. {
  310. m_dwFlags |= READONLY;
  311. } // if: set the read only flag
  312. else
  313. {
  314. m_dwFlags &= ~READONLY;
  315. } // else: clear the read only flag
  316. m_bstrName = bstrName;
  317. _hr = HrConvertVariantTypeToClusterFormat( varValue, varValue.vt, &_cpfFormat );
  318. if ( SUCCEEDED( _hr ) )
  319. {
  320. _hr = HrCreateValuesCollection( varValue, CLUSPROP_TYPE_LIST_VALUE, _cpfFormat );
  321. } // if:
  322. return _hr;
  323. } //*** CClusProperty::Create()
  324. /////////////////////////////////////////////////////////////////////////////
  325. //++
  326. //
  327. // CClusProperty::Create
  328. //
  329. // Description:
  330. // Finish creating a ClusProperty object. This is where the real
  331. // work is done -- not the ctor.
  332. //
  333. // Arguments:
  334. // bstrName [IN] - The name of the property.
  335. // rpvlValue [IN] - The value list of the property.
  336. // bPrivate [IN] - Is it a private property?
  337. // bReadOnly [IN] - Is it a read only property?
  338. //
  339. // Return Value:
  340. // S_OK if successful, or other HRESULT error.
  341. //
  342. //--
  343. /////////////////////////////////////////////////////////////////////////////
  344. HRESULT CClusProperty::Create(
  345. IN BSTR bstrName,
  346. IN const CClusPropValueList & rpvlValue,
  347. IN BOOL bPrivate,
  348. IN BOOL bReadOnly
  349. )
  350. {
  351. if ( bPrivate )
  352. {
  353. m_dwFlags |= PRIVATE;
  354. } // if: set the private flag
  355. else
  356. {
  357. m_dwFlags &= ~PRIVATE;
  358. } // else: clear the private flag
  359. if ( bReadOnly )
  360. {
  361. m_dwFlags |= READONLY;
  362. } // if: set the read only flag
  363. else
  364. {
  365. m_dwFlags &= ~READONLY;
  366. } // else: clear the read only flag
  367. m_bstrName = bstrName;
  368. return HrCreateValuesCollection( rpvlValue );
  369. } //*** CClusProperty::Create()
  370. /////////////////////////////////////////////////////////////////////////////
  371. //++
  372. //
  373. // CClusProperty::HrCreateValuesCollection
  374. //
  375. // Description:
  376. // Create the values collection from a value list.
  377. //
  378. // Arguments:
  379. // rpvlValue [IN] - The value list.
  380. //
  381. // Return Value:
  382. // S_OK if successful, or other HRESULT error if not.
  383. //
  384. //--
  385. /////////////////////////////////////////////////////////////////////////////
  386. HRESULT CClusProperty::HrCreateValuesCollection(
  387. IN const CClusPropValueList & rpvlValue
  388. )
  389. {
  390. HRESULT _hr = S_FALSE;
  391. _hr = CComObject< CClusPropertyValues >::CreateInstance( &m_pValues );
  392. if ( SUCCEEDED( _hr ) )
  393. {
  394. CSmartPtr< CComObject< CClusPropertyValues > > _ptrValues( m_pValues );
  395. _hr = _ptrValues->Create( rpvlValue, ( m_dwFlags & READONLY ) );
  396. if ( SUCCEEDED( _hr ) )
  397. {
  398. _ptrValues->AddRef();
  399. } // if:
  400. }
  401. return _hr;
  402. } //*** CClusProperty::HrCreateValuesCollection()
  403. /////////////////////////////////////////////////////////////////////////////
  404. //++
  405. //
  406. // CClusProperty::HrCreateValuesCollection
  407. //
  408. // Description:
  409. // Create the values collection from a variant.
  410. //
  411. // Arguments:
  412. // varValue [IN] - The value.
  413. // cptType [IN] - The cluster property type.
  414. // cpfFormat [IN] - The cluster property format.
  415. //
  416. // Return Value:
  417. // S_OK if successful, or other HRESULT error if not.
  418. //
  419. //--
  420. /////////////////////////////////////////////////////////////////////////////
  421. HRESULT CClusProperty::HrCreateValuesCollection(
  422. IN VARIANT varValue,
  423. IN CLUSTER_PROPERTY_TYPE cptType,
  424. IN CLUSTER_PROPERTY_FORMAT cpfFormat
  425. )
  426. {
  427. HRESULT _hr = S_FALSE;
  428. _hr = CComObject< CClusPropertyValues >::CreateInstance( &m_pValues );
  429. if ( SUCCEEDED( _hr ) )
  430. {
  431. CSmartPtr< CComObject< CClusPropertyValues > > _ptrValues( m_pValues );
  432. _hr = _ptrValues->Create( varValue, cptType, cpfFormat, ( m_dwFlags & READONLY ) );
  433. if ( SUCCEEDED( _hr ) )
  434. {
  435. _ptrValues->AddRef();
  436. } // if:
  437. }
  438. return _hr;
  439. } //*** CClusProperty::HrCreateValuesCollection()
  440. /////////////////////////////////////////////////////////////////////////////
  441. //++
  442. //
  443. // CClusProperty::get_Name
  444. //
  445. // Description:
  446. // Return the name of this property.
  447. //
  448. // Arguments:
  449. // pbstrName [OUT] - Catches the name of this property.
  450. //
  451. // Return Value:
  452. // S_OK if successful, E_POINTER, or other HRESULT error.
  453. //
  454. //--
  455. /////////////////////////////////////////////////////////////////////////////
  456. STDMETHODIMP CClusProperty::get_Name( OUT BSTR * pbstrName )
  457. {
  458. //ASSERT( pbstrName != NULL );
  459. HRESULT _hr = E_POINTER;
  460. if ( pbstrName != NULL )
  461. {
  462. *pbstrName = m_bstrName.Copy();
  463. _hr = S_OK;
  464. }
  465. return _hr;
  466. } //*** CClusProperty::get_Name()
  467. /////////////////////////////////////////////////////////////////////////////
  468. //++
  469. //
  470. // CClusProperty::put_Name
  471. //
  472. // Description:
  473. // Change the name of this property.
  474. //
  475. // Arguments:
  476. // bstrName [IN] - The new property name.
  477. //
  478. // Return Value:
  479. // S_OK if successful, or S_FALSE if the property is read only.
  480. //
  481. //--
  482. /////////////////////////////////////////////////////////////////////////////
  483. STDMETHODIMP CClusProperty::put_Name( IN BSTR bstrName )
  484. {
  485. HRESULT _hr = S_FALSE;
  486. if ( ( m_dwFlags & READONLY ) == 0 )
  487. {
  488. m_bstrName = bstrName;
  489. _hr = S_OK;
  490. }
  491. return _hr;
  492. } //*** CClusProperty::put_Name()
  493. /////////////////////////////////////////////////////////////////////////////
  494. //++
  495. //
  496. // CClusProperty::get_Type
  497. //
  498. // Description:
  499. // Return the cluster property type for the default value.
  500. //
  501. // Arguments:
  502. // pcptType [OUT] - Catches the type.
  503. //
  504. // Return Value:
  505. // S_OK if successful, E_POINTER, or other HRESULT error.
  506. //
  507. //--
  508. /////////////////////////////////////////////////////////////////////////////
  509. STDMETHODIMP CClusProperty::get_Type( OUT CLUSTER_PROPERTY_TYPE * pcptType )
  510. {
  511. //ASSERT( pcptType != NULL );
  512. HRESULT _hr = E_POINTER;
  513. if ( pcptType != NULL )
  514. {
  515. _hr = (*m_pValues)[ 0 ]->get_Type( pcptType );
  516. } // if: property type return value specified
  517. return _hr;
  518. } //*** CClusProperty::get_Type()
  519. /////////////////////////////////////////////////////////////////////////////
  520. //++
  521. //
  522. // CClusProperty::put_Type
  523. //
  524. // Description:
  525. // Change the cluster property type of the default value.
  526. //
  527. // Arguments:
  528. // cptType [IN] - The new cluster property type.
  529. //
  530. // Return Value:
  531. // S_OK if successful, or other HRESULT error.
  532. //
  533. //--
  534. /////////////////////////////////////////////////////////////////////////////
  535. STDMETHODIMP CClusProperty::put_Type( IN CLUSTER_PROPERTY_TYPE cptType )
  536. {
  537. return (*m_pValues)[ 0 ]->put_Type( cptType );
  538. } //*** CClusProperty::put_Type()
  539. /////////////////////////////////////////////////////////////////////////////
  540. //++
  541. //
  542. // CClusProperty::get_Format
  543. //
  544. // Description:
  545. // Returns the cluster property format for the default value.
  546. //
  547. // Arguments:
  548. // pcpfFormat [OUT] - Catches the format.
  549. //
  550. // Return Value:
  551. // S_OK if successful, E_POINTER, or other HRESULT error.
  552. //
  553. //--
  554. /////////////////////////////////////////////////////////////////////////////
  555. STDMETHODIMP CClusProperty::get_Format(
  556. OUT CLUSTER_PROPERTY_FORMAT * pcpfFormat
  557. )
  558. {
  559. //ASSERT( pcpfFormat != NULL );
  560. HRESULT _hr = E_POINTER;
  561. if ( pcpfFormat != NULL )
  562. {
  563. _hr = (*m_pValues)[ 0 ]->get_Format( pcpfFormat );
  564. } // if: property format return value specified
  565. return _hr;
  566. } //*** CClusProperty::get_Format()
  567. /////////////////////////////////////////////////////////////////////////////
  568. //++
  569. //
  570. // CClusProperty::put_Format
  571. //
  572. // Description:
  573. // Change the cluster property format of the default value.
  574. //
  575. // Arguments:
  576. // cpfFormat [IN] - The new cluster property format.
  577. //
  578. // Return Value:
  579. // S_OK if successful, or other HRESULT error.
  580. //
  581. //--
  582. /////////////////////////////////////////////////////////////////////////////
  583. STDMETHODIMP CClusProperty::put_Format(
  584. IN CLUSTER_PROPERTY_FORMAT cpfFormat
  585. )
  586. {
  587. return (*m_pValues)[ 0 ]->put_Format( cpfFormat );
  588. } //*** CClusProperty::put_Format()
  589. /////////////////////////////////////////////////////////////////////////////
  590. //++
  591. //
  592. // CClusProperty::get_Length
  593. //
  594. // Description:
  595. // Returns the length of the default value.
  596. //
  597. // Arguments:
  598. // plLenght [OUT] - Catches the length.
  599. //
  600. // Return Value:
  601. // S_OK if successful, or other HRESULT error.
  602. //
  603. //--
  604. /////////////////////////////////////////////////////////////////////////////
  605. STDMETHODIMP CClusProperty::get_Length( OUT long * plLength )
  606. {
  607. return (*m_pValues)[ 0 ]->get_Length( plLength );
  608. } //*** CClusProperty::get_Length()
  609. /////////////////////////////////////////////////////////////////////////////
  610. //++
  611. //
  612. // CClusProperty::get_ValueCount
  613. //
  614. // Description:
  615. // Return the count of ClusPropertyValue object in the ClusPropertyValues
  616. // collection.
  617. //
  618. // Arguments:
  619. // plCount [OUT] - Catches the count.
  620. //
  621. // Return Value:
  622. // S_OK if successful, or other HRESULT error.
  623. //
  624. //--
  625. /////////////////////////////////////////////////////////////////////////////
  626. STDMETHODIMP CClusProperty::get_ValueCount( OUT long * plCount )
  627. {
  628. return m_pValues->get_Count( plCount );
  629. } //*** CClusProperty::get_ValueCount()
  630. /////////////////////////////////////////////////////////////////////////////
  631. //++
  632. //
  633. // CClusProperty::get_Values
  634. //
  635. // Description:
  636. // Returns the property values collection.
  637. //
  638. // Arguments:
  639. // ppClusterPropertyValues [OUT] - Catches the values collection.
  640. //
  641. // Return Value:
  642. // S_OK if successful, E_POINTER, or other HRESULT error.
  643. //
  644. //--
  645. /////////////////////////////////////////////////////////////////////////////
  646. STDMETHODIMP CClusProperty::get_Values(
  647. ISClusPropertyValues ** ppClusterPropertyValues
  648. )
  649. {
  650. //ASSERT( ppClusterPropertyValues );
  651. HRESULT _hr = E_POINTER;
  652. if ( ppClusterPropertyValues != NULL )
  653. {
  654. _hr = m_pValues->QueryInterface( IID_ISClusPropertyValues, (void **) ppClusterPropertyValues );
  655. }
  656. return _hr;
  657. } //*** CClusProperty::get_Values()
  658. /////////////////////////////////////////////////////////////////////////////
  659. //++
  660. //
  661. // CClusProperty::Modified
  662. //
  663. // Description:
  664. // Sets the modified state of the property.
  665. //
  666. // Arguments:
  667. // bModified [IN] - The new modfied state.
  668. //
  669. // Return Value:
  670. // The old state.
  671. //
  672. //--
  673. /////////////////////////////////////////////////////////////////////////////
  674. BOOL CClusProperty::Modified( IN BOOL bModified )
  675. {
  676. BOOL _bTemp = ( m_dwFlags & MODIFIED );
  677. if ( bModified )
  678. {
  679. m_dwFlags |= MODIFIED;
  680. } // if: set the modified flag
  681. else
  682. {
  683. m_dwFlags &= ~MODIFIED;
  684. } // else: clear the modified flag
  685. return _bTemp;
  686. } //*** CClusProperty::Modified()
  687. /////////////////////////////////////////////////////////////////////////////
  688. //++
  689. //
  690. // CClusProperty::get_Value
  691. //
  692. // Description:
  693. // Get the value of the default value from the values collection.
  694. //
  695. // Arguments:
  696. // pvarValue [OUT] - Catches the value.
  697. //
  698. // Return Value:
  699. // S_OK if successful, or other HRESULT error.
  700. //
  701. //--
  702. /////////////////////////////////////////////////////////////////////////////
  703. STDMETHODIMP CClusProperty::get_Value( OUT VARIANT * pvarValue )
  704. {
  705. //ASSERT( pvarValue != NULL );
  706. HRESULT _hr = E_POINTER;
  707. if ( pvarValue != NULL )
  708. {
  709. CComObject< CClusPropertyValue > * _pPropValue = (*m_pValues)[ 0 ];
  710. CComVariant _varPropValue = _pPropValue->Value();
  711. _hr = ::VariantCopyInd( pvarValue, &_varPropValue );
  712. }
  713. return _hr;
  714. } //*** _CClusProperty::get_Value()
  715. /////////////////////////////////////////////////////////////////////////////
  716. //++
  717. //
  718. // CClusProperty::put_Value
  719. //
  720. // Description:
  721. // Change the value of the default value in the values collection.
  722. //
  723. // Arguments:
  724. // varValue [IN] - The new value.
  725. //
  726. // Return Value:
  727. // S_OK if successful, S_FALSE is read only, or other HRESULT error.
  728. //
  729. //--
  730. /////////////////////////////////////////////////////////////////////////////
  731. STDMETHODIMP CClusProperty::put_Value( IN VARIANT varValue )
  732. {
  733. HRESULT _hr = S_FALSE;
  734. if ( ( m_dwFlags & READONLY ) == 0 )
  735. {
  736. CComObject< CClusPropertyValue > * _pPropValue = (*m_pValues)[ 0 ];
  737. CLUSTER_PROPERTY_FORMAT _cpfFormat = CLUSPROP_FORMAT_UNKNOWN;
  738. _hr = _pPropValue->get_Format( &_cpfFormat );
  739. if ( SUCCEEDED( _hr ) )
  740. {
  741. CComVariant _varOldValue = _pPropValue->Value();
  742. _hr = HrCoerceVariantType( _cpfFormat, varValue );
  743. if ( SUCCEEDED( _hr ) )
  744. {
  745. if ( _cpfFormat == CLUSPROP_FORMAT_BINARY )
  746. {
  747. BOOL bEqual = TRUE;
  748. _hr = HrBinaryCompare( _varOldValue, varValue, &bEqual );
  749. if ( ( SUCCEEDED( _hr ) ) && ( ! bEqual ) )
  750. {
  751. _hr = HrSaveBinaryProperty( _pPropValue, varValue );
  752. if ( SUCCEEDED( _hr ) )
  753. {
  754. m_dwFlags |= MODIFIED;
  755. m_dwFlags &= ~USEDEFAULT;
  756. } // if: the binary value was saved
  757. } // if:
  758. } // if:
  759. else
  760. {
  761. if ( _varOldValue != varValue )
  762. {
  763. _pPropValue->Value( varValue );
  764. m_dwFlags |= MODIFIED;
  765. m_dwFlags &= ~USEDEFAULT;
  766. } // if:
  767. } // else:
  768. } // if:
  769. } // if:
  770. } // if:
  771. return _hr;
  772. } //*** CClusProperty::put_Value()
  773. /////////////////////////////////////////////////////////////////////////////
  774. //++
  775. //
  776. // CClusProperty::get_ReadOnly
  777. //
  778. // Description:
  779. // Is this property read only?
  780. //
  781. // Arguments:
  782. // pvarReadOnly [OUT] - catches the property's read only state.
  783. //
  784. // Return Value:
  785. // S_OK if successful, or E_POINTER.
  786. //
  787. //--
  788. /////////////////////////////////////////////////////////////////////////////
  789. STDMETHODIMP CClusProperty::get_ReadOnly( OUT VARIANT * pvarReadOnly )
  790. {
  791. //ASSERT( pvarReadOnly != NULL );
  792. HRESULT _hr = E_POINTER;
  793. if ( pvarReadOnly != NULL )
  794. {
  795. pvarReadOnly->vt = VT_BOOL;
  796. if ( m_dwFlags & READONLY )
  797. {
  798. pvarReadOnly->boolVal = VARIANT_TRUE;
  799. } // if: if this is a read only property...
  800. else
  801. {
  802. pvarReadOnly->boolVal = VARIANT_FALSE;
  803. } // else: it is not a read only property...
  804. _hr = S_OK;
  805. } // if:
  806. return _hr;
  807. } //*** CClusProperty::get_ReadOnly()
  808. /////////////////////////////////////////////////////////////////////////////
  809. //++
  810. //
  811. // CClusProperty::get_Private
  812. //
  813. // Description:
  814. // Is this a private property?
  815. //
  816. // Arguments:
  817. // pvarPrivate [OUT] - catches the private property state.
  818. //
  819. // Return Value:
  820. // S_OK if successful, or E_POINTER
  821. //
  822. //--
  823. /////////////////////////////////////////////////////////////////////////////
  824. STDMETHODIMP CClusProperty::get_Private( OUT VARIANT * pvarPrivate )
  825. {
  826. //ASSERT( pvarPrivate != NULL );
  827. HRESULT _hr = E_POINTER;
  828. if ( pvarPrivate != NULL )
  829. {
  830. pvarPrivate->vt = VT_BOOL;
  831. if ( m_dwFlags & PRIVATE )
  832. {
  833. pvarPrivate->boolVal = VARIANT_TRUE;
  834. } // if: if this is private property...
  835. else
  836. {
  837. pvarPrivate->boolVal = VARIANT_FALSE;
  838. } // else: it is not a private property...
  839. _hr = S_OK;
  840. } // if:
  841. return _hr;
  842. } //*** CClusProperty::get_Private()
  843. /////////////////////////////////////////////////////////////////////////////
  844. //++
  845. //
  846. // CClusProperty::get_Common
  847. //
  848. // Description:
  849. // Is this a common property?
  850. //
  851. // Arguments:
  852. // pvarCommon [OUT] - catches the common property state.
  853. //
  854. // Return Value:
  855. // S_OK if successful, or E_POINTER
  856. //
  857. //--
  858. /////////////////////////////////////////////////////////////////////////////
  859. STDMETHODIMP CClusProperty::get_Common( OUT VARIANT * pvarCommon )
  860. {
  861. //ASSERT( pvarCommon != NULL );
  862. HRESULT _hr = E_POINTER;
  863. if ( pvarCommon != NULL )
  864. {
  865. pvarCommon->vt = VT_BOOL;
  866. if ( ( m_dwFlags & PRIVATE ) == 0 )
  867. {
  868. pvarCommon->boolVal = VARIANT_TRUE;
  869. } // if: if this is not a private property then it must be a common one...
  870. else
  871. {
  872. pvarCommon->boolVal = VARIANT_FALSE;
  873. } // else: it is a private property...
  874. _hr = S_OK;
  875. } // if:
  876. return _hr;
  877. } //*** CClusProperty::get_Common()
  878. /////////////////////////////////////////////////////////////////////////////
  879. //++
  880. //
  881. // CClusProperty::get_Modified
  882. //
  883. // Description:
  884. // Has this property been modified?
  885. //
  886. // Arguments:
  887. // pvarModified [OUT] - catches the modified state.
  888. //
  889. // Return Value:
  890. // S_OK if successful, or E_POINTER
  891. //
  892. //--
  893. /////////////////////////////////////////////////////////////////////////////
  894. STDMETHODIMP CClusProperty::get_Modified( OUT VARIANT * pvarModified )
  895. {
  896. //ASSERT( pvarModified != NULL );
  897. HRESULT _hr = E_POINTER;
  898. if ( pvarModified != NULL )
  899. {
  900. pvarModified->vt = VT_BOOL;
  901. if ( m_dwFlags & MODIFIED )
  902. {
  903. pvarModified->boolVal = VARIANT_TRUE;
  904. } // if: if it's been modified set the varint to true...
  905. else
  906. {
  907. pvarModified->boolVal = VARIANT_FALSE;
  908. } // else: if not the set the variant to false...
  909. _hr = S_OK;
  910. } // if:
  911. return _hr;
  912. } //*** CClusProperty::get_Modified()
  913. /////////////////////////////////////////////////////////////////////////////
  914. //++
  915. //
  916. // CClusProperty::HrSaveBinaryProperty
  917. //
  918. // Description:
  919. // Save the passed in SafeArray into our own SafeArray that is stored in
  920. // in a variant.
  921. //
  922. // Arguments:
  923. // pPropValue [IN] - PropertyValue that gets the copy.
  924. // rvarValue [IN] - The safe array to copy.
  925. //
  926. // Return Value:
  927. // S_OK if successful, or E_POINTER
  928. //
  929. //--
  930. /////////////////////////////////////////////////////////////////////////////
  931. HRESULT CClusProperty::HrSaveBinaryProperty(
  932. IN CComObject< CClusPropertyValue > * pPropValue,
  933. IN const VARIANT & rvarValue
  934. )
  935. {
  936. ASSERT( pPropValue != NULL );
  937. HRESULT _hr = E_POINTER;
  938. if ( pPropValue != NULL )
  939. {
  940. SAFEARRAY * _psa = NULL;
  941. _hr = ::SafeArrayCopy( rvarValue.parray, &_psa );
  942. if ( SUCCEEDED( _hr ) )
  943. {
  944. _hr = pPropValue->HrBinaryValue( _psa );
  945. } // if:
  946. } // if:
  947. return _hr;
  948. } //*** CClusProperty::HrSaveBinaryProperty()
  949. /////////////////////////////////////////////////////////////////////////////
  950. //++
  951. //
  952. // CClusProperty::UseDefaultValue
  953. //
  954. // Description:
  955. // Mark this property to restore its default value. This effectivly
  956. // deletes the property.
  957. //
  958. // Arguments:
  959. // None.
  960. //
  961. // Return Value:
  962. // S_OK.
  963. //
  964. //--
  965. /////////////////////////////////////////////////////////////////////////////
  966. HRESULT CClusProperty::UseDefaultValue( void )
  967. {
  968. HRESULT _hr = S_OK;
  969. //
  970. // Mark this property as being modified and needing to be reset to
  971. // its default value.
  972. //
  973. m_dwFlags |= USEDEFAULT;
  974. m_dwFlags |= MODIFIED;
  975. //
  976. // Now we need to empty the value
  977. //
  978. CComObject< CClusPropertyValue > * _pPropValue = (*m_pValues)[ 0 ];
  979. CLUSTER_PROPERTY_FORMAT _cpfFormat = CLUSPROP_FORMAT_UNKNOWN;
  980. _hr = _pPropValue->get_Format( &_cpfFormat );
  981. if ( SUCCEEDED( _hr ) )
  982. {
  983. VARIANT _var;
  984. ::VariantInit( &_var );
  985. switch ( _cpfFormat )
  986. {
  987. case CLUSPROP_FORMAT_BINARY:
  988. {
  989. SAFEARRAY * _psa = NULL;
  990. SAFEARRAYBOUND _sab[ 1 ];
  991. _sab[ 0 ].lLbound = 0;
  992. _sab[ 0 ].cElements = 0;
  993. //
  994. // allocate a one dimensional SafeArray of BYTES
  995. //
  996. _psa = ::SafeArrayCreate( VT_UI1, 1, _sab );
  997. if ( _psa != NULL )
  998. {
  999. _hr = _pPropValue->HrBinaryValue( _psa );
  1000. } // if the safe array was allocated
  1001. else
  1002. {
  1003. _hr = E_OUTOFMEMORY;
  1004. } // else: safe array was not allocated
  1005. break;
  1006. } // case:
  1007. #if CLUSAPI_VERSION >= 0x0500
  1008. case CLUSPROP_FORMAT_LONG:
  1009. #endif // CLUSAPI_VERSION >= 0x0500
  1010. case CLUSPROP_FORMAT_DWORD:
  1011. case CLUSPROP_FORMAT_ULARGE_INTEGER:
  1012. case CLUSPROP_FORMAT_SZ:
  1013. case CLUSPROP_FORMAT_EXPAND_SZ:
  1014. case CLUSPROP_FORMAT_MULTI_SZ:
  1015. {
  1016. _var.vt = VT_EMPTY;
  1017. _pPropValue->Value( _var );
  1018. break;
  1019. } // case:
  1020. #if CLUSAPI_VERSION >= 0x0500
  1021. case CLUSPROP_FORMAT_EXPANDED_SZ:
  1022. #endif // CLUSAPI_VERSION >= 0x0500
  1023. case CLUSPROP_FORMAT_UNKNOWN:
  1024. default:
  1025. {
  1026. _hr = E_INVALIDARG;
  1027. break;
  1028. } // default:
  1029. } // switch: on property format
  1030. } // if: we got the format
  1031. return _hr;
  1032. } //*** CClusProperty::UseDefaultValue()
  1033. //*************************************************************************//
  1034. /////////////////////////////////////////////////////////////////////////////
  1035. // CClusProperties class
  1036. /////////////////////////////////////////////////////////////////////////////
  1037. /////////////////////////////////////////////////////////////////////////////
  1038. //++
  1039. //
  1040. // CClusProperties::CClusProperties
  1041. //
  1042. // Description:
  1043. // Constsructor
  1044. //
  1045. // Arguments:
  1046. // None.
  1047. //
  1048. // Return Value:
  1049. // None.
  1050. //
  1051. //--
  1052. /////////////////////////////////////////////////////////////////////////////
  1053. CClusProperties::CClusProperties( void )
  1054. {
  1055. m_dwFlags = 0;
  1056. m_pcoParent = NULL;
  1057. m_piids = (const IID *) iidCClusProperties;
  1058. m_piidsSize = ARRAYSIZE( iidCClusProperties );
  1059. } //*** CClusProperties::CClusProperties()
  1060. /////////////////////////////////////////////////////////////////////////////
  1061. //++
  1062. //
  1063. // CClusProperties::~CClusProperties
  1064. //
  1065. // Description:
  1066. // Destructor
  1067. //
  1068. // Arguments:
  1069. // None.
  1070. //
  1071. // Return Value:
  1072. // None.
  1073. //
  1074. //--
  1075. /////////////////////////////////////////////////////////////////////////////
  1076. CClusProperties::~CClusProperties( void )
  1077. {
  1078. Clear();
  1079. } //*** CClusProperties::~CClusProperties()
  1080. /////////////////////////////////////////////////////////////////////////////
  1081. //++
  1082. //
  1083. // CClusProperties::Clear
  1084. //
  1085. // Description:
  1086. // Clean out the vector or ClusProperty objects.
  1087. //
  1088. // Arguments:
  1089. // None.
  1090. //
  1091. // Return Value:
  1092. // None.
  1093. //
  1094. //--
  1095. /////////////////////////////////////////////////////////////////////////////
  1096. void CClusProperties::Clear( void )
  1097. {
  1098. ::ReleaseAndEmptyCollection< CClusPropertyVector, CComObject< CClusProperty > >( m_Properties );
  1099. } //*** CClusProperties::Clear()
  1100. /////////////////////////////////////////////////////////////////////////////
  1101. //++
  1102. //
  1103. // CClusProperties::get_Count
  1104. //
  1105. // Description:
  1106. // Returns the count of elements (properties) in the collection.
  1107. //
  1108. // Arguments:
  1109. // plCount [OUT] - Catches the count.
  1110. //
  1111. // Return Value:
  1112. // S_OK if successful, or E_POINTER if not.
  1113. //
  1114. //--
  1115. /////////////////////////////////////////////////////////////////////////////
  1116. STDMETHODIMP CClusProperties::get_Count( OUT long * plCount )
  1117. {
  1118. //ASSERT( plCount != NULL );
  1119. HRESULT _hr = E_POINTER;
  1120. if ( plCount != NULL )
  1121. {
  1122. *plCount = m_Properties.size();
  1123. _hr = S_OK;
  1124. }
  1125. return _hr;
  1126. } //*** CClusProperties::get_Count()
  1127. /////////////////////////////////////////////////////////////////////////////
  1128. //++
  1129. //
  1130. // CClusProperties::FindItem
  1131. //
  1132. // Description:
  1133. // Find the property that has the passed in name.
  1134. //
  1135. // Arguments:
  1136. // pszPropName [IN] - The name of the property to find.
  1137. // pnIndex [OUT] - The index of the property.
  1138. //
  1139. // Return Value:
  1140. // S_OK if successful, E_INVALIDARG, or other HRESULT error.
  1141. //
  1142. //--
  1143. /////////////////////////////////////////////////////////////////////////////
  1144. HRESULT CClusProperties::FindItem(
  1145. IN LPWSTR pszPropName,
  1146. OUT UINT * pnIndex
  1147. )
  1148. {
  1149. //ASSERT( pszPropName != NULL );
  1150. //ASSERT( pnIndex != NULL );
  1151. HRESULT _hr = E_POINTER;
  1152. if ( ( pszPropName != NULL ) && ( pnIndex != NULL ) )
  1153. {
  1154. CComObject< CClusProperty > * _pProperty = NULL;
  1155. CClusPropertyVector::const_iterator _first = m_Properties.begin();
  1156. CClusPropertyVector::const_iterator _last = m_Properties.end();
  1157. UINT _nIndex = 0;
  1158. _hr = E_INVALIDARG;
  1159. for ( ; _first != _last; _first++, _nIndex++ )
  1160. {
  1161. _pProperty = *_first;
  1162. if ( _pProperty && ( lstrcmpi( pszPropName, _pProperty->Name() ) == 0 ) )
  1163. {
  1164. *pnIndex = _nIndex;
  1165. _hr = S_OK;
  1166. break;
  1167. }
  1168. }
  1169. }
  1170. return _hr;
  1171. } //*** CClusProperties::FindItem()
  1172. /////////////////////////////////////////////////////////////////////////////
  1173. //++
  1174. //
  1175. // CClusProperties::FindItem
  1176. //
  1177. // Description:
  1178. // Find the passed in property in the collection.
  1179. //
  1180. // Arguments:
  1181. // pProperty [IN] - The property to find.
  1182. // pnIndex [OUT] - The index of the property.
  1183. //
  1184. // Return Value:
  1185. // S_OK if successful, or other HRESULT error.
  1186. //
  1187. //--
  1188. /////////////////////////////////////////////////////////////////////////////
  1189. HRESULT CClusProperties::FindItem(
  1190. IN ISClusProperty * pProperty,
  1191. OUT UINT * pnIndex
  1192. )
  1193. {
  1194. //ASSERT( pProperty != NULL );
  1195. //ASSERT( pnIndex != NULL );
  1196. HRESULT _hr = E_POINTER;
  1197. if ( ( pProperty != NULL ) && ( pnIndex != NULL ) )
  1198. {
  1199. CComBSTR _bstrName;
  1200. _hr = pProperty->get_Name( &_bstrName );
  1201. if ( SUCCEEDED( _hr ) )
  1202. {
  1203. _hr = FindItem( _bstrName, pnIndex );
  1204. }
  1205. }
  1206. return _hr;
  1207. } //*** CClusProperties::FindItem()
  1208. /////////////////////////////////////////////////////////////////////////////
  1209. //++
  1210. //
  1211. // CClusProperties::GetIndex
  1212. //
  1213. // Description:
  1214. // Get the index from the passed in variant.
  1215. //
  1216. // Arguments:
  1217. // varIndex [IN] - Hold the index. This is a one based number,
  1218. // or the name of the property as a string.
  1219. // pnIndex [OUT] - Catches the zero based index in the collection.
  1220. //
  1221. // Return Value:
  1222. // S_OK if successful, E_POINTER, or E_INVALIDARG if the index is out
  1223. // of range.
  1224. //
  1225. //--
  1226. /////////////////////////////////////////////////////////////////////////////
  1227. HRESULT CClusProperties::GetIndex(
  1228. IN VARIANT varIndex,
  1229. OUT UINT * pnIndex
  1230. )
  1231. {
  1232. //ASSERT( pnIndex != NULL );
  1233. HRESULT _hr = E_POINTER;
  1234. if ( pnIndex != NULL )
  1235. {
  1236. CComVariant _v;
  1237. UINT _nIndex = 0;
  1238. *pnIndex = 0;
  1239. _v.Copy( &varIndex );
  1240. // Check to see if the index is a number.
  1241. _hr = _v.ChangeType( VT_I4 );
  1242. if ( SUCCEEDED( _hr ) )
  1243. {
  1244. _nIndex = _v.lVal;
  1245. _nIndex--; // Adjust index to be 0 relative instead of 1 relative
  1246. }
  1247. else
  1248. {
  1249. // Check to see if the index is a string.
  1250. _hr = _v.ChangeType( VT_BSTR );
  1251. if ( SUCCEEDED( _hr ) )
  1252. {
  1253. // Search for the string.
  1254. _hr = FindItem( _v.bstrVal, &_nIndex );
  1255. }
  1256. }
  1257. // We found an index, now check the range.
  1258. if ( SUCCEEDED( _hr ) )
  1259. {
  1260. if ( _nIndex < m_Properties.size() )
  1261. {
  1262. *pnIndex = _nIndex;
  1263. }
  1264. else
  1265. {
  1266. _hr = E_INVALIDARG;
  1267. }
  1268. }
  1269. }
  1270. return _hr;
  1271. } //*** CClusProperties::GetIndex()
  1272. /////////////////////////////////////////////////////////////////////////////
  1273. //++
  1274. //
  1275. // CClusProperties::get_Item
  1276. //
  1277. // Description:
  1278. // Returns the object (property) at the passed in index.
  1279. //
  1280. // Arguments:
  1281. // varIndex [IN] - Hold the index. This is a one based number.
  1282. // ppProperty [OUT] - Catches the property.
  1283. //
  1284. // Return Value:
  1285. // S_OK if successful, E_POINTER, or E_INVALIDARG if the index is out
  1286. // of range, or other HRESULT error.
  1287. //
  1288. //--
  1289. /////////////////////////////////////////////////////////////////////////////
  1290. STDMETHODIMP CClusProperties::get_Item(
  1291. IN VARIANT varIndex,
  1292. OUT ISClusProperty ** ppProperty
  1293. )
  1294. {
  1295. //ASSERT( ppProperty != NULL );
  1296. HRESULT _hr = E_POINTER;
  1297. if ( ppProperty != NULL )
  1298. {
  1299. CComObject< CClusProperty > * _pProperty = NULL;
  1300. UINT _nIndex = 0;
  1301. //
  1302. // Zero the out param
  1303. //
  1304. *ppProperty = 0;
  1305. _hr = GetIndex( varIndex, &_nIndex );
  1306. if ( SUCCEEDED( _hr ) )
  1307. {
  1308. _pProperty = m_Properties[ _nIndex ];
  1309. _hr = _pProperty->QueryInterface( IID_ISClusProperty, (void **) ppProperty );
  1310. }
  1311. }
  1312. return _hr;
  1313. } //*** CClusProperties::get_Item()
  1314. /////////////////////////////////////////////////////////////////////////////
  1315. //++
  1316. //
  1317. // CClusProperties::get__NewEnum
  1318. //
  1319. // Description:
  1320. // Create and return a new enumeration for this collection.
  1321. //
  1322. // Arguments:
  1323. // ppunk [OUT] - Catches the new enumeration.
  1324. //
  1325. // Return Value:
  1326. // S_OK if successful, E_POINTER, or other HRESULT error.
  1327. //
  1328. //--
  1329. /////////////////////////////////////////////////////////////////////////////
  1330. STDMETHODIMP CClusProperties::get__NewEnum( OUT IUnknown ** ppunk )
  1331. {
  1332. return ::HrNewIDispatchEnum< CClusPropertyVector, CComObject< CClusProperty > >( ppunk, m_Properties );
  1333. } //*** CClusProperties::get__NewEnum()
  1334. /////////////////////////////////////////////////////////////////////////////
  1335. //++
  1336. //
  1337. // CClusProperties::CreateItem
  1338. //
  1339. // Description:
  1340. // Create a new property and add it to the collection.
  1341. //
  1342. // Arguments:
  1343. // bstrName [IN] - property name.
  1344. // varValue [IN] - the value to add.
  1345. // ppProperty [OUT] - catches the newly created object.
  1346. //
  1347. // Return Value:
  1348. // S_OK if successful, or other HRESULT error.
  1349. //
  1350. //--
  1351. /////////////////////////////////////////////////////////////////////////////
  1352. STDMETHODIMP CClusProperties::CreateItem(
  1353. IN BSTR bstrName,
  1354. IN VARIANT varValue,
  1355. OUT ISClusProperty ** ppProperty
  1356. )
  1357. {
  1358. //ASSERT( ppProperty != NULL );
  1359. HRESULT _hr = E_POINTER;
  1360. if ( ppProperty != NULL )
  1361. {
  1362. //
  1363. // You can only add to not read only and private property lists. Meaning
  1364. // only the PrivateProperties collection can have new, unknown properties
  1365. // added to it. This should be reflected in the idl, but since there is
  1366. // only one properties collection...
  1367. //
  1368. if ( ( ( m_dwFlags & READONLY ) == 0 ) && ( m_dwFlags & PRIVATE ) )
  1369. {
  1370. UINT _nIndex = 0;
  1371. CComObject< CClusProperty > * _pProperty = NULL;
  1372. _hr = FindItem( bstrName, &_nIndex );
  1373. if ( SUCCEEDED( _hr ) )
  1374. {
  1375. _pProperty = m_Properties[ _nIndex ];
  1376. _hr = _pProperty->put_Value( varValue );
  1377. if ( SUCCEEDED( _hr ) )
  1378. {
  1379. _hr = _pProperty->QueryInterface( IID_ISClusProperty, (void **) ppProperty );
  1380. } // if: the value was changed
  1381. } // if: the item is in the list, change it...
  1382. else
  1383. {
  1384. //
  1385. // Create a new property and add it to the list.
  1386. //
  1387. _hr = CComObject< CClusProperty >::CreateInstance( &_pProperty );
  1388. if ( SUCCEEDED( _hr ) )
  1389. {
  1390. CSmartPtr< CComObject< CClusProperty > > _ptrProperty( _pProperty );
  1391. _hr = _ptrProperty->Create( bstrName, varValue, ( m_dwFlags & PRIVATE ), ( m_dwFlags & READONLY ) );
  1392. if ( SUCCEEDED( _hr ) )
  1393. {
  1394. _hr = _ptrProperty->QueryInterface( IID_ISClusProperty, (void **) ppProperty );
  1395. if ( SUCCEEDED( _hr ) )
  1396. {
  1397. _ptrProperty->AddRef();
  1398. m_Properties.insert( m_Properties.end(), _pProperty );
  1399. m_dwFlags |= MODIFIED;
  1400. _ptrProperty->Modified( TRUE );
  1401. }
  1402. }
  1403. }
  1404. } // else: new item
  1405. }
  1406. else
  1407. {
  1408. _hr = S_FALSE;
  1409. } // else: this is not the PrivateProperties collection!
  1410. }
  1411. return _hr;
  1412. } //*** CClusProperties::CreateItem()
  1413. /////////////////////////////////////////////////////////////////////////////
  1414. //++
  1415. //
  1416. // CClusProperties::UseDefaultValue
  1417. //
  1418. // Description:
  1419. // Remove the item from the collection at the passed in index.
  1420. //
  1421. // Arguments:
  1422. // varIdex [IN] - contains the index to remove.
  1423. //
  1424. // Return Value:
  1425. // S_OK if successful, E_INVALIDARG, or other HRESULT error.
  1426. //
  1427. //--
  1428. /////////////////////////////////////////////////////////////////////////////
  1429. STDMETHODIMP CClusProperties::UseDefaultValue( IN VARIANT varIndex )
  1430. {
  1431. HRESULT _hr = S_FALSE;
  1432. if ( ( m_dwFlags & READONLY ) == 0 )
  1433. {
  1434. UINT _nIndex = 0;
  1435. _hr = GetIndex( varIndex, &_nIndex );
  1436. if ( SUCCEEDED( _hr ) )
  1437. {
  1438. CComObject< CClusProperty > * _pProp = NULL;
  1439. _hr = E_POINTER;
  1440. _pProp = m_Properties [_nIndex];
  1441. if ( _pProp != NULL )
  1442. {
  1443. _hr = _pProp->UseDefaultValue();
  1444. } // if: we have a property
  1445. } // if: we got the index from the variant
  1446. } // if: the collection is not read only
  1447. return _hr;
  1448. } //*** CClusProperties::UseDefaultValue()
  1449. /*
  1450. /////////////////////////////////////////////////////////////////////////////
  1451. //++
  1452. //
  1453. // CClusProperties::RemoveAt
  1454. //
  1455. // Description:
  1456. // Remove the object (property) at the passed in index/position from the
  1457. // collection.
  1458. //
  1459. // Arguments:
  1460. // nPos [IN] - Index of the object to remove.
  1461. //
  1462. // Return Value:
  1463. // S_OK if successful, or other HRESULT error.
  1464. //
  1465. //--
  1466. /////////////////////////////////////////////////////////////////////////////
  1467. HRESULT CClusProperties::RemoveAt( IN size_t nPos )
  1468. {
  1469. CComObject< CClusProperty > * _pProperty = NULL;
  1470. CClusPropertyVector::iterator _first = m_Properties.begin();
  1471. CClusPropertyVector::const_iterator _last = m_Properties.end();
  1472. HRESULT _hr = E_INVALIDARG;
  1473. size_t _nIndex;
  1474. for ( _nIndex = 0; ( _nIndex < nPos ) && ( _first != _last ); _nIndex++, _first++ )
  1475. {
  1476. }
  1477. if ( _first != _last )
  1478. {
  1479. _pProperty = *_first;
  1480. if ( _pProperty )
  1481. {
  1482. _pProperty->Release();
  1483. }
  1484. m_Properties.erase( _first );
  1485. _hr = S_OK;
  1486. }
  1487. return _hr;
  1488. } //*** CClusProperties::RemoveAt()
  1489. */
  1490. /////////////////////////////////////////////////////////////////////////////
  1491. //++
  1492. //
  1493. // CClusProperties::SaveChanges
  1494. //
  1495. // Description:
  1496. // Save the changes to the properties to the cluster database.
  1497. //
  1498. // Arguments:
  1499. // pvarStatusCode [OUT] - Catches an additional status code.
  1500. // e.g. ERROR_RESOURCE_PROPERTIES_STORED.
  1501. //
  1502. // Return Value:
  1503. // S_OK if successful, or other Win32 error as HRESULT if not.
  1504. //
  1505. //--
  1506. /////////////////////////////////////////////////////////////////////////////
  1507. STDMETHODIMP CClusProperties::SaveChanges( OUT VARIANT * pvarStatusCode )
  1508. {
  1509. ASSERT( m_pcoParent != NULL );
  1510. HRESULT _hr = E_POINTER;
  1511. if ( m_pcoParent != NULL )
  1512. {
  1513. if ( ( m_dwFlags & READONLY ) == 0 )
  1514. {
  1515. VARIANT _vsc;
  1516. _hr = m_pcoParent->HrSaveProperties( m_Properties, ( m_dwFlags & PRIVATE ), &_vsc );
  1517. if ( SUCCEEDED( _hr ) )
  1518. {
  1519. if ( pvarStatusCode != NULL )
  1520. {
  1521. ::VariantCopy( pvarStatusCode, &_vsc );
  1522. } // if: optional arg is not NULL
  1523. _hr = Refresh();
  1524. } // if: properties were saved
  1525. } // if: this collection is not read only
  1526. else
  1527. {
  1528. _hr = S_FALSE;
  1529. } // else: this collection is read only
  1530. } // if: args and members vars are not NULL
  1531. return _hr;
  1532. } //*** CClusProperties::SaveChanges()
  1533. /////////////////////////////////////////////////////////////////////////////
  1534. //++
  1535. //
  1536. // CClusProperties::Refresh
  1537. //
  1538. // Description:
  1539. // Load the properties collection from the cluster database.
  1540. //
  1541. // Arguments:
  1542. // None.
  1543. //
  1544. // Return Value:
  1545. // S_OK if successful, or Win32 error as HRESULT if not.
  1546. //
  1547. //--
  1548. /////////////////////////////////////////////////////////////////////////////
  1549. STDMETHODIMP CClusProperties::Refresh( void )
  1550. {
  1551. ASSERT( m_pcoParent != NULL );
  1552. HRESULT _hr = E_POINTER;
  1553. if ( m_pcoParent != NULL )
  1554. {
  1555. CClusPropList _cplPropList;
  1556. _hr = m_pcoParent->HrLoadProperties( _cplPropList, ( m_dwFlags & READONLY ), ( m_dwFlags & PRIVATE ) );
  1557. if ( SUCCEEDED( _hr ) )
  1558. {
  1559. Clear();
  1560. m_dwFlags &= ~MODIFIED;
  1561. if ( _cplPropList.Cprops() > 0 )
  1562. {
  1563. _hr = HrFillPropertyVector( _cplPropList );
  1564. } // if: are there any properties in the list?
  1565. } // if: loaded properties successfully
  1566. } // if: no parent
  1567. return _hr;
  1568. } //*** CClusProperties::Refresh()
  1569. /////////////////////////////////////////////////////////////////////////////
  1570. //++
  1571. //
  1572. // CClusProperties::Create
  1573. //
  1574. // Description:
  1575. // Do the heavy weight construction.
  1576. //
  1577. // Arguments:
  1578. // pcoParent [IN] - Back pointer to the parent cluster object.
  1579. // bPrivate [IN] - Are these private properties?
  1580. // bReadOnly [IN] - Are these read only properties?
  1581. //
  1582. // Return Value:
  1583. // S_OK if successful, or E_POINTER.
  1584. //
  1585. //--
  1586. /////////////////////////////////////////////////////////////////////////////
  1587. HRESULT CClusProperties::Create(
  1588. IN CClusterObject * pcoParent,
  1589. IN BOOL bPrivate,
  1590. IN BOOL bReadOnly
  1591. )
  1592. {
  1593. //ASSERT( pcoParent != NULL );
  1594. HRESULT _hr = E_POINTER;
  1595. if ( pcoParent != NULL )
  1596. {
  1597. m_pcoParent = pcoParent;
  1598. if ( bPrivate )
  1599. {
  1600. m_dwFlags |= PRIVATE;
  1601. } // if: set the private flag
  1602. else
  1603. {
  1604. m_dwFlags &= ~PRIVATE;
  1605. } // else: clear the private flag
  1606. if ( bReadOnly )
  1607. {
  1608. m_dwFlags |= READONLY;
  1609. } // if: set the read only flag
  1610. else
  1611. {
  1612. m_dwFlags &= ~READONLY;
  1613. } // else: clear the read only flag
  1614. _hr = S_OK;
  1615. } // if: parent specified
  1616. return _hr;
  1617. } //*** CClusProperties::Create()
  1618. /////////////////////////////////////////////////////////////////////////////
  1619. //++
  1620. //
  1621. // CClusProperties::HrFillPropertyVector
  1622. //
  1623. // Description:
  1624. // Parse the passed in property list into a collection of properties.
  1625. //
  1626. // Arguments:
  1627. // rcplPropList [IN] - The property list to parse.
  1628. //
  1629. // Return Value:
  1630. // S_OK if successful, or other HRESULT error.
  1631. //
  1632. //--
  1633. /////////////////////////////////////////////////////////////////////////////
  1634. HRESULT CClusProperties::HrFillPropertyVector(
  1635. IN CClusPropList & rcplPropList
  1636. )
  1637. {
  1638. HRESULT _hr = S_OK;
  1639. DWORD _sc;
  1640. CComObject< CClusProperty > * _pProp = NULL;
  1641. _sc = rcplPropList.ScMoveToFirstProperty();
  1642. if ( _sc == ERROR_SUCCESS )
  1643. {
  1644. do
  1645. {
  1646. _hr = CComObject< CClusProperty >::CreateInstance( &_pProp );
  1647. if ( SUCCEEDED( _hr ) )
  1648. {
  1649. CSmartPtr< CComObject < CClusProperty > > _ptrProp( _pProp );
  1650. _hr = _ptrProp->Create(
  1651. const_cast< BSTR >( rcplPropList.PszCurrentPropertyName() ),
  1652. rcplPropList.RPvlPropertyValue(),
  1653. ( m_dwFlags & PRIVATE ),
  1654. ( m_dwFlags & READONLY )
  1655. );
  1656. if ( SUCCEEDED( _hr ) )
  1657. {
  1658. _ptrProp->AddRef();
  1659. m_Properties.insert( m_Properties.end(), _ptrProp );
  1660. } // if: create property ok
  1661. else
  1662. {
  1663. break;
  1664. } // else: error creating the property
  1665. } // if: create property instance ok
  1666. //
  1667. // Move to the next property in the list.
  1668. //
  1669. _sc = rcplPropList.ScMoveToNextProperty();
  1670. } while ( _sc == ERROR_SUCCESS ); // do-while: there are properties in the list
  1671. } // if: moved to the first property successfully
  1672. if ( _sc != ERROR_NO_MORE_ITEMS )
  1673. {
  1674. _hr = HRESULT_FROM_WIN32( _sc );
  1675. } // if: error moving to property
  1676. return _hr;
  1677. } //*** CClusProperties::HrFillPropertyVector()
  1678. /////////////////////////////////////////////////////////////////////////////
  1679. //++
  1680. //
  1681. // CClusProperties::get_ReadOnly
  1682. //
  1683. // Description:
  1684. // Is this property collection read only?
  1685. //
  1686. // Arguments:
  1687. // pvarReadOnly [OUT] - catches the property's read only state.
  1688. //
  1689. // Return Value:
  1690. // S_OK if successful, or E_POINTER.
  1691. //
  1692. //--
  1693. /////////////////////////////////////////////////////////////////////////////
  1694. STDMETHODIMP CClusProperties::get_ReadOnly( OUT VARIANT * pvarReadOnly )
  1695. {
  1696. //ASSERT( pvarReadOnly != NULL );
  1697. HRESULT _hr = E_POINTER;
  1698. if ( pvarReadOnly != NULL )
  1699. {
  1700. pvarReadOnly->vt = VT_BOOL;
  1701. if ( m_dwFlags & READONLY )
  1702. {
  1703. pvarReadOnly->boolVal = VARIANT_TRUE;
  1704. } // if: if this is a read only property...
  1705. else
  1706. {
  1707. pvarReadOnly->boolVal = VARIANT_FALSE;
  1708. } // else: it is not a read only property...
  1709. _hr = S_OK;
  1710. } // if:
  1711. return _hr;
  1712. } //*** CClusProperties::get_ReadOnly()
  1713. /////////////////////////////////////////////////////////////////////////////
  1714. //++
  1715. //
  1716. // CClusProperties::get_Private
  1717. //
  1718. // Description:
  1719. // Is this a private property collection?
  1720. //
  1721. // Arguments:
  1722. // pvarPrivate [OUT] - catches the private property state.
  1723. //
  1724. // Return Value:
  1725. // S_OK if successful, or E_POINTER
  1726. //
  1727. //--
  1728. /////////////////////////////////////////////////////////////////////////////
  1729. STDMETHODIMP CClusProperties::get_Private( OUT VARIANT * pvarPrivate )
  1730. {
  1731. //ASSERT( pvarPrivate != NULL );
  1732. HRESULT _hr = E_POINTER;
  1733. if ( pvarPrivate != NULL )
  1734. {
  1735. pvarPrivate->vt = VT_BOOL;
  1736. if ( m_dwFlags & PRIVATE )
  1737. {
  1738. pvarPrivate->boolVal = VARIANT_TRUE;
  1739. } // if: if this is private property...
  1740. else
  1741. {
  1742. pvarPrivate->boolVal = VARIANT_FALSE;
  1743. } // else: it is not a private property...
  1744. _hr = S_OK;
  1745. } // if:
  1746. return _hr;
  1747. } //*** CClusProperties::get_Private()
  1748. /////////////////////////////////////////////////////////////////////////////
  1749. //++
  1750. //
  1751. // CClusProperties::get_Common
  1752. //
  1753. // Description:
  1754. // Is this a common property collection?
  1755. //
  1756. // Arguments:
  1757. // pvarCommon [OUT] - catches the common property state.
  1758. //
  1759. // Return Value:
  1760. // S_OK if successful, or E_POINTER
  1761. //
  1762. //--
  1763. /////////////////////////////////////////////////////////////////////////////
  1764. STDMETHODIMP CClusProperties::get_Common( OUT VARIANT * pvarCommon )
  1765. {
  1766. //ASSERT( pvarCommon != NULL );
  1767. HRESULT _hr = E_POINTER;
  1768. if ( pvarCommon != NULL )
  1769. {
  1770. pvarCommon->vt = VT_BOOL;
  1771. if ( ( m_dwFlags & PRIVATE ) == 0 )
  1772. {
  1773. pvarCommon->boolVal = VARIANT_TRUE;
  1774. } // if: if this is not a private property then it must be a common one...
  1775. else
  1776. {
  1777. pvarCommon->boolVal = VARIANT_FALSE;
  1778. } // else: it is a private property...
  1779. _hr = S_OK;
  1780. } // if:
  1781. return _hr;
  1782. } //*** CClusProperties::get_Common()
  1783. /////////////////////////////////////////////////////////////////////////////
  1784. //++
  1785. //
  1786. // CClusProperties::get_Modified
  1787. //
  1788. // Description:
  1789. // Has this property collection been modified?
  1790. //
  1791. // Arguments:
  1792. // pvarModified [OUT] - catches the modified state.
  1793. //
  1794. // Return Value:
  1795. // S_OK if successful, or E_POINTER
  1796. //
  1797. //--
  1798. /////////////////////////////////////////////////////////////////////////////
  1799. STDMETHODIMP CClusProperties::get_Modified( OUT VARIANT * pvarModified )
  1800. {
  1801. //ASSERT( pvarModified != NULL );
  1802. HRESULT _hr = E_POINTER;
  1803. if ( pvarModified != NULL )
  1804. {
  1805. pvarModified->vt = VT_BOOL;
  1806. if ( m_dwFlags & MODIFIED )
  1807. {
  1808. pvarModified->boolVal = VARIANT_TRUE;
  1809. _hr = S_OK;
  1810. } // if: has an add or a remove been done?
  1811. else
  1812. {
  1813. CComObject< CClusProperty > * _pProperty = NULL;
  1814. CClusPropertyVector::iterator _itCurrent = m_Properties.begin();
  1815. CClusPropertyVector::const_iterator _itLast = m_Properties.end();
  1816. pvarModified->boolVal = VARIANT_FALSE; // init to false
  1817. _hr = S_OK;
  1818. for ( ; _itCurrent != _itLast ; _itCurrent++ )
  1819. {
  1820. _pProperty = *_itCurrent;
  1821. if ( _pProperty )
  1822. {
  1823. if ( _pProperty->Modified() )
  1824. {
  1825. pvarModified->boolVal = VARIANT_TRUE;
  1826. break;
  1827. } // if: has this property been modified?
  1828. }
  1829. } // for: each property in the collection
  1830. } // else: not adds or remove, check each property's modified state.
  1831. } // if: is the pointer arg any good?
  1832. return _hr;
  1833. } //*** CClusProperties::get_Modified()