//+-------------------------------------------------------------- // // Microsoft Windows // Copyright (C) Microsoft Corporation, 1992 - 1996. // // File: cpropvar.cxx // //--------------------------------------------------------------- #include "cpropvar.hxx" #include "chresult.hxx" #include #include "../../h/tchar.h" // this function is from refstg BOOLEAN STDCALL RtlCompareVariants( USHORT CodePage, PROPVARIANT const *pvar1, PROPVARIANT const *pvar2); DEFINE_CPROPVARIANT_ASSIGNMENT_OPERATOR(LPSTR, LPSTR); DEFINE_CPROPVARIANT_CONVERSION_OPERATOR(LPSTR, calpstr, pszVal ); DEFINE_CPROPVARIANT_ASSIGNMENT_OPERATOR(LPWSTR, LPWSTR); DEFINE_CPROPVARIANT_CONVERSION_OPERATOR(LPWSTR, calpwstr, pwszVal ); DEFINE_CPROPVARIANT_ASSIGNMENT_OPERATOR(CF, CLIPDATA&); DEFINE_CPROPVARIANT_ASSIGNMENT_OPERATOR(CF, CClipData&); DEFINE_CPROPVARIANT_ASSIGNMENT_OPERATOR(CLSID, CLSID); CPropVariant::CPropVariant( VARENUM v, ULONG cElements) { Init(v, cElements); } void CPropVariant::Init( VARENUM v, ULONG cElements) { ULONG cbElement; BOOLEAN fZero = FALSE; // Ignore vector flag. This constructor is always for vectors only. vt = v | VT_VECTOR; switch (vt) { case VT_VECTOR | VT_UI1: cbElement = sizeof(caub.pElems[0]); break; case VT_VECTOR | VT_I2: case VT_VECTOR | VT_UI2: case VT_VECTOR | VT_BOOL: cbElement = sizeof(cai.pElems[0]); break; case VT_VECTOR | VT_I4: case VT_VECTOR | VT_UI4: case VT_VECTOR | VT_R4: case VT_VECTOR | VT_ERROR: cbElement = sizeof(cal.pElems[0]); break; case VT_VECTOR | VT_I8: case VT_VECTOR | VT_UI8: case VT_VECTOR | VT_R8: case VT_VECTOR | VT_CY: case VT_VECTOR | VT_DATE: case VT_VECTOR | VT_FILETIME: cbElement = sizeof(cah.pElems[0]); break; case VT_VECTOR | VT_CLSID: cbElement = sizeof(GUID); fZero = TRUE; break; case VT_VECTOR | VT_CF: cbElement = sizeof(CLIPDATA); fZero = TRUE; break; case VT_VECTOR | VT_BSTR: case VT_VECTOR | VT_LPSTR: case VT_VECTOR | VT_LPWSTR: cbElement = sizeof(VOID *); fZero = TRUE; break; case VT_VECTOR | VT_VARIANT: cbElement = sizeof(PROPVARIANT); ASSERT(VT_EMPTY == 0); fZero = TRUE; break; default: ASSERT(!"CAllocStorageVariant -- Invalid vector type"); vt = VT_EMPTY; break; } if (vt != VT_EMPTY) { caub.cElems = 0; caub.pElems = (BYTE *) CoTaskMemAlloc(cElements * cbElement); if (caub.pElems != NULL) { if (fZero) { memset(caub.pElems, 0, cElements * cbElement); } caub.cElems = cElements; } } } VOID * CPropVariant::_AddStringToVector( unsigned pos, VOID *pv, ULONG cb) { ASSERT(vt == (VT_VECTOR | VT_BSTR) || vt == (VT_VECTOR | VT_LPSTR) || vt == (VT_VECTOR | VT_LPWSTR) || vt == (VT_VECTOR | VT_CF) ); ASSERT(calpstr.pElems != NULL); if (pos >= calpstr.cElems) { char **ppsz = calpstr.pElems; calpstr.pElems = (char **) CoTaskMemAlloc((pos + 1) * sizeof(calpstr.pElems[0])); if (calpstr.pElems == NULL) { calpstr.pElems = ppsz; return(NULL); } memcpy(calpstr.pElems, ppsz, calpstr.cElems * sizeof(calpstr.pElems[0])); memset( &calpstr.pElems[calpstr.cElems], 0, ((pos + 1) - calpstr.cElems) * sizeof(calpstr.pElems[0])); calpstr.cElems = pos + 1; CoTaskMemFree(ppsz); } LPSTR psz; if( (VT_VECTOR | VT_BSTR) == vt ) { psz = (LPSTR) SysAllocString( (BSTR) pv ); if (psz == NULL) { return(NULL); } if (calpstr.pElems[pos] != NULL) { SysFreeString((BSTR) calpstr.pElems[pos]); } calpstr.pElems[pos] = psz; } else { psz = (LPSTR) CoTaskMemAlloc((VT_BSTR == (vt & ~VT_VECTOR) ) ? cb + sizeof(ULONG) : cb ); if (psz == NULL) { return(NULL); } memcpy(psz, pv, cb); if (calpstr.pElems[pos] != NULL) { CoTaskMemFree(calpstr.pElems[pos]); } calpstr.pElems[pos] = psz; } return(calpstr.pElems[pos]); } VOID * CPropVariant::_AddScalerToVector( unsigned pos, VOID *pv, ULONG cb) { ASSERT(calpstr.pElems != NULL); if (pos >= calpstr.cElems) { char **ppsz = calpstr.pElems; calpstr.pElems = (char **) CoTaskMemAlloc((pos + 1) * cb); if (calpstr.pElems == NULL) { calpstr.pElems = ppsz; return(NULL); } memset( calpstr.pElems, 0, ((pos + 1) - calpstr.cElems) * cb); memcpy(calpstr.pElems, ppsz, calpstr.cElems * cb); calpstr.cElems = pos + 1; CoTaskMemFree(ppsz); } memcpy( (BYTE*)calpstr.pElems + pos*cb, pv, cb ); return( (BYTE*)calpstr.pElems + pos*cb ); } void CPropVariant::SetLPSTR( char const *psz, unsigned pos) { if (vt != (VT_VECTOR | VT_LPSTR)) { PropVariantClear( this ); new (this) CPropVariant(VT_LPSTR, pos); } _AddStringToVector(pos, (VOID *) psz, strlen(psz) + 1); } void CPropVariant::SetLPWSTR( WCHAR const *pwsz, unsigned pos) { if (vt != (VT_VECTOR | VT_LPWSTR)) { PropVariantClear( this ); new (this) CPropVariant(VT_LPWSTR, pos); } _AddStringToVector(pos, (VOID *) pwsz, sizeof(WCHAR) * (wcslen(pwsz) + 1) ); } void CPropVariant::SetCF( const CLIPDATA *pclipdata, unsigned pos) { CLIPDATA *pclipdataNew; if (vt != (VT_VECTOR | VT_CF)) { PropVariantClear( this ); new (this) CPropVariant(VT_CF, pos); } pclipdataNew = (CLIPDATA*) _AddScalerToVector(pos, (VOID *) pclipdata, sizeof(CLIPDATA) ); if( NULL != pclipdataNew && NULL != pclipdata ) { pclipdataNew->pClipData = (BYTE*) CoTaskMemAlloc( CBPCLIPDATA(*pclipdata) ); if( NULL == pclipdataNew->pClipData ) { ASSERT( !"Couldn't allocate pclipdataNew" ); return; } else { pclipdataNew->cbSize = pclipdata->cbSize; pclipdataNew->ulClipFmt = pclipdata->ulClipFmt; memcpy( pclipdataNew->pClipData, pclipdata->pClipData, CBPCLIPDATA(*pclipdata) ); return; } } } void CPropVariant::SetBSTR( const BSTR pbstr, unsigned int pos) { if (vt != (VT_VECTOR | VT_BSTR)) { PropVariantClear( this ); new (this) CPropVariant(VT_BSTR, pos+1); } _AddStringToVector(pos, (VOID *) pbstr, sizeof(OLECHAR) * (ocslen(pbstr) + 1) ); } BSTR CPropVariant::GetBSTR( int nSubscript ) { ASSERT( vt & VT_VECTOR ); ASSERT( vt == (VT_BSTR | VT_VECTOR) ); ASSERT( wReserved1 > 0 ); if( wReserved1 > 0 && cabstr.cElems > 0 && wReserved1 <= cabstr.cElems ) { int nSubscript = wReserved1 - 1; wReserved1 = INVALID_SUBSCRIPT; return( cabstr.pElems[ nSubscript ] ); } else return( NULL ); } CPropVariant & CPropVariant::operator=(LPPROPVARIANT lppropvar) { if( INVALID_SUBSCRIPT == wReserved1 ) { ASSERT( INVALID_SUBSCRIPT != wReserved1 ); PropVariantClear(this); Init(); return (*this); } else { if( !(vt & VT_VECTOR) || (vt & ~VT_VECTOR) != VT_VARIANT ) { USHORT wReserved1Save = wReserved1; PropVariantClear(this); Init(VT_VARIANT, wReserved1Save ); wReserved1 = wReserved1Save; } SetLPPROPVARIANT( lppropvar, wReserved1 - 1 ); wReserved1 = INVALID_SUBSCRIPT; return (*this); } } CPropVariant::operator LPPROPVARIANT() { if( vt & VT_VECTOR ) { if( wReserved1 > 0 && capropvar.cElems > 0 && wReserved1 <= capropvar.cElems ) { int nSubscript = wReserved1 - 1; wReserved1 = INVALID_SUBSCRIPT; return( &capropvar.pElems[ nSubscript ] ); } else { ASSERT( INVALID_SUBSCRIPT == wReserved1 ); return( (LPPROPVARIANT) this ); } } else return( (LPPROPVARIANT) this ); } void CPropVariant::SetLPPROPVARIANT( LPPROPVARIANT lppropvar, unsigned pos ) { if (vt != (VT_VECTOR | VT_VARIANT)) { PropVariantClear( this ); new (this) CPropVariant(VT_VARIANT, pos + 1); } if (pos >= capropvar.cElems) { LPPROPVARIANT rgpropvar = capropvar.pElems; capropvar.pElems = (PROPVARIANT *) CoTaskMemAlloc((pos + 1) * sizeof(capropvar.pElems[0])); if (capropvar.pElems == NULL) { capropvar.pElems = rgpropvar; return; } memcpy(capropvar.pElems, rgpropvar, capropvar.cElems * sizeof(capropvar.pElems[0])); memset( &capropvar.pElems[capropvar.cElems], 0, ((pos + 1) - capropvar.cElems) * sizeof(capropvar.pElems[0])); capropvar.cElems = pos + 1; CoTaskMemFree(rgpropvar); } PropVariantClear( &capropvar.pElems[pos] ); PropVariantCopy( &capropvar.pElems[pos], lppropvar ); return; } void CPropVariant::Init(const CLIPDATA *p) { Init(); if( NULL == p ) return; pclipdata = (CLIPDATA*) CoTaskMemAlloc( sizeof(CLIPDATA) ); if( NULL == pclipdata ) { return; } pclipdata->cbSize = p->cbSize; pclipdata->ulClipFmt = p->ulClipFmt; pclipdata->pClipData = NULL; if( sizeof(pclipdata->ulClipFmt) > p->cbSize ) { Init(); return; } if( NULL != p->pClipData ) { pclipdata->pClipData = (BYTE*) CoTaskMemAlloc( pclipdata->cbSize - sizeof(pclipdata->ulClipFmt) ); if( NULL == pclipdata->pClipData ) return; memcpy( pclipdata->pClipData, p->pClipData, pclipdata->cbSize - sizeof(pclipdata->ulClipFmt) ); } vt = VT_CF; } void CPropVariant::SetCLSID( const CLSID &clsid ) { PropVariantClear( this ); puuid = (CLSID*) CoTaskMemAlloc( sizeof(CLSID) ); if( NULL == puuid ) { assert(FALSE && "out of memory!"); exit(-1); } *puuid = clsid; vt = VT_CLSID; } void CPropVariant::SetCLSID( const CLSID &clsid, unsigned pos) { CLSID *pclsidNew; if (vt != (VT_VECTOR | VT_CLSID)) { PropVariantClear( this ); new (this) CPropVariant(VT_CLSID, pos); } pclsidNew = (CLSID*) _AddScalerToVector(pos, (VOID *) &clsid, sizeof(CLSID) ); if( NULL != pclsidNew ) { *pclsidNew = clsid; } } HRESULT CPropVariant::Compare( PROPVARIANT *ppropvar1, PROPVARIANT *ppropvar2 ) { if( RtlCompareVariants( CP_ACP, // Ignored, ppropvar1, ppropvar2 )) { return( S_OK ); } else { return( S_FALSE ); } }