1// Windows/PropVariant.cpp 2 3#include "StdAfx.h" 4 5#include "PropVariant.h" 6 7#include "../Common/Defs.h" 8 9namespace NWindows { 10namespace NCOM { 11 12CPropVariant::CPropVariant(const PROPVARIANT &varSrc) 13{ 14 vt = VT_EMPTY; 15 InternalCopy(&varSrc); 16} 17 18CPropVariant::CPropVariant(const CPropVariant &varSrc) 19{ 20 vt = VT_EMPTY; 21 InternalCopy(&varSrc); 22} 23 24CPropVariant::CPropVariant(BSTR bstrSrc) 25{ 26 vt = VT_EMPTY; 27 *this = bstrSrc; 28} 29 30CPropVariant::CPropVariant(LPCOLESTR lpszSrc) 31{ 32 vt = VT_EMPTY; 33 *this = lpszSrc; 34} 35 36CPropVariant& CPropVariant::operator=(const CPropVariant &varSrc) 37{ 38 InternalCopy(&varSrc); 39 return *this; 40} 41CPropVariant& CPropVariant::operator=(const PROPVARIANT &varSrc) 42{ 43 InternalCopy(&varSrc); 44 return *this; 45} 46 47CPropVariant& CPropVariant::operator=(BSTR bstrSrc) 48{ 49 *this = (LPCOLESTR)bstrSrc; 50 return *this; 51} 52 53static const char *kMemException = "out of memory"; 54 55CPropVariant& CPropVariant::operator=(LPCOLESTR lpszSrc) 56{ 57 InternalClear(); 58 vt = VT_BSTR; 59 wReserved1 = 0; 60 bstrVal = ::SysAllocString(lpszSrc); 61 if (bstrVal == NULL && lpszSrc != NULL) 62 { 63 throw kMemException; 64 // vt = VT_ERROR; 65 // scode = E_OUTOFMEMORY; 66 } 67 return *this; 68} 69 70 71CPropVariant& CPropVariant::operator=(const char *s) 72{ 73 InternalClear(); 74 vt = VT_BSTR; 75 wReserved1 = 0; 76 UINT len = (UINT)strlen(s); 77 bstrVal = ::SysAllocStringByteLen(0, (UINT)len * sizeof(OLECHAR)); 78 if (bstrVal == NULL) 79 { 80 throw kMemException; 81 // vt = VT_ERROR; 82 // scode = E_OUTOFMEMORY; 83 } 84 else 85 { 86 for (UINT i = 0; i <= len; i++) 87 bstrVal[i] = s[i]; 88 } 89 return *this; 90} 91 92CPropVariant& CPropVariant::operator=(bool bSrc) 93{ 94 if (vt != VT_BOOL) 95 { 96 InternalClear(); 97 vt = VT_BOOL; 98 } 99 boolVal = bSrc ? VARIANT_TRUE : VARIANT_FALSE; 100 return *this; 101} 102 103#define SET_PROP_FUNC(type, id, dest) \ 104 CPropVariant& CPropVariant::operator=(type value) \ 105 { if (vt != id) { InternalClear(); vt = id; } \ 106 dest = value; return *this; } 107 108SET_PROP_FUNC(Byte, VT_UI1, bVal) 109SET_PROP_FUNC(Int16, VT_I2, iVal) 110SET_PROP_FUNC(Int32, VT_I4, lVal) 111SET_PROP_FUNC(UInt32, VT_UI4, ulVal) 112SET_PROP_FUNC(UInt64, VT_UI8, uhVal.QuadPart) 113SET_PROP_FUNC(const FILETIME &, VT_FILETIME, filetime) 114 115static HRESULT MyPropVariantClear(PROPVARIANT *prop) 116{ 117 switch(prop->vt) 118 { 119 case VT_UI1: 120 case VT_I1: 121 case VT_I2: 122 case VT_UI2: 123 case VT_BOOL: 124 case VT_I4: 125 case VT_UI4: 126 case VT_R4: 127 case VT_INT: 128 case VT_UINT: 129 case VT_ERROR: 130 case VT_FILETIME: 131 case VT_UI8: 132 case VT_R8: 133 case VT_CY: 134 case VT_DATE: 135 prop->vt = VT_EMPTY; 136 prop->wReserved1 = 0; 137 return S_OK; 138 } 139 return ::VariantClear((VARIANTARG *)prop); 140} 141 142HRESULT CPropVariant::Clear() 143{ 144 return MyPropVariantClear(this); 145} 146 147HRESULT CPropVariant::Copy(const PROPVARIANT* pSrc) 148{ 149 ::VariantClear((tagVARIANT *)this); 150 switch(pSrc->vt) 151 { 152 case VT_UI1: 153 case VT_I1: 154 case VT_I2: 155 case VT_UI2: 156 case VT_BOOL: 157 case VT_I4: 158 case VT_UI4: 159 case VT_R4: 160 case VT_INT: 161 case VT_UINT: 162 case VT_ERROR: 163 case VT_FILETIME: 164 case VT_UI8: 165 case VT_R8: 166 case VT_CY: 167 case VT_DATE: 168 memmove((PROPVARIANT*)this, pSrc, sizeof(PROPVARIANT)); 169 return S_OK; 170 } 171 return ::VariantCopy((tagVARIANT *)this, (tagVARIANT *)const_cast<PROPVARIANT *>(pSrc)); 172} 173 174 175HRESULT CPropVariant::Attach(PROPVARIANT *pSrc) 176{ 177 HRESULT hr = Clear(); 178 if (FAILED(hr)) 179 return hr; 180 memcpy(this, pSrc, sizeof(PROPVARIANT)); 181 pSrc->vt = VT_EMPTY; 182 return S_OK; 183} 184 185HRESULT CPropVariant::Detach(PROPVARIANT *pDest) 186{ 187 HRESULT hr = MyPropVariantClear(pDest); 188 if (FAILED(hr)) 189 return hr; 190 memcpy(pDest, this, sizeof(PROPVARIANT)); 191 vt = VT_EMPTY; 192 return S_OK; 193} 194 195HRESULT CPropVariant::InternalClear() 196{ 197 HRESULT hr = Clear(); 198 if (FAILED(hr)) 199 { 200 vt = VT_ERROR; 201 scode = hr; 202 } 203 return hr; 204} 205 206void CPropVariant::InternalCopy(const PROPVARIANT *pSrc) 207{ 208 HRESULT hr = Copy(pSrc); 209 if (FAILED(hr)) 210 { 211 if (hr == E_OUTOFMEMORY) 212 throw kMemException; 213 vt = VT_ERROR; 214 scode = hr; 215 } 216} 217 218int CPropVariant::Compare(const CPropVariant &a) 219{ 220 if (vt != a.vt) 221 return MyCompare(vt, a.vt); 222 switch (vt) 223 { 224 case VT_EMPTY: return 0; 225 // case VT_I1: return MyCompare(cVal, a.cVal); 226 case VT_UI1: return MyCompare(bVal, a.bVal); 227 case VT_I2: return MyCompare(iVal, a.iVal); 228 case VT_UI2: return MyCompare(uiVal, a.uiVal); 229 case VT_I4: return MyCompare(lVal, a.lVal); 230 case VT_UI4: return MyCompare(ulVal, a.ulVal); 231 // case VT_UINT: return MyCompare(uintVal, a.uintVal); 232 case VT_I8: return MyCompare(hVal.QuadPart, a.hVal.QuadPart); 233 case VT_UI8: return MyCompare(uhVal.QuadPart, a.uhVal.QuadPart); 234 case VT_BOOL: return -MyCompare(boolVal, a.boolVal); 235 case VT_FILETIME: return ::CompareFileTime(&filetime, &a.filetime); 236 case VT_BSTR: 237 return 0; // Not implemented 238 // return MyCompare(aPropVarint.cVal); 239 default: return 0; 240 } 241} 242 243}} 244