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