|
|
/////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 1997-2002 Microsoft Corporation
//
// Module Name:
// Property.cpp
//
// Description:
// Implementation of the cluster property classes for the MSCLUS
// automation classes.
//
// Author:
// Charles Stacy Harris (stacyh) 28-Feb-1997
// Galen Barbee (galenb) July 1998
//
// Revision History:
// July 1998 GalenB Maaaaaajjjjjjjjjoooooorrrr clean up
//
// Notes:
//
/////////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "ClusterObject.h"
#include "property.h"
/////////////////////////////////////////////////////////////////////////////
// Global variables
/////////////////////////////////////////////////////////////////////////////
static const IID * iidCClusProperty[] = { &IID_ISClusProperty };
static const IID * iidCClusProperties[] = { &IID_ISClusProperties };
//*************************************************************************//
/////////////////////////////////////////////////////////////////////////////
// CClusProperty class
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusProperty::CClusProperty
//
// Description:
// Constructor
//
// Arguments:
// None.
//
// Return Value:
// None.
//
//--
/////////////////////////////////////////////////////////////////////////////
CClusProperty::CClusProperty( void ) { m_dwFlags = 0; m_pValues = NULL; m_piids = (const IID *) iidCClusProperty; m_piidsSize = ARRAYSIZE( iidCClusProperty );
} //*** CClusProperty::CClusProperty()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusProperty::~CClusProperty
//
// Description:
// Destructor
//
// Arguments:
// None.
//
// Return Value:
// None.
//
//--
/////////////////////////////////////////////////////////////////////////////
CClusProperty::~CClusProperty( void ) { if ( m_pValues != NULL ) { m_pValues->Release(); } // if:
} //*** CClusProperty::~CClusProperty()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusProperty::HrCoerceVariantType
//
// Description:
// Coerce the passed in variant to a type that matches the cluster
// property type.
//
// Arguments:
// cpfFormat [IN] - CLUSPROP_FORMAT_xxxx of the property.
// rvarValue [IN] - The variant to coerce.
//
// Return Value:
// S_OK if successful, or other HRESULT error.
//
//--
/////////////////////////////////////////////////////////////////////////////
HRESULT CClusProperty::HrCoerceVariantType( IN CLUSTER_PROPERTY_FORMAT cpfFormat, IN VARIANT & rvarValue ) { HRESULT _hr = S_OK; VARIANT _var;
::VariantInit( &_var );
switch ( cpfFormat ) { case CLUSPROP_FORMAT_BINARY: { if ( ! ( rvarValue.vt & VT_ARRAY ) ) { _hr = E_INVALIDARG; } // if:
break; } // case:
#if CLUSAPI_VERSION >= 0x0500
case CLUSPROP_FORMAT_LONG: #endif // CLUSAPI_VERSION >= 0x0500
case CLUSPROP_FORMAT_DWORD: { _hr = VariantChangeTypeEx( &_var, &rvarValue, LOCALE_SYSTEM_DEFAULT, 0, VT_I4 ); break; } // case:
case CLUSPROP_FORMAT_SZ: case CLUSPROP_FORMAT_EXPAND_SZ: case CLUSPROP_FORMAT_MULTI_SZ: { _hr = VariantChangeTypeEx( &_var, &rvarValue, LOCALE_SYSTEM_DEFAULT, 0, VT_BSTR ); break; } // case:
case CLUSPROP_FORMAT_ULARGE_INTEGER: { _hr = VariantChangeTypeEx( &_var, &rvarValue, LOCALE_SYSTEM_DEFAULT, 0, VT_I8 ); break; } // case:
#if CLUSAPI_VERSION >= 0x0500
case CLUSPROP_FORMAT_EXPANDED_SZ: #endif // CLUSAPI_VERSION >= 0x0500
case CLUSPROP_FORMAT_UNKNOWN: default: { _hr = E_INVALIDARG; break; } // default:
} // switch:
return _hr;
} //*** CClusProperty::HrCoerceVariantType()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusProperty::HrBinaryCompare
//
// Description:
// Compare two SafeArrays and return whether or not they are equal.
//
// Arguments:
// rvarOldValue [IN] - Old value
// rvarValue [IN] - New value.
// pbEqual [OUT] - Catches the equality state.
//
// Return Value:
// S_OK if successful, or other HRESULT error.
//
//--
/////////////////////////////////////////////////////////////////////////////
HRESULT CClusProperty::HrBinaryCompare( IN const CComVariant rvarOldValue, IN const VARIANT & rvarValue, OUT BOOL * pbEqual ) { ASSERT( pbEqual != NULL );
HRESULT _hr = S_OK; PBYTE _pbOld = NULL; SAFEARRAY * _psaOld = NULL; BOOL _bEqual = FALSE; long _cbNew = 0; long _cbOld = 0; SAFEARRAY * _psaNew = NULL; PBYTE _pbNew = NULL;
_psaOld = rvarOldValue.parray;
_hr = HrSafeArraySizeof( _psaOld, 1, &_cbOld ); if ( SUCCEEDED( _hr ) ) { _psaNew = rvarValue.parray;
_hr = HrSafeArraySizeof( _psaNew, 1, &_cbNew ); if ( SUCCEEDED( _hr ) ) { if ( _cbNew == _cbOld ) { _hr = ::SafeArrayAccessData( _psaOld, (PVOID *) &_pbOld ); if ( SUCCEEDED( _hr ) ) { _hr = ::SafeArrayAccessData( _psaNew, (PVOID *) &_pbNew ); if ( SUCCEEDED( _hr ) ) { if ( _psaOld->cbElements == _psaNew->cbElements ) { _bEqual = ( ::memcmp( _pbOld, _pbNew, _cbOld ) == 0 ); } // if:
_hr = ::SafeArrayUnaccessData( _psaNew ); } // if:
_hr = ::SafeArrayUnaccessData( _psaOld ); } // if:
} // if:
} // if:
} // if:
if ( pbEqual != NULL ) { *pbEqual = _bEqual; } // if:
return _hr;
} //*** CClusProperty::HrBinaryCompare()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusProperty::HrConvertVariantTypeToClusterFormat
//
// Description:
// Given a variant, pick the best CLUSPROP_FORMAT_xxx.
//
// Arguments:
// rvar [IN] - variant to check.
// varType [IN] - variant type.
// pcpfFormat [OUT] - catches the cluster property format
//
// Return Value:
// S_OK if successful, or other HRESULT error.
//
//--
/////////////////////////////////////////////////////////////////////////////
HRESULT CClusProperty::HrConvertVariantTypeToClusterFormat( IN const VARIANT & rvar, IN VARTYPE varType, OUT CLUSTER_PROPERTY_FORMAT * pcpfFormat ) { HRESULT _hr = E_INVALIDARG;
do { if ( ( varType & VT_ARRAY ) && ( varType & VT_UI1 ) ) { *pcpfFormat = CLUSPROP_FORMAT_BINARY; _hr = S_OK; 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 ) ) { *pcpfFormat = CLUSPROP_FORMAT_DWORD; _hr = S_OK; break; } // if:
else if ( varType == VT_BSTR ) { *pcpfFormat = CLUSPROP_FORMAT_SZ; _hr = S_OK; break; } // else if:
else if ( ( varType == VT_I8 ) || ( varType == VT_R8 ) ) { *pcpfFormat = CLUSPROP_FORMAT_ULARGE_INTEGER; _hr = S_OK; break; } // else if:
else if ( varType == VT_VARIANT ) { _hr = HrConvertVariantTypeToClusterFormat( *rvar.pvarVal, rvar.pvarVal->vt, pcpfFormat ); break; } // else if:
else { break; } // else:
} while( TRUE ); // do-while: want to avoid using a goto ;-)
return _hr;
} //*** CClusProperty::HrConvertVariantTypeToClusterFormat()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusProperty::Create
//
// Description:
// Finish creating a ClusProperty object. This is where the real
// work is done -- not the ctor.
//
// Arguments:
// bstrName [IN] - The name of the property.
// varValue [IN] - The value of the property.
// bPrivate [IN] - Is it a private property?
// bReadOnly [IN] - Is it a read only property?
//
// Return Value:
// S_OK if successful, or other HRESULT error.
//
//--
/////////////////////////////////////////////////////////////////////////////
HRESULT CClusProperty::Create( IN BSTR bstrName, IN VARIANT varValue, IN BOOL bPrivate, IN BOOL bReadOnly ) { HRESULT _hr = S_OK; CLUSTER_PROPERTY_FORMAT _cpfFormat = CLUSPROP_FORMAT_UNKNOWN;
if ( bPrivate ) { m_dwFlags |= PRIVATE; } // if: set the private flag
else { m_dwFlags &= ~PRIVATE; } // else: clear the private flag
if ( bReadOnly ) { m_dwFlags |= READONLY; } // if: set the read only flag
else { m_dwFlags &= ~READONLY; } // else: clear the read only flag
m_bstrName = bstrName;
_hr = HrConvertVariantTypeToClusterFormat( varValue, varValue.vt, &_cpfFormat ); if ( SUCCEEDED( _hr ) ) { _hr = HrCreateValuesCollection( varValue, CLUSPROP_TYPE_LIST_VALUE, _cpfFormat ); } // if:
return _hr;
} //*** CClusProperty::Create()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusProperty::Create
//
// Description:
// Finish creating a ClusProperty object. This is where the real
// work is done -- not the ctor.
//
// Arguments:
// bstrName [IN] - The name of the property.
// rpvlValue [IN] - The value list of the property.
// bPrivate [IN] - Is it a private property?
// bReadOnly [IN] - Is it a read only property?
//
// Return Value:
// S_OK if successful, or other HRESULT error.
//
//--
/////////////////////////////////////////////////////////////////////////////
HRESULT CClusProperty::Create( IN BSTR bstrName, IN const CClusPropValueList & rpvlValue, IN BOOL bPrivate, IN BOOL bReadOnly ) { if ( bPrivate ) { m_dwFlags |= PRIVATE; } // if: set the private flag
else { m_dwFlags &= ~PRIVATE; } // else: clear the private flag
if ( bReadOnly ) { m_dwFlags |= READONLY; } // if: set the read only flag
else { m_dwFlags &= ~READONLY; } // else: clear the read only flag
m_bstrName = bstrName;
return HrCreateValuesCollection( rpvlValue );
} //*** CClusProperty::Create()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusProperty::HrCreateValuesCollection
//
// Description:
// Create the values collection from a value list.
//
// Arguments:
// rpvlValue [IN] - The value list.
//
// Return Value:
// S_OK if successful, or other HRESULT error if not.
//
//--
/////////////////////////////////////////////////////////////////////////////
HRESULT CClusProperty::HrCreateValuesCollection( IN const CClusPropValueList & rpvlValue ) { HRESULT _hr = S_FALSE;
_hr = CComObject< CClusPropertyValues >::CreateInstance( &m_pValues ); if ( SUCCEEDED( _hr ) ) { CSmartPtr< CComObject< CClusPropertyValues > > _ptrValues( m_pValues );
_hr = _ptrValues->Create( rpvlValue, ( m_dwFlags & READONLY ) ); if ( SUCCEEDED( _hr ) ) { _ptrValues->AddRef(); } // if:
}
return _hr;
} //*** CClusProperty::HrCreateValuesCollection()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusProperty::HrCreateValuesCollection
//
// Description:
// Create the values collection from a variant.
//
// Arguments:
// varValue [IN] - The value.
// cptType [IN] - The cluster property type.
// cpfFormat [IN] - The cluster property format.
//
// Return Value:
// S_OK if successful, or other HRESULT error if not.
//
//--
/////////////////////////////////////////////////////////////////////////////
HRESULT CClusProperty::HrCreateValuesCollection( IN VARIANT varValue, IN CLUSTER_PROPERTY_TYPE cptType, IN CLUSTER_PROPERTY_FORMAT cpfFormat ) { HRESULT _hr = S_FALSE;
_hr = CComObject< CClusPropertyValues >::CreateInstance( &m_pValues ); if ( SUCCEEDED( _hr ) ) { CSmartPtr< CComObject< CClusPropertyValues > > _ptrValues( m_pValues );
_hr = _ptrValues->Create( varValue, cptType, cpfFormat, ( m_dwFlags & READONLY ) ); if ( SUCCEEDED( _hr ) ) { _ptrValues->AddRef(); } // if:
}
return _hr;
} //*** CClusProperty::HrCreateValuesCollection()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusProperty::get_Name
//
// Description:
// Return the name of this property.
//
// Arguments:
// pbstrName [OUT] - Catches the name of this property.
//
// Return Value:
// S_OK if successful, E_POINTER, or other HRESULT error.
//
//--
/////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CClusProperty::get_Name( OUT BSTR * pbstrName ) { //ASSERT( pbstrName != NULL );
HRESULT _hr = E_POINTER;
if ( pbstrName != NULL ) { *pbstrName = m_bstrName.Copy(); _hr = S_OK; }
return _hr;
} //*** CClusProperty::get_Name()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusProperty::put_Name
//
// Description:
// Change the name of this property.
//
// Arguments:
// bstrName [IN] - The new property name.
//
// Return Value:
// S_OK if successful, or S_FALSE if the property is read only.
//
//--
/////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CClusProperty::put_Name( IN BSTR bstrName ) { HRESULT _hr = S_FALSE;
if ( ( m_dwFlags & READONLY ) == 0 ) { m_bstrName = bstrName; _hr = S_OK; }
return _hr;
} //*** CClusProperty::put_Name()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusProperty::get_Type
//
// Description:
// Return the cluster property type for the default value.
//
// Arguments:
// pcptType [OUT] - Catches the type.
//
// Return Value:
// S_OK if successful, E_POINTER, or other HRESULT error.
//
//--
/////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CClusProperty::get_Type( OUT CLUSTER_PROPERTY_TYPE * pcptType ) { //ASSERT( pcptType != NULL );
HRESULT _hr = E_POINTER;
if ( pcptType != NULL ) { _hr = (*m_pValues)[ 0 ]->get_Type( pcptType ); } // if: property type return value specified
return _hr;
} //*** CClusProperty::get_Type()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusProperty::put_Type
//
// Description:
// Change the cluster property type of the default value.
//
// Arguments:
// cptType [IN] - The new cluster property type.
//
// Return Value:
// S_OK if successful, or other HRESULT error.
//
//--
/////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CClusProperty::put_Type( IN CLUSTER_PROPERTY_TYPE cptType ) { return (*m_pValues)[ 0 ]->put_Type( cptType );
} //*** CClusProperty::put_Type()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusProperty::get_Format
//
// Description:
// Returns the cluster property format for the default value.
//
// Arguments:
// pcpfFormat [OUT] - Catches the format.
//
// Return Value:
// S_OK if successful, E_POINTER, or other HRESULT error.
//
//--
/////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CClusProperty::get_Format( OUT CLUSTER_PROPERTY_FORMAT * pcpfFormat ) { //ASSERT( pcpfFormat != NULL );
HRESULT _hr = E_POINTER;
if ( pcpfFormat != NULL ) { _hr = (*m_pValues)[ 0 ]->get_Format( pcpfFormat ); } // if: property format return value specified
return _hr;
} //*** CClusProperty::get_Format()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusProperty::put_Format
//
// Description:
// Change the cluster property format of the default value.
//
// Arguments:
// cpfFormat [IN] - The new cluster property format.
//
// Return Value:
// S_OK if successful, or other HRESULT error.
//
//--
/////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CClusProperty::put_Format( IN CLUSTER_PROPERTY_FORMAT cpfFormat ) { return (*m_pValues)[ 0 ]->put_Format( cpfFormat );
} //*** CClusProperty::put_Format()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusProperty::get_Length
//
// Description:
// Returns the length of the default value.
//
// Arguments:
// plLenght [OUT] - Catches the length.
//
// Return Value:
// S_OK if successful, or other HRESULT error.
//
//--
/////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CClusProperty::get_Length( OUT long * plLength ) { return (*m_pValues)[ 0 ]->get_Length( plLength );
} //*** CClusProperty::get_Length()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusProperty::get_ValueCount
//
// Description:
// Return the count of ClusPropertyValue object in the ClusPropertyValues
// collection.
//
// Arguments:
// plCount [OUT] - Catches the count.
//
// Return Value:
// S_OK if successful, or other HRESULT error.
//
//--
/////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CClusProperty::get_ValueCount( OUT long * plCount ) { return m_pValues->get_Count( plCount );
} //*** CClusProperty::get_ValueCount()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusProperty::get_Values
//
// Description:
// Returns the property values collection.
//
// Arguments:
// ppClusterPropertyValues [OUT] - Catches the values collection.
//
// Return Value:
// S_OK if successful, E_POINTER, or other HRESULT error.
//
//--
/////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CClusProperty::get_Values( ISClusPropertyValues ** ppClusterPropertyValues ) { //ASSERT( ppClusterPropertyValues );
HRESULT _hr = E_POINTER;
if ( ppClusterPropertyValues != NULL ) { _hr = m_pValues->QueryInterface( IID_ISClusPropertyValues, (void **) ppClusterPropertyValues ); }
return _hr;
} //*** CClusProperty::get_Values()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusProperty::Modified
//
// Description:
// Sets the modified state of the property.
//
// Arguments:
// bModified [IN] - The new modfied state.
//
// Return Value:
// The old state.
//
//--
/////////////////////////////////////////////////////////////////////////////
BOOL CClusProperty::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;
} //*** CClusProperty::Modified()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusProperty::get_Value
//
// Description:
// Get the value of the default value from the values collection.
//
// Arguments:
// pvarValue [OUT] - Catches the value.
//
// Return Value:
// S_OK if successful, or other HRESULT error.
//
//--
/////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CClusProperty::get_Value( OUT VARIANT * pvarValue ) { //ASSERT( pvarValue != NULL );
HRESULT _hr = E_POINTER;
if ( pvarValue != NULL ) { CComObject< CClusPropertyValue > * _pPropValue = (*m_pValues)[ 0 ]; CComVariant _varPropValue = _pPropValue->Value();
_hr = ::VariantCopyInd( pvarValue, &_varPropValue ); }
return _hr;
} //*** _CClusProperty::get_Value()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusProperty::put_Value
//
// Description:
// Change the value of the default value in the values collection.
//
// Arguments:
// varValue [IN] - The new value.
//
// Return Value:
// S_OK if successful, S_FALSE is read only, or other HRESULT error.
//
//--
/////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CClusProperty::put_Value( IN VARIANT varValue ) { HRESULT _hr = S_FALSE;
if ( ( m_dwFlags & READONLY ) == 0 ) { CComObject< CClusPropertyValue > * _pPropValue = (*m_pValues)[ 0 ]; CLUSTER_PROPERTY_FORMAT _cpfFormat = CLUSPROP_FORMAT_UNKNOWN; VARIANT _var;
::VariantInit( &_var );
//
// TODO: 17-JAN-2003 GalenB
//
// I am wondering if I should have simply deref'd the variant
// and called this function recursivley? My fix only works
// for one level of indirection... I didn't think of this
// at first and since time is short I don't want to reset
// the testing effort.
//
//
// The variant that we are handed could be a "pointer" to the real
// variant. If thats the case then we need to "deref" the pointer
// and use the real variant.
//
// The code below will always make a copy of the variant and use
// that copy for all operations. I chose to make a copy because
// I think that is more clear than using a flag and the ternary
// operator to control how we use varValue. Do we simply use it,
// or do we "deref" down into the another variant?
//
if ( varValue.vt == ( VT_BYREF | VT_VARIANT ) ) { _hr = ::VariantCopy( &_var, varValue.pvarVal ); } // if: the variant contains a ref to another variant so copy that variant
else { _hr = ::VariantCopy( &_var, &varValue ); } // else: we can copy the variant directly
if ( SUCCEEDED( _hr ) ) { _hr = _pPropValue->get_Format( &_cpfFormat ); if ( SUCCEEDED( _hr ) ) { CComVariant _varOldValue = _pPropValue->Value();
_hr = HrCoerceVariantType( _cpfFormat, _var ); if ( SUCCEEDED( _hr ) ) { if ( _cpfFormat == CLUSPROP_FORMAT_BINARY ) { BOOL bEqual = TRUE;
_hr = HrBinaryCompare( _varOldValue, _var, &bEqual ); if ( ( SUCCEEDED( _hr ) ) && ( ! bEqual ) ) { _hr = HrSaveBinaryProperty( _pPropValue, _var ); if ( SUCCEEDED( _hr ) ) { m_dwFlags |= MODIFIED; m_dwFlags &= ~USEDEFAULT; } // if: the binary value was saved
} // if: This is a new value
} // if: This is a binary property
else { if ( _varOldValue != _var ) { _pPropValue->Value( _var ); m_dwFlags |= MODIFIED; m_dwFlags &= ~USEDEFAULT; } // if: This is a new value
} // else: This is not a binary property
} // if: HrCoerceVariantType succeeded
} // if: get_Format succeeded
} // if: VariantCopy succeeded
} // if: this property is not read only
return _hr;
} //*** CClusProperty::put_Value()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusProperty::get_ReadOnly
//
// Description:
// Is this property read only?
//
// Arguments:
// pvarReadOnly [OUT] - catches the property's read only state.
//
// Return Value:
// S_OK if successful, or E_POINTER.
//
//--
/////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CClusProperty::get_ReadOnly( OUT VARIANT * pvarReadOnly ) { //ASSERT( pvarReadOnly != NULL );
HRESULT _hr = E_POINTER;
if ( pvarReadOnly != NULL ) { pvarReadOnly->vt = VT_BOOL;
if ( m_dwFlags & READONLY ) { pvarReadOnly->boolVal = VARIANT_TRUE; } // if: if this is a read only property...
else { pvarReadOnly->boolVal = VARIANT_FALSE; } // else: it is not a read only property...
_hr = S_OK; } // if:
return _hr;
} //*** CClusProperty::get_ReadOnly()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusProperty::get_Private
//
// Description:
// Is this a private property?
//
// Arguments:
// pvarPrivate [OUT] - catches the private property state.
//
// Return Value:
// S_OK if successful, or E_POINTER
//
//--
/////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CClusProperty::get_Private( OUT VARIANT * pvarPrivate ) { //ASSERT( pvarPrivate != NULL );
HRESULT _hr = E_POINTER;
if ( pvarPrivate != NULL ) { pvarPrivate->vt = VT_BOOL;
if ( m_dwFlags & PRIVATE ) { pvarPrivate->boolVal = VARIANT_TRUE; } // if: if this is private property...
else { pvarPrivate->boolVal = VARIANT_FALSE; } // else: it is not a private property...
_hr = S_OK; } // if:
return _hr;
} //*** CClusProperty::get_Private()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusProperty::get_Common
//
// Description:
// Is this a common property?
//
// Arguments:
// pvarCommon [OUT] - catches the common property state.
//
// Return Value:
// S_OK if successful, or E_POINTER
//
//--
/////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CClusProperty::get_Common( OUT VARIANT * pvarCommon ) { //ASSERT( pvarCommon != NULL );
HRESULT _hr = E_POINTER;
if ( pvarCommon != NULL ) { pvarCommon->vt = VT_BOOL;
if ( ( m_dwFlags & PRIVATE ) == 0 ) { pvarCommon->boolVal = VARIANT_TRUE; } // if: if this is not a private property then it must be a common one...
else { pvarCommon->boolVal = VARIANT_FALSE; } // else: it is a private property...
_hr = S_OK; } // if:
return _hr;
} //*** CClusProperty::get_Common()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusProperty::get_Modified
//
// Description:
// Has this property been modified?
//
// Arguments:
// pvarModified [OUT] - catches the modified state.
//
// Return Value:
// S_OK if successful, or E_POINTER
//
//--
/////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CClusProperty::get_Modified( OUT VARIANT * pvarModified ) { //ASSERT( pvarModified != NULL );
HRESULT _hr = E_POINTER;
if ( pvarModified != NULL ) { pvarModified->vt = VT_BOOL;
if ( m_dwFlags & MODIFIED ) { pvarModified->boolVal = VARIANT_TRUE; } // if: if it's been modified set the varint to true...
else { pvarModified->boolVal = VARIANT_FALSE; } // else: if not the set the variant to false...
_hr = S_OK; } // if:
return _hr;
} //*** CClusProperty::get_Modified()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusProperty::HrSaveBinaryProperty
//
// Description:
// Save the passed in SafeArray into our own SafeArray that is stored in
// in a variant.
//
// Arguments:
// pPropValue [IN] - PropertyValue that gets the copy.
// rvarValue [IN] - The safe array to copy.
//
// Return Value:
// S_OK if successful, or E_POINTER
//
//--
/////////////////////////////////////////////////////////////////////////////
HRESULT CClusProperty::HrSaveBinaryProperty( IN CComObject< CClusPropertyValue > * pPropValue, IN const VARIANT & rvarValue ) { ASSERT( pPropValue != NULL );
HRESULT _hr = E_POINTER;
if ( pPropValue != NULL ) { SAFEARRAY * _psa = NULL;
_hr = ::SafeArrayCopy( rvarValue.parray, &_psa ); if ( SUCCEEDED( _hr ) ) { _hr = pPropValue->HrBinaryValue( _psa ); } // if:
} // if:
return _hr;
} //*** CClusProperty::HrSaveBinaryProperty()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusProperty::UseDefaultValue
//
// Description:
// Mark this property to restore its default value. This effectivly
// deletes the property.
//
// Arguments:
// None.
//
// Return Value:
// S_OK.
//
//--
/////////////////////////////////////////////////////////////////////////////
HRESULT CClusProperty::UseDefaultValue( void ) { HRESULT _hr = S_OK;
//
// Mark this property as being modified and needing to be reset to
// its default value.
//
m_dwFlags |= USEDEFAULT; m_dwFlags |= MODIFIED;
//
// Now we need to empty the value
//
CComObject< CClusPropertyValue > * _pPropValue = (*m_pValues)[ 0 ]; CLUSTER_PROPERTY_FORMAT _cpfFormat = CLUSPROP_FORMAT_UNKNOWN;
_hr = _pPropValue->get_Format( &_cpfFormat ); if ( SUCCEEDED( _hr ) ) { VARIANT _var;
::VariantInit( &_var );
switch ( _cpfFormat ) { case CLUSPROP_FORMAT_BINARY: { SAFEARRAY * _psa = NULL; SAFEARRAYBOUND _sab[ 1 ];
_sab[ 0 ].lLbound = 0; _sab[ 0 ].cElements = 0;
//
// allocate a one dimensional SafeArray of BYTES
//
_psa = ::SafeArrayCreate( VT_UI1, 1, _sab ); if ( _psa != NULL ) { _hr = _pPropValue->HrBinaryValue( _psa ); } // if the safe array was allocated
else { _hr = E_OUTOFMEMORY; } // else: safe array was not allocated
break; } // case:
#if CLUSAPI_VERSION >= 0x0500
case CLUSPROP_FORMAT_LONG: #endif // CLUSAPI_VERSION >= 0x0500
case CLUSPROP_FORMAT_DWORD: case CLUSPROP_FORMAT_ULARGE_INTEGER: case CLUSPROP_FORMAT_SZ: case CLUSPROP_FORMAT_EXPAND_SZ: case CLUSPROP_FORMAT_MULTI_SZ: { _var.vt = VT_EMPTY; _pPropValue->Value( _var ); break; } // case:
#if CLUSAPI_VERSION >= 0x0500
case CLUSPROP_FORMAT_EXPANDED_SZ: #endif // CLUSAPI_VERSION >= 0x0500
case CLUSPROP_FORMAT_UNKNOWN: default: { _hr = E_INVALIDARG; break; } // default:
} // switch: on property format
} // if: we got the format
return _hr;
} //*** CClusProperty::UseDefaultValue()
//*************************************************************************//
/////////////////////////////////////////////////////////////////////////////
// CClusProperties class
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusProperties::CClusProperties
//
// Description:
// Constsructor
//
// Arguments:
// None.
//
// Return Value:
// None.
//
//--
/////////////////////////////////////////////////////////////////////////////
CClusProperties::CClusProperties( void ) { m_dwFlags = 0; m_pcoParent = NULL; m_piids = (const IID *) iidCClusProperties; m_piidsSize = ARRAYSIZE( iidCClusProperties );
} //*** CClusProperties::CClusProperties()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusProperties::~CClusProperties
//
// Description:
// Destructor
//
// Arguments:
// None.
//
// Return Value:
// None.
//
//--
/////////////////////////////////////////////////////////////////////////////
CClusProperties::~CClusProperties( void ) { Clear();
} //*** CClusProperties::~CClusProperties()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusProperties::Clear
//
// Description:
// Clean out the vector or ClusProperty objects.
//
// Arguments:
// None.
//
// Return Value:
// None.
//
//--
/////////////////////////////////////////////////////////////////////////////
void CClusProperties::Clear( void ) { ::ReleaseAndEmptyCollection< CClusPropertyVector, CComObject< CClusProperty > >( m_Properties );
} //*** CClusProperties::Clear()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusProperties::get_Count
//
// Description:
// Returns the count of elements (properties) in the collection.
//
// Arguments:
// plCount [OUT] - Catches the count.
//
// Return Value:
// S_OK if successful, or E_POINTER if not.
//
//--
/////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CClusProperties::get_Count( OUT long * plCount ) { //ASSERT( plCount != NULL );
HRESULT _hr = E_POINTER;
if ( plCount != NULL ) { *plCount = m_Properties.size(); _hr = S_OK; }
return _hr;
} //*** CClusProperties::get_Count()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusProperties::FindItem
//
// Description:
// Find the property that has the passed in name.
//
// Arguments:
// pszPropName [IN] - The name of the property to find.
// pnIndex [OUT] - The index of the property.
//
// Return Value:
// S_OK if successful, E_INVALIDARG, or other HRESULT error.
//
//--
/////////////////////////////////////////////////////////////////////////////
HRESULT CClusProperties::FindItem( IN LPWSTR pszPropName, OUT UINT * pnIndex ) { //ASSERT( pszPropName != NULL );
//ASSERT( pnIndex != NULL );
HRESULT _hr = E_POINTER;
if ( ( pszPropName != NULL ) && ( pnIndex != NULL ) ) { CComObject< CClusProperty > * _pProperty = NULL; CClusPropertyVector::const_iterator _first = m_Properties.begin(); CClusPropertyVector::const_iterator _last = m_Properties.end(); UINT _nIndex = 0;
_hr = E_INVALIDARG;
for ( ; _first != _last; _first++, _nIndex++ ) { _pProperty = *_first;
if ( _pProperty && ( lstrcmpi( pszPropName, _pProperty->Name() ) == 0 ) ) { *pnIndex = _nIndex; _hr = S_OK; break; } } }
return _hr;
} //*** CClusProperties::FindItem()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusProperties::FindItem
//
// Description:
// Find the passed in property in the collection.
//
// Arguments:
// pProperty [IN] - The property to find.
// pnIndex [OUT] - The index of the property.
//
// Return Value:
// S_OK if successful, or other HRESULT error.
//
//--
/////////////////////////////////////////////////////////////////////////////
HRESULT CClusProperties::FindItem( IN ISClusProperty * pProperty, OUT UINT * pnIndex ) { //ASSERT( pProperty != NULL );
//ASSERT( pnIndex != NULL );
HRESULT _hr = E_POINTER;
if ( ( pProperty != NULL ) && ( pnIndex != NULL ) ) { CComBSTR _bstrName;
_hr = pProperty->get_Name( &_bstrName ); if ( SUCCEEDED( _hr ) ) { _hr = FindItem( _bstrName, pnIndex ); } }
return _hr;
} //*** CClusProperties::FindItem()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusProperties::GetIndex
//
// Description:
// Get the index from the passed in variant.
//
// Arguments:
// varIndex [IN] - Hold the index. This is a one based number,
// or the name of the property as a string.
// 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 CClusProperties::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
} else { // Check to see if the index is a string.
_hr = _v.ChangeType( VT_BSTR ); if ( SUCCEEDED( _hr ) ) { // Search for the string.
_hr = FindItem( _v.bstrVal, &_nIndex ); } }
// We found an index, now check the range.
if ( SUCCEEDED( _hr ) ) { if ( _nIndex < m_Properties.size() ) { *pnIndex = _nIndex; } else { _hr = E_INVALIDARG; } } }
return _hr;
} //*** CClusProperties::GetIndex()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusProperties::get_Item
//
// Description:
// Returns the object (property) at the passed in index.
//
// Arguments:
// varIndex [IN] - Hold the index. This is a one based number.
// ppProperty [OUT] - Catches the property.
//
// Return Value:
// S_OK if successful, E_POINTER, or E_INVALIDARG if the index is out
// of range, or other HRESULT error.
//
//--
/////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CClusProperties::get_Item( IN VARIANT varIndex, OUT ISClusProperty ** ppProperty ) { //ASSERT( ppProperty != NULL );
HRESULT _hr = E_POINTER;
if ( ppProperty != NULL ) { CComObject< CClusProperty > * _pProperty = NULL; UINT _nIndex = 0;
//
// Zero the out param
//
*ppProperty = 0;
_hr = GetIndex( varIndex, &_nIndex ); if ( SUCCEEDED( _hr ) ) { _pProperty = m_Properties[ _nIndex ]; _hr = _pProperty->QueryInterface( IID_ISClusProperty, (void **) ppProperty ); } }
return _hr;
} //*** CClusProperties::get_Item()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusProperties::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 CClusProperties::get__NewEnum( OUT IUnknown ** ppunk ) { return ::HrNewIDispatchEnum< CClusPropertyVector, CComObject< CClusProperty > >( ppunk, m_Properties );
} //*** CClusProperties::get__NewEnum()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusProperties::CreateItem
//
// Description:
// Create a new property and add it to the collection.
//
// Arguments:
// bstrName [IN] - property name.
// varValue [IN] - the value to add.
// ppProperty [OUT] - catches the newly created object.
//
// Return Value:
// S_OK if successful, or other HRESULT error.
//
//--
/////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CClusProperties::CreateItem( IN BSTR bstrName, IN VARIANT varValue, OUT ISClusProperty ** ppProperty ) { //ASSERT( ppProperty != NULL );
HRESULT _hr = E_POINTER;
if ( ppProperty != NULL ) { //
// You can only add to not read only and private property lists. Meaning
// only the PrivateProperties collection can have new, unknown properties
// added to it. This should be reflected in the idl, but since there is
// only one properties collection...
//
if ( ( ( m_dwFlags & READONLY ) == 0 ) && ( m_dwFlags & PRIVATE ) ) { UINT _nIndex = 0; CComObject< CClusProperty > * _pProperty = NULL;
_hr = FindItem( bstrName, &_nIndex ); if ( SUCCEEDED( _hr ) ) { _pProperty = m_Properties[ _nIndex ]; _hr = _pProperty->put_Value( varValue ); if ( SUCCEEDED( _hr ) ) { _hr = _pProperty->QueryInterface( IID_ISClusProperty, (void **) ppProperty ); } // if: the value was changed
} // if: the item is in the list, change it...
else { //
// Create a new property and add it to the list.
//
_hr = CComObject< CClusProperty >::CreateInstance( &_pProperty ); if ( SUCCEEDED( _hr ) ) { CSmartPtr< CComObject< CClusProperty > > _ptrProperty( _pProperty );
_hr = _ptrProperty->Create( bstrName, varValue, ( m_dwFlags & PRIVATE ), ( m_dwFlags & READONLY ) ); if ( SUCCEEDED( _hr ) ) { _hr = _ptrProperty->QueryInterface( IID_ISClusProperty, (void **) ppProperty ); if ( SUCCEEDED( _hr ) ) { _ptrProperty->AddRef(); m_Properties.insert( m_Properties.end(), _pProperty ); m_dwFlags |= MODIFIED; _ptrProperty->Modified( TRUE ); } } } } // else: new item
} else { _hr = S_FALSE; } // else: this is not the PrivateProperties collection!
}
return _hr;
} //*** CClusProperties::CreateItem()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusProperties::UseDefaultValue
//
// Description:
// Remove the item from the collection at the passed in index.
//
// Arguments:
// varIdex [IN] - contains the index to remove.
//
// Return Value:
// S_OK if successful, E_INVALIDARG, or other HRESULT error.
//
//--
/////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CClusProperties::UseDefaultValue( IN VARIANT varIndex ) { HRESULT _hr = S_FALSE;
if ( ( m_dwFlags & READONLY ) == 0 ) { UINT _nIndex = 0;
_hr = GetIndex( varIndex, &_nIndex ); if ( SUCCEEDED( _hr ) ) { CComObject< CClusProperty > * _pProp = NULL;
_hr = E_POINTER;
_pProp = m_Properties [_nIndex]; if ( _pProp != NULL ) { _hr = _pProp->UseDefaultValue(); } // if: we have a property
} // if: we got the index from the variant
} // if: the collection is not read only
return _hr;
} //*** CClusProperties::UseDefaultValue()
/*
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusProperties::RemoveAt
//
// Description:
// Remove the object (property) at the passed in index/position from the
// collection.
//
// Arguments:
// nPos [IN] - Index of the object to remove.
//
// Return Value:
// S_OK if successful, or other HRESULT error.
//
//--
/////////////////////////////////////////////////////////////////////////////
HRESULT CClusProperties::RemoveAt( IN size_t nPos ) { CComObject< CClusProperty > * _pProperty = NULL; CClusPropertyVector::iterator _first = m_Properties.begin(); CClusPropertyVector::const_iterator _last = m_Properties.end(); HRESULT _hr = E_INVALIDARG; size_t _nIndex;
for ( _nIndex = 0; ( _nIndex < nPos ) && ( _first != _last ); _nIndex++, _first++ ) { }
if ( _first != _last ) { _pProperty = *_first; if ( _pProperty ) { _pProperty->Release(); }
m_Properties.erase( _first ); _hr = S_OK; }
return _hr;
} //*** CClusProperties::RemoveAt()
*/ /////////////////////////////////////////////////////////////////////////////
//++
//
// CClusProperties::SaveChanges
//
// Description:
// Save the changes to the properties to the cluster database.
//
// Arguments:
// pvarStatusCode [OUT] - Catches an additional status code.
// e.g. ERROR_RESOURCE_PROPERTIES_STORED.
//
// Return Value:
// S_OK if successful, or other Win32 error as HRESULT if not.
//
//--
/////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CClusProperties::SaveChanges( OUT VARIANT * pvarStatusCode ) { ASSERT( m_pcoParent != NULL );
HRESULT _hr = E_POINTER;
if ( m_pcoParent != NULL ) { if ( ( m_dwFlags & READONLY ) == 0 ) { VARIANT _vsc;
_hr = m_pcoParent->HrSaveProperties( m_Properties, ( m_dwFlags & PRIVATE ), &_vsc ); if ( SUCCEEDED( _hr ) ) { if ( pvarStatusCode != NULL ) { _hr = ::VariantCopy( pvarStatusCode, &_vsc ); if ( FAILED( _hr ) ) { goto Cleanup; } } // if: optional arg is not NULL
_hr = Refresh(); } // if: properties were saved
} // if: this collection is not read only
else { _hr = S_FALSE; } // else: this collection is read only
} // if: args and members vars are not NULL
Cleanup:
return _hr;
} //*** CClusProperties::SaveChanges()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusProperties::Refresh
//
// Description:
// Load the properties collection from the cluster database.
//
// Arguments:
// None.
//
// Return Value:
// S_OK if successful, or Win32 error as HRESULT if not.
//
//--
/////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CClusProperties::Refresh( void ) { ASSERT( m_pcoParent != NULL );
HRESULT _hr = E_POINTER;
if ( m_pcoParent != NULL ) { CClusPropList _cplPropList;
_hr = m_pcoParent->HrLoadProperties( _cplPropList, ( m_dwFlags & READONLY ), ( m_dwFlags & PRIVATE ) ); if ( SUCCEEDED( _hr ) ) { Clear(); m_dwFlags &= ~MODIFIED;
if ( _cplPropList.Cprops() > 0 ) { _hr = HrFillPropertyVector( _cplPropList ); } // if: are there any properties in the list?
} // if: loaded properties successfully
} // if: no parent
return _hr;
} //*** CClusProperties::Refresh()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusProperties::Create
//
// Description:
// Do the heavy weight construction.
//
// Arguments:
// pcoParent [IN] - Back pointer to the parent cluster object.
// bPrivate [IN] - Are these private properties?
// bReadOnly [IN] - Are these read only properties?
//
// Return Value:
// S_OK if successful, or E_POINTER.
//
//--
/////////////////////////////////////////////////////////////////////////////
HRESULT CClusProperties::Create( IN CClusterObject * pcoParent, IN BOOL bPrivate, IN BOOL bReadOnly ) { //ASSERT( pcoParent != NULL );
HRESULT _hr = E_POINTER;
if ( pcoParent != NULL ) { m_pcoParent = pcoParent;
if ( bPrivate ) { m_dwFlags |= PRIVATE; } // if: set the private flag
else { m_dwFlags &= ~PRIVATE; } // else: clear the private flag
if ( bReadOnly ) { m_dwFlags |= READONLY; } // if: set the read only flag
else { m_dwFlags &= ~READONLY; } // else: clear the read only flag
_hr = S_OK; } // if: parent specified
return _hr;
} //*** CClusProperties::Create()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusProperties::HrFillPropertyVector
//
// Description:
// Parse the passed in property list into a collection of properties.
//
// Arguments:
// rcplPropList [IN] - The property list to parse.
//
// Return Value:
// S_OK if successful, or other HRESULT error.
//
//--
/////////////////////////////////////////////////////////////////////////////
HRESULT CClusProperties::HrFillPropertyVector( IN CClusPropList & rcplPropList ) { HRESULT _hr = S_OK; DWORD _sc; CComObject< CClusProperty > * _pProp = NULL;
_sc = rcplPropList.ScMoveToFirstProperty(); if ( _sc == ERROR_SUCCESS ) { do { _hr = CComObject< CClusProperty >::CreateInstance( &_pProp ); if ( SUCCEEDED( _hr ) ) { CSmartPtr< CComObject < CClusProperty > > _ptrProp( _pProp );
_hr = _ptrProp->Create( const_cast< BSTR >( rcplPropList.PszCurrentPropertyName() ), rcplPropList.RPvlPropertyValue(), ( m_dwFlags & PRIVATE ), ( m_dwFlags & READONLY ) ); if ( SUCCEEDED( _hr ) ) { _ptrProp->AddRef(); m_Properties.insert( m_Properties.end(), _ptrProp ); } // if: create property ok
else { break; } // else: error creating the property
} // if: create property instance ok
//
// Move to the next property in the list.
//
_sc = rcplPropList.ScMoveToNextProperty();
} while ( _sc == ERROR_SUCCESS ); // do-while: there are properties in the list
} // if: moved to the first property successfully
if ( _sc != ERROR_NO_MORE_ITEMS ) { _hr = HRESULT_FROM_WIN32( _sc ); } // if: error moving to property
return _hr;
} //*** CClusProperties::HrFillPropertyVector()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusProperties::get_ReadOnly
//
// Description:
// Is this property collection read only?
//
// Arguments:
// pvarReadOnly [OUT] - catches the property's read only state.
//
// Return Value:
// S_OK if successful, or E_POINTER.
//
//--
/////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CClusProperties::get_ReadOnly( OUT VARIANT * pvarReadOnly ) { //ASSERT( pvarReadOnly != NULL );
HRESULT _hr = E_POINTER;
if ( pvarReadOnly != NULL ) { pvarReadOnly->vt = VT_BOOL;
if ( m_dwFlags & READONLY ) { pvarReadOnly->boolVal = VARIANT_TRUE; } // if: if this is a read only property...
else { pvarReadOnly->boolVal = VARIANT_FALSE; } // else: it is not a read only property...
_hr = S_OK; } // if:
return _hr;
} //*** CClusProperties::get_ReadOnly()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusProperties::get_Private
//
// Description:
// Is this a private property collection?
//
// Arguments:
// pvarPrivate [OUT] - catches the private property state.
//
// Return Value:
// S_OK if successful, or E_POINTER
//
//--
/////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CClusProperties::get_Private( OUT VARIANT * pvarPrivate ) { //ASSERT( pvarPrivate != NULL );
HRESULT _hr = E_POINTER;
if ( pvarPrivate != NULL ) { pvarPrivate->vt = VT_BOOL;
if ( m_dwFlags & PRIVATE ) { pvarPrivate->boolVal = VARIANT_TRUE; } // if: if this is private property...
else { pvarPrivate->boolVal = VARIANT_FALSE; } // else: it is not a private property...
_hr = S_OK; } // if:
return _hr;
} //*** CClusProperties::get_Private()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusProperties::get_Common
//
// Description:
// Is this a common property collection?
//
// Arguments:
// pvarCommon [OUT] - catches the common property state.
//
// Return Value:
// S_OK if successful, or E_POINTER
//
//--
/////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CClusProperties::get_Common( OUT VARIANT * pvarCommon ) { //ASSERT( pvarCommon != NULL );
HRESULT _hr = E_POINTER;
if ( pvarCommon != NULL ) { pvarCommon->vt = VT_BOOL;
if ( ( m_dwFlags & PRIVATE ) == 0 ) { pvarCommon->boolVal = VARIANT_TRUE; } // if: if this is not a private property then it must be a common one...
else { pvarCommon->boolVal = VARIANT_FALSE; } // else: it is a private property...
_hr = S_OK; } // if:
return _hr;
} //*** CClusProperties::get_Common()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusProperties::get_Modified
//
// Description:
// Has this property collection been modified?
//
// Arguments:
// pvarModified [OUT] - catches the modified state.
//
// Return Value:
// S_OK if successful, or E_POINTER
//
//--
/////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CClusProperties::get_Modified( OUT VARIANT * pvarModified ) { //ASSERT( pvarModified != NULL );
HRESULT _hr = E_POINTER;
if ( pvarModified != NULL ) { pvarModified->vt = VT_BOOL;
if ( m_dwFlags & MODIFIED ) { pvarModified->boolVal = VARIANT_TRUE; _hr = S_OK; } // if: has an add or a remove been done?
else { CComObject< CClusProperty > * _pProperty = NULL; CClusPropertyVector::iterator _itCurrent = m_Properties.begin(); CClusPropertyVector::const_iterator _itLast = m_Properties.end();
pvarModified->boolVal = VARIANT_FALSE; // init to false
_hr = S_OK;
for ( ; _itCurrent != _itLast ; _itCurrent++ ) { _pProperty = *_itCurrent; if ( _pProperty ) { if ( _pProperty->Modified() ) { pvarModified->boolVal = VARIANT_TRUE; break; } // if: has this property been modified?
} } // for: each property in the collection
} // else: not adds or remove, check each property's modified state.
} // if: is the pointer arg any good?
return _hr;
} //*** CClusProperties::get_Modified()
/////////////////////////////////////////////////////////////////////////////
//++
//
// HrSafeArraySizeof
//
// Description:
// Little helper function to get the sizeof() a safe array.
//
// Arguments:
// psa
// The safe array to get the sizeof.
//
// nDimension
// The dimension of the safe array to get the sizeof.
//
// pcElements
// The count of elements in the safe array.
//
// Return Value:
// S_OK if successful, or E_POINTER
//
//--
/////////////////////////////////////////////////////////////////////////////
HRESULT HrSafeArraySizeof( SAFEARRAY * psa , unsigned int nDimension , long * pcElements ) { ASSERT( psa != NULL ); ASSERT( pcElements != NULL );
HRESULT _hr = S_OK; long _lUBound; long _lLBound;
_hr = SafeArrayGetUBound( psa, nDimension, &_lUBound ); if ( SUCCEEDED( _hr ) ) { _hr = SafeArrayGetLBound( psa, nDimension, &_lLBound ); if ( SUCCEEDED( _hr ) ) { *pcElements = ( _lUBound - _lLBound ) + 1; // convert from upper and lower bounds to sizeof()
} // if:
} // if:
return _hr;
} //*** HrSafeArraySizeof()
|