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