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.
329 lines
7.6 KiB
329 lines
7.6 KiB
///////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Copyright (c) 1997, Microsoft Corp. All rights reserved.
|
|
//
|
|
// FILE
|
|
//
|
|
// VarVec.h
|
|
//
|
|
// SYNOPSIS
|
|
//
|
|
// This file describes the class CVariantVector
|
|
//
|
|
// MODIFICATION HISTORY
|
|
//
|
|
// 08/05/1997 Original version.
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
#ifndef _VARVEC_H_
|
|
#define _VARVEC_H_
|
|
|
|
#include "nocopy.h"
|
|
|
|
#pragma warning( disable : 4290 )
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// CLASS
|
|
//
|
|
// CVariantVector
|
|
//
|
|
// DESCRIPTION
|
|
//
|
|
// This class provides a wrapper around a one-dimensional SAFEARRAY stored
|
|
// in a VARIANT.
|
|
//
|
|
// CAVEATS
|
|
//
|
|
// This class does not assume ownership of the VARIANT struct. In other
|
|
// words, you are responsible for calling VariantClear() to free any
|
|
// allocated memory.
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
template <class T>
|
|
class CVariantVector : NonCopyable
|
|
{
|
|
public:
|
|
|
|
// Manipulates an existing array.
|
|
explicit CVariantVector(VARIANT* pv) throw (_com_error);
|
|
|
|
// Creates a new array cElements in length.
|
|
CVariantVector(
|
|
VARIANT* pv,
|
|
unsigned int cElements
|
|
) throw (_com_error);
|
|
|
|
// Create or manipulate a safe array of any automation compatible type
|
|
CVariantVector(
|
|
VARIANT* pv,
|
|
VARTYPE vt,
|
|
unsigned int cElements
|
|
) throw (_com_error);
|
|
|
|
~CVariantVector() throw()
|
|
{
|
|
SafeArrayUnaccessData(m_psa);
|
|
}
|
|
|
|
T* data() throw()
|
|
{
|
|
return m_pData;
|
|
}
|
|
|
|
long size() const throw()
|
|
{
|
|
return m_lSize;
|
|
}
|
|
|
|
T& operator[](size_t index) throw()
|
|
{
|
|
return m_pData[index];
|
|
}
|
|
|
|
protected:
|
|
|
|
SAFEARRAY* m_psa; // The SAFEARRAY being manipulated.
|
|
long m_lSize; // The number of elements in the array.
|
|
T* m_pData; // The raw array inside the SAFEARRAY.
|
|
};
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// These inline functions convert a C++ type to a VARTYPE.
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
inline VARTYPE GetVARTYPE(BYTE*)
|
|
{
|
|
return VT_UI1;
|
|
}
|
|
|
|
inline VARTYPE GetVARTYPE(short*)
|
|
{
|
|
return VT_I2;
|
|
}
|
|
|
|
inline VARTYPE GetVARTYPE(long*)
|
|
{
|
|
return VT_I4;
|
|
}
|
|
|
|
inline VARTYPE GetVARTYPE(float*)
|
|
{
|
|
return VT_R4;
|
|
}
|
|
|
|
inline VARTYPE GetVARTYPE(double*)
|
|
{
|
|
return VT_R8;
|
|
}
|
|
|
|
inline VARTYPE GetVARTYPE(CY*)
|
|
{
|
|
return VT_CY;
|
|
}
|
|
|
|
inline VARTYPE GetVARTYPE(BSTR*)
|
|
{
|
|
return VT_BSTR;
|
|
}
|
|
|
|
inline VARTYPE GetVARTYPE(IDispatch**)
|
|
{
|
|
return VT_DISPATCH;
|
|
}
|
|
|
|
inline VARTYPE GetVARTYPE(IUnknown**)
|
|
{
|
|
return VT_UNKNOWN;
|
|
}
|
|
|
|
inline VARTYPE GetVARTYPE(VARIANT*)
|
|
{
|
|
return VT_VARIANT;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// METHOD
|
|
//
|
|
// CVariantVector::CVariantVector
|
|
//
|
|
// DESCRIPTION
|
|
//
|
|
// Creates a CVariantVector that accesses an existing SAFEARRAY (which
|
|
// is contained in the passed in VARIANT).
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
template <class T>
|
|
CVariantVector<T>::CVariantVector(VARIANT* pv) throw (_com_error)
|
|
: m_psa(V_ARRAY(pv))
|
|
{
|
|
using _com_util::CheckError;
|
|
|
|
// Make sure the variant contains a one-dimensional array of the right type.
|
|
if (V_VT(pv) != (VT_ARRAY | GetVARTYPE((T*)NULL)) ||
|
|
SafeArrayGetDim(m_psa) != 1)
|
|
{
|
|
throw _com_error(DISP_E_TYPEMISMATCH);
|
|
}
|
|
|
|
// Get the upper and lower bound.
|
|
long lLBound, lUBound;
|
|
CheckError(SafeArrayGetLBound(m_psa, 1, &lLBound));
|
|
CheckError(SafeArrayGetUBound(m_psa, 1, &lUBound));
|
|
|
|
// Compute the size.
|
|
m_lSize = lUBound - lLBound + 1;
|
|
if (m_lSize < 0)
|
|
{
|
|
throw _com_error(DISP_E_BADINDEX);
|
|
}
|
|
|
|
// Lock the array data.
|
|
CheckError(SafeArrayAccessData(m_psa, (void**)&m_pData));
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// METHOD
|
|
//
|
|
// CVariantVector::CVariantVector
|
|
//
|
|
// DESCRIPTION
|
|
//
|
|
// Initializes both the passed in VARIANT and the CVariantVector to
|
|
// manipulate a new array, cElements in length.
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
template <class T>
|
|
CVariantVector<T>::CVariantVector(
|
|
VARIANT* pv,
|
|
unsigned int cElements
|
|
) throw (_com_error)
|
|
: m_lSize(cElements)
|
|
{
|
|
// Initalize the variant.
|
|
VariantInit(pv);
|
|
|
|
// Create the SAFEARRAY.
|
|
V_ARRAY(pv) = SafeArrayCreateVector(GetVARTYPE((T*)NULL), 0, cElements);
|
|
|
|
if ((m_psa = V_ARRAY(pv)) == NULL)
|
|
{
|
|
throw _com_error(E_OUTOFMEMORY);
|
|
}
|
|
|
|
// Set the type.
|
|
V_VT(pv) = VT_ARRAY | GetVARTYPE((T*)NULL);
|
|
|
|
// Lock the array data.
|
|
HRESULT hr = SafeArrayAccessData(m_psa, (void**)&m_pData);
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
// Free the memory we allocated.
|
|
VariantClear(pv);
|
|
|
|
throw _com_error(hr);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// METHOD
|
|
//
|
|
// CVariantVector::CVariantVector
|
|
//
|
|
// DESCRIPTION
|
|
//
|
|
// Create a new safe array or manipulate an existing safearray of any
|
|
// automation compatible type
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
template <class T>
|
|
CVariantVector<T>::CVariantVector(
|
|
VARIANT* pv,
|
|
VARTYPE vt,
|
|
unsigned int cElements
|
|
) throw (_com_error)
|
|
{
|
|
if ( 0 == cElements )
|
|
{
|
|
// Manipulate an existing array
|
|
|
|
m_psa = V_ARRAY(pv);
|
|
|
|
// Make sure the variant contains a one-dimensional array of the right type.
|
|
if ( V_VT(pv) != (VT_ARRAY | vt) || SafeArrayGetDim(m_psa) != 1)
|
|
{
|
|
throw _com_error(DISP_E_TYPEMISMATCH);
|
|
}
|
|
|
|
// Get the upper and lower bound.
|
|
long lLBound, lUBound;
|
|
HRESULT hr = SafeArrayGetLBound(m_psa, 1, &lLBound);
|
|
if ( FAILED(hr) )
|
|
{
|
|
throw _com_error(hr);
|
|
}
|
|
hr = SafeArrayGetUBound(m_psa, 1, &lUBound);
|
|
if ( FAILED(hr) )
|
|
{
|
|
throw _com_error(hr);
|
|
}
|
|
|
|
// Compute the size.
|
|
m_lSize = lUBound - lLBound + 1;
|
|
if (m_lSize < 0)
|
|
{
|
|
throw _com_error(DISP_E_BADINDEX);
|
|
}
|
|
|
|
// Lock the array data.
|
|
hr = SafeArrayAccessData(m_psa, (void**)&m_pData);
|
|
if ( FAILED(hr) )
|
|
{
|
|
throw _com_error(hr);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Create a new array
|
|
|
|
m_lSize = cElements;
|
|
|
|
// Initalize the variant.
|
|
VariantInit(pv);
|
|
|
|
// Create the SAFEARRAY.
|
|
_ASSERT( vt < VT_ARRAY );
|
|
V_ARRAY(pv) = SafeArrayCreateVector(vt, 0, cElements);
|
|
|
|
if ( NULL == (m_psa = V_ARRAY(pv)) )
|
|
{
|
|
throw _com_error(E_OUTOFMEMORY);
|
|
}
|
|
|
|
// Set the type.
|
|
V_VT(pv) = VT_ARRAY | vt;
|
|
|
|
// Lock the array data.
|
|
HRESULT hr = SafeArrayAccessData(m_psa, (void**)&m_pData);
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
// Free the memory we allocated.
|
|
VariantClear(pv);
|
|
throw _com_error(hr);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
#endif // _VARVEC_H_
|