Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

2224 lines
60 KiB

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