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.

2224 lines
60 KiB

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