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.

1849 lines
42 KiB

  1. /////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) 1998-2000 Microsoft Corporation
  4. //
  5. // Module Name:
  6. // PropertyValue.cpp
  7. //
  8. // Description:
  9. // Implementation of the cluster property value classes for the MSCLUS
  10. // automation classes.
  11. //
  12. // Author:
  13. // Galen Barbee (GalenB) 16-Dec-1998
  14. //
  15. // Revision History:
  16. //
  17. // Notes:
  18. //
  19. /////////////////////////////////////////////////////////////////////////////
  20. #include "stdafx.h"
  21. #include "Property.h"
  22. #include "PropertyValue.h"
  23. /////////////////////////////////////////////////////////////////////////////
  24. // Global variables
  25. /////////////////////////////////////////////////////////////////////////////
  26. static const IID * iidCClusPropertyValue[] =
  27. {
  28. &IID_ISClusPropertyValue
  29. };
  30. static const IID * iidCClusPropertyValues[] =
  31. {
  32. &IID_ISClusPropertyValues
  33. };
  34. static const IID * iidCClusPropertyValueData[] =
  35. {
  36. &IID_ISClusPropertyValueData
  37. };
  38. //*************************************************************************//
  39. /////////////////////////////////////////////////////////////////////////////
  40. // CClusPropertyValue class
  41. /////////////////////////////////////////////////////////////////////////////
  42. /////////////////////////////////////////////////////////////////////////////
  43. //++
  44. //
  45. // CClusPropertyValue::CClusPropertyValue
  46. //
  47. // Description:
  48. // Constructor.
  49. //
  50. // Arguments:
  51. // None.
  52. //
  53. // Return Value:
  54. // None.
  55. //
  56. //--
  57. /////////////////////////////////////////////////////////////////////////////
  58. CClusPropertyValue::CClusPropertyValue( void )
  59. {
  60. m_dwFlags = 0;
  61. m_pcpvdData = NULL;
  62. #if CLUSAPI_VERSION >= 0x0500
  63. m_cptType = CLUSPROP_TYPE_UNKNOWN;
  64. #else
  65. m_cptType = (CLUSTER_PROPERTY_TYPE) -1;
  66. #endif // CLUSAPI_VERSION >= 0x0500
  67. m_cpfFormat = CLUSPROP_FORMAT_UNKNOWN;
  68. m_cbLength = 0;
  69. m_piids = (const IID *) iidCClusPropertyValue;
  70. m_piidsSize = ARRAYSIZE( iidCClusPropertyValue );
  71. } //*** CClusPropertyValue::CClusPropertyValue()
  72. /////////////////////////////////////////////////////////////////////////////
  73. //++
  74. //
  75. // CClusPropertyValue::~CClusPropertyValue
  76. //
  77. // Description:
  78. // Destructor.
  79. //
  80. // Arguments:
  81. // None.
  82. //
  83. // Return Value:
  84. // None.
  85. //
  86. //--
  87. /////////////////////////////////////////////////////////////////////////////
  88. CClusPropertyValue::~CClusPropertyValue( void )
  89. {
  90. if ( m_pcpvdData != NULL )
  91. {
  92. m_pcpvdData->Release();
  93. } // if: data vector has been allocated
  94. } //*** CClusPropertyValue::~CClusPropertyValue()
  95. /////////////////////////////////////////////////////////////////////////////
  96. //++
  97. //
  98. // CClusPropertyValue::Create
  99. //
  100. // Description:
  101. // Finish the heavy weight construction for a single value.
  102. //
  103. // Arguments:
  104. // varValue [IN] - The value.
  105. // cptType [IN] - The cluster property type of the value.
  106. // cpfFormat [IN] - The cluster property format of the value.
  107. // cbLength [IN] - The length of the value.
  108. // bReadOnly [IN] - Is this a read only property?
  109. //
  110. // Return Value:
  111. // S_OK if successful, or other HRESULT error.
  112. //
  113. //--
  114. /////////////////////////////////////////////////////////////////////////////
  115. HRESULT CClusPropertyValue::Create(
  116. IN VARIANT varValue,
  117. IN CLUSTER_PROPERTY_TYPE cptType,
  118. IN CLUSTER_PROPERTY_FORMAT cpfFormat,
  119. IN size_t cbLength,
  120. IN BOOL bReadOnly
  121. )
  122. {
  123. HRESULT _hr = S_FALSE;
  124. m_cptType = cptType;
  125. m_cpfFormat = cpfFormat;
  126. m_cbLength = cbLength;
  127. if ( bReadOnly )
  128. {
  129. m_dwFlags |= READONLY;
  130. } // if: set the read only flag
  131. else
  132. {
  133. m_dwFlags &= ~READONLY;
  134. } // else: clear the read only flag
  135. _hr = CComObject< CClusPropertyValueData >::CreateInstance( &m_pcpvdData );
  136. if ( SUCCEEDED( _hr ) )
  137. {
  138. CSmartPtr< CComObject < CClusPropertyValueData > > _ptrData( m_pcpvdData );
  139. _hr = _ptrData->Create( varValue, cpfFormat, bReadOnly );
  140. if ( SUCCEEDED( _hr ) )
  141. {
  142. _ptrData->AddRef();
  143. } // if:
  144. } // if: Can create an instance of CClusPropertyValueData
  145. return _hr;
  146. } //*** CClusPropertyValue::Create()
  147. /////////////////////////////////////////////////////////////////////////////
  148. //++
  149. //
  150. // CClusPropertyValue::Create
  151. //
  152. // Description:
  153. // Finish the heavy weight construction for a value list.
  154. //
  155. // Arguments:
  156. // cbhValue [IN] - The value list buffer helper.
  157. // bReadOnly [IN] - Is this a read only property?
  158. //
  159. // Return Value:
  160. // S_OK if successful, or other HRESULT error.
  161. //
  162. //--
  163. /////////////////////////////////////////////////////////////////////////////
  164. HRESULT CClusPropertyValue::Create(
  165. IN CLUSPROP_BUFFER_HELPER cbhValue,
  166. IN BOOL bReadOnly
  167. )
  168. {
  169. HRESULT _hr = S_FALSE;
  170. m_cptType = (CLUSTER_PROPERTY_TYPE) cbhValue.pValue->Syntax.wType;
  171. m_cpfFormat = (CLUSTER_PROPERTY_FORMAT) cbhValue.pValue->Syntax.wFormat;
  172. m_cbLength = cbhValue.pValue->cbLength;
  173. if ( bReadOnly )
  174. {
  175. m_dwFlags |= READONLY;
  176. } // if: set the read only flag
  177. else
  178. {
  179. m_dwFlags &= ~READONLY;
  180. } // else: clear the read only flag
  181. _hr = CComObject< CClusPropertyValueData >::CreateInstance( &m_pcpvdData );
  182. if ( SUCCEEDED( _hr ) )
  183. {
  184. CSmartPtr< CComObject < CClusPropertyValueData > > _ptrData( m_pcpvdData );
  185. _hr = _ptrData->Create( cbhValue, bReadOnly );
  186. if ( SUCCEEDED( _hr ) )
  187. {
  188. _ptrData->AddRef();
  189. } // if:
  190. } // if: Can create an instance of CClusPropertyValueData
  191. return _hr;
  192. } //*** CClusPropertyValue::Create
  193. /////////////////////////////////////////////////////////////////////////////
  194. //++
  195. //
  196. // CClusPropertyValue::get_Value
  197. //
  198. // Description:
  199. // Return the default value data for this value.
  200. //
  201. // Arguments:
  202. // pvarValue [IN] - Catches the data value.
  203. //
  204. // Return Value:
  205. // S_OK if successful, or E_POINTER if not.
  206. //
  207. //--
  208. /////////////////////////////////////////////////////////////////////////////
  209. STDMETHODIMP CClusPropertyValue::get_Value( IN VARIANT * pvarValue )
  210. {
  211. //ASSERT( pvarValue != NULL );
  212. HRESULT _hr = E_POINTER;
  213. if ( pvarValue != NULL )
  214. {
  215. _hr = VariantCopyInd( pvarValue, &(*m_pcpvdData)[ 0 ] );
  216. }
  217. return _hr;
  218. } //*** CClusPropertyValue::get_Value()
  219. /////////////////////////////////////////////////////////////////////////////
  220. //++
  221. //
  222. // CClusPropertyValue::put_Value
  223. //
  224. // Description:
  225. // Change the default data value.
  226. //
  227. // Arguments:
  228. // varValue [IN] - The new data value.
  229. //
  230. // Return Value:
  231. // S_OK if successful, or S_FALSE if read only.
  232. //
  233. //--
  234. /////////////////////////////////////////////////////////////////////////////
  235. STDMETHODIMP CClusPropertyValue::put_Value( IN VARIANT varValue )
  236. {
  237. HRESULT _hr = S_FALSE;
  238. if ( ( m_dwFlags & READONLY ) == 0 )
  239. {
  240. CComVariant _varNew( varValue );
  241. CComVariant _varOld( (*m_pcpvdData)[ 0 ] );
  242. _hr = S_OK;
  243. if ( _varOld != _varNew )
  244. {
  245. (*m_pcpvdData)[ 0 ] = _varNew;
  246. m_dwFlags |= MODIFIED;
  247. } // if: value changed
  248. } // if:
  249. return _hr;
  250. } //*** CClusPropertyValue::put_Value()
  251. /////////////////////////////////////////////////////////////////////////////
  252. //++
  253. //
  254. // CClusPropertyValue::get_Type
  255. //
  256. // Description:
  257. // Get this value's cluster property type.
  258. //
  259. // Arguments:
  260. // pcptType [OUT] - Catches the value type.
  261. //
  262. // Return Value:
  263. // S_OK if successful, or E_POINTER if not.
  264. //
  265. //--
  266. /////////////////////////////////////////////////////////////////////////////
  267. STDMETHODIMP CClusPropertyValue::get_Type(
  268. OUT CLUSTER_PROPERTY_TYPE * pcptType
  269. )
  270. {
  271. //ASSERT( pcptType != NULL );
  272. HRESULT _hr = E_POINTER;
  273. if ( pcptType != NULL )
  274. {
  275. *pcptType = m_cptType;
  276. _hr = S_OK;
  277. } // if: property type pointer specified
  278. return _hr;
  279. } //*** CClusPropertyValue::get_Type()
  280. /////////////////////////////////////////////////////////////////////////////
  281. //++
  282. //
  283. // CClusPropertyValue::put_Type
  284. //
  285. // Description:
  286. // Set this value's cluster property type.
  287. //
  288. // Arguments:
  289. // cptType [IN] - The new type.
  290. //
  291. // Return Value:
  292. // S_OK if successful, or S_FALSE if read only.
  293. //
  294. // Note:
  295. // It is possible that this should be removed. You cannot ever change
  296. // a value's type.
  297. //--
  298. /////////////////////////////////////////////////////////////////////////////
  299. STDMETHODIMP CClusPropertyValue::put_Type( IN CLUSTER_PROPERTY_TYPE cptType )
  300. {
  301. HRESULT _hr = S_FALSE;
  302. if ( ( m_dwFlags & READONLY ) == 0 )
  303. {
  304. m_cptType = cptType;
  305. _hr = S_OK;
  306. } // if:
  307. return _hr;
  308. } //*** CClusPropertyValue::put_Type()
  309. /////////////////////////////////////////////////////////////////////////////
  310. //++
  311. //
  312. // CClusPropertyValue::get_Format
  313. //
  314. // Description:
  315. // Get the value's cluster property format.
  316. //
  317. // Arguments:
  318. // pcpfFormat [OUT] - Catches the format.
  319. //
  320. // Return Value:
  321. // S_OK if successful, or E_POINTER if not.
  322. //
  323. //--
  324. /////////////////////////////////////////////////////////////////////////////
  325. STDMETHODIMP CClusPropertyValue::get_Format(
  326. OUT CLUSTER_PROPERTY_FORMAT * pcpfFormat
  327. )
  328. {
  329. //ASSERT( pcpfFormat != NULL );
  330. HRESULT _hr = E_POINTER;
  331. if ( pcpfFormat != NULL )
  332. {
  333. *pcpfFormat = m_cpfFormat;
  334. _hr = S_OK;
  335. } // if: property format pointer specified
  336. return _hr;
  337. } //*** CClusPropertyValue::get_Format()
  338. /////////////////////////////////////////////////////////////////////////////
  339. //++
  340. //
  341. // CClusPropertyValue::put_Format
  342. //
  343. // Description:
  344. // Set the value's cluster property format.
  345. //
  346. // Arguments:
  347. // cpfFormat [IN] - The new format for the value.
  348. //
  349. // Return Value:
  350. // S_OK if successful, or S_FALSE if read only.
  351. //
  352. // Note:
  353. // It is possible that this should be removed. You cannot ever change
  354. // a value's format.
  355. //
  356. //--
  357. /////////////////////////////////////////////////////////////////////////////
  358. STDMETHODIMP CClusPropertyValue::put_Format(
  359. IN CLUSTER_PROPERTY_FORMAT cpfFormat
  360. )
  361. {
  362. HRESULT _hr = S_FALSE;
  363. if ( ( m_dwFlags & READONLY ) == 0 )
  364. {
  365. m_cpfFormat = cpfFormat;
  366. _hr = S_OK;
  367. } // if:
  368. return _hr;
  369. } //*** CClusPropertyValue::put_Format()
  370. /////////////////////////////////////////////////////////////////////////////
  371. //++
  372. //
  373. // CClusPropertyValue::get_Length
  374. //
  375. // Description:
  376. // Returns the length of this value.
  377. //
  378. // Arguments:
  379. // plLength [OUT] - Catches the length of this value.
  380. //
  381. // Return Value:
  382. // S_OK if successful, or E_POINTER if not.
  383. //
  384. //--
  385. /////////////////////////////////////////////////////////////////////////////
  386. STDMETHODIMP CClusPropertyValue::get_Length( OUT long * plLength )
  387. {
  388. //ASSERT( plLength != NULL );
  389. HRESULT _hr = E_POINTER;
  390. if ( plLength != NULL )
  391. {
  392. *plLength = (long) m_cbLength;
  393. _hr = S_OK;
  394. } // if: length pointer specified
  395. return _hr;
  396. } //*** CClusPropertyValue::get_Length()
  397. /////////////////////////////////////////////////////////////////////////////
  398. //++
  399. //
  400. // CClusPropertyValue::get_DataCount
  401. //
  402. // Description:
  403. // Return the count of VARIANTS in the ClusProperyValueData object.
  404. //
  405. // Arguments:
  406. // plCount [OUT] - Catches the count.
  407. //
  408. // Return Value:
  409. // S_OK if successful, or other HRESULT error.
  410. //
  411. //--
  412. /////////////////////////////////////////////////////////////////////////////
  413. STDMETHODIMP CClusPropertyValue::get_DataCount( OUT long * plCount )
  414. {
  415. return m_pcpvdData->get_Count( plCount );
  416. } //*** CClusPropertyValue::get_DataCount()
  417. /////////////////////////////////////////////////////////////////////////////
  418. //++
  419. //
  420. // CClusPropertyValue::get_Data
  421. //
  422. // Description:
  423. // Returns the data collection.
  424. //
  425. // Arguments:
  426. // ppClusterPropertyValueData [OUT] - Catches the data collection.
  427. //
  428. // Return Value:
  429. // S_OK if successful, E_POINTER, or other HRESULT error.
  430. //
  431. //--
  432. /////////////////////////////////////////////////////////////////////////////
  433. STDMETHODIMP CClusPropertyValue::get_Data(
  434. OUT ISClusPropertyValueData ** ppClusterPropertyValueData
  435. )
  436. {
  437. //ASSERT( ppClusterPropertyValueData );
  438. HRESULT _hr = E_POINTER;
  439. if ( ppClusterPropertyValueData != NULL )
  440. {
  441. _hr = m_pcpvdData->QueryInterface( IID_ISClusPropertyValueData, (void **) ppClusterPropertyValueData );
  442. }
  443. return _hr;
  444. } //*** CClusPropertyValue::get_Data()
  445. /////////////////////////////////////////////////////////////////////////////
  446. //++
  447. //
  448. // CClusPropertyValue::Modified
  449. //
  450. // Description:
  451. // Sets this value to modified and returns the old modified state.
  452. //
  453. // Arguments:
  454. // bModified [IN] - New modified state.
  455. //
  456. // Return Value:
  457. // The old modified state.
  458. //
  459. //--
  460. /////////////////////////////////////////////////////////////////////////////
  461. BOOL CClusPropertyValue::Modified( IN BOOL bModified )
  462. {
  463. BOOL _bTemp = ( m_dwFlags & MODIFIED );
  464. if ( bModified )
  465. {
  466. m_dwFlags |= MODIFIED;
  467. } // if: set the modified flag
  468. else
  469. {
  470. m_dwFlags &= ~MODIFIED;
  471. } // else: clear the modified flag
  472. return _bTemp;
  473. } //*** CClusPropertyValue::Modified()
  474. /////////////////////////////////////////////////////////////////////////////
  475. //++
  476. //
  477. // CClusPropertyValue::Value
  478. //
  479. // Description:
  480. // Set a new value into this property value.
  481. //
  482. // Arguments:
  483. // rvarValue [IN] - the new value
  484. //
  485. // Return Value:
  486. // The old value.
  487. //
  488. //--
  489. /////////////////////////////////////////////////////////////////////////////
  490. CComVariant CClusPropertyValue::Value( const CComVariant & rvarValue )
  491. {
  492. CComVariant _varNew( rvarValue );
  493. CComVariant _varOld( (*m_pcpvdData)[ 0 ] );
  494. if ( _varOld != _varNew )
  495. {
  496. (*m_pcpvdData)[ 0 ] = _varNew;
  497. m_dwFlags |= MODIFIED;
  498. } // if: data changed
  499. return _varOld;
  500. } //*** CClusPropertyValue::Value()
  501. /////////////////////////////////////////////////////////////////////////////
  502. //++
  503. //
  504. // CClusPropertyValue::HrBinaryValue
  505. //
  506. // Description:
  507. // Set the binary value of property value.
  508. //
  509. // Arguments:
  510. // psa [IN] - The SAFEARRY to save.
  511. //
  512. // Return Value:
  513. // S_OK if successful, or other HRESULT error.
  514. //
  515. //--
  516. /////////////////////////////////////////////////////////////////////////////
  517. HRESULT CClusPropertyValue::HrBinaryValue( IN SAFEARRAY * psa )
  518. {
  519. return m_pcpvdData->HrBinaryValue( psa );
  520. } //*** CClusPropertyValue::HrBinaryValue()
  521. //*************************************************************************//
  522. /////////////////////////////////////////////////////////////////////////////
  523. // CClusPropertyValues class
  524. /////////////////////////////////////////////////////////////////////////////
  525. /////////////////////////////////////////////////////////////////////////////
  526. //++
  527. //
  528. // CClusPropertyValues::CClusPropertyValues
  529. //
  530. // Description:
  531. // Constructor.
  532. //
  533. // Arguments:
  534. // None.
  535. //
  536. // Return Value:
  537. // None.
  538. //
  539. //--
  540. /////////////////////////////////////////////////////////////////////////////
  541. CClusPropertyValues::CClusPropertyValues( void )
  542. {
  543. m_piids = (const IID *) iidCClusPropertyValues;
  544. m_piidsSize = ARRAYSIZE( iidCClusPropertyValues );
  545. } //*** CClusPropertyValues::CClusPropertyValues()
  546. /////////////////////////////////////////////////////////////////////////////
  547. //++
  548. //
  549. // CClusPropertyValues::~CClusPropertyValues
  550. //
  551. // Description:
  552. // Destructor.
  553. //
  554. // Arguments:
  555. // None.
  556. //
  557. // Return Value:
  558. // None.
  559. //
  560. //--
  561. /////////////////////////////////////////////////////////////////////////////
  562. CClusPropertyValues::~CClusPropertyValues( void )
  563. {
  564. Clear();
  565. } //*** CClusPropertyValues::~CClusPropertyValues()
  566. /////////////////////////////////////////////////////////////////////////////
  567. //++
  568. //
  569. // CClusPropertyValues::Clear
  570. //
  571. // Description:
  572. // Releases the values in the collection.
  573. //
  574. // Arguments:
  575. // None.
  576. //
  577. // Return Value:
  578. // None.
  579. //
  580. //--
  581. /////////////////////////////////////////////////////////////////////////////
  582. void CClusPropertyValues::Clear( void )
  583. {
  584. ::ReleaseAndEmptyCollection< CClusPropertyValueVector, CComObject< CClusPropertyValue > >( m_cpvvValues );
  585. } //*** CClusPropertyValues::Clear()
  586. /////////////////////////////////////////////////////////////////////////////
  587. //++
  588. //
  589. // CClusPropertyValues::HrGetVariantLength
  590. //
  591. // Description:
  592. // Compute the length of the data from its variant type.
  593. //
  594. // Arguments:
  595. // rvarValue [IN] - The new value to compute the length of.
  596. // pcbLength [OUT] - Catches the length.
  597. // cpfFormat [IN] - The cluster property format.
  598. //
  599. // Return Value:
  600. // S_OK if successful, or E_INVALIDARG if the type is bogus.
  601. //
  602. //--
  603. /////////////////////////////////////////////////////////////////////////////
  604. HRESULT CClusPropertyValues::HrGetVariantLength(
  605. IN const VARIANT rvarValue,
  606. OUT PDWORD pcbLength,
  607. IN CLUSTER_PROPERTY_FORMAT cpfFormat
  608. )
  609. {
  610. HRESULT _hr = E_INVALIDARG;
  611. VARTYPE _varType = rvarValue.vt;
  612. do
  613. {
  614. if ( ( _varType & VT_ARRAY ) && ( _varType & VT_UI1 ) )
  615. {
  616. SAFEARRAY * _psa = rvarValue.parray;
  617. //
  618. // only accept single dimensional arrays!
  619. //
  620. if ( ( _psa != NULL ) && ( ::SafeArrayGetDim( _psa ) == 1 ) )
  621. {
  622. size_t _cbElem = ::SafeArrayGetElemsize( _psa );
  623. *pcbLength = _cbElem * _psa->cbElements;
  624. _hr = S_OK;
  625. } // if:
  626. break;
  627. } // if:
  628. if ( _varType & VT_VECTOR )
  629. {
  630. break;
  631. } // if: Don't know what to do with a vector...
  632. _varType &= ~VT_BYREF; // mask off the by ref bit if it was set...
  633. if ( ( _varType == VT_I2 ) || ( _varType == VT_I4 ) || ( _varType == VT_BOOL ) || ( _varType == VT_R4 ) )
  634. {
  635. *pcbLength = sizeof( DWORD );
  636. _hr = S_OK;
  637. break;
  638. } // if:
  639. else if ( _varType == VT_BSTR )
  640. {
  641. CComBSTR _bstr;
  642. _bstr.Attach( rvarValue.bstrVal );
  643. *pcbLength = _bstr.Length();
  644. _bstr.Detach();
  645. _hr = S_OK;
  646. break;
  647. } // else if:
  648. else if ( ( _varType == VT_I8 ) || ( _varType == VT_R8 ) )
  649. {
  650. *pcbLength = sizeof( ULONGLONG );
  651. _hr = S_OK;
  652. break;
  653. } // else if:
  654. else if ( _varType == VT_VARIANT )
  655. {
  656. _hr = HrGetVariantLength( *rvarValue.pvarVal, pcbLength, cpfFormat );
  657. break;
  658. } // else if:
  659. }
  660. while( TRUE ); // do-while: want to avoid using a goto ;-)
  661. return _hr;
  662. } //*** CClusPropertyValues::HrGetVariantLength()
  663. /////////////////////////////////////////////////////////////////////////////
  664. //++
  665. //
  666. // CClusPropertyValues::get_Count
  667. //
  668. // Description:
  669. // Returns the count of elements (values) in the collection.
  670. //
  671. // Arguments:
  672. // plCount [OUT] - Catches the count.
  673. //
  674. // Return Value:
  675. // S_OK if successful, or E_POINTER if not.
  676. //
  677. //--
  678. /////////////////////////////////////////////////////////////////////////////
  679. STDMETHODIMP CClusPropertyValues::get_Count( OUT long * plCount )
  680. {
  681. //ASSERT( plCount != NULL );
  682. HRESULT _hr = E_POINTER;
  683. if ( plCount != NULL )
  684. {
  685. *plCount = m_cpvvValues.size();
  686. _hr = S_OK;
  687. }
  688. return _hr;
  689. } //*** CClusPropertyValues::get_Count()
  690. /////////////////////////////////////////////////////////////////////////////
  691. //++
  692. //
  693. // CClusPropertyValues::GetIndex
  694. //
  695. // Description:
  696. // Get the index from the passed in variant.
  697. //
  698. // Arguments:
  699. // varIndex [IN] - Hold the index. This is a one based number.
  700. // pnIndex [OUT] - Catches the zero based index in the collection.
  701. //
  702. // Return Value:
  703. // S_OK if successful, E_POINTER, or E_INVALIDARG if the index is out
  704. // of range.
  705. //
  706. //--
  707. /////////////////////////////////////////////////////////////////////////////
  708. HRESULT CClusPropertyValues::GetIndex(
  709. IN VARIANT varIndex,
  710. OUT UINT * pnIndex
  711. )
  712. {
  713. //ASSERT( pnIndex != NULL );
  714. HRESULT _hr = E_POINTER;
  715. if ( pnIndex != NULL )
  716. {
  717. CComVariant _v;
  718. UINT _nIndex = 0;
  719. *pnIndex = 0;
  720. _v.Copy( &varIndex );
  721. // Check to see if the index is a number.
  722. _hr = _v.ChangeType( VT_I4 );
  723. if ( SUCCEEDED( _hr ) )
  724. {
  725. _nIndex = _v.lVal;
  726. _nIndex--; // Adjust index to be 0 relative instead of 1 relative
  727. }
  728. // We found an index, now check the range.
  729. if ( SUCCEEDED( _hr ) )
  730. {
  731. if ( _nIndex < m_cpvvValues.size() )
  732. {
  733. *pnIndex = _nIndex;
  734. }
  735. else
  736. {
  737. _hr = E_INVALIDARG;
  738. }
  739. }
  740. }
  741. return _hr;
  742. } //*** CClusPropertyValues::GetIndex()
  743. /////////////////////////////////////////////////////////////////////////////
  744. //++
  745. //
  746. // CClusPropertyValues::get_Item
  747. //
  748. // Description:
  749. // Returns the object (value) at the passed in index.
  750. //
  751. // Arguments:
  752. // varIndex [IN] - Hold the index. This is a one based number.
  753. // ppPropertyValue [OUT] - Catches the property value.
  754. //
  755. // Return Value:
  756. // S_OK if successful, E_POINTER, or E_INVALIDARG if the index is out
  757. // of range, or other HRESULT error.
  758. //
  759. //--
  760. /////////////////////////////////////////////////////////////////////////////
  761. STDMETHODIMP CClusPropertyValues::get_Item(
  762. IN VARIANT varIndex,
  763. OUT ISClusPropertyValue ** ppPropertyValue
  764. )
  765. {
  766. //ASSERT( ppPropertyValue != NULL );
  767. HRESULT _hr = E_POINTER;
  768. if ( ppPropertyValue != NULL )
  769. {
  770. CComObject< CClusPropertyValue > * _pPropertyValue = NULL;
  771. UINT _nIndex = 0;
  772. //
  773. // Zero the out param
  774. //
  775. *ppPropertyValue = 0;
  776. _hr = GetIndex( varIndex, &_nIndex );
  777. if ( SUCCEEDED( _hr ) )
  778. {
  779. _pPropertyValue = m_cpvvValues[ _nIndex ];
  780. _hr = _pPropertyValue->QueryInterface( IID_ISClusPropertyValue, (void **) ppPropertyValue );
  781. }
  782. }
  783. return _hr;
  784. } //*** CClusPropertyValues::get_Item()
  785. /////////////////////////////////////////////////////////////////////////////
  786. //++
  787. //
  788. // CClusPropertyValues::get__NewEnum
  789. //
  790. // Description:
  791. // Create and return a new enumeration for this collection.
  792. //
  793. // Arguments:
  794. // ppunk [OUT] - Catches the new enumeration.
  795. //
  796. // Return Value:
  797. // S_OK if successful, E_POINTER, or other HRESULT error.
  798. //
  799. //--
  800. /////////////////////////////////////////////////////////////////////////////
  801. STDMETHODIMP CClusPropertyValues::get__NewEnum( IUnknown ** ppunk )
  802. {
  803. return ::HrNewIDispatchEnum< CClusPropertyValueVector, CComObject< CClusPropertyValue > >( ppunk, m_cpvvValues );
  804. } //*** CClusPropertyValues::get__NewEnum()
  805. /////////////////////////////////////////////////////////////////////////////
  806. //++
  807. //
  808. // CClusPropertyValues::Create
  809. //
  810. // Description:
  811. // Finish the heavy weight construction.
  812. //
  813. // Arguments:
  814. // varValue [IN] - The value.
  815. // cptType [IN] - The cluster property type.
  816. // cpfFormat [IN] - The cluster format type.
  817. // bReadOnly [IN] - Is this a read only value/property?
  818. //
  819. // Return Value:
  820. // S_OK if successful, or other HRESULT error if not.
  821. //
  822. //--
  823. /////////////////////////////////////////////////////////////////////////////
  824. HRESULT CClusPropertyValues::Create(
  825. IN VARIANT varValue,
  826. IN CLUSTER_PROPERTY_TYPE cptType,
  827. IN CLUSTER_PROPERTY_FORMAT cpfFormat,
  828. IN BOOL bReadOnly
  829. )
  830. {
  831. HRESULT _hr = S_FALSE;
  832. CComObject< CClusPropertyValue > * _pValue = NULL;
  833. _hr = CComObject< CClusPropertyValue >::CreateInstance( &_pValue );
  834. if ( SUCCEEDED( _hr ) )
  835. {
  836. CSmartPtr< CComObject < CClusPropertyValue > > _ptrValue( _pValue );
  837. DWORD _cbLength = 0;
  838. _hr = HrGetVariantLength( varValue, &_cbLength, cpfFormat );
  839. if ( SUCCEEDED( _hr ) )
  840. {
  841. _hr = _ptrValue->Create( varValue, cptType, cpfFormat, _cbLength, bReadOnly );
  842. if ( SUCCEEDED( _hr ) )
  843. {
  844. m_cpvvValues.insert( m_cpvvValues.end(), _ptrValue );
  845. _ptrValue->AddRef();
  846. } // if:
  847. } // if:
  848. } // if: Can create an instance of CClusPropertyValueData
  849. return _hr;
  850. } //*** CClusPropertyValues::Create()
  851. /////////////////////////////////////////////////////////////////////////////
  852. //++
  853. //
  854. // CClusPropertyValues::Create
  855. //
  856. // Description:
  857. // Finish the heavy weight construction.
  858. //
  859. // Arguments:
  860. // rpvlValue [IN] - The value list.
  861. // bReadOnly [IN] - Is this a read only value/property?
  862. //
  863. // Return Value:
  864. // S_OK if successful, or other HRESULT error if not.
  865. //
  866. //--
  867. /////////////////////////////////////////////////////////////////////////////
  868. HRESULT CClusPropertyValues::Create(
  869. IN const CClusPropValueList & rpvlValue,
  870. IN BOOL bReadOnly
  871. )
  872. {
  873. return HrFillPropertyValuesVector( const_cast< CClusPropValueList & >( rpvlValue ), bReadOnly );
  874. } //*** CClusPropertyValues::Create()
  875. /////////////////////////////////////////////////////////////////////////////
  876. //++
  877. //
  878. // CClusPropertyValues::CreateItem
  879. //
  880. // Description:
  881. // Create a new property value object and add it to the collection.
  882. //
  883. // Arguments:
  884. // bstrName [IN] - property name.
  885. // varValue [IN] - the value to add.
  886. // ppPropertyValue [OUT] - catches the newly created object.
  887. //
  888. // Return Value:
  889. // S_OK if successful, E_POINTER, or other HRESULT error.
  890. //
  891. //--
  892. /////////////////////////////////////////////////////////////////////////////
  893. STDMETHODIMP CClusPropertyValues::CreateItem(
  894. IN BSTR bstrName,
  895. IN VARIANT varValue,
  896. OUT ISClusPropertyValue ** ppPropertyValue
  897. )
  898. {
  899. //ASSERT( ppPropertyValue != NULL );
  900. HRESULT _hr = E_POINTER;
  901. //
  902. // TODO: GalenB 17 Jan 2000
  903. //
  904. // If are going to allow Multi-valued property creation we need to implement this method?
  905. //
  906. if ( ppPropertyValue != NULL )
  907. {
  908. _hr = E_NOTIMPL;
  909. } // if: property value interface pointer not specified
  910. return _hr;
  911. } //*** CClusPropertyValues::CreateItem()
  912. /////////////////////////////////////////////////////////////////////////////
  913. //++
  914. //
  915. // CClusPropertyValues::RemoveItem
  916. //
  917. // Description:
  918. // Remove the property value at the passed in index from the collection.
  919. //
  920. // Arguments:
  921. // varIndex [IN] - contains the index to remove.
  922. //
  923. // Return Value:
  924. // S_OK if successful, S_FALSE if read only, or other HRESULT error.
  925. //
  926. //--
  927. /////////////////////////////////////////////////////////////////////////////
  928. STDMETHODIMP CClusPropertyValues::RemoveItem( VARIANT varIndex )
  929. {
  930. //
  931. // TODO: GalenB 17 Jan 2000
  932. //
  933. // If are going to allow Multi-valued property creation we need to implement this method?
  934. //
  935. return E_NOTIMPL;
  936. } //*** CClusPropertyValues::RemoveItem()
  937. /////////////////////////////////////////////////////////////////////////////
  938. //++
  939. //
  940. // CClusPropertyValues::HrFillPropertyValuesVector
  941. //
  942. // Description:
  943. // Fill the collection from the passes in value list.
  944. //
  945. // Arguments:
  946. // cplPropValueList [IN] - The value list to parse.
  947. // bReadOnly [IN] - Is this part of a read only property?
  948. //
  949. // Return Value:
  950. // S_OK if successful, or Win32 error as HRESULT.
  951. //
  952. //--
  953. /////////////////////////////////////////////////////////////////////////////
  954. HRESULT CClusPropertyValues::HrFillPropertyValuesVector(
  955. IN CClusPropValueList & cplPropValueList,
  956. IN BOOL bReadOnly
  957. )
  958. {
  959. HRESULT _hr = S_OK;
  960. DWORD _sc;
  961. CComVariant _var;
  962. CComObject< CClusPropertyValue > * _pPropVal = NULL;
  963. CLUSPROP_BUFFER_HELPER _cbhValue = { NULL };
  964. _sc = cplPropValueList.ScMoveToFirstValue();
  965. if ( _sc != ERROR_SUCCESS )
  966. {
  967. _hr = HRESULT_FROM_WIN32( _sc );
  968. } // if: error moving to the first value
  969. else
  970. {
  971. do
  972. {
  973. _cbhValue = cplPropValueList;
  974. _hr = CComObject< CClusPropertyValue >::CreateInstance( &_pPropVal );
  975. if ( SUCCEEDED( _hr ) )
  976. {
  977. CSmartPtr< CComObject < CClusPropertyValue > > _ptrProp( _pPropVal );
  978. _hr = _ptrProp->Create( _cbhValue, bReadOnly );
  979. if ( SUCCEEDED( _hr ) )
  980. {
  981. _ptrProp->AddRef();
  982. m_cpvvValues.insert( m_cpvvValues.end(), _ptrProp );
  983. } // if: create property ok
  984. } // if: create property instance ok
  985. //
  986. // Move to the next value.
  987. //
  988. _sc = cplPropValueList.ScMoveToNextValue();
  989. } while ( _sc == ERROR_SUCCESS ); // do-while: there are value in the list
  990. if ( _sc != ERROR_NO_MORE_ITEMS )
  991. {
  992. _hr = HRESULT_FROM_WIN32( _sc );
  993. } // if: error occurred moving to the next value
  994. } // else: moved to the first value successfully
  995. return _hr;
  996. } //*** CClusPropertyValues::HrFillPropertyValuesVector()
  997. //*************************************************************************//
  998. /////////////////////////////////////////////////////////////////////////////
  999. // CClusPropertyValueData class
  1000. /////////////////////////////////////////////////////////////////////////////
  1001. /////////////////////////////////////////////////////////////////////////////
  1002. //++
  1003. //
  1004. // CClusPropertyValueData::CClusPropertyValueData
  1005. //
  1006. // Description:
  1007. // Constructor.
  1008. //
  1009. // Arguments:
  1010. // None.
  1011. //
  1012. // Return Value:
  1013. // None.
  1014. //
  1015. //--
  1016. /////////////////////////////////////////////////////////////////////////////
  1017. CClusPropertyValueData::CClusPropertyValueData( void )
  1018. {
  1019. m_cpfFormat = CLUSPROP_FORMAT_UNKNOWN;
  1020. m_dwFlags = 0;
  1021. m_piids = (const IID *) iidCClusPropertyValueData;
  1022. m_piidsSize = ARRAYSIZE( iidCClusPropertyValueData );
  1023. } //*** CClusPropertyValueData::CClusPropertyValueData()
  1024. /////////////////////////////////////////////////////////////////////////////
  1025. //++
  1026. //
  1027. // CClusPropertyValueData::~CClusPropertyValueData
  1028. //
  1029. // Description:
  1030. // Destructor.
  1031. //
  1032. // Arguments:
  1033. // None.
  1034. //
  1035. // Return Value:
  1036. // None.
  1037. //
  1038. //--
  1039. /////////////////////////////////////////////////////////////////////////////
  1040. CClusPropertyValueData::~CClusPropertyValueData( void )
  1041. {
  1042. Clear();
  1043. } //*** CClusPropertyValueData::~CClusPropertyValueData()
  1044. /////////////////////////////////////////////////////////////////////////////
  1045. //++
  1046. //
  1047. // CClusPropertyValueData::Clear
  1048. //
  1049. // Description:
  1050. // Erase the data collection.
  1051. //
  1052. // Arguments:
  1053. // None.
  1054. //
  1055. // Return Value:
  1056. // None.
  1057. //
  1058. //--
  1059. /////////////////////////////////////////////////////////////////////////////
  1060. void CClusPropertyValueData::Clear( void )
  1061. {
  1062. if ( ! m_cpvdvData.empty() )
  1063. {
  1064. m_cpvdvData.erase( m_cpvdvData.begin(), m_cpvdvData.end() );
  1065. } // if:
  1066. } //*** CClusPropertyValueData::Clear()
  1067. /////////////////////////////////////////////////////////////////////////////
  1068. //++
  1069. //
  1070. // CClusPropertyValueData::get_Count
  1071. //
  1072. // Description:
  1073. // Returns the count of elements (data) in the collection.
  1074. //
  1075. // Arguments:
  1076. // plCount [OUT] - Catches the count.
  1077. //
  1078. // Return Value:
  1079. // S_OK if successful, or E_POINTER if not.
  1080. //
  1081. //--
  1082. /////////////////////////////////////////////////////////////////////////////
  1083. STDMETHODIMP CClusPropertyValueData::get_Count( OUT long * plCount )
  1084. {
  1085. //ASSERT( plCount != NULL );
  1086. HRESULT _hr = E_POINTER;
  1087. if ( plCount != NULL )
  1088. {
  1089. *plCount = m_cpvdvData.size();
  1090. _hr = S_OK;
  1091. }
  1092. return _hr;
  1093. } //*** CClusPropertyValueData::get_Count()
  1094. /////////////////////////////////////////////////////////////////////////////
  1095. //++
  1096. //
  1097. // CClusPropertyValueData::GetIndex
  1098. //
  1099. // Description:
  1100. // Get the index from the passed in variant.
  1101. //
  1102. // Arguments:
  1103. // varIndex [IN] - Hold the index. This is a one based number.
  1104. // pnIndex [OUT] - Catches the zero based index in the collection.
  1105. //
  1106. // Return Value:
  1107. // S_OK if successful, E_POINTER, or E_INVALIDARG if the index is out
  1108. // of range.
  1109. //
  1110. //--
  1111. /////////////////////////////////////////////////////////////////////////////
  1112. HRESULT CClusPropertyValueData::GetIndex(
  1113. IN VARIANT varIndex,
  1114. OUT UINT * pnIndex
  1115. )
  1116. {
  1117. //ASSERT( pnIndex != NULL );
  1118. HRESULT _hr = E_POINTER;
  1119. if ( pnIndex != NULL )
  1120. {
  1121. CComVariant _v;
  1122. UINT _nIndex = 0;
  1123. *pnIndex = 0;
  1124. _v.Copy( &varIndex );
  1125. // Check to see if the index is a number.
  1126. _hr = _v.ChangeType( VT_I4 );
  1127. if ( SUCCEEDED( _hr ) )
  1128. {
  1129. _nIndex = _v.lVal;
  1130. _nIndex--; // Adjust index to be 0 relative instead of 1 relative
  1131. }
  1132. // We found an index, now check the range.
  1133. if ( SUCCEEDED( _hr ) )
  1134. {
  1135. if ( _nIndex < m_cpvdvData.size() )
  1136. {
  1137. *pnIndex = _nIndex;
  1138. }
  1139. else
  1140. {
  1141. _hr = E_INVALIDARG;
  1142. }
  1143. }
  1144. }
  1145. return _hr;
  1146. } //*** CClusPropertyValueData::GetIndex()
  1147. /////////////////////////////////////////////////////////////////////////////
  1148. //++
  1149. //
  1150. // CClusPropertyValueData::get_Item
  1151. //
  1152. // Description:
  1153. // Returns the object (data) at the passed in index.
  1154. //
  1155. // Arguments:
  1156. // varIndex [IN] - Hold the index. This is a one based number.
  1157. // pvarData [OUT] - Catches the property value.
  1158. //
  1159. // Return Value:
  1160. // S_OK if successful, E_POINTER, or E_INVALIDARG if the index is out
  1161. // of range, or other HRESULT error.
  1162. //
  1163. //--
  1164. /////////////////////////////////////////////////////////////////////////////
  1165. STDMETHODIMP CClusPropertyValueData::get_Item(
  1166. IN VARIANT varIndex,
  1167. OUT VARIANT * pvarData
  1168. )
  1169. {
  1170. //ASSERT( pvarData != NULL );
  1171. HRESULT _hr = E_POINTER;
  1172. if ( pvarData != NULL )
  1173. {
  1174. UINT _nIndex = 0;
  1175. _hr = GetIndex( varIndex, &_nIndex );
  1176. if ( SUCCEEDED( _hr ) )
  1177. {
  1178. _hr = VariantCopyInd( pvarData, &m_cpvdvData[ _nIndex ] );
  1179. }
  1180. }
  1181. return _hr;
  1182. } //*** CClusPropertyValueData::get_Item()
  1183. /////////////////////////////////////////////////////////////////////////////
  1184. //++
  1185. //
  1186. // CClusPropertyValueData::get__NewEnum
  1187. //
  1188. // Description:
  1189. // Create and return a new enumeration for this collection.
  1190. //
  1191. // Arguments:
  1192. // ppunk [OUT] - Catches the new enumeration.
  1193. //
  1194. // Return Value:
  1195. // S_OK if successful, E_POINTER, or other HRESULT error.
  1196. //
  1197. //--
  1198. /////////////////////////////////////////////////////////////////////////////
  1199. STDMETHODIMP CClusPropertyValueData::get__NewEnum( IUnknown ** ppunk )
  1200. {
  1201. return ::HrNewVariantEnum< CClusPropertyValueDataVector >( ppunk, m_cpvdvData );
  1202. } //*** CClusPropertyValueData::get__NewEnum()
  1203. /////////////////////////////////////////////////////////////////////////////
  1204. //++
  1205. //
  1206. // CClusPropertyValueData::Create
  1207. //
  1208. // Description:
  1209. // Finish the heavy weight construction.
  1210. //
  1211. // Arguments:
  1212. // varValue [IN] - The data value.
  1213. // cpfFormat [IN] - The cluster property format.
  1214. // bReadOnly [IN] - Is this data for a read only property?
  1215. //
  1216. // Return Value:
  1217. // S_OK -- Always!!!
  1218. //
  1219. //--
  1220. /////////////////////////////////////////////////////////////////////////////
  1221. HRESULT CClusPropertyValueData::Create(
  1222. IN VARIANT varValue,
  1223. IN CLUSTER_PROPERTY_FORMAT cpfFormat,
  1224. IN BOOL bReadOnly
  1225. )
  1226. {
  1227. if ( bReadOnly )
  1228. {
  1229. m_dwFlags |= READONLY;
  1230. } // if: set the read only flag
  1231. else
  1232. {
  1233. m_dwFlags &= ~READONLY;
  1234. } // else: clear the read only flag
  1235. m_cpfFormat = cpfFormat;
  1236. if ( ( varValue.vt & VT_BYREF ) && ( varValue.vt & VT_VARIANT ) )
  1237. {
  1238. m_cpvdvData.insert( m_cpvdvData.end(), *varValue.pvarVal );
  1239. } // if: the variant is a reference to another variant...
  1240. else
  1241. {
  1242. m_cpvdvData.insert( m_cpvdvData.end(), varValue );
  1243. } // else: the variant is the data...
  1244. return S_OK;
  1245. } //*** CClusPropertyValueData::Create()
  1246. /////////////////////////////////////////////////////////////////////////////
  1247. //++
  1248. //
  1249. // CClusPropertyValueData::Create
  1250. //
  1251. // Description:
  1252. // Finish the heavy weight construction.
  1253. //
  1254. // Arguments:
  1255. // cbhValue [IN] - The value buffer helper.
  1256. // bReadOnly [IN] - Is this data for a read only property?
  1257. //
  1258. // Return Value:
  1259. // S_OK if successful, or other HRESULT error if not.
  1260. //
  1261. //--
  1262. /////////////////////////////////////////////////////////////////////////////
  1263. HRESULT CClusPropertyValueData::Create(
  1264. IN CLUSPROP_BUFFER_HELPER cbhValue,
  1265. IN BOOL bReadOnly
  1266. )
  1267. {
  1268. HRESULT _hr = S_OK;
  1269. if ( bReadOnly )
  1270. {
  1271. m_dwFlags |= READONLY;
  1272. } // if: set the read only flag
  1273. else
  1274. {
  1275. m_dwFlags &= ~READONLY;
  1276. } // else: clear the read only flag
  1277. m_cpfFormat = (CLUSTER_PROPERTY_FORMAT) cbhValue.pValue->Syntax.wFormat;
  1278. switch( m_cpfFormat )
  1279. {
  1280. #if CLUSAPI_VERSION >= 0x0500
  1281. case CLUSPROP_FORMAT_EXPANDED_SZ:
  1282. #endif // CLUSAPI_VERSION >= 0x0500
  1283. case CLUSPROP_FORMAT_SZ:
  1284. case CLUSPROP_FORMAT_EXPAND_SZ:
  1285. {
  1286. m_cpvdvData.insert( m_cpvdvData.end(), cbhValue.pStringValue->sz );
  1287. break;
  1288. } // case:
  1289. #if CLUSAPI_VERSION >= 0x0500
  1290. case CLUSPROP_FORMAT_LONG:
  1291. #endif // CLUSAPI_VERSION >= 0x0500
  1292. case CLUSPROP_FORMAT_DWORD:
  1293. {
  1294. #if CLUSAPI_VERSION >= 0x0500
  1295. m_cpvdvData.insert( m_cpvdvData.end(), cbhValue.pLongValue->l );
  1296. #else
  1297. m_cpvdvData.insert( m_cpvdvData.end(), (long) cbhValue.pDwordValue->dw );
  1298. #endif // CLUSAPI_VERSION >= 0x0500
  1299. break;
  1300. } // case:
  1301. case CLUSPROP_FORMAT_MULTI_SZ:
  1302. {
  1303. _hr = HrCreateMultiSz( cbhValue );
  1304. break;
  1305. } // case:
  1306. case CLUSPROP_FORMAT_BINARY:
  1307. {
  1308. _hr = HrCreateBinary( cbhValue );
  1309. break;
  1310. } // case:
  1311. default:
  1312. {
  1313. break;
  1314. } // default:
  1315. } // switch:
  1316. return _hr;
  1317. } //*** CClusPropertyValueData::Create()
  1318. /////////////////////////////////////////////////////////////////////////////
  1319. //++
  1320. //
  1321. // CClusPropertyValueData::CreateItem
  1322. //
  1323. // Description:
  1324. // Create a new object and add it to the collection.
  1325. //
  1326. // Arguments:
  1327. // varValue [IN] - value to add.
  1328. // pvarData [OUT] - catches the new created object.
  1329. //
  1330. // Return Value:
  1331. // S_OK if successful, S_FALSE if read only, or other HRESULT error.
  1332. //
  1333. //--
  1334. /////////////////////////////////////////////////////////////////////////////
  1335. STDMETHODIMP CClusPropertyValueData::CreateItem(
  1336. IN VARIANT varValue,
  1337. OUT VARIANT * pvarData
  1338. )
  1339. {
  1340. //ASSERT( pvarData != NULL );
  1341. HRESULT _hr = E_POINTER;
  1342. if ( pvarData != NULL )
  1343. {
  1344. if ( ( m_dwFlags & READONLY ) == 0 )
  1345. {
  1346. if ( ( m_cpfFormat == CLUSPROP_FORMAT_MULTI_SZ ) && ( varValue.vt == VT_BSTR ) )
  1347. {
  1348. m_cpvdvData.insert( m_cpvdvData.end(), varValue );
  1349. *pvarData = varValue; // kinda acquard, but that's automation for ya'
  1350. _hr = S_OK;
  1351. } // if:
  1352. else
  1353. {
  1354. _hr = E_INVALIDARG;
  1355. } // else:
  1356. } // if:
  1357. else
  1358. {
  1359. _hr = S_FALSE;
  1360. } // else:
  1361. } // if:
  1362. return _hr;
  1363. } //*** CClusPropertyValueData::CreateItem()
  1364. /////////////////////////////////////////////////////////////////////////////
  1365. //++
  1366. //
  1367. // CClusPropertyValueData::RemoveItem
  1368. //
  1369. // Description:
  1370. // Remove the data at the passed in index.
  1371. //
  1372. // Arguments:
  1373. // varIndex [IN] - variant that contains the index to remove.
  1374. //
  1375. // Return Value:
  1376. // S_OK if successful, S_FALSE if read only, or other HRESULT error.
  1377. //
  1378. //
  1379. //--
  1380. /////////////////////////////////////////////////////////////////////////////
  1381. STDMETHODIMP CClusPropertyValueData::RemoveItem( IN VARIANT varIndex )
  1382. {
  1383. HRESULT _hr = S_FALSE;
  1384. if ( ( m_dwFlags & READONLY ) == 0 )
  1385. {
  1386. UINT _iDelete = 0;
  1387. _hr = GetIndex( varIndex, &_iDelete );
  1388. if ( SUCCEEDED( _hr ) )
  1389. {
  1390. CClusPropertyValueDataVector::iterator _itDelete = m_cpvdvData.begin();
  1391. CClusPropertyValueDataVector::const_iterator _itLast = m_cpvdvData.end();
  1392. UINT _nCount;
  1393. for ( _nCount = 0; ( ( _iDelete < _nCount ) && ( _itDelete != _itLast ) ); _itDelete++, _nCount++ )
  1394. {
  1395. } // for:
  1396. m_cpvdvData.erase( _itDelete );
  1397. _hr = S_OK;
  1398. }
  1399. } // if:
  1400. return _hr;
  1401. } //*** CClusPropertyValueData::RemoveItem()
  1402. /////////////////////////////////////////////////////////////////////////////
  1403. //++
  1404. //
  1405. // CClusPropertyValueData::operator=
  1406. //
  1407. // Description:
  1408. // Saves the passed in data into the collection at the default
  1409. // position.
  1410. //
  1411. // Arguments:
  1412. // varvalue [IN] - The data to save.
  1413. //
  1414. // Return Value:
  1415. // The old data.
  1416. //
  1417. //--
  1418. /////////////////////////////////////////////////////////////////////////////
  1419. const CComVariant & CClusPropertyValueData::operator=(
  1420. IN const CComVariant & varData
  1421. )
  1422. {
  1423. m_cpvdvData[ 0 ] = varData;
  1424. return m_cpvdvData[ 0 ];
  1425. } //*** CClusPropertyValueData::operator=()
  1426. /////////////////////////////////////////////////////////////////////////////
  1427. //++
  1428. //
  1429. // CClusPropertyValueData::HrCreateMultiSz
  1430. //
  1431. // Description:
  1432. // Parse the passed in multi string into a collection of strings.
  1433. //
  1434. // Arguments:
  1435. // cbhValue [IN] - The property value buffer helper.
  1436. //
  1437. // Return Value:
  1438. // S_OK -- Always!
  1439. //
  1440. //--
  1441. /////////////////////////////////////////////////////////////////////////////
  1442. HRESULT CClusPropertyValueData::HrCreateMultiSz(
  1443. IN CLUSPROP_BUFFER_HELPER cbhValue
  1444. )
  1445. {
  1446. HRESULT _hr = S_OK;
  1447. LPWSTR _psz = cbhValue.pMultiSzValue->sz;
  1448. do
  1449. {
  1450. m_cpvdvData.insert( m_cpvdvData.end(), _psz );
  1451. _psz += lstrlenW( _psz ) + 1;
  1452. }
  1453. while( *_psz != L'\0' ); // do-while not at end of string...
  1454. return _hr;
  1455. } //*** CClusPropertyValueData::HrCreateMultiSz()
  1456. /////////////////////////////////////////////////////////////////////////////
  1457. //++
  1458. //
  1459. // CClusPropertyValueData::HrFillMultiSzBuffer
  1460. //
  1461. // Description:
  1462. // Create a multi string from the collection of strings.
  1463. //
  1464. // Arguments:
  1465. // ppsz [OUT] - Catches the mutli string.
  1466. //
  1467. // Return Value:
  1468. // S_OK if successful, or Win32 error as HRESULT if not.
  1469. //
  1470. //--
  1471. /////////////////////////////////////////////////////////////////////////////
  1472. HRESULT CClusPropertyValueData::HrFillMultiSzBuffer( OUT LPWSTR * ppsz ) const
  1473. {
  1474. //ASSERT( ppsz != NULL );
  1475. HRESULT _hr = E_POINTER;
  1476. DWORD _cbLength = 0;
  1477. CClusPropertyValueDataVector::const_iterator _itFirst = m_cpvdvData.begin();
  1478. CClusPropertyValueDataVector::const_iterator _itLast = m_cpvdvData.end();
  1479. if ( ppsz != NULL )
  1480. {
  1481. _hr = S_OK;
  1482. for ( ; _itFirst != _itLast; _itFirst++ )
  1483. {
  1484. if ( (*_itFirst).vt == VT_BSTR )
  1485. {
  1486. _cbLength += ( ::lstrlenW( (*_itFirst).bstrVal ) + 1 ); // don't forget the NULL!
  1487. } // if:
  1488. else
  1489. {
  1490. _hr = E_INVALIDARG;
  1491. break;
  1492. } // else:
  1493. } // for:
  1494. if ( SUCCEEDED( _hr ) )
  1495. {
  1496. LPWSTR _psz = NULL;
  1497. *ppsz = (LPWSTR) ::LocalAlloc( LMEM_ZEROINIT, _cbLength + 2 ); // ends in NULL NULL
  1498. if ( *ppsz != NULL )
  1499. {
  1500. _psz = *ppsz;
  1501. for ( _itFirst = m_cpvdvData.begin(); _itFirst != _itLast; _itFirst++ )
  1502. {
  1503. _cbLength = lstrlenW( (*_itFirst).bstrVal );
  1504. ::lstrcpyW( _psz, (*_itFirst).bstrVal );
  1505. _psz += ( _cbLength + 1 );
  1506. } // for:
  1507. } // if:
  1508. else
  1509. {
  1510. DWORD _sc = ::GetLastError();
  1511. _hr = HRESULT_FROM_WIN32( _sc );
  1512. } // else:
  1513. } // if:
  1514. } // if:
  1515. return _hr;
  1516. } //*** CClusPropertyValueData::HrFillMultiSzBuffer()
  1517. /////////////////////////////////////////////////////////////////////////////
  1518. //++
  1519. //
  1520. // CClusPropertyValueData::HrCreateBinary
  1521. //
  1522. // Description:
  1523. // Create a safeArray from the passed in binary property value.
  1524. //
  1525. // Arguments:
  1526. // cbhValue [IN] - The binary property value.
  1527. //
  1528. // Return Value:
  1529. // S_OK if successful, or other HRESULT error if not.
  1530. //
  1531. //--
  1532. /////////////////////////////////////////////////////////////////////////////
  1533. HRESULT CClusPropertyValueData::HrCreateBinary(
  1534. IN CLUSPROP_BUFFER_HELPER cbhValue
  1535. )
  1536. {
  1537. HRESULT _hr = E_OUTOFMEMORY;
  1538. SAFEARRAY * _psa = NULL;
  1539. SAFEARRAYBOUND _sab[ 1 ];
  1540. _sab[ 0 ].lLbound = 0;
  1541. _sab[ 0 ].cElements = cbhValue.pValue->cbLength;
  1542. //
  1543. // allocate a one dimensional SafeArray of BYTES
  1544. //
  1545. _psa = ::SafeArrayCreate( VT_UI1, 1, _sab );
  1546. if ( _psa != NULL )
  1547. {
  1548. PBYTE _pb = NULL;
  1549. //
  1550. // get a pointer to the SafeArray
  1551. //
  1552. _hr = ::SafeArrayAccessData( _psa, (PVOID *) &_pb );
  1553. if ( SUCCEEDED( _hr ) )
  1554. {
  1555. CComVariant _var;
  1556. ::CopyMemory( _pb, cbhValue.pBinaryValue->rgb, cbhValue.pValue->cbLength );
  1557. //
  1558. // tell the variant what it is holding onto
  1559. //
  1560. _var.parray = _psa;
  1561. _var.vt = VT_ARRAY | VT_UI1;
  1562. m_cpvdvData.insert( m_cpvdvData.end(), _var );
  1563. //
  1564. // release the pointer into the SafeArray
  1565. //
  1566. _hr = ::SafeArrayUnaccessData( _psa );
  1567. } // if:
  1568. } // if:
  1569. return _hr;
  1570. } //*** CClusPropertyValueData::HrCreateBinary()
  1571. /////////////////////////////////////////////////////////////////////////////
  1572. //++
  1573. //
  1574. // CClusPropertyValueData::HrBinaryValue
  1575. //
  1576. // Description:
  1577. // Set the binary value of this property value data.
  1578. //
  1579. // Arguments:
  1580. // psa [IN] - The SAFEARRY to save.
  1581. //
  1582. // Return Value:
  1583. // S_OK if successful, or other HRESULT error.
  1584. //
  1585. //--
  1586. /////////////////////////////////////////////////////////////////////////////
  1587. HRESULT CClusPropertyValueData::HrBinaryValue( IN SAFEARRAY * psa )
  1588. {
  1589. ASSERT( psa != NULL );
  1590. HRESULT _hr = E_POINTER;
  1591. if ( psa != NULL )
  1592. {
  1593. CComVariant _var;
  1594. if ( ! m_cpvdvData.empty() )
  1595. {
  1596. m_cpvdvData.erase( m_cpvdvData.begin() );
  1597. } // if:
  1598. //
  1599. // tell the variant what it is holding onto
  1600. //
  1601. _var.parray = psa;
  1602. _var.vt = VT_ARRAY | VT_UI1;
  1603. m_cpvdvData.insert( m_cpvdvData.begin(), _var );
  1604. _hr = S_OK;
  1605. } // if:
  1606. return _hr;
  1607. } //*** CClusPropertyValueData::HrBinaryValue()