xref: /aosp_15_r20/external/lzma/CPP/Windows/PropVariant.cpp (revision f6dc9357d832569d4d1f5d24eacdb3935a1ae8e6)
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 
AllocBstrFromAscii(const char * s)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 
PropVarEm_Alloc_Bstr(PROPVARIANT * p,unsigned numChars)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 
PropVarEm_Set_Str(PROPVARIANT * p,const char * s)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 
CPropVariant(const PROPVARIANT & varSrc)52 CPropVariant::CPropVariant(const PROPVARIANT &varSrc)
53 {
54   vt = VT_EMPTY;
55   InternalCopy(&varSrc);
56 }
57 
CPropVariant(const CPropVariant & varSrc)58 CPropVariant::CPropVariant(const CPropVariant &varSrc)
59 {
60   vt = VT_EMPTY;
61   InternalCopy(&varSrc);
62 }
63 
CPropVariant(BSTR bstrSrc)64 CPropVariant::CPropVariant(BSTR bstrSrc)
65 {
66   vt = VT_EMPTY;
67   *this = bstrSrc;
68 }
69 
CPropVariant(LPCOLESTR lpszSrc)70 CPropVariant::CPropVariant(LPCOLESTR lpszSrc)
71 {
72   vt = VT_EMPTY;
73   *this = lpszSrc;
74 }
75 
operator =(const CPropVariant & varSrc)76 CPropVariant& CPropVariant::operator=(const CPropVariant &varSrc)
77 {
78   InternalCopy(&varSrc);
79   return *this;
80 }
81 
operator =(const PROPVARIANT & varSrc)82 CPropVariant& CPropVariant::operator=(const PROPVARIANT &varSrc)
83 {
84   InternalCopy(&varSrc);
85   return *this;
86 }
87 
operator =(BSTR bstrSrc)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 
operator =(LPCOLESTR lpszSrc)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 
operator =(const UString & s)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 
operator =(const UString2 & s)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 
operator =(const char * s)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 
operator =(bool bSrc)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 
AllocBstr(unsigned numChars)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; wReserved1 = 0;
197 
Set_Int32(Int32 value)198 void CPropVariant::Set_Int32(Int32 value) throw()
199 {
200   SET_PROP_id_dest(VT_I4, lVal)
201 }
202 
Set_Int64(Int64 value)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 
SET_PROP_FUNC(Byte,VT_UI1,bVal)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 #define CASE_SIMPLE_VT_VALUES \
221     case VT_EMPTY:    \
222     case VT_BOOL:     \
223     case VT_FILETIME: \
224     case VT_UI8:      \
225     case VT_UI4:      \
226     case VT_UI2:      \
227     case VT_UI1:      \
228     case VT_I8:       \
229     case VT_I4:       \
230     case VT_I2:       \
231     case VT_I1:       \
232     case VT_UINT:     \
233     case VT_INT:      \
234     case VT_NULL:     \
235     case VT_ERROR:    \
236     case VT_R4:       \
237     case VT_R8:       \
238     case VT_CY:       \
239     case VT_DATE:     \
240 
241 
242 /*
243   ::VariantClear() and ::VariantCopy() don't work, if (vt == VT_FILETIME)
244   So we handle VT_FILETIME and another simple types directly
245   we call system functions for VT_BSTR and for unknown typed
246 */
247 
248 CPropVariant::~CPropVariant() throw()
249 {
250   switch ((unsigned)vt)
251   {
252     CASE_SIMPLE_VT_VALUES
253       // vt = VT_EMPTY; // it's optional
254       return;
255     default: break;
256   }
257   ::VariantClear((tagVARIANT *)this);
258 }
259 
PropVariant_Clear(PROPVARIANT * prop)260 HRESULT PropVariant_Clear(PROPVARIANT *prop) throw()
261 {
262   switch ((unsigned)prop->vt)
263   {
264     CASE_SIMPLE_VT_VALUES
265       prop->vt = VT_EMPTY;
266       break;
267     default:
268     {
269       const HRESULT res = ::VariantClear((VARIANTARG *)prop);
270       if (res != S_OK || prop->vt != VT_EMPTY)
271         return res;
272       break;
273     }
274   }
275   prop->wReserved1 = 0;
276   prop->wReserved2 = 0;
277   prop->wReserved3 = 0;
278   prop->uhVal.QuadPart = 0;
279   return S_OK;
280 }
281 
Clear()282 HRESULT CPropVariant::Clear() throw()
283 {
284   if (vt == VT_EMPTY)
285   {
286     wReserved1 = 0;
287     return S_OK;
288   }
289   return PropVariant_Clear(this);
290 }
291 
Copy(const PROPVARIANT * pSrc)292 HRESULT CPropVariant::Copy(const PROPVARIANT* pSrc) throw()
293 {
294   Clear();
295   switch ((unsigned)pSrc->vt)
296   {
297     CASE_SIMPLE_VT_VALUES
298       memmove((PROPVARIANT*)this, pSrc, sizeof(PROPVARIANT));
299       return S_OK;
300     default: break;
301   }
302   return ::VariantCopy((tagVARIANT *)this, (tagVARIANT *)const_cast<PROPVARIANT *>(pSrc));
303 }
304 
305 
Attach(PROPVARIANT * pSrc)306 HRESULT CPropVariant::Attach(PROPVARIANT *pSrc) throw()
307 {
308   const HRESULT hr = Clear();
309   if (FAILED(hr))
310     return hr;
311   // memcpy((PROPVARIANT *)this, pSrc, sizeof(PROPVARIANT));
312   *(PROPVARIANT *)this = *pSrc;
313   pSrc->vt = VT_EMPTY;
314   pSrc->wReserved1 = 0;
315   return S_OK;
316 }
317 
Detach(PROPVARIANT * pDest)318 HRESULT CPropVariant::Detach(PROPVARIANT *pDest) throw()
319 {
320   if (pDest->vt != VT_EMPTY)
321   {
322     const HRESULT hr = PropVariant_Clear(pDest);
323     if (FAILED(hr))
324       return hr;
325   }
326   // memcpy(pDest, this, sizeof(PROPVARIANT));
327   *pDest = *(PROPVARIANT *)this;
328   vt = VT_EMPTY;
329   wReserved1 = 0;
330   return S_OK;
331 }
332 
InternalClear()333 HRESULT CPropVariant::InternalClear() throw()
334 {
335   if (vt == VT_EMPTY)
336   {
337     wReserved1 = 0;
338     return S_OK;
339   }
340   const HRESULT hr = Clear();
341   if (FAILED(hr))
342   {
343     vt = VT_ERROR;
344     scode = hr;
345   }
346   return hr;
347 }
348 
InternalCopy(const PROPVARIANT * pSrc)349 void CPropVariant::InternalCopy(const PROPVARIANT *pSrc)
350 {
351   const HRESULT hr = Copy(pSrc);
352   if (FAILED(hr))
353   {
354     if (hr == E_OUTOFMEMORY)
355       throw kMemException;
356     vt = VT_ERROR;
357     scode = hr;
358   }
359 }
360 
361 
Compare(const CPropVariant & a)362 int CPropVariant::Compare(const CPropVariant &a) throw()
363 {
364   if (vt != a.vt)
365     return MyCompare(vt, a.vt);
366   switch ((unsigned)vt)
367   {
368     case VT_EMPTY: return 0;
369     // case VT_I1: return MyCompare(cVal, a.cVal);
370     case VT_UI1: return MyCompare(bVal, a.bVal);
371     case VT_I2: return MyCompare(iVal, a.iVal);
372     case VT_UI2: return MyCompare(uiVal, a.uiVal);
373     case VT_I4: return MyCompare(lVal, a.lVal);
374     case VT_UI4: return MyCompare(ulVal, a.ulVal);
375     // case VT_UINT: return MyCompare(uintVal, a.uintVal);
376     case VT_I8: return MyCompare(hVal.QuadPart, a.hVal.QuadPart);
377     case VT_UI8: return MyCompare(uhVal.QuadPart, a.uhVal.QuadPart);
378     case VT_BOOL: return -MyCompare(boolVal, a.boolVal);
379     case VT_FILETIME:
380     {
381       const int res = CompareFileTime(&filetime, &a.filetime);
382       if (res != 0)
383         return res;
384       const unsigned v1 = Get_Ns100();
385       const unsigned v2 = a.Get_Ns100();
386       return MyCompare(v1, v2);
387     }
388     case VT_BSTR: return 0; // Not implemented
389     default: return 0;
390   }
391 }
392 
393 }}
394