windows-nt/Source/XPSP1/NT/base/cluster/admin/msclus/propertyvalue.cpp
2020-09-26 16:20:57 +08:00

1850 lines
42 KiB
C++

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