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

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_