aboutsummaryrefslogtreecommitdiff
path: root/CPP/Windows/PropVariant.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--CPP/Windows/PropVariant.cpp361
1 files changed, 361 insertions, 0 deletions
diff --git a/CPP/Windows/PropVariant.cpp b/CPP/Windows/PropVariant.cpp
new file mode 100644
index 0000000..6e43c7b
--- /dev/null
+++ b/CPP/Windows/PropVariant.cpp
@@ -0,0 +1,361 @@
1// Windows/PropVariant.cpp
2
3#include "StdAfx.h"
4
5#include "../Common/Defs.h"
6
7#include "PropVariant.h"
8
9namespace NWindows {
10namespace NCOM {
11
12BSTR AllocBstrFromAscii(const char *s) throw()
13{
14 if (!s)
15 return NULL;
16 UINT len = (UINT)strlen(s);
17 BSTR p = ::SysAllocStringLen(NULL, len);
18 if (p)
19 {
20 for (UINT i = 0; i <= len; i++)
21 p[i] = (Byte)s[i];
22 }
23 return p;
24}
25
26HRESULT PropVarEm_Alloc_Bstr(PROPVARIANT *p, unsigned numChars) throw()
27{
28 p->bstrVal = ::SysAllocStringLen(NULL, numChars);
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 return S_OK;
37}
38
39HRESULT PropVarEm_Set_Str(PROPVARIANT *p, const char *s) throw()
40{
41 p->bstrVal = AllocBstrFromAscii(s);
42 if (p->bstrVal)
43 {
44 p->vt = VT_BSTR;
45 return S_OK;
46 }
47 p->vt = VT_ERROR;
48 p->scode = E_OUTOFMEMORY;
49 return E_OUTOFMEMORY;
50}
51
52CPropVariant::CPropVariant(const PROPVARIANT &varSrc)
53{
54 vt = VT_EMPTY;
55 InternalCopy(&varSrc);
56}
57
58CPropVariant::CPropVariant(const CPropVariant &varSrc)
59{
60 vt = VT_EMPTY;
61 InternalCopy(&varSrc);
62}
63
64CPropVariant::CPropVariant(BSTR bstrSrc)
65{
66 vt = VT_EMPTY;
67 *this = bstrSrc;
68}
69
70CPropVariant::CPropVariant(LPCOLESTR lpszSrc)
71{
72 vt = VT_EMPTY;
73 *this = lpszSrc;
74}
75
76CPropVariant& CPropVariant::operator=(const CPropVariant &varSrc)
77{
78 InternalCopy(&varSrc);
79 return *this;
80}
81
82CPropVariant& CPropVariant::operator=(const PROPVARIANT &varSrc)
83{
84 InternalCopy(&varSrc);
85 return *this;
86}
87
88CPropVariant& CPropVariant::operator=(BSTR bstrSrc)
89{
90 *this = (LPCOLESTR)bstrSrc;
91 return *this;
92}
93
94static const char * const kMemException = "out of memory";
95
96CPropVariant& CPropVariant::operator=(LPCOLESTR lpszSrc)
97{
98 InternalClear();
99 vt = VT_BSTR;
100 wReserved1 = 0;
101 bstrVal = ::SysAllocString(lpszSrc);
102 if (!bstrVal && lpszSrc)
103 {
104 throw kMemException;
105 // vt = VT_ERROR;
106 // scode = E_OUTOFMEMORY;
107 }
108 return *this;
109}
110
111CPropVariant& CPropVariant::operator=(const UString &s)
112{
113 InternalClear();
114 vt = VT_BSTR;
115 wReserved1 = 0;
116 bstrVal = ::SysAllocStringLen(s, s.Len());
117 if (!bstrVal)
118 throw kMemException;
119 return *this;
120}
121
122CPropVariant& CPropVariant::operator=(const UString2 &s)
123{
124 /*
125 if (s.IsEmpty())
126 *this = L"";
127 else
128 */
129 {
130 InternalClear();
131 vt = VT_BSTR;
132 wReserved1 = 0;
133 bstrVal = ::SysAllocStringLen(s.GetRawPtr(), s.Len());
134 if (!bstrVal)
135 throw kMemException;
136 /* SysAllocStringLen probably appends a null-terminating character for NULL string.
137 But it doesn't specified in MSDN.
138 But we suppose that it works
139
140 if (!s.GetRawPtr())
141 {
142 *bstrVal = 0;
143 }
144 */
145
146 /* MSDN: Windows CE: SysAllocStringLen() : Passing invalid (and under some circumstances NULL)
147 pointers to this function causes an unexpected termination of the application.
148 Is it safe? Maybe we must chamnge the code for that case ? */
149 }
150 return *this;
151}
152
153CPropVariant& CPropVariant::operator=(const char *s)
154{
155 InternalClear();
156 vt = VT_BSTR;
157 wReserved1 = 0;
158 bstrVal = AllocBstrFromAscii(s);
159 if (!bstrVal)
160 {
161 throw kMemException;
162 // vt = VT_ERROR;
163 // scode = E_OUTOFMEMORY;
164 }
165 return *this;
166}
167
168CPropVariant& CPropVariant::operator=(bool bSrc) throw()
169{
170 if (vt != VT_BOOL)
171 {
172 InternalClear();
173 vt = VT_BOOL;
174 }
175 boolVal = bSrc ? VARIANT_TRUE : VARIANT_FALSE;
176 return *this;
177}
178
179BSTR CPropVariant::AllocBstr(unsigned numChars)
180{
181 if (vt != VT_EMPTY)
182 InternalClear();
183 vt = VT_BSTR;
184 wReserved1 = 0;
185 bstrVal = ::SysAllocStringLen(NULL, numChars);
186 if (!bstrVal)
187 {
188 throw kMemException;
189 // vt = VT_ERROR;
190 // scode = E_OUTOFMEMORY;
191 }
192 return bstrVal;
193}
194
195#define SET_PROP_id_dest(id, dest) \
196 if (vt != id) { InternalClear(); vt = id; } dest = value;
197
198void CPropVariant::Set_Int32(Int32 value) throw()
199{
200 SET_PROP_id_dest(VT_I4, lVal);
201}
202
203void CPropVariant::Set_Int64(Int64 value) throw()
204{
205 SET_PROP_id_dest(VT_I8, hVal.QuadPart);
206}
207
208#define SET_PROP_FUNC(type, id, dest) \
209 CPropVariant& CPropVariant::operator=(type value) throw() \
210 { SET_PROP_id_dest(id, dest); return *this; }
211
212SET_PROP_FUNC(Byte, VT_UI1, bVal)
213// SET_PROP_FUNC(Int16, VT_I2, iVal)
214// SET_PROP_FUNC(Int32, VT_I4, lVal)
215SET_PROP_FUNC(UInt32, VT_UI4, ulVal)
216SET_PROP_FUNC(UInt64, VT_UI8, uhVal.QuadPart)
217// SET_PROP_FUNC(Int64, VT_I8, hVal.QuadPart)
218SET_PROP_FUNC(const FILETIME &, VT_FILETIME, filetime)
219
220HRESULT PropVariant_Clear(PROPVARIANT *prop) throw()
221{
222 switch (prop->vt)
223 {
224 case VT_EMPTY:
225 case VT_UI1:
226 case VT_I1:
227 case VT_I2:
228 case VT_UI2:
229 case VT_BOOL:
230 case VT_I4:
231 case VT_UI4:
232 case VT_R4:
233 case VT_INT:
234 case VT_UINT:
235 case VT_ERROR:
236 case VT_FILETIME:
237 case VT_UI8:
238 case VT_R8:
239 case VT_CY:
240 case VT_DATE:
241 prop->vt = VT_EMPTY;
242 prop->wReserved1 = 0;
243 prop->wReserved2 = 0;
244 prop->wReserved3 = 0;
245 prop->uhVal.QuadPart = 0;
246 return S_OK;
247 }
248 return ::VariantClear((VARIANTARG *)prop);
249 // return ::PropVariantClear(prop);
250 // PropVariantClear can clear VT_BLOB.
251}
252
253HRESULT CPropVariant::Clear() throw()
254{
255 if (vt == VT_EMPTY)
256 return S_OK;
257 return PropVariant_Clear(this);
258}
259
260HRESULT CPropVariant::Copy(const PROPVARIANT* pSrc) throw()
261{
262 ::VariantClear((tagVARIANT *)this);
263 switch (pSrc->vt)
264 {
265 case VT_UI1:
266 case VT_I1:
267 case VT_I2:
268 case VT_UI2:
269 case VT_BOOL:
270 case VT_I4:
271 case VT_UI4:
272 case VT_R4:
273 case VT_INT:
274 case VT_UINT:
275 case VT_ERROR:
276 case VT_FILETIME:
277 case VT_UI8:
278 case VT_R8:
279 case VT_CY:
280 case VT_DATE:
281 memmove((PROPVARIANT*)this, pSrc, sizeof(PROPVARIANT));
282 return S_OK;
283 }
284 return ::VariantCopy((tagVARIANT *)this, (tagVARIANT *)const_cast<PROPVARIANT *>(pSrc));
285}
286
287
288HRESULT CPropVariant::Attach(PROPVARIANT *pSrc) throw()
289{
290 HRESULT hr = Clear();
291 if (FAILED(hr))
292 return hr;
293 // memcpy((PROPVARIANT *)this, pSrc, sizeof(PROPVARIANT));
294 *(PROPVARIANT *)this = *pSrc;
295 pSrc->vt = VT_EMPTY;
296 return S_OK;
297}
298
299HRESULT CPropVariant::Detach(PROPVARIANT *pDest) throw()
300{
301 if (pDest->vt != VT_EMPTY)
302 {
303 HRESULT hr = PropVariant_Clear(pDest);
304 if (FAILED(hr))
305 return hr;
306 }
307 // memcpy(pDest, this, sizeof(PROPVARIANT));
308 *pDest = *(PROPVARIANT *)this;
309 vt = VT_EMPTY;
310 return S_OK;
311}
312
313HRESULT CPropVariant::InternalClear() throw()
314{
315 if (vt == VT_EMPTY)
316 return S_OK;
317 HRESULT hr = Clear();
318 if (FAILED(hr))
319 {
320 vt = VT_ERROR;
321 scode = hr;
322 }
323 return hr;
324}
325
326void CPropVariant::InternalCopy(const PROPVARIANT *pSrc)
327{
328 HRESULT hr = Copy(pSrc);
329 if (FAILED(hr))
330 {
331 if (hr == E_OUTOFMEMORY)
332 throw kMemException;
333 vt = VT_ERROR;
334 scode = hr;
335 }
336}
337
338int CPropVariant::Compare(const CPropVariant &a) throw()
339{
340 if (vt != a.vt)
341 return MyCompare(vt, a.vt);
342 switch (vt)
343 {
344 case VT_EMPTY: return 0;
345 // case VT_I1: return MyCompare(cVal, a.cVal);
346 case VT_UI1: return MyCompare(bVal, a.bVal);
347 case VT_I2: return MyCompare(iVal, a.iVal);
348 case VT_UI2: return MyCompare(uiVal, a.uiVal);
349 case VT_I4: return MyCompare(lVal, a.lVal);
350 case VT_UI4: return MyCompare(ulVal, a.ulVal);
351 // case VT_UINT: return MyCompare(uintVal, a.uintVal);
352 case VT_I8: return MyCompare(hVal.QuadPart, a.hVal.QuadPart);
353 case VT_UI8: return MyCompare(uhVal.QuadPart, a.uhVal.QuadPart);
354 case VT_BOOL: return -MyCompare(boolVal, a.boolVal);
355 case VT_FILETIME: return ::CompareFileTime(&filetime, &a.filetime);
356 case VT_BSTR: return 0; // Not implemented
357 default: return 0;
358 }
359}
360
361}}