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