1 // Windows/PropVariant.cpp 2 3 #include "StdAfx.h" 4 5 #include "PropVariant.h" 6 7 #include "../Common/Defs.h" 8 9 namespace NWindows { 10 namespace NCOM { 11 12 CPropVariant::CPropVariant(const PROPVARIANT &varSrc) 13 { 14 vt = VT_EMPTY; 15 InternalCopy(&varSrc); 16 } 17 18 CPropVariant::CPropVariant(const CPropVariant &varSrc) 19 { 20 vt = VT_EMPTY; 21 InternalCopy(&varSrc); 22 } 23 24 CPropVariant::CPropVariant(BSTR bstrSrc) 25 { 26 vt = VT_EMPTY; 27 *this = bstrSrc; 28 } 29 30 CPropVariant::CPropVariant(LPCOLESTR lpszSrc) 31 { 32 vt = VT_EMPTY; 33 *this = lpszSrc; 34 } 35 36 CPropVariant& CPropVariant::operator=(const CPropVariant &varSrc) 37 { 38 InternalCopy(&varSrc); 39 return *this; 40 } 41 CPropVariant& CPropVariant::operator=(const PROPVARIANT &varSrc) 42 { 43 InternalCopy(&varSrc); 44 return *this; 45 } 46 47 CPropVariant& CPropVariant::operator=(BSTR bstrSrc) 48 { 49 *this = (LPCOLESTR)bstrSrc; 50 return *this; 51 } 52 53 static const char *kMemException = "out of memory"; 54 55 CPropVariant& 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 71 CPropVariant& 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 92 CPropVariant& 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 108 SET_PROP_FUNC(Byte, VT_UI1, bVal) 109 SET_PROP_FUNC(Int16, VT_I2, iVal) 110 SET_PROP_FUNC(Int32, VT_I4, lVal) 111 SET_PROP_FUNC(UInt32, VT_UI4, ulVal) 112 SET_PROP_FUNC(UInt64, VT_UI8, uhVal.QuadPart) 113 SET_PROP_FUNC(const FILETIME &, VT_FILETIME, filetime) 114 115 static 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 142 HRESULT CPropVariant::Clear() 143 { 144 return MyPropVariantClear(this); 145 } 146 147 HRESULT 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 175 HRESULT 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 185 HRESULT 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 195 HRESULT 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 206 void 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 218 int 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