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
PropVarEm_Alloc_Bstr(PROPVARIANT * p,unsigned numChars)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
PropVarEm_Set_Str(PROPVARIANT * p,const char * s)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
CPropVariant(const PROPVARIANT & varSrc)42 CPropVariant::CPropVariant(const PROPVARIANT &varSrc)
43 {
44 vt = VT_EMPTY;
45 InternalCopy(&varSrc);
46 }
47
CPropVariant(const CPropVariant & varSrc)48 CPropVariant::CPropVariant(const CPropVariant &varSrc)
49 {
50 vt = VT_EMPTY;
51 InternalCopy(&varSrc);
52 }
53
CPropVariant(BSTR bstrSrc)54 CPropVariant::CPropVariant(BSTR bstrSrc)
55 {
56 vt = VT_EMPTY;
57 *this = bstrSrc;
58 }
59
CPropVariant(LPCOLESTR lpszSrc)60 CPropVariant::CPropVariant(LPCOLESTR lpszSrc)
61 {
62 vt = VT_EMPTY;
63 *this = lpszSrc;
64 }
65
operator =(const CPropVariant & varSrc)66 CPropVariant& CPropVariant::operator=(const CPropVariant &varSrc)
67 {
68 InternalCopy(&varSrc);
69 return *this;
70 }
operator =(const PROPVARIANT & varSrc)71 CPropVariant& CPropVariant::operator=(const PROPVARIANT &varSrc)
72 {
73 InternalCopy(&varSrc);
74 return *this;
75 }
76
operator =(BSTR bstrSrc)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
operator =(LPCOLESTR lpszSrc)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
operator =(const char * s)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
operator =(bool bSrc)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
AllocBstr(unsigned numChars)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
SET_PROP_FUNC(Byte,VT_UI1,bVal)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
Clear()194 HRESULT CPropVariant::Clear() throw()
195 {
196 if (vt == VT_EMPTY)
197 return S_OK;
198 return PropVariant_Clear(this);
199 }
200
Copy(const PROPVARIANT * pSrc)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
Attach(PROPVARIANT * pSrc)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
Detach(PROPVARIANT * pDest)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
InternalClear()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
InternalCopy(const PROPVARIANT * pSrc)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
Compare(const CPropVariant & a)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