diff options
Diffstat (limited to '')
-rw-r--r-- | CPP/Windows/PropVariant.cpp | 361 |
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 | |||
9 | namespace NWindows { | ||
10 | namespace NCOM { | ||
11 | |||
12 | BSTR 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 | |||
26 | HRESULT 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 | |||
39 | HRESULT 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 | |||
52 | CPropVariant::CPropVariant(const PROPVARIANT &varSrc) | ||
53 | { | ||
54 | vt = VT_EMPTY; | ||
55 | InternalCopy(&varSrc); | ||
56 | } | ||
57 | |||
58 | CPropVariant::CPropVariant(const CPropVariant &varSrc) | ||
59 | { | ||
60 | vt = VT_EMPTY; | ||
61 | InternalCopy(&varSrc); | ||
62 | } | ||
63 | |||
64 | CPropVariant::CPropVariant(BSTR bstrSrc) | ||
65 | { | ||
66 | vt = VT_EMPTY; | ||
67 | *this = bstrSrc; | ||
68 | } | ||
69 | |||
70 | CPropVariant::CPropVariant(LPCOLESTR lpszSrc) | ||
71 | { | ||
72 | vt = VT_EMPTY; | ||
73 | *this = lpszSrc; | ||
74 | } | ||
75 | |||
76 | CPropVariant& CPropVariant::operator=(const CPropVariant &varSrc) | ||
77 | { | ||
78 | InternalCopy(&varSrc); | ||
79 | return *this; | ||
80 | } | ||
81 | |||
82 | CPropVariant& CPropVariant::operator=(const PROPVARIANT &varSrc) | ||
83 | { | ||
84 | InternalCopy(&varSrc); | ||
85 | return *this; | ||
86 | } | ||
87 | |||
88 | CPropVariant& CPropVariant::operator=(BSTR bstrSrc) | ||
89 | { | ||
90 | *this = (LPCOLESTR)bstrSrc; | ||
91 | return *this; | ||
92 | } | ||
93 | |||
94 | static const char * const kMemException = "out of memory"; | ||
95 | |||
96 | CPropVariant& 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 | |||
111 | CPropVariant& 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 | |||
122 | CPropVariant& 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 | |||
153 | CPropVariant& 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 | |||
168 | CPropVariant& 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 | |||
179 | BSTR 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 | |||
198 | void CPropVariant::Set_Int32(Int32 value) throw() | ||
199 | { | ||
200 | SET_PROP_id_dest(VT_I4, lVal); | ||
201 | } | ||
202 | |||
203 | void 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 | |||
212 | SET_PROP_FUNC(Byte, VT_UI1, bVal) | ||
213 | // SET_PROP_FUNC(Int16, VT_I2, iVal) | ||
214 | // SET_PROP_FUNC(Int32, VT_I4, lVal) | ||
215 | SET_PROP_FUNC(UInt32, VT_UI4, ulVal) | ||
216 | SET_PROP_FUNC(UInt64, VT_UI8, uhVal.QuadPart) | ||
217 | // SET_PROP_FUNC(Int64, VT_I8, hVal.QuadPart) | ||
218 | SET_PROP_FUNC(const FILETIME &, VT_FILETIME, filetime) | ||
219 | |||
220 | HRESULT 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 | |||
253 | HRESULT CPropVariant::Clear() throw() | ||
254 | { | ||
255 | if (vt == VT_EMPTY) | ||
256 | return S_OK; | ||
257 | return PropVariant_Clear(this); | ||
258 | } | ||
259 | |||
260 | HRESULT 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 | |||
288 | HRESULT 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 | |||
299 | HRESULT 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 | |||
313 | HRESULT 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 | |||
326 | void 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 | |||
338 | int 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 | }} | ||