///////////////////////////////////////////////////////////////////////////// // // Copyright (c) 1998-2000 Microsoft Corporation // // Module Name: // PropertyValue.cpp // // Description: // Implementation of the cluster property value classes for the MSCLUS // automation classes. // // Author: // Galen Barbee (GalenB) 16-Dec-1998 // // Revision History: // // Notes: // ///////////////////////////////////////////////////////////////////////////// #include "stdafx.h" #include "Property.h" #include "PropertyValue.h" ///////////////////////////////////////////////////////////////////////////// // Global variables ///////////////////////////////////////////////////////////////////////////// static const IID * iidCClusPropertyValue[] = { &IID_ISClusPropertyValue }; static const IID * iidCClusPropertyValues[] = { &IID_ISClusPropertyValues }; static const IID * iidCClusPropertyValueData[] = { &IID_ISClusPropertyValueData }; //*************************************************************************// ///////////////////////////////////////////////////////////////////////////// // CClusPropertyValue class ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// //++ // // CClusPropertyValue::CClusPropertyValue // // Description: // Constructor. // // Arguments: // None. // // Return Value: // None. // //-- ///////////////////////////////////////////////////////////////////////////// CClusPropertyValue::CClusPropertyValue( void ) { m_dwFlags = 0; m_pcpvdData = NULL; #if CLUSAPI_VERSION >= 0x0500 m_cptType = CLUSPROP_TYPE_UNKNOWN; #else m_cptType = (CLUSTER_PROPERTY_TYPE) -1; #endif // CLUSAPI_VERSION >= 0x0500 m_cpfFormat = CLUSPROP_FORMAT_UNKNOWN; m_cbLength = 0; m_piids = (const IID *) iidCClusPropertyValue; m_piidsSize = ARRAYSIZE( iidCClusPropertyValue ); } //*** CClusPropertyValue::CClusPropertyValue() ///////////////////////////////////////////////////////////////////////////// //++ // // CClusPropertyValue::~CClusPropertyValue // // Description: // Destructor. // // Arguments: // None. // // Return Value: // None. // //-- ///////////////////////////////////////////////////////////////////////////// CClusPropertyValue::~CClusPropertyValue( void ) { if ( m_pcpvdData != NULL ) { m_pcpvdData->Release(); } // if: data vector has been allocated } //*** CClusPropertyValue::~CClusPropertyValue() ///////////////////////////////////////////////////////////////////////////// //++ // // CClusPropertyValue::Create // // Description: // Finish the heavy weight construction for a single value. // // Arguments: // varValue [IN] - The value. // cptType [IN] - The cluster property type of the value. // cpfFormat [IN] - The cluster property format of the value. // cbLength [IN] - The length of the value. // bReadOnly [IN] - Is this a read only property? // // Return Value: // S_OK if successful, or other HRESULT error. // //-- ///////////////////////////////////////////////////////////////////////////// HRESULT CClusPropertyValue::Create( IN VARIANT varValue, IN CLUSTER_PROPERTY_TYPE cptType, IN CLUSTER_PROPERTY_FORMAT cpfFormat, IN size_t cbLength, IN BOOL bReadOnly ) { HRESULT _hr = S_FALSE; m_cptType = cptType; m_cpfFormat = cpfFormat; m_cbLength = cbLength; if ( bReadOnly ) { m_dwFlags |= READONLY; } // if: set the read only flag else { m_dwFlags &= ~READONLY; } // else: clear the read only flag _hr = CComObject< CClusPropertyValueData >::CreateInstance( &m_pcpvdData ); if ( SUCCEEDED( _hr ) ) { CSmartPtr< CComObject < CClusPropertyValueData > > _ptrData( m_pcpvdData ); _hr = _ptrData->Create( varValue, cpfFormat, bReadOnly ); if ( SUCCEEDED( _hr ) ) { _ptrData->AddRef(); } // if: } // if: Can create an instance of CClusPropertyValueData return _hr; } //*** CClusPropertyValue::Create() ///////////////////////////////////////////////////////////////////////////// //++ // // CClusPropertyValue::Create // // Description: // Finish the heavy weight construction for a value list. // // Arguments: // cbhValue [IN] - The value list buffer helper. // bReadOnly [IN] - Is this a read only property? // // Return Value: // S_OK if successful, or other HRESULT error. // //-- ///////////////////////////////////////////////////////////////////////////// HRESULT CClusPropertyValue::Create( IN CLUSPROP_BUFFER_HELPER cbhValue, IN BOOL bReadOnly ) { HRESULT _hr = S_FALSE; m_cptType = (CLUSTER_PROPERTY_TYPE) cbhValue.pValue->Syntax.wType; m_cpfFormat = (CLUSTER_PROPERTY_FORMAT) cbhValue.pValue->Syntax.wFormat; m_cbLength = cbhValue.pValue->cbLength; if ( bReadOnly ) { m_dwFlags |= READONLY; } // if: set the read only flag else { m_dwFlags &= ~READONLY; } // else: clear the read only flag _hr = CComObject< CClusPropertyValueData >::CreateInstance( &m_pcpvdData ); if ( SUCCEEDED( _hr ) ) { CSmartPtr< CComObject < CClusPropertyValueData > > _ptrData( m_pcpvdData ); _hr = _ptrData->Create( cbhValue, bReadOnly ); if ( SUCCEEDED( _hr ) ) { _ptrData->AddRef(); } // if: } // if: Can create an instance of CClusPropertyValueData return _hr; } //*** CClusPropertyValue::Create ///////////////////////////////////////////////////////////////////////////// //++ // // CClusPropertyValue::get_Value // // Description: // Return the default value data for this value. // // Arguments: // pvarValue [IN] - Catches the data value. // // Return Value: // S_OK if successful, or E_POINTER if not. // //-- ///////////////////////////////////////////////////////////////////////////// STDMETHODIMP CClusPropertyValue::get_Value( IN VARIANT * pvarValue ) { //ASSERT( pvarValue != NULL ); HRESULT _hr = E_POINTER; if ( pvarValue != NULL ) { _hr = VariantCopyInd( pvarValue, &(*m_pcpvdData)[ 0 ] ); } return _hr; } //*** CClusPropertyValue::get_Value() ///////////////////////////////////////////////////////////////////////////// //++ // // CClusPropertyValue::put_Value // // Description: // Change the default data value. // // Arguments: // varValue [IN] - The new data value. // // Return Value: // S_OK if successful, or S_FALSE if read only. // //-- ///////////////////////////////////////////////////////////////////////////// STDMETHODIMP CClusPropertyValue::put_Value( IN VARIANT varValue ) { HRESULT _hr = S_FALSE; if ( ( m_dwFlags & READONLY ) == 0 ) { CComVariant _varNew( varValue ); CComVariant _varOld( (*m_pcpvdData)[ 0 ] ); _hr = S_OK; if ( _varOld != _varNew ) { (*m_pcpvdData)[ 0 ] = _varNew; m_dwFlags |= MODIFIED; } // if: value changed } // if: return _hr; } //*** CClusPropertyValue::put_Value() ///////////////////////////////////////////////////////////////////////////// //++ // // CClusPropertyValue::get_Type // // Description: // Get this value's cluster property type. // // Arguments: // pcptType [OUT] - Catches the value type. // // Return Value: // S_OK if successful, or E_POINTER if not. // //-- ///////////////////////////////////////////////////////////////////////////// STDMETHODIMP CClusPropertyValue::get_Type( OUT CLUSTER_PROPERTY_TYPE * pcptType ) { //ASSERT( pcptType != NULL ); HRESULT _hr = E_POINTER; if ( pcptType != NULL ) { *pcptType = m_cptType; _hr = S_OK; } // if: property type pointer specified return _hr; } //*** CClusPropertyValue::get_Type() ///////////////////////////////////////////////////////////////////////////// //++ // // CClusPropertyValue::put_Type // // Description: // Set this value's cluster property type. // // Arguments: // cptType [IN] - The new type. // // Return Value: // S_OK if successful, or S_FALSE if read only. // // Note: // It is possible that this should be removed. You cannot ever change // a value's type. //-- ///////////////////////////////////////////////////////////////////////////// STDMETHODIMP CClusPropertyValue::put_Type( IN CLUSTER_PROPERTY_TYPE cptType ) { HRESULT _hr = S_FALSE; if ( ( m_dwFlags & READONLY ) == 0 ) { m_cptType = cptType; _hr = S_OK; } // if: return _hr; } //*** CClusPropertyValue::put_Type() ///////////////////////////////////////////////////////////////////////////// //++ // // CClusPropertyValue::get_Format // // Description: // Get the value's cluster property format. // // Arguments: // pcpfFormat [OUT] - Catches the format. // // Return Value: // S_OK if successful, or E_POINTER if not. // //-- ///////////////////////////////////////////////////////////////////////////// STDMETHODIMP CClusPropertyValue::get_Format( OUT CLUSTER_PROPERTY_FORMAT * pcpfFormat ) { //ASSERT( pcpfFormat != NULL ); HRESULT _hr = E_POINTER; if ( pcpfFormat != NULL ) { *pcpfFormat = m_cpfFormat; _hr = S_OK; } // if: property format pointer specified return _hr; } //*** CClusPropertyValue::get_Format() ///////////////////////////////////////////////////////////////////////////// //++ // // CClusPropertyValue::put_Format // // Description: // Set the value's cluster property format. // // Arguments: // cpfFormat [IN] - The new format for the value. // // Return Value: // S_OK if successful, or S_FALSE if read only. // // Note: // It is possible that this should be removed. You cannot ever change // a value's format. // //-- ///////////////////////////////////////////////////////////////////////////// STDMETHODIMP CClusPropertyValue::put_Format( IN CLUSTER_PROPERTY_FORMAT cpfFormat ) { HRESULT _hr = S_FALSE; if ( ( m_dwFlags & READONLY ) == 0 ) { m_cpfFormat = cpfFormat; _hr = S_OK; } // if: return _hr; } //*** CClusPropertyValue::put_Format() ///////////////////////////////////////////////////////////////////////////// //++ // // CClusPropertyValue::get_Length // // Description: // Returns the length of this value. // // Arguments: // plLength [OUT] - Catches the length of this value. // // Return Value: // S_OK if successful, or E_POINTER if not. // //-- ///////////////////////////////////////////////////////////////////////////// STDMETHODIMP CClusPropertyValue::get_Length( OUT long * plLength ) { //ASSERT( plLength != NULL ); HRESULT _hr = E_POINTER; if ( plLength != NULL ) { *plLength = (long) m_cbLength; _hr = S_OK; } // if: length pointer specified return _hr; } //*** CClusPropertyValue::get_Length() ///////////////////////////////////////////////////////////////////////////// //++ // // CClusPropertyValue::get_DataCount // // Description: // Return the count of VARIANTS in the ClusProperyValueData object. // // Arguments: // plCount [OUT] - Catches the count. // // Return Value: // S_OK if successful, or other HRESULT error. // //-- ///////////////////////////////////////////////////////////////////////////// STDMETHODIMP CClusPropertyValue::get_DataCount( OUT long * plCount ) { return m_pcpvdData->get_Count( plCount ); } //*** CClusPropertyValue::get_DataCount() ///////////////////////////////////////////////////////////////////////////// //++ // // CClusPropertyValue::get_Data // // Description: // Returns the data collection. // // Arguments: // ppClusterPropertyValueData [OUT] - Catches the data collection. // // Return Value: // S_OK if successful, E_POINTER, or other HRESULT error. // //-- ///////////////////////////////////////////////////////////////////////////// STDMETHODIMP CClusPropertyValue::get_Data( OUT ISClusPropertyValueData ** ppClusterPropertyValueData ) { //ASSERT( ppClusterPropertyValueData ); HRESULT _hr = E_POINTER; if ( ppClusterPropertyValueData != NULL ) { _hr = m_pcpvdData->QueryInterface( IID_ISClusPropertyValueData, (void **) ppClusterPropertyValueData ); } return _hr; } //*** CClusPropertyValue::get_Data() ///////////////////////////////////////////////////////////////////////////// //++ // // CClusPropertyValue::Modified // // Description: // Sets this value to modified and returns the old modified state. // // Arguments: // bModified [IN] - New modified state. // // Return Value: // The old modified state. // //-- ///////////////////////////////////////////////////////////////////////////// BOOL CClusPropertyValue::Modified( IN BOOL bModified ) { BOOL _bTemp = ( m_dwFlags & MODIFIED ); if ( bModified ) { m_dwFlags |= MODIFIED; } // if: set the modified flag else { m_dwFlags &= ~MODIFIED; } // else: clear the modified flag return _bTemp; } //*** CClusPropertyValue::Modified() ///////////////////////////////////////////////////////////////////////////// //++ // // CClusPropertyValue::Value // // Description: // Set a new value into this property value. // // Arguments: // rvarValue [IN] - the new value // // Return Value: // The old value. // //-- ///////////////////////////////////////////////////////////////////////////// CComVariant CClusPropertyValue::Value( const CComVariant & rvarValue ) { CComVariant _varNew( rvarValue ); CComVariant _varOld( (*m_pcpvdData)[ 0 ] ); if ( _varOld != _varNew ) { (*m_pcpvdData)[ 0 ] = _varNew; m_dwFlags |= MODIFIED; } // if: data changed return _varOld; } //*** CClusPropertyValue::Value() ///////////////////////////////////////////////////////////////////////////// //++ // // CClusPropertyValue::HrBinaryValue // // Description: // Set the binary value of property value. // // Arguments: // psa [IN] - The SAFEARRY to save. // // Return Value: // S_OK if successful, or other HRESULT error. // //-- ///////////////////////////////////////////////////////////////////////////// HRESULT CClusPropertyValue::HrBinaryValue( IN SAFEARRAY * psa ) { return m_pcpvdData->HrBinaryValue( psa ); } //*** CClusPropertyValue::HrBinaryValue() //*************************************************************************// ///////////////////////////////////////////////////////////////////////////// // CClusPropertyValues class ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// //++ // // CClusPropertyValues::CClusPropertyValues // // Description: // Constructor. // // Arguments: // None. // // Return Value: // None. // //-- ///////////////////////////////////////////////////////////////////////////// CClusPropertyValues::CClusPropertyValues( void ) { m_piids = (const IID *) iidCClusPropertyValues; m_piidsSize = ARRAYSIZE( iidCClusPropertyValues ); } //*** CClusPropertyValues::CClusPropertyValues() ///////////////////////////////////////////////////////////////////////////// //++ // // CClusPropertyValues::~CClusPropertyValues // // Description: // Destructor. // // Arguments: // None. // // Return Value: // None. // //-- ///////////////////////////////////////////////////////////////////////////// CClusPropertyValues::~CClusPropertyValues( void ) { Clear(); } //*** CClusPropertyValues::~CClusPropertyValues() ///////////////////////////////////////////////////////////////////////////// //++ // // CClusPropertyValues::Clear // // Description: // Releases the values in the collection. // // Arguments: // None. // // Return Value: // None. // //-- ///////////////////////////////////////////////////////////////////////////// void CClusPropertyValues::Clear( void ) { ::ReleaseAndEmptyCollection< CClusPropertyValueVector, CComObject< CClusPropertyValue > >( m_cpvvValues ); } //*** CClusPropertyValues::Clear() ///////////////////////////////////////////////////////////////////////////// //++ // // CClusPropertyValues::HrGetVariantLength // // Description: // Compute the length of the data from its variant type. // // Arguments: // rvarValue [IN] - The new value to compute the length of. // pcbLength [OUT] - Catches the length. // cpfFormat [IN] - The cluster property format. // // Return Value: // S_OK if successful, or E_INVALIDARG if the type is bogus. // //-- ///////////////////////////////////////////////////////////////////////////// HRESULT CClusPropertyValues::HrGetVariantLength( IN const VARIANT rvarValue, OUT PDWORD pcbLength, IN CLUSTER_PROPERTY_FORMAT cpfFormat ) { HRESULT _hr = E_INVALIDARG; VARTYPE _varType = rvarValue.vt; do { if ( ( _varType & VT_ARRAY ) && ( _varType & VT_UI1 ) ) { SAFEARRAY * _psa = rvarValue.parray; // // only accept single dimensional arrays! // if ( ( _psa != NULL ) && ( ::SafeArrayGetDim( _psa ) == 1 ) ) { size_t _cbElem = ::SafeArrayGetElemsize( _psa ); *pcbLength = _cbElem * _psa->cbElements; _hr = S_OK; } // if: break; } // if: if ( _varType & VT_VECTOR ) { break; } // if: Don't know what to do with a vector... _varType &= ~VT_BYREF; // mask off the by ref bit if it was set... if ( ( _varType == VT_I2 ) || ( _varType == VT_I4 ) || ( _varType == VT_BOOL ) || ( _varType == VT_R4 ) ) { *pcbLength = sizeof( DWORD ); _hr = S_OK; break; } // if: else if ( _varType == VT_BSTR ) { CComBSTR _bstr; _bstr.Attach( rvarValue.bstrVal ); *pcbLength = _bstr.Length(); _bstr.Detach(); _hr = S_OK; break; } // else if: else if ( ( _varType == VT_I8 ) || ( _varType == VT_R8 ) ) { *pcbLength = sizeof( ULONGLONG ); _hr = S_OK; break; } // else if: else if ( _varType == VT_VARIANT ) { _hr = HrGetVariantLength( *rvarValue.pvarVal, pcbLength, cpfFormat ); break; } // else if: } while( TRUE ); // do-while: want to avoid using a goto ;-) return _hr; } //*** CClusPropertyValues::HrGetVariantLength() ///////////////////////////////////////////////////////////////////////////// //++ // // CClusPropertyValues::get_Count // // Description: // Returns the count of elements (values) in the collection. // // Arguments: // plCount [OUT] - Catches the count. // // Return Value: // S_OK if successful, or E_POINTER if not. // //-- ///////////////////////////////////////////////////////////////////////////// STDMETHODIMP CClusPropertyValues::get_Count( OUT long * plCount ) { //ASSERT( plCount != NULL ); HRESULT _hr = E_POINTER; if ( plCount != NULL ) { *plCount = m_cpvvValues.size(); _hr = S_OK; } return _hr; } //*** CClusPropertyValues::get_Count() ///////////////////////////////////////////////////////////////////////////// //++ // // CClusPropertyValues::GetIndex // // Description: // Get the index from the passed in variant. // // Arguments: // varIndex [IN] - Hold the index. This is a one based number. // pnIndex [OUT] - Catches the zero based index in the collection. // // Return Value: // S_OK if successful, E_POINTER, or E_INVALIDARG if the index is out // of range. // //-- ///////////////////////////////////////////////////////////////////////////// HRESULT CClusPropertyValues::GetIndex( IN VARIANT varIndex, OUT UINT * pnIndex ) { //ASSERT( pnIndex != NULL ); HRESULT _hr = E_POINTER; if ( pnIndex != NULL ) { CComVariant _v; UINT _nIndex = 0; *pnIndex = 0; _v.Copy( &varIndex ); // Check to see if the index is a number. _hr = _v.ChangeType( VT_I4 ); if ( SUCCEEDED( _hr ) ) { _nIndex = _v.lVal; _nIndex--; // Adjust index to be 0 relative instead of 1 relative } // We found an index, now check the range. if ( SUCCEEDED( _hr ) ) { if ( _nIndex < m_cpvvValues.size() ) { *pnIndex = _nIndex; } else { _hr = E_INVALIDARG; } } } return _hr; } //*** CClusPropertyValues::GetIndex() ///////////////////////////////////////////////////////////////////////////// //++ // // CClusPropertyValues::get_Item // // Description: // Returns the object (value) at the passed in index. // // Arguments: // varIndex [IN] - Hold the index. This is a one based number. // ppPropertyValue [OUT] - Catches the property value. // // Return Value: // S_OK if successful, E_POINTER, or E_INVALIDARG if the index is out // of range, or other HRESULT error. // //-- ///////////////////////////////////////////////////////////////////////////// STDMETHODIMP CClusPropertyValues::get_Item( IN VARIANT varIndex, OUT ISClusPropertyValue ** ppPropertyValue ) { //ASSERT( ppPropertyValue != NULL ); HRESULT _hr = E_POINTER; if ( ppPropertyValue != NULL ) { CComObject< CClusPropertyValue > * _pPropertyValue = NULL; UINT _nIndex = 0; // // Zero the out param // *ppPropertyValue = 0; _hr = GetIndex( varIndex, &_nIndex ); if ( SUCCEEDED( _hr ) ) { _pPropertyValue = m_cpvvValues[ _nIndex ]; _hr = _pPropertyValue->QueryInterface( IID_ISClusPropertyValue, (void **) ppPropertyValue ); } } return _hr; } //*** CClusPropertyValues::get_Item() ///////////////////////////////////////////////////////////////////////////// //++ // // CClusPropertyValues::get__NewEnum // // Description: // Create and return a new enumeration for this collection. // // Arguments: // ppunk [OUT] - Catches the new enumeration. // // Return Value: // S_OK if successful, E_POINTER, or other HRESULT error. // //-- ///////////////////////////////////////////////////////////////////////////// STDMETHODIMP CClusPropertyValues::get__NewEnum( IUnknown ** ppunk ) { return ::HrNewIDispatchEnum< CClusPropertyValueVector, CComObject< CClusPropertyValue > >( ppunk, m_cpvvValues ); } //*** CClusPropertyValues::get__NewEnum() ///////////////////////////////////////////////////////////////////////////// //++ // // CClusPropertyValues::Create // // Description: // Finish the heavy weight construction. // // Arguments: // varValue [IN] - The value. // cptType [IN] - The cluster property type. // cpfFormat [IN] - The cluster format type. // bReadOnly [IN] - Is this a read only value/property? // // Return Value: // S_OK if successful, or other HRESULT error if not. // //-- ///////////////////////////////////////////////////////////////////////////// HRESULT CClusPropertyValues::Create( IN VARIANT varValue, IN CLUSTER_PROPERTY_TYPE cptType, IN CLUSTER_PROPERTY_FORMAT cpfFormat, IN BOOL bReadOnly ) { HRESULT _hr = S_FALSE; CComObject< CClusPropertyValue > * _pValue = NULL; _hr = CComObject< CClusPropertyValue >::CreateInstance( &_pValue ); if ( SUCCEEDED( _hr ) ) { CSmartPtr< CComObject < CClusPropertyValue > > _ptrValue( _pValue ); DWORD _cbLength = 0; _hr = HrGetVariantLength( varValue, &_cbLength, cpfFormat ); if ( SUCCEEDED( _hr ) ) { _hr = _ptrValue->Create( varValue, cptType, cpfFormat, _cbLength, bReadOnly ); if ( SUCCEEDED( _hr ) ) { m_cpvvValues.insert( m_cpvvValues.end(), _ptrValue ); _ptrValue->AddRef(); } // if: } // if: } // if: Can create an instance of CClusPropertyValueData return _hr; } //*** CClusPropertyValues::Create() ///////////////////////////////////////////////////////////////////////////// //++ // // CClusPropertyValues::Create // // Description: // Finish the heavy weight construction. // // Arguments: // rpvlValue [IN] - The value list. // bReadOnly [IN] - Is this a read only value/property? // // Return Value: // S_OK if successful, or other HRESULT error if not. // //-- ///////////////////////////////////////////////////////////////////////////// HRESULT CClusPropertyValues::Create( IN const CClusPropValueList & rpvlValue, IN BOOL bReadOnly ) { return HrFillPropertyValuesVector( const_cast< CClusPropValueList & >( rpvlValue ), bReadOnly ); } //*** CClusPropertyValues::Create() ///////////////////////////////////////////////////////////////////////////// //++ // // CClusPropertyValues::CreateItem // // Description: // Create a new property value object and add it to the collection. // // Arguments: // bstrName [IN] - property name. // varValue [IN] - the value to add. // ppPropertyValue [OUT] - catches the newly created object. // // Return Value: // S_OK if successful, E_POINTER, or other HRESULT error. // //-- ///////////////////////////////////////////////////////////////////////////// STDMETHODIMP CClusPropertyValues::CreateItem( IN BSTR bstrName, IN VARIANT varValue, OUT ISClusPropertyValue ** ppPropertyValue ) { //ASSERT( ppPropertyValue != NULL ); HRESULT _hr = E_POINTER; // // TODO: GalenB 17 Jan 2000 // // If are going to allow Multi-valued property creation we need to implement this method? // if ( ppPropertyValue != NULL ) { _hr = E_NOTIMPL; } // if: property value interface pointer not specified return _hr; } //*** CClusPropertyValues::CreateItem() ///////////////////////////////////////////////////////////////////////////// //++ // // CClusPropertyValues::RemoveItem // // Description: // Remove the property value at the passed in index from the collection. // // Arguments: // varIndex [IN] - contains the index to remove. // // Return Value: // S_OK if successful, S_FALSE if read only, or other HRESULT error. // //-- ///////////////////////////////////////////////////////////////////////////// STDMETHODIMP CClusPropertyValues::RemoveItem( VARIANT varIndex ) { // // TODO: GalenB 17 Jan 2000 // // If are going to allow Multi-valued property creation we need to implement this method? // return E_NOTIMPL; } //*** CClusPropertyValues::RemoveItem() ///////////////////////////////////////////////////////////////////////////// //++ // // CClusPropertyValues::HrFillPropertyValuesVector // // Description: // Fill the collection from the passes in value list. // // Arguments: // cplPropValueList [IN] - The value list to parse. // bReadOnly [IN] - Is this part of a read only property? // // Return Value: // S_OK if successful, or Win32 error as HRESULT. // //-- ///////////////////////////////////////////////////////////////////////////// HRESULT CClusPropertyValues::HrFillPropertyValuesVector( IN CClusPropValueList & cplPropValueList, IN BOOL bReadOnly ) { HRESULT _hr = S_OK; DWORD _sc; CComVariant _var; CComObject< CClusPropertyValue > * _pPropVal = NULL; CLUSPROP_BUFFER_HELPER _cbhValue = { NULL }; _sc = cplPropValueList.ScMoveToFirstValue(); if ( _sc != ERROR_SUCCESS ) { _hr = HRESULT_FROM_WIN32( _sc ); } // if: error moving to the first value else { do { _cbhValue = cplPropValueList; _hr = CComObject< CClusPropertyValue >::CreateInstance( &_pPropVal ); if ( SUCCEEDED( _hr ) ) { CSmartPtr< CComObject < CClusPropertyValue > > _ptrProp( _pPropVal ); _hr = _ptrProp->Create( _cbhValue, bReadOnly ); if ( SUCCEEDED( _hr ) ) { _ptrProp->AddRef(); m_cpvvValues.insert( m_cpvvValues.end(), _ptrProp ); } // if: create property ok } // if: create property instance ok // // Move to the next value. // _sc = cplPropValueList.ScMoveToNextValue(); } while ( _sc == ERROR_SUCCESS ); // do-while: there are value in the list if ( _sc != ERROR_NO_MORE_ITEMS ) { _hr = HRESULT_FROM_WIN32( _sc ); } // if: error occurred moving to the next value } // else: moved to the first value successfully return _hr; } //*** CClusPropertyValues::HrFillPropertyValuesVector() //*************************************************************************// ///////////////////////////////////////////////////////////////////////////// // CClusPropertyValueData class ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// //++ // // CClusPropertyValueData::CClusPropertyValueData // // Description: // Constructor. // // Arguments: // None. // // Return Value: // None. // //-- ///////////////////////////////////////////////////////////////////////////// CClusPropertyValueData::CClusPropertyValueData( void ) { m_cpfFormat = CLUSPROP_FORMAT_UNKNOWN; m_dwFlags = 0; m_piids = (const IID *) iidCClusPropertyValueData; m_piidsSize = ARRAYSIZE( iidCClusPropertyValueData ); } //*** CClusPropertyValueData::CClusPropertyValueData() ///////////////////////////////////////////////////////////////////////////// //++ // // CClusPropertyValueData::~CClusPropertyValueData // // Description: // Destructor. // // Arguments: // None. // // Return Value: // None. // //-- ///////////////////////////////////////////////////////////////////////////// CClusPropertyValueData::~CClusPropertyValueData( void ) { Clear(); } //*** CClusPropertyValueData::~CClusPropertyValueData() ///////////////////////////////////////////////////////////////////////////// //++ // // CClusPropertyValueData::Clear // // Description: // Erase the data collection. // // Arguments: // None. // // Return Value: // None. // //-- ///////////////////////////////////////////////////////////////////////////// void CClusPropertyValueData::Clear( void ) { if ( ! m_cpvdvData.empty() ) { m_cpvdvData.erase( m_cpvdvData.begin(), m_cpvdvData.end() ); } // if: } //*** CClusPropertyValueData::Clear() ///////////////////////////////////////////////////////////////////////////// //++ // // CClusPropertyValueData::get_Count // // Description: // Returns the count of elements (data) in the collection. // // Arguments: // plCount [OUT] - Catches the count. // // Return Value: // S_OK if successful, or E_POINTER if not. // //-- ///////////////////////////////////////////////////////////////////////////// STDMETHODIMP CClusPropertyValueData::get_Count( OUT long * plCount ) { //ASSERT( plCount != NULL ); HRESULT _hr = E_POINTER; if ( plCount != NULL ) { *plCount = m_cpvdvData.size(); _hr = S_OK; } return _hr; } //*** CClusPropertyValueData::get_Count() ///////////////////////////////////////////////////////////////////////////// //++ // // CClusPropertyValueData::GetIndex // // Description: // Get the index from the passed in variant. // // Arguments: // varIndex [IN] - Hold the index. This is a one based number. // pnIndex [OUT] - Catches the zero based index in the collection. // // Return Value: // S_OK if successful, E_POINTER, or E_INVALIDARG if the index is out // of range. // //-- ///////////////////////////////////////////////////////////////////////////// HRESULT CClusPropertyValueData::GetIndex( IN VARIANT varIndex, OUT UINT * pnIndex ) { //ASSERT( pnIndex != NULL ); HRESULT _hr = E_POINTER; if ( pnIndex != NULL ) { CComVariant _v; UINT _nIndex = 0; *pnIndex = 0; _v.Copy( &varIndex ); // Check to see if the index is a number. _hr = _v.ChangeType( VT_I4 ); if ( SUCCEEDED( _hr ) ) { _nIndex = _v.lVal; _nIndex--; // Adjust index to be 0 relative instead of 1 relative } // We found an index, now check the range. if ( SUCCEEDED( _hr ) ) { if ( _nIndex < m_cpvdvData.size() ) { *pnIndex = _nIndex; } else { _hr = E_INVALIDARG; } } } return _hr; } //*** CClusPropertyValueData::GetIndex() ///////////////////////////////////////////////////////////////////////////// //++ // // CClusPropertyValueData::get_Item // // Description: // Returns the object (data) at the passed in index. // // Arguments: // varIndex [IN] - Hold the index. This is a one based number. // pvarData [OUT] - Catches the property value. // // Return Value: // S_OK if successful, E_POINTER, or E_INVALIDARG if the index is out // of range, or other HRESULT error. // //-- ///////////////////////////////////////////////////////////////////////////// STDMETHODIMP CClusPropertyValueData::get_Item( IN VARIANT varIndex, OUT VARIANT * pvarData ) { //ASSERT( pvarData != NULL ); HRESULT _hr = E_POINTER; if ( pvarData != NULL ) { UINT _nIndex = 0; _hr = GetIndex( varIndex, &_nIndex ); if ( SUCCEEDED( _hr ) ) { _hr = VariantCopyInd( pvarData, &m_cpvdvData[ _nIndex ] ); } } return _hr; } //*** CClusPropertyValueData::get_Item() ///////////////////////////////////////////////////////////////////////////// //++ // // CClusPropertyValueData::get__NewEnum // // Description: // Create and return a new enumeration for this collection. // // Arguments: // ppunk [OUT] - Catches the new enumeration. // // Return Value: // S_OK if successful, E_POINTER, or other HRESULT error. // //-- ///////////////////////////////////////////////////////////////////////////// STDMETHODIMP CClusPropertyValueData::get__NewEnum( IUnknown ** ppunk ) { return ::HrNewVariantEnum< CClusPropertyValueDataVector >( ppunk, m_cpvdvData ); } //*** CClusPropertyValueData::get__NewEnum() ///////////////////////////////////////////////////////////////////////////// //++ // // CClusPropertyValueData::Create // // Description: // Finish the heavy weight construction. // // Arguments: // varValue [IN] - The data value. // cpfFormat [IN] - The cluster property format. // bReadOnly [IN] - Is this data for a read only property? // // Return Value: // S_OK -- Always!!! // //-- ///////////////////////////////////////////////////////////////////////////// HRESULT CClusPropertyValueData::Create( IN VARIANT varValue, IN CLUSTER_PROPERTY_FORMAT cpfFormat, IN BOOL bReadOnly ) { if ( bReadOnly ) { m_dwFlags |= READONLY; } // if: set the read only flag else { m_dwFlags &= ~READONLY; } // else: clear the read only flag m_cpfFormat = cpfFormat; if ( ( varValue.vt & VT_BYREF ) && ( varValue.vt & VT_VARIANT ) ) { m_cpvdvData.insert( m_cpvdvData.end(), *varValue.pvarVal ); } // if: the variant is a reference to another variant... else { m_cpvdvData.insert( m_cpvdvData.end(), varValue ); } // else: the variant is the data... return S_OK; } //*** CClusPropertyValueData::Create() ///////////////////////////////////////////////////////////////////////////// //++ // // CClusPropertyValueData::Create // // Description: // Finish the heavy weight construction. // // Arguments: // cbhValue [IN] - The value buffer helper. // bReadOnly [IN] - Is this data for a read only property? // // Return Value: // S_OK if successful, or other HRESULT error if not. // //-- ///////////////////////////////////////////////////////////////////////////// HRESULT CClusPropertyValueData::Create( IN CLUSPROP_BUFFER_HELPER cbhValue, IN BOOL bReadOnly ) { HRESULT _hr = S_OK; if ( bReadOnly ) { m_dwFlags |= READONLY; } // if: set the read only flag else { m_dwFlags &= ~READONLY; } // else: clear the read only flag m_cpfFormat = (CLUSTER_PROPERTY_FORMAT) cbhValue.pValue->Syntax.wFormat; switch( m_cpfFormat ) { #if CLUSAPI_VERSION >= 0x0500 case CLUSPROP_FORMAT_EXPANDED_SZ: #endif // CLUSAPI_VERSION >= 0x0500 case CLUSPROP_FORMAT_SZ: case CLUSPROP_FORMAT_EXPAND_SZ: { m_cpvdvData.insert( m_cpvdvData.end(), cbhValue.pStringValue->sz ); break; } // case: #if CLUSAPI_VERSION >= 0x0500 case CLUSPROP_FORMAT_LONG: #endif // CLUSAPI_VERSION >= 0x0500 case CLUSPROP_FORMAT_DWORD: { #if CLUSAPI_VERSION >= 0x0500 m_cpvdvData.insert( m_cpvdvData.end(), cbhValue.pLongValue->l ); #else m_cpvdvData.insert( m_cpvdvData.end(), (long) cbhValue.pDwordValue->dw ); #endif // CLUSAPI_VERSION >= 0x0500 break; } // case: case CLUSPROP_FORMAT_MULTI_SZ: { _hr = HrCreateMultiSz( cbhValue ); break; } // case: case CLUSPROP_FORMAT_BINARY: { _hr = HrCreateBinary( cbhValue ); break; } // case: default: { break; } // default: } // switch: return _hr; } //*** CClusPropertyValueData::Create() ///////////////////////////////////////////////////////////////////////////// //++ // // CClusPropertyValueData::CreateItem // // Description: // Create a new object and add it to the collection. // // Arguments: // varValue [IN] - value to add. // pvarData [OUT] - catches the new created object. // // Return Value: // S_OK if successful, S_FALSE if read only, or other HRESULT error. // //-- ///////////////////////////////////////////////////////////////////////////// STDMETHODIMP CClusPropertyValueData::CreateItem( IN VARIANT varValue, OUT VARIANT * pvarData ) { //ASSERT( pvarData != NULL ); HRESULT _hr = E_POINTER; if ( pvarData != NULL ) { if ( ( m_dwFlags & READONLY ) == 0 ) { if ( ( m_cpfFormat == CLUSPROP_FORMAT_MULTI_SZ ) && ( varValue.vt == VT_BSTR ) ) { m_cpvdvData.insert( m_cpvdvData.end(), varValue ); *pvarData = varValue; // kinda acquard, but that's automation for ya' _hr = S_OK; } // if: else { _hr = E_INVALIDARG; } // else: } // if: else { _hr = S_FALSE; } // else: } // if: return _hr; } //*** CClusPropertyValueData::CreateItem() ///////////////////////////////////////////////////////////////////////////// //++ // // CClusPropertyValueData::RemoveItem // // Description: // Remove the data at the passed in index. // // Arguments: // varIndex [IN] - variant that contains the index to remove. // // Return Value: // S_OK if successful, S_FALSE if read only, or other HRESULT error. // // //-- ///////////////////////////////////////////////////////////////////////////// STDMETHODIMP CClusPropertyValueData::RemoveItem( IN VARIANT varIndex ) { HRESULT _hr = S_FALSE; if ( ( m_dwFlags & READONLY ) == 0 ) { UINT _iDelete = 0; _hr = GetIndex( varIndex, &_iDelete ); if ( SUCCEEDED( _hr ) ) { CClusPropertyValueDataVector::iterator _itDelete = m_cpvdvData.begin(); CClusPropertyValueDataVector::const_iterator _itLast = m_cpvdvData.end(); UINT _nCount; for ( _nCount = 0; ( ( _iDelete < _nCount ) && ( _itDelete != _itLast ) ); _itDelete++, _nCount++ ) { } // for: m_cpvdvData.erase( _itDelete ); _hr = S_OK; } } // if: return _hr; } //*** CClusPropertyValueData::RemoveItem() ///////////////////////////////////////////////////////////////////////////// //++ // // CClusPropertyValueData::operator= // // Description: // Saves the passed in data into the collection at the default // position. // // Arguments: // varvalue [IN] - The data to save. // // Return Value: // The old data. // //-- ///////////////////////////////////////////////////////////////////////////// const CComVariant & CClusPropertyValueData::operator=( IN const CComVariant & varData ) { m_cpvdvData[ 0 ] = varData; return m_cpvdvData[ 0 ]; } //*** CClusPropertyValueData::operator=() ///////////////////////////////////////////////////////////////////////////// //++ // // CClusPropertyValueData::HrCreateMultiSz // // Description: // Parse the passed in multi string into a collection of strings. // // Arguments: // cbhValue [IN] - The property value buffer helper. // // Return Value: // S_OK -- Always! // //-- ///////////////////////////////////////////////////////////////////////////// HRESULT CClusPropertyValueData::HrCreateMultiSz( IN CLUSPROP_BUFFER_HELPER cbhValue ) { HRESULT _hr = S_OK; LPWSTR _psz = cbhValue.pMultiSzValue->sz; do { m_cpvdvData.insert( m_cpvdvData.end(), _psz ); _psz += lstrlenW( _psz ) + 1; } while( *_psz != L'\0' ); // do-while not at end of string... return _hr; } //*** CClusPropertyValueData::HrCreateMultiSz() ///////////////////////////////////////////////////////////////////////////// //++ // // CClusPropertyValueData::HrFillMultiSzBuffer // // Description: // Create a multi string from the collection of strings. // // Arguments: // ppsz [OUT] - Catches the mutli string. // // Return Value: // S_OK if successful, or Win32 error as HRESULT if not. // //-- ///////////////////////////////////////////////////////////////////////////// HRESULT CClusPropertyValueData::HrFillMultiSzBuffer( OUT LPWSTR * ppsz ) const { //ASSERT( ppsz != NULL ); HRESULT _hr = E_POINTER; DWORD _cbLength = 0; CClusPropertyValueDataVector::const_iterator _itFirst = m_cpvdvData.begin(); CClusPropertyValueDataVector::const_iterator _itLast = m_cpvdvData.end(); if ( ppsz != NULL ) { _hr = S_OK; for ( ; _itFirst != _itLast; _itFirst++ ) { if ( (*_itFirst).vt == VT_BSTR ) { _cbLength += ( ::lstrlenW( (*_itFirst).bstrVal ) + 1 ); // don't forget the NULL! } // if: else { _hr = E_INVALIDARG; break; } // else: } // for: if ( SUCCEEDED( _hr ) ) { LPWSTR _psz = NULL; *ppsz = (LPWSTR) ::LocalAlloc( LMEM_ZEROINIT, _cbLength + 2 ); // ends in NULL NULL if ( *ppsz != NULL ) { _psz = *ppsz; for ( _itFirst = m_cpvdvData.begin(); _itFirst != _itLast; _itFirst++ ) { _cbLength = lstrlenW( (*_itFirst).bstrVal ); ::lstrcpyW( _psz, (*_itFirst).bstrVal ); _psz += ( _cbLength + 1 ); } // for: } // if: else { DWORD _sc = ::GetLastError(); _hr = HRESULT_FROM_WIN32( _sc ); } // else: } // if: } // if: return _hr; } //*** CClusPropertyValueData::HrFillMultiSzBuffer() ///////////////////////////////////////////////////////////////////////////// //++ // // CClusPropertyValueData::HrCreateBinary // // Description: // Create a safeArray from the passed in binary property value. // // Arguments: // cbhValue [IN] - The binary property value. // // Return Value: // S_OK if successful, or other HRESULT error if not. // //-- ///////////////////////////////////////////////////////////////////////////// HRESULT CClusPropertyValueData::HrCreateBinary( IN CLUSPROP_BUFFER_HELPER cbhValue ) { HRESULT _hr = E_OUTOFMEMORY; SAFEARRAY * _psa = NULL; SAFEARRAYBOUND _sab[ 1 ]; _sab[ 0 ].lLbound = 0; _sab[ 0 ].cElements = cbhValue.pValue->cbLength; // // allocate a one dimensional SafeArray of BYTES // _psa = ::SafeArrayCreate( VT_UI1, 1, _sab ); if ( _psa != NULL ) { PBYTE _pb = NULL; // // get a pointer to the SafeArray // _hr = ::SafeArrayAccessData( _psa, (PVOID *) &_pb ); if ( SUCCEEDED( _hr ) ) { CComVariant _var; ::CopyMemory( _pb, cbhValue.pBinaryValue->rgb, cbhValue.pValue->cbLength ); // // tell the variant what it is holding onto // _var.parray = _psa; _var.vt = VT_ARRAY | VT_UI1; m_cpvdvData.insert( m_cpvdvData.end(), _var ); // // release the pointer into the SafeArray // _hr = ::SafeArrayUnaccessData( _psa ); } // if: } // if: return _hr; } //*** CClusPropertyValueData::HrCreateBinary() ///////////////////////////////////////////////////////////////////////////// //++ // // CClusPropertyValueData::HrBinaryValue // // Description: // Set the binary value of this property value data. // // Arguments: // psa [IN] - The SAFEARRY to save. // // Return Value: // S_OK if successful, or other HRESULT error. // //-- ///////////////////////////////////////////////////////////////////////////// HRESULT CClusPropertyValueData::HrBinaryValue( IN SAFEARRAY * psa ) { ASSERT( psa != NULL ); HRESULT _hr = E_POINTER; if ( psa != NULL ) { CComVariant _var; if ( ! m_cpvdvData.empty() ) { m_cpvdvData.erase( m_cpvdvData.begin() ); } // if: // // tell the variant what it is holding onto // _var.parray = psa; _var.vt = VT_ARRAY | VT_UI1; m_cpvdvData.insert( m_cpvdvData.begin(), _var ); _hr = S_OK; } // if: return _hr; } //*** CClusPropertyValueData::HrBinaryValue()