|
|
/////////////////////////////////////////////////////////////////////////////
//
// 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()
|