#ifndef _CPROPVAR_HXX_ #define _CPROPVAR_HXX_ #ifndef _MAC #include #include #include #endif #include "CHResult.hxx" #include #ifndef ASSERT #if DBG==1 #ifdef _MAC #define ASSERT(assertion) PROPASSERT(assertion) #else #include "debnot.h" #define ASSERT(assertion) {if(!(assertion)) Win4AssertEx(__FILE__, __LINE__, (#assertion));} #endif #else #define ASSERT(assertion) #endif #endif class CClipData; class CBlob; class CPropVariant; class CClipData : private CLIPDATA { public: ~CClipData() { if( NULL != pClipData) CoTaskMemFree( pClipData); } CClipData() { cbSize = sizeof( ulClipFmt ); ulClipFmt = (ULONG) -1; pClipData = NULL; } CClipData( ULONG ul, const void *p, ULONG cb ) { HRESULT hr; this->CClipData::CClipData(); hr = Set( ul, p, cb ); ASSERT( SUCCEEDED(hr) ); } CClipData( LPSTR psz ) { this->CClipData::CClipData( (ULONG) -1, psz, strlen(psz) + 1 ); } CClipData( LPWSTR pwsz ) { this->CClipData::CClipData( (ULONG) -1, pwsz, sizeof(WCHAR) * (wcslen(pwsz) + 1) ); } CClipData( CClipData &cClipData ) { HRESULT hr; hr = Set( cClipData.ulClipFmt, cClipData.pClipData, cClipData.cbSize - sizeof(ulClipFmt)); ASSERT( SUCCEEDED(hr) ); } CClipData& operator =(CClipData &cClipData) { HRESULT hr; hr = Set( cClipData.ulClipFmt, cClipData.pClipData, cClipData.cbSize - sizeof(ulClipFmt)); ASSERT( SUCCEEDED(hr) ); return( *this ); } HRESULT Set( ULONG ul, const void *p, ULONG cb ) { if( NULL != pClipData ) { cb = sizeof( ulClipFmt ); ulClipFmt = (ULONG) -1; CoTaskMemFree( pClipData ); } if( NULL != p ) { pClipData = (BYTE*) CoTaskMemAlloc( cb ); if( NULL == pClipData ) return( (HRESULT) E_OUTOFMEMORY ); memcpy( pClipData, p, cb ); } cbSize = sizeof( ulClipFmt ) + cb; ulClipFmt = ul; return( S_OK ); } operator const CLIPDATA*() { return( this ); } operator CLIPDATA*() { return( this ); } }; #define INVALID_SUBSCRIPT 0 template< VARENUM tpltVT, class tpltType > void TCPropVarAssignmentOperator( CPropVariant *pThis, tpltType Type ) { if( INVALID_SUBSCRIPT == pThis->wReserved1 ) { PropVariantClear(pThis); pThis->Set(tpltVT, (void*) &Type, INVALID_SUBSCRIPT ); return; } else { if( !(pThis->vt & VT_VECTOR) || (pThis->vt & ~VT_VECTOR) != tpltVT ) { WORD wReserved1Save = pThis->wReserved1; PropVariantClear(pThis); pThis->wReserved1 = wReserved1Save; } pThis->Set( tpltVT | VT_VECTOR, (void*) &Type, pThis->wReserved1 - 1); pThis->wReserved1 = INVALID_SUBSCRIPT; return; } } template< VARENUM tpltVT, class TCountedArray, class TProperty > TProperty TCPropVarConversionOperator( CPropVariant *pThis, TCountedArray *pca, TProperty *pSingleton ) { if( pThis->vt & VT_VECTOR ) { ASSERT( pThis->vt == (tpltVT | VT_VECTOR) || pThis->vt == (VT_VARIANT | VT_VECTOR) ); ASSERT( pThis->wReserved1 > 0 ); if( pThis->wReserved1 > 0 && pca->cElems > 0 && pThis->wReserved1 <= (pca->cElems) ) { USHORT usSubscript = pThis->wReserved1 - 1; pThis->wReserved1 = 0; if( (pThis->vt & ~VT_VECTOR) == VT_VARIANT ) return( (TProperty) *(CPropVariant*)(PROPVARIANT*) &((CAPROPVARIANT*)pca)->pElems[usSubscript] ); else return( pca->pElems[ usSubscript ] ); } else { throw CHRESULT( (HRESULT) E_INVALIDARG, OLESTR("Index not set on conversion of vector") ); // This unnecessary statement avoids a compiler error. return pca->pElems[ 0 ]; } } else { ASSERT( vt == tpltVT ); return( *pSingleton ); } } #define DECLARE_CPROPVARIANT_ASSIGNMENT_OPERATOR(Type) \ CPropVariant & operator =( Type); #define DEFINE_CPROPVARIANT_ASSIGNMENT_OPERATOR(VT, Type ) \ \ CPropVariant & CPropVariant::operator =( Type pType) \ { \ if( INVALID_SUBSCRIPT == wReserved1 ) \ { \ PropVariantClear(this); \ this->CPropVariant::CPropVariant(pType); \ return (*this); \ } \ else \ { \ if( !(vt & VT_VECTOR) \ || \ (vt & ~VT_VECTOR) != VT_##VT ) \ { \ WORD wReserved1Save = wReserved1; \ PropVariantClear(this); \ this->CPropVariant::CPropVariant( VT_##VT, \ wReserved1Save ); \ wReserved1 = wReserved1Save; \ } \ \ Set##VT( pType, wReserved1 - 1); \ wReserved1 = 0; \ return (*this); \ } \ } #define DECLARE_CPROPVARIANT_CONVERSION_OPERATOR(VarType) \ operator VarType(); #define DEFINE_CPROPVARIANT_CONVERSION_OPERATOR(VarType, CAName, SingletonName) \ CPropVariant::operator VarType() \ { \ if( vt & VT_VECTOR ) \ { \ ASSERT( vt == (VT_##VarType | VT_VECTOR) \ || \ vt == (VT_VARIANT | VT_VECTOR) ); \ ASSERT( wReserved1 > 0 ); \ \ if( wReserved1 > 0 \ && \ ##CAName.cElems > 0 \ && \ wReserved1 <= (##CAName.cElems) ) \ { \ USHORT usSubscript = wReserved1 - 1; \ wReserved1 = 0; \ if( (vt & ~VT_VECTOR) == VT_VARIANT ) \ return( capropvar.pElems[ usSubscript ].##SingletonName );\ else \ return( ##CAName.pElems[ usSubscript ] ); \ } \ else \ return( NULL ); \ } \ else \ { \ ASSERT( vt == VT_##VarType ); \ return( ##SingletonName ); \ } \ } class CPropVariant : public tagPROPVARIANT { public: // -------------------------------- // Default Constructor & Destructor // -------------------------------- CPropVariant() { Init(); wReserved1 = INVALID_SUBSCRIPT; } ~CPropVariant() { Clear(); } CPropVariant( CPropVariant &cpropvar ) { Init(); PropVariantCopy( this, &cpropvar ); } // ------------------- // Generic Set routine // ------------------- void Set( VARTYPE vtSet, void *pv, ULONG pos ); // ------------------------------------------------------------ // Constructors, assignment operators, and conversion functions // ------------------------------------------------------------ // VT_I1 (CHAR) CPropVariant(CHAR c) { Init(); SetI1(c); } void SetI1(CHAR c) { Clear(); vt = VT_I1; cVal = c; } void SetI1( CHAR c, ULONG pos ) { if( vt != (VT_I1 | VT_VECTOR) ) Clear(); _AddScalerToVector( pos, &c, sizeof(c) ); vt = VT_I1 | VT_VECTOR; } UCHAR GetI1() { _ValidateGet( VT_I1 ); return( cVal ); } UCHAR GetI1( ULONG pos ) { _ValidateGet( VT_I1, pos ); return( cac.pElems[pos] ); } CPropVariant & operator =(CHAR c) { TCPropVarAssignmentOperator(this, c ); return (*this); } operator CHAR() { return TCPropVarConversionOperator ( this, &cac, &cVal ); } // VT_UI1 (UCHAR) CPropVariant(UCHAR b) { Init(); SetUI1(b); } void SetUI1(UCHAR b) { Clear(); vt = VT_UI1; bVal = b; } void SetUI1( UCHAR b, ULONG pos ) { if( vt != (VT_UI1 | VT_VECTOR) ) Clear(); _AddScalerToVector( pos, &b, sizeof(b) ); vt = VT_UI1 | VT_VECTOR; } UCHAR GetUI1() { _ValidateGet( VT_UI1 ); return( bVal ); } UCHAR GetUI1( ULONG pos ) { _ValidateGet( VT_UI1, pos ); return( caub.pElems[pos] ); } CPropVariant & operator =(UCHAR b) { TCPropVarAssignmentOperator(this, b ); return (*this); } operator UCHAR() { return TCPropVarConversionOperator ( this, &caub, &bVal ); } // VT_I2 (short) CPropVariant(short i) { Init(); SetI2(i); } void SetI2(short i) { Clear(); vt = VT_I2; iVal = i; } void SetI2( short i, ULONG pos ) { if( vt != (VT_I2 | VT_VECTOR) ) Clear(); _AddScalerToVector( pos, &i, sizeof(i) ); vt = VT_I2 | VT_VECTOR; } short GetI2() { _ValidateGet( VT_I2 ); return(iVal); } short GetI2( ULONG pos ) { _ValidateGet( VT_I2, pos ); return( cai.pElems[pos] ); } CPropVariant & operator =(short i) { TCPropVarAssignmentOperator(this, i); return (*this); } operator short() { return TCPropVarConversionOperator ( this, &cai, &iVal ); } // VT_UI2 (USHORT) CPropVariant(USHORT ui) { Init(); SetUI2(ui); } void SetUI2(USHORT ui) { Clear(); vt = VT_UI2; uiVal = ui; } void SetUI2( USHORT ui, ULONG pos ) { if( vt != (VT_UI2 | VT_VECTOR) ) Clear(); _AddScalerToVector( pos, &ui, sizeof(ui) ); vt = VT_UI2 | VT_VECTOR; } USHORT GetUI2() { _ValidateGet( VT_UI2 ); return( uiVal ); } USHORT GetUI2( ULONG pos ) { _ValidateGet( VT_UI2, pos ); return( caui.pElems[pos] ); } CPropVariant & operator =(USHORT ui) { TCPropVarAssignmentOperator(this, ui); return (*this); } operator USHORT() { return TCPropVarConversionOperator ( this, &caui, &uiVal ); } // VT_I4 (long) CPropVariant(long l) { Init(); SetI4(l); } void SetI4(long l) { Clear(); vt = VT_I4; lVal = l; } void SetI4( long l, ULONG pos ) { if( vt != (VT_I4 | VT_VECTOR) ) Clear(); _AddScalerToVector( pos, &l, sizeof(l) ); vt = VT_I4 | VT_VECTOR; } long GetI4() { _ValidateGet( VT_I4 ); return( lVal ); } long GetI4( ULONG pos ) { _ValidateGet( VT_I4, pos ); return( cal.pElems[ pos ] ); } CPropVariant & operator =(long l) { TCPropVarAssignmentOperator(this, l); return (*this); } CPropVariant & operator =(int i) // Assume sizeof(int)==sizeof(long) { TCPropVarAssignmentOperator(this, i); return (*this); } operator long() { return TCPropVarConversionOperator ( this, &cal, &lVal ); } // VT_INT (long) void SetINT(long l) { Clear(); vt = VT_INT; intVal = l; } long GetINT() { _ValidateGet( VT_INT ); return( intVal ); } // VT_UI4 (ULONG) CPropVariant(ULONG ul) { Init(); SetUI4(ul); } void SetUI4(ULONG ul) { Clear(); vt = VT_UI4; ulVal = ul; } void SetUI4( ULONG ul, ULONG pos ) { if( vt != (VT_UI4 | VT_VECTOR) ) Clear(); _AddScalerToVector( pos, &ul, sizeof(ul) ); vt = VT_UI4 | VT_VECTOR; } ULONG GetUI4() { _ValidateGet( VT_UI4 ); return( ulVal ); } ULONG GetUI4( ULONG pos ) { _ValidateGet( VT_UI4, pos ); return( caul.pElems[ pos ] ); } CPropVariant & operator =(ULONG ul) { TCPropVarAssignmentOperator(this, ul); return (*this); } operator ULONG() { return TCPropVarConversionOperator ( this, &caul, &ulVal ); } // VT_UINT (unsigned long) void SetUINT(ULONG ul) { Clear(); vt = VT_UINT; uintVal = ul; } long GetUINT() { _ValidateGet( VT_UINT ); return( uintVal ); } // VT_I8 (LARGE_INTEGER) CPropVariant(LARGE_INTEGER h) { Init(); SetI8(h); } void SetI8(LARGE_INTEGER h) { Clear(); vt = VT_I8; hVal = h; } void SetI8( LARGE_INTEGER h, ULONG pos ) { if( vt != (VT_I8 | VT_VECTOR) ) Clear(); _AddScalerToVector( pos, &h, sizeof(h) ); vt = VT_I8 | VT_VECTOR; } LARGE_INTEGER GetI8() { _ValidateGet( VT_I8 ); return( hVal ); } LARGE_INTEGER GetI8( ULONG pos ) { _ValidateGet( VT_I8, pos ); return( cah.pElems[ pos ] ); } CPropVariant & operator=(LARGE_INTEGER h) { TCPropVarAssignmentOperator(this, h); return (*this); } operator LARGE_INTEGER() { return TCPropVarConversionOperator ( this, &cah, &hVal ); } // VT_UI8 (ULARGE_INTEGER) CPropVariant(ULARGE_INTEGER uh) { Init(); SetUI8(uh); } void SetUI8(ULARGE_INTEGER uh) { Clear(); vt = VT_UI8; uhVal = uh; } void SetUI8( ULARGE_INTEGER uh, ULONG pos ) { if( vt != (VT_UI8 | VT_VECTOR) ) Clear(); _AddScalerToVector( pos, &uh, sizeof(uh) ); vt = VT_UI8 | VT_VECTOR; } ULARGE_INTEGER GetUI8() { _ValidateGet( VT_UI8 ); return( uhVal ); } ULARGE_INTEGER GetUI8( ULONG pos ) { _ValidateGet( VT_UI8, pos ); return( cauh.pElems[ pos ] ); } CPropVariant & operator=(ULARGE_INTEGER uh) { TCPropVarAssignmentOperator(this, uh); return (*this); } operator ULARGE_INTEGER() { return TCPropVarConversionOperator ( this, &cauh, &uhVal ); } // VT_R4 (float) CPropVariant(float flt) { Init(); SetR4(flt); } void SetR4(float flt) { Clear(); vt = VT_R4; fltVal = flt; } void SetR4( float flt, ULONG pos ) { if( vt != (VT_R4 | VT_VECTOR) ) Clear(); _AddScalerToVector( pos, &flt, sizeof(flt) ); vt = VT_R4 | VT_VECTOR; } float GetR4() { _ValidateGet( VT_R4 ); return( fltVal ); } float GetR4( ULONG pos ) { _ValidateGet( VT_R4, pos ); return( caflt.pElems[ pos ] ); } CPropVariant & operator=(float flt) { TCPropVarAssignmentOperator(this, flt); return (*this); } operator float() { return TCPropVarConversionOperator ( this, &caflt, &fltVal ); } // VT_R8 (double) CPropVariant(double dbl) { Init(); SetR8(dbl); } void SetR8(double dbl) { Clear(); vt = VT_R8; dblVal = dbl; } void SetR8( double dbl, ULONG pos ) { if( vt != (VT_R8 | VT_VECTOR) ) Clear(); _AddScalerToVector( pos, &dbl, sizeof(dbl) ); vt = VT_R8 | VT_VECTOR; } double GetR8() { _ValidateGet( VT_R8 ); return( dblVal ); } double GetR8( ULONG pos ) { _ValidateGet( VT_R8, pos ); return( cadbl.pElems[ pos ] ); } CPropVariant & operator=(double dbl) { TCPropVarAssignmentOperator(this, dbl); return (*this); } operator double() { return TCPropVarConversionOperator ( this, &cadbl, &dblVal ); } // VT_CY (CY) CPropVariant(CY cy) { Init(); SetCY(cy); } void SetCY(const CY &cy) { Clear(); vt = VT_CY; cyVal = cy; } void SetCY( const CY &cy, ULONG pos ) { if( vt != (VT_CY | VT_VECTOR) ) Clear(); _AddScalerToVector( pos, &cy, sizeof(cy) ); vt = VT_CY | VT_VECTOR; } CPropVariant & operator=(const CY &cy) { TCPropVarAssignmentOperator(this, cy); return (*this); } CY GetCY() { _ValidateGet( VT_CY ); return( cyVal ); } CY GetCY( ULONG pos ) { _ValidateGet( VT_CY, pos ); return( cacy.pElems[ pos ] ); } operator CY() { return TCPropVarConversionOperator ( this, &cacy, &cyVal ); } // VT_FILETIME (FILETIME) CPropVariant(const FILETIME &filetime) { Init(); SetFILETIME(filetime); } void SetFILETIME(const FILETIME &ft) { Clear(); vt = VT_FILETIME; filetime = ft; } void SetFILETIME( const FILETIME &ft, ULONG pos ) { if( vt != (VT_FILETIME | VT_VECTOR) ) Clear(); _AddScalerToVector( pos, &ft, sizeof(ft) ); vt = VT_FILETIME | VT_VECTOR; } FILETIME GetFILETIME() { _ValidateGet( VT_FILETIME ); return( filetime ); } FILETIME GetFILETIME( ULONG pos ) { _ValidateGet( VT_FILETIME, pos ); return( cafiletime.pElems[ pos ] ); } CPropVariant & operator=(const FILETIME &ft) { TCPropVarAssignmentOperator(this, ft); return (*this); } operator FILETIME() { return TCPropVarConversionOperator ( this, &cafiletime, &filetime ); } // VT_CLSID (CLSID) CPropVariant(CLSID *pclsid) { Init(); SetCLSID(pclsid); } void SetCLSID(const CLSID *pclsid); void SetCLSID(const CLSID &clsid) { SetCLSID( &clsid ); } void SetCLSID(const CLSID *pclsid, unsigned pos); void SetCLSID(const CLSID &clsid, unsigned pos ) { if( vt != (VT_CLSID | VT_VECTOR) ) { Clear(); vt = VT_CLSID | VT_VECTOR; } SetCLSID( &clsid, pos ); } CLSID* GetCLSID() { _ValidateGet( VT_CLSID ); return( puuid ); } CLSID* GetCLSID( ULONG pos ) { _ValidateGet( VT_CLSID, pos ); return( &cauuid.pElems[ pos ] ); } CPropVariant & operator=(const CLSID *pclsid) { TCPropVarAssignmentOperator(this, pclsid); return( *this ); } CPropVariant & operator=(const CLSID &clsid) { TCPropVarAssignmentOperator(this, &clsid); return( *this ); } operator CLSID() { return TCPropVarConversionOperator ( this, &cauuid, puuid ); } // VT_STREAM (IStream*) CPropVariant( IStream *pStm ) { Init(); SetSTREAM( pStm ); } void SetSTREAM( IStream *pStm ) { Clear(); vt = VT_STREAM; pStream = pStm; if( NULL != pStream ) pStream->AddRef(); } IStream* GetSTREAM() { _ValidateGet( VT_STREAM ); return( pStream ); } CPropVariant & operator= ( IStream *pStm ) { Clear(); SetSTREAM( pStm ); return (*this); } operator IStream*() { return( GetSTREAM() ); } // VT_VERSIONED_STREAM CPropVariant( VERSIONEDSTREAM& verstream ) { Init(); SetVERSIONEDSTREAM( &verstream ); } void SetVERSIONEDSTREAM( VERSIONEDSTREAM *pverstream) { Clear(); vt = VT_VERSIONED_STREAM; pVersionedStream = (LPVERSIONEDSTREAM) CoTaskMemAlloc( sizeof(*pVersionedStream) ); if( NULL == pVersionedStream ) throw CHRESULT( (HRESULT) E_OUTOFMEMORY, OLESTR("Failed CoTaskMemAlloc for VT_VERSIONED_STREAM") ); pVersionedStream->guidVersion = pverstream->guidVersion; if( NULL != pverstream->pStream ) pverstream->pStream->AddRef(); pVersionedStream->pStream = pverstream->pStream; } VERSIONEDSTREAM GetVERSIONEDSTREAM() { _ValidateGet( VT_VERSIONED_STREAM ); return( *pVersionedStream ); } CPropVariant & operator= ( VERSIONEDSTREAM &verstream ) { Clear(); SetVERSIONEDSTREAM( &verstream ); return (*this); } operator VERSIONEDSTREAM() { return( GetVERSIONEDSTREAM() ); } // VT_STORAGE (IStorage*) CPropVariant( IStorage *pStg ) { Init(); SetSTORAGE( pStg ); } void SetSTORAGE( IStorage *pStg ) { vt = VT_STORAGE; pStorage = pStg; if( NULL != pStorage ) pStorage->AddRef(); } IStorage* GetSTORAGE() { _ValidateGet( VT_STORAGE ); return( pStorage ); } CPropVariant & operator = ( IStorage *pStg ) { Clear(); SetSTORAGE( pStg ); return (*this); } operator IStorage*() { return( GetSTORAGE() ); } // VT_LPSTR (LPSTR) CPropVariant( const LPSTR psz ) { Init(); SetLPSTR(psz); } void SetLPSTR(const LPSTR psz) { Clear(); pszVal = (LPSTR) CoTaskMemAlloc( strlen(psz) + 1 ); if( NULL == pszVal ) throw CHRESULT( (HRESULT) E_OUTOFMEMORY, OLESTR("Failed CoTaskMemAlloc for VT_LPSTR") ); vt = VT_LPSTR; strcpy( pszVal, psz ); } void SetLPSTR( const LPSTR psz, ULONG pos ) { if( vt != (VT_LPSTR | VT_VECTOR) ) Clear(); _AddStringToVector( pos, psz, strlen(psz) + 1, VT_LPSTR ); vt = VT_LPSTR | VT_VECTOR; } LPSTR GetLPSTR() { _ValidateGet( VT_LPSTR ); return( pszVal ); } LPSTR GetLPSTR( ULONG pos ) { _ValidateGet( VT_LPSTR, pos ); return( calpstr.pElems[ pos ] ); } CPropVariant & operator=(const LPSTR psz) { TCPropVarAssignmentOperator(this, psz); return (*this); } operator LPSTR() { return TCPropVarConversionOperator ( this, &calpstr, &pszVal ); } // VT_LPWSTR (LPWSTR) CPropVariant( const LPWSTR pwsz ) { Init(); SetLPWSTR(pwsz); } void SetLPWSTR(const LPWSTR pwsz) { Clear(); pwszVal = (LPWSTR) CoTaskMemAlloc( sizeof(WCHAR) * (wcslen(pwsz) + 1) ); if( NULL == pwszVal ) throw CHRESULT( (HRESULT) E_OUTOFMEMORY, OLESTR("Failed CoTaskMemAlloc for VT_LPWSTR") ); vt = VT_LPWSTR; wcscpy( pwszVal, pwsz ); } void SetLPWSTR( const LPWSTR pwsz, ULONG pos ) { if( vt != (VT_LPWSTR | VT_VECTOR) ) Clear(); _AddStringToVector( pos, pwsz, 2 * (wcslen(pwsz) + 1), VT_LPWSTR ); vt = VT_LPWSTR | VT_VECTOR; } LPWSTR GetLPWSTR() { _ValidateGet( VT_LPWSTR ); return( pwszVal ); } LPWSTR GetLPWSTR( ULONG pos ) { _ValidateGet( VT_LPWSTR, pos ); return( calpwstr.pElems[ pos ] ); } CPropVariant & operator=(const LPWSTR pwsz) { TCPropVarAssignmentOperator(this, pwsz); return (*this); } operator LPWSTR() { return TCPropVarConversionOperator ( this, &calpwstr, &pwszVal ); } // VT_CF (CLIPDATA*) CPropVariant( const CLIPDATA *pclip ) { Init(); SetCF(pclip); } void SetCF( const CLIPDATA *pclip ); void SetCF( const CLIPDATA *pclip, ULONG pos ); CLIPDATA* GetCF() { _ValidateGet( VT_CF ); return( pclipdata ); } CLIPDATA* GetCF( ULONG pos ) { _ValidateGet( VT_CF, pos ); return( &caclipdata.pElems[ pos ] ); } CPropVariant & operator= ( const CLIPDATA *pclip ) { TCPropVarAssignmentOperator(this, pclip); return (*this); } CPropVariant & operator= ( const CLIPDATA &clip ) { TCPropVarAssignmentOperator(this, &clip); return (*this); } CPropVariant & operator= ( CClipData &cclipdata ) { // This parameter should be const, but when it is, the compiler won't // convert it to (const CLIPDATA*). TCPropVarAssignmentOperator(this, (const CLIPDATA*)cclipdata); return (*this); } operator CLIPDATA*() { // We can't use TCPropVarConversionOperator template, because the caclipdata // member holds different types (CLIPDATA) than does the pclipdata // member (CLIPDATA*). The template assumes that the singleton properties // and vector properties are of the same type. if( wReserved1 > 0 ) { USHORT usSubscript = wReserved1 - 1; wReserved1 = 0; return GetCF( usSubscript ); } else { return GetCF(); } } // VT_BLOB (BLOB*) CPropVariant(const BLOB &blobIn) { Init(); SetBLOB(blobIn); } void SetBLOB(const BLOB &blobIn) { Clear(); blob.pBlobData = (BYTE*) CoTaskMemAlloc( blobIn.cbSize ); if( NULL == blob.pBlobData ) throw CHRESULT( (HRESULT) E_OUTOFMEMORY, OLESTR("CPropVariant couldn't alloc for VT_BLOB") ); memcpy( blob.pBlobData, blobIn.pBlobData, blobIn.cbSize ); blob.cbSize = blobIn.cbSize; vt = VT_BLOB; } BLOB GetBLOB() { _ValidateGet( VT_BLOB ); return( blob ); } CPropVariant & operator=(const BLOB &blobIn) { TCPropVarAssignmentOperator(this, blobIn); return (*this); } operator BLOB() { return( GetBLOB() ); } CPropVariant( const CBlob &cblobIn ) { Init(); SetBLOB( *(BLOB*) &cblobIn ); } CPropVariant &operator = (CBlob &cblobIn) { TCPropVarAssignmentOperator(this, *(BLOB*)&cblobIn ); return( *this ); } // VT_BSTR (BSTR) void SetBSTR(const BSTR bstrIn) { Clear(); bstrVal = SysAllocString( bstrIn ); if( NULL == bstrIn ) throw CHRESULT( (HRESULT) E_OUTOFMEMORY, OLESTR("Failed CoTaskMemAlloc for VT_BSTR") ); vt = VT_BSTR; } void SetBSTR( const BSTR bstrIn, ULONG pos ); LPWSTR GetBSTR() { _ValidateGet( VT_BSTR ); return( bstrVal ); } LPWSTR GetBSTR( ULONG pos ) { _ValidateGet( VT_BSTR, pos ); return( cabstr.pElems[ pos ] ); } // VT_BOOL (VARIANT_BOOL) void SetBOOL( VARIANT_BOOL boolIn) { Clear(); boolVal = boolIn; vt = VT_BOOL; } void SetBOOL( VARIANT_BOOL boolIn, ULONG pos ) { if( vt != (VT_BOOL | VT_VECTOR) ) Clear(); _AddScalerToVector( pos, &boolIn, sizeof(boolIn) ); vt = VT_BOOL | VT_VECTOR; } BOOL GetBOOL() { _ValidateGet( VT_BOOL ); return( boolVal ); } BOOL GetBOOL( ULONG pos ) { _ValidateGet( VT_BOOL, pos ); return( cabool.pElems[ pos ] ); } // VT_ERROR (SCODE) void SetERROR( SCODE scodeIn) { Clear(); scode = scodeIn; vt = VT_ERROR; } void SetERROR( SCODE scodeIn, ULONG pos ) { if( vt != (VT_ERROR | VT_VECTOR) ) Clear(); _AddScalerToVector( pos, &scodeIn, sizeof(scodeIn) ); vt = VT_ERROR | VT_VECTOR; } BOOL GetERROR() { _ValidateGet( VT_ERROR ); return( scode ); } BOOL GetERROR( ULONG pos ) { _ValidateGet( VT_ERROR, pos ); return( cascode.pElems[ pos ] ); } // VT_DATE (DATE) void SetDATE( DATE dateIn) { Clear(); date = dateIn; vt = VT_DATE; } void SetDATE( DATE dateIn, ULONG pos) { if( vt != (VT_DATE | VT_VECTOR) ) Clear(); _AddScalerToVector( pos, &dateIn, sizeof(dateIn) ); vt = VT_DATE | VT_VECTOR; } DATE GetDATE() { _ValidateGet( VT_DATE ); return( date ); } DATE GetDATE( ULONG pos ) { _ValidateGet( VT_DATE, pos ); return( cadate.pElems[ pos ] ); } // VT_VARIANT (PROPVARIANT) void SetPROPVARIANT( PROPVARIANT &propvar, ULONG pos ); PROPVARIANT &GetPROPVARIANT( ULONG pos ) { _ValidateGet( VT_VARIANT, pos ); return( capropvar.pElems[ pos ] ); } CPropVariant & operator=(PROPVARIANT &propvar); operator PROPVARIANT&() { return( GetPROPVARIANT( wReserved1 ) ); } // VT_DECIMAL (DECIMAL) void SetDECIMAL( const DECIMAL &decimal ) { Clear(); decVal = decimal; vt = VT_DECIMAL; } DECIMAL GetDECIMAL() { _ValidateGet( VT_DECIMAL ); return( decVal ); } CPropVariant & operator=(const DECIMAL &decimal) { TCPropVarAssignmentOperator(this, decimal); return (*this); } operator DECIMAL() { return( GetDECIMAL() ); } public: CPropVariant & operator[] (int nSubscript) { wReserved1 = (WORD) nSubscript + 1; return (*this); } LPPROPVARIANT operator&() { return( this ); } public: VARTYPE VarType() const { return( vt ); } void Clear() { PropVariantClear( this ); } void Init() { PropVariantInit( this ); wReserved1 = INVALID_SUBSCRIPT; } ULONG Count() const { if( vt & VT_VECTOR ) return caui.cElems; else return 0; } void SetVarType(VARTYPE vtNew) { PropVariantClear( this ); vt = vtNew; } public: static HRESULT Compare( PROPVARIANT* ppropvar1, PROPVARIANT *ppropvar2 ); private: VOID *_AddStringToVector( unsigned pos, const VOID *pv, ULONG cb, VARTYPE vtNew ); VOID *_AddScalerToVector( unsigned pos, const VOID *pv, ULONG cb); void _ValidateGet( const VARTYPE vtGet ) { if( vtGet != vt ) throw CHRESULT( (HRESULT) ERROR_INVALID_DATATYPE, OLESTR("Attempt to get incorrect type") ); } void _ValidateGet( const VARTYPE vtGet, const ULONG pos ) { _ValidateGet( vtGet | VT_VECTOR ); if( INVALID_SUBSCRIPT == pos || pos >= caub.cElems ) { throw CHRESULT( (HRESULT) ERROR_INVALID_DATATYPE, OLESTR("Attempt to get a non-existent vector element") ); } } }; class CPropSpec : public PROPSPEC { public: CPropSpec() { ulKind = PRSPEC_PROPID; propid = 0; } ~CPropSpec() { FreeResources(); this->CPropSpec::CPropSpec(); } void FreeResources() { if( PRSPEC_LPWSTR == ulKind ) { CoTaskMemFree( lpwstr ); lpwstr = NULL; } } void Alloc( ULONG cch ) { ULONG cb = sizeof(OLECHAR)*cch + sizeof(OLECHAR); lpwstr = (LPOLESTR) CoTaskMemAlloc( cb ); } operator PROPSPEC*() { return( this ); } PROPSPEC* operator&() { return( this ); } operator CPropSpec&() { return( *this ); } CPropSpec( LPCOLESTR posz ) { memset( this, 0, sizeof(PROPSPEC) ); this->operator=(posz); } CPropSpec & operator = (LPCOLESTR posz) { FreeResources(); Alloc( ocslen(posz) ); if( NULL != lpwstr ) { ocscpy( lpwstr, posz ); ulKind = PRSPEC_LPWSTR; } return( *this ); } CPropSpec & operator = (PROPID propidNew) { FreeResources(); ulKind = PRSPEC_PROPID; propid = propidNew; return( *this ); } OLECHAR & operator[]( int i ) { ulKind = PRSPEC_LPWSTR; return( this->lpwstr[ i ] ); } OLECHAR & operator[]( ULONG i ) { ulKind = PRSPEC_LPWSTR; return( this->lpwstr[ i ] ); } }; class CBlob : public BLOB { public: ~CBlob() { if( NULL != pBlobData ) CoTaskMemFree( pBlobData ); } CBlob( LPSTR psz ) { ULONG cb = 0; if( NULL != psz ) { cb = strlen( psz ) + sizeof(CHAR); } pBlobData = (BYTE*) CoTaskMemAlloc( cb ); if( NULL == pBlobData ) throw CHRESULT( (HRESULT) E_OUTOFMEMORY, OLESTR("Couldn't allocate for CBlob") ); cbSize = cb; memcpy( pBlobData, psz, cbSize ); } CBlob( LPWSTR pwsz ) { ULONG cb = 0; if( NULL != pwsz ) { cb = wcslen( pwsz ) + sizeof(WCHAR); } pBlobData = (BYTE*) CoTaskMemAlloc( cb + sizeof(cb) ); if( NULL == pBlobData ) throw CHRESULT( (HRESULT) E_OUTOFMEMORY, OLESTR("Couldn't allocate for CBlob") ); cbSize = cb; memcpy( pBlobData, pwsz, cbSize ); } CBlob( ULONG cb ) { pBlobData = (BYTE*) CoTaskMemAlloc( cb ); if( NULL == pBlobData ) throw CHRESULT( (HRESULT) E_OUTOFMEMORY, OLESTR("Couldn't allocate for CBlob") ); cbSize = cb; memset( pBlobData, 0, cb ); } CBlob( int cb ) { this->CBlob::CBlob( (ULONG) cb ); } }; inline BOOL operator == ( CPropVariant &cpropvar1, CPropVariant &cpropvar2 ) { return( S_OK == CPropVariant::Compare(&cpropvar1, &cpropvar2) ); } inline BOOL operator == ( CPropVariant &cpropvar, PROPVARIANT &propvar ) { return( (HRESULT) S_OK == CPropVariant::Compare(&cpropvar, &propvar) ); } inline BOOL operator == ( PROPVARIANT &propvar, CPropVariant &cpropvar ) { return( (HRESULT) S_OK == CPropVariant::Compare(&cpropvar, &propvar) ); } inline BOOL operator == ( PROPVARIANT propvar1, PROPVARIANT propvar2) { return( (HRESULT) S_OK == CPropVariant::Compare(&propvar1, &propvar2) ); } inline BOOL operator != ( CPropVariant &cpropvar1, CPropVariant &cpropvar2 ) { return( (HRESULT) S_FALSE == CPropVariant::Compare(&cpropvar1, &cpropvar2) ); } inline BOOL operator != ( CPropVariant &cpropvar, PROPVARIANT &propvar ) { return( (HRESULT) S_FALSE == CPropVariant::Compare(&cpropvar, &propvar) ); } inline BOOL operator != ( PROPVARIANT &propvar, CPropVariant &cpropvar ) { return( (HRESULT) S_FALSE == CPropVariant::Compare(&cpropvar, &propvar) ); } inline BOOL operator != ( PROPVARIANT &propvar1, PROPVARIANT &propvar2) { return( (HRESULT) S_FALSE == CPropVariant::Compare(&propvar1, &propvar2) ); } #endif // !_CPROPVAR_HXX_