/**************************************************************************************** * NAME: SafeArray.h * * CLASS: CSafeArray * * OVERVIEW * * Internet Authentication Server: Utility class for SafeArray * * Copyright (c) 1998, Microsoft Corporation. All Rights Reserved. * * History: * 3/1/98 Created byao * This file is created according to the online web document: * "Ole Development: Article 5: The Safe OLE Way of Handling Arrays" * by Bruce McKinney, http://tahiti/oledev/olecome/article5.htm" * * 5/14/98 Modified byao * CSafeArray used 0x80 as a contructed flag in fFeature. * This flag is now used in the official Win32API header file * We get rid of this flag, and added another private member for * the same purpose * * *****************************************************************************************/ #ifndef _SAFEARRAY_H_ #define _SAFEARRAY_H_ // Dim class encapsulates an array dimension //@B Dim class Dim : public SAFEARRAYBOUND { public: Dim(const long iLo, const long iHi) { cElements = abs(iHi - iLo) + 1; lLbound = iLo; } Dim(const long c) { cElements = c; lLbound = 0; } const Dim & operator=(const Dim & dim) { cElements = dim.cElements; lLbound = dim.lLbound; return *this; } const Dim & operator=(const long c) { cElements = c; lLbound = 0; return *this; } ~Dim() {} long Elements() { return cElements; } long LBound() { return lLbound; } long UBound() { return lLbound + cElements - 1; } }; //@E Dim // CSafeArray container class for OLE types //@B CSafeArray1 template class CSafeArray { public: // Constructors CSafeArray(); CSafeArray(SAFEARRAY * psaSrc); CSafeArray(Dim & dim); // Copy constructor CSafeArray(const CSafeArray & saSrc); // Destructor ~CSafeArray(); // Operator equal const CSafeArray & operator=(const CSafeArray & saSrc); // Indexing T & Get(long i); T & Set(T & t, long i); T & operator[](const long i); // C++ style (0-indexed) T & operator()(const long i); // Basic style (LBound-indexed) //@E CSafeArray1 // Type casts operator SAFEARRAY(); operator SAFEARRAY() const; // operator Variant(); // operator Variant() const; // Operations BOOL ReDim(Dim & dim); long LBound(); long UBound(); long Elements(); long Dimensions(); BOOL IsSizable(); void Lock(); void Unlock(); //@B CSafeArray2 private: SAFEARRAY * psa; BOOL m_fConstructed; // is this safe array constructed? void Destroy(); }; //@E CSafeArray2 // Private helpers template inline void CSafeArray::Destroy() { m_fConstructed = FALSE; HRESULT hres = SafeArrayDestroy(psa); if (hres) { throw hres; } } // Constructors template inline CSafeArray::CSafeArray() { Dim dim(0); psa = SafeArrayCreate(vt, 1, &dim); if (psa == NULL) { throw E_OUTOFMEMORY; } m_fConstructed = TRUE; } template inline CSafeArray::CSafeArray(SAFEARRAY * psaSrc) { if (SafeArrayGetDim(psaSrc) != 1) throw E_INVALIDARG; HRESULT hres = SafeArrayCopy(psaSrc, &psa); if (hres) { throw hres; } m_fConstructed = TRUE; } template inline CSafeArray::CSafeArray(const CSafeArray & saSrc) { HRESULT hres = SafeArrayCopy(saSrc.psa, &psa); if (hres) { throw hres; } m_fConstructed = TRUE; } template inline CSafeArray::CSafeArray(Dim & dim) { psa = SafeArrayCreate(vt, 1, &dim); if (psa == NULL) { throw E_OUTOFMEMORY; } m_fConstructed = TRUE; } // Destructor template inline CSafeArray::~CSafeArray() { if (m_fConstructed) { Destroy(); } } // Operator = template const CSafeArray & CSafeArray::operator=(const CSafeArray & saSrc) { if (psa) { SafeArrayDestroy(psa); } HRESULT hres = SafeArrayCopy(saSrc.psa, &psa); if (hres) { throw hres; } m_fConstructed = TRUE; return *this; } // Type casts template inline CSafeArray::operator SAFEARRAY() { return *psa; } template CSafeArray::operator SAFEARRAY() const { static SAFEARRAY * psaT; SafeArrayCopy(psa, &psaT); return *psaT; } /* template CSafeArray::operator Variant() { return Variant(psa); } template CSafeArray::operator Variant() const { static Variant v(psa); return v; } */ // Indexing template T & CSafeArray::Get(long i) { static T tRes; HRESULT hres = SafeArrayGetElement(psa, &i, &tRes); if (hres) throw hres; return tRes; } //@B Indexing template inline T & CSafeArray::Set(T & t, long i) { HRESULT hres = SafeArrayPutElement(psa, &i, (T *)&t); if (hres) throw hres; return t; } template inline T & CSafeArray::operator[](const long i) { if (i < 0 || i > Elements() - 1) throw DISP_E_BADINDEX; return ((T*)psa->pvData)[i]; } template T & CSafeArray::operator()(const long i) { if (i < LBound() || i > UBound()) throw DISP_E_BADINDEX; return ((T*)psa->pvData)[i - LBound()]; } //@E Indexing // Operations template BOOL CSafeArray::ReDim(Dim &dim) { if (!IsSizable()) { return FALSE; } HRESULT hres = SafeArrayRedim(psa, &dim); if (hres) throw hres; return TRUE; } template long CSafeArray::LBound() { long iRes; HRESULT hres = SafeArrayGetLBound(psa, 1, &iRes); if (hres) throw hres; return iRes; } template inline long CSafeArray::Elements() { return psa->rgsabound[0].cElements; } template long CSafeArray::UBound() { long iRes; HRESULT hres = SafeArrayGetUBound(psa, 1, &iRes); if (hres) throw hres; return iRes; } template inline long CSafeArray::Dimensions() { return 1; } template inline BOOL CSafeArray::IsSizable() { return (psa->fFeatures & FADF_FIXEDSIZE) ? FALSE : TRUE; } template inline void CSafeArray::Lock() { HRESULT hres = SafeArrayLock(psa); if (hres) { throw hres; } } template inline void CSafeArray::Unlock() { HRESULT hres = SafeArrayUnlock(psa); if (hres) { throw hres; } } #endif // _SAFEARRAY_H_