1370b324cSopenharmony_ci// Windows/PropVariant.cpp
2370b324cSopenharmony_ci
3370b324cSopenharmony_ci#include "StdAfx.h"
4370b324cSopenharmony_ci
5370b324cSopenharmony_ci#include "../Common/Defs.h"
6370b324cSopenharmony_ci
7370b324cSopenharmony_ci#include "PropVariant.h"
8370b324cSopenharmony_ci
9370b324cSopenharmony_cinamespace NWindows {
10370b324cSopenharmony_cinamespace NCOM {
11370b324cSopenharmony_ci
12370b324cSopenharmony_ciBSTR AllocBstrFromAscii(const char *s) throw()
13370b324cSopenharmony_ci{
14370b324cSopenharmony_ci  if (!s)
15370b324cSopenharmony_ci    return NULL;
16370b324cSopenharmony_ci  UINT len = (UINT)strlen(s);
17370b324cSopenharmony_ci  BSTR p = ::SysAllocStringLen(NULL, len);
18370b324cSopenharmony_ci  if (p)
19370b324cSopenharmony_ci  {
20370b324cSopenharmony_ci    for (UINT i = 0; i <= len; i++)
21370b324cSopenharmony_ci      p[i] = (Byte)s[i];
22370b324cSopenharmony_ci  }
23370b324cSopenharmony_ci  return p;
24370b324cSopenharmony_ci}
25370b324cSopenharmony_ci
26370b324cSopenharmony_ciHRESULT PropVarEm_Alloc_Bstr(PROPVARIANT *p, unsigned numChars) throw()
27370b324cSopenharmony_ci{
28370b324cSopenharmony_ci  p->bstrVal = ::SysAllocStringLen(NULL, numChars);
29370b324cSopenharmony_ci  if (!p->bstrVal)
30370b324cSopenharmony_ci  {
31370b324cSopenharmony_ci    p->vt = VT_ERROR;
32370b324cSopenharmony_ci    p->scode = E_OUTOFMEMORY;
33370b324cSopenharmony_ci    return E_OUTOFMEMORY;
34370b324cSopenharmony_ci  }
35370b324cSopenharmony_ci  p->vt = VT_BSTR;
36370b324cSopenharmony_ci  return S_OK;
37370b324cSopenharmony_ci}
38370b324cSopenharmony_ci
39370b324cSopenharmony_ciHRESULT PropVarEm_Set_Str(PROPVARIANT *p, const char *s) throw()
40370b324cSopenharmony_ci{
41370b324cSopenharmony_ci  p->bstrVal = AllocBstrFromAscii(s);
42370b324cSopenharmony_ci  if (p->bstrVal)
43370b324cSopenharmony_ci  {
44370b324cSopenharmony_ci    p->vt = VT_BSTR;
45370b324cSopenharmony_ci    return S_OK;
46370b324cSopenharmony_ci  }
47370b324cSopenharmony_ci  p->vt = VT_ERROR;
48370b324cSopenharmony_ci  p->scode = E_OUTOFMEMORY;
49370b324cSopenharmony_ci  return E_OUTOFMEMORY;
50370b324cSopenharmony_ci}
51370b324cSopenharmony_ci
52370b324cSopenharmony_ciCPropVariant::CPropVariant(const PROPVARIANT &varSrc)
53370b324cSopenharmony_ci{
54370b324cSopenharmony_ci  vt = VT_EMPTY;
55370b324cSopenharmony_ci  InternalCopy(&varSrc);
56370b324cSopenharmony_ci}
57370b324cSopenharmony_ci
58370b324cSopenharmony_ciCPropVariant::CPropVariant(const CPropVariant &varSrc)
59370b324cSopenharmony_ci{
60370b324cSopenharmony_ci  vt = VT_EMPTY;
61370b324cSopenharmony_ci  InternalCopy(&varSrc);
62370b324cSopenharmony_ci}
63370b324cSopenharmony_ci
64370b324cSopenharmony_ciCPropVariant::CPropVariant(BSTR bstrSrc)
65370b324cSopenharmony_ci{
66370b324cSopenharmony_ci  vt = VT_EMPTY;
67370b324cSopenharmony_ci  *this = bstrSrc;
68370b324cSopenharmony_ci}
69370b324cSopenharmony_ci
70370b324cSopenharmony_ciCPropVariant::CPropVariant(LPCOLESTR lpszSrc)
71370b324cSopenharmony_ci{
72370b324cSopenharmony_ci  vt = VT_EMPTY;
73370b324cSopenharmony_ci  *this = lpszSrc;
74370b324cSopenharmony_ci}
75370b324cSopenharmony_ci
76370b324cSopenharmony_ciCPropVariant& CPropVariant::operator=(const CPropVariant &varSrc)
77370b324cSopenharmony_ci{
78370b324cSopenharmony_ci  InternalCopy(&varSrc);
79370b324cSopenharmony_ci  return *this;
80370b324cSopenharmony_ci}
81370b324cSopenharmony_ci
82370b324cSopenharmony_ciCPropVariant& CPropVariant::operator=(const PROPVARIANT &varSrc)
83370b324cSopenharmony_ci{
84370b324cSopenharmony_ci  InternalCopy(&varSrc);
85370b324cSopenharmony_ci  return *this;
86370b324cSopenharmony_ci}
87370b324cSopenharmony_ci
88370b324cSopenharmony_ciCPropVariant& CPropVariant::operator=(BSTR bstrSrc)
89370b324cSopenharmony_ci{
90370b324cSopenharmony_ci  *this = (LPCOLESTR)bstrSrc;
91370b324cSopenharmony_ci  return *this;
92370b324cSopenharmony_ci}
93370b324cSopenharmony_ci
94370b324cSopenharmony_cistatic const char * const kMemException = "out of memory";
95370b324cSopenharmony_ci
96370b324cSopenharmony_ciCPropVariant& CPropVariant::operator=(LPCOLESTR lpszSrc)
97370b324cSopenharmony_ci{
98370b324cSopenharmony_ci  InternalClear();
99370b324cSopenharmony_ci  vt = VT_BSTR;
100370b324cSopenharmony_ci  wReserved1 = 0;
101370b324cSopenharmony_ci  bstrVal = ::SysAllocString(lpszSrc);
102370b324cSopenharmony_ci  if (!bstrVal && lpszSrc)
103370b324cSopenharmony_ci  {
104370b324cSopenharmony_ci    throw kMemException;
105370b324cSopenharmony_ci    // vt = VT_ERROR;
106370b324cSopenharmony_ci    // scode = E_OUTOFMEMORY;
107370b324cSopenharmony_ci  }
108370b324cSopenharmony_ci  return *this;
109370b324cSopenharmony_ci}
110370b324cSopenharmony_ci
111370b324cSopenharmony_ciCPropVariant& CPropVariant::operator=(const UString &s)
112370b324cSopenharmony_ci{
113370b324cSopenharmony_ci  InternalClear();
114370b324cSopenharmony_ci  vt = VT_BSTR;
115370b324cSopenharmony_ci  wReserved1 = 0;
116370b324cSopenharmony_ci  bstrVal = ::SysAllocStringLen(s, s.Len());
117370b324cSopenharmony_ci  if (!bstrVal)
118370b324cSopenharmony_ci    throw kMemException;
119370b324cSopenharmony_ci  return *this;
120370b324cSopenharmony_ci}
121370b324cSopenharmony_ci
122370b324cSopenharmony_ciCPropVariant& CPropVariant::operator=(const UString2 &s)
123370b324cSopenharmony_ci{
124370b324cSopenharmony_ci  /*
125370b324cSopenharmony_ci  if (s.IsEmpty())
126370b324cSopenharmony_ci    *this = L"";
127370b324cSopenharmony_ci  else
128370b324cSopenharmony_ci  */
129370b324cSopenharmony_ci  {
130370b324cSopenharmony_ci    InternalClear();
131370b324cSopenharmony_ci    vt = VT_BSTR;
132370b324cSopenharmony_ci    wReserved1 = 0;
133370b324cSopenharmony_ci    bstrVal = ::SysAllocStringLen(s.GetRawPtr(), s.Len());
134370b324cSopenharmony_ci    if (!bstrVal)
135370b324cSopenharmony_ci      throw kMemException;
136370b324cSopenharmony_ci    /* SysAllocStringLen probably appends a null-terminating character for NULL string.
137370b324cSopenharmony_ci       But it doesn't specified in MSDN.
138370b324cSopenharmony_ci       But we suppose that it works
139370b324cSopenharmony_ci
140370b324cSopenharmony_ci    if (!s.GetRawPtr())
141370b324cSopenharmony_ci    {
142370b324cSopenharmony_ci      *bstrVal = 0;
143370b324cSopenharmony_ci    }
144370b324cSopenharmony_ci    */
145370b324cSopenharmony_ci
146370b324cSopenharmony_ci    /* MSDN: Windows CE: SysAllocStringLen() : Passing invalid (and under some circumstances NULL)
147370b324cSopenharmony_ci                         pointers to this function causes  an unexpected termination of the application.
148370b324cSopenharmony_ci       Is it safe? Maybe we must chamnge the code for that case ? */
149370b324cSopenharmony_ci  }
150370b324cSopenharmony_ci  return *this;
151370b324cSopenharmony_ci}
152370b324cSopenharmony_ci
153370b324cSopenharmony_ciCPropVariant& CPropVariant::operator=(const char *s)
154370b324cSopenharmony_ci{
155370b324cSopenharmony_ci  InternalClear();
156370b324cSopenharmony_ci  vt = VT_BSTR;
157370b324cSopenharmony_ci  wReserved1 = 0;
158370b324cSopenharmony_ci  bstrVal = AllocBstrFromAscii(s);
159370b324cSopenharmony_ci  if (!bstrVal)
160370b324cSopenharmony_ci  {
161370b324cSopenharmony_ci    throw kMemException;
162370b324cSopenharmony_ci    // vt = VT_ERROR;
163370b324cSopenharmony_ci    // scode = E_OUTOFMEMORY;
164370b324cSopenharmony_ci  }
165370b324cSopenharmony_ci  return *this;
166370b324cSopenharmony_ci}
167370b324cSopenharmony_ci
168370b324cSopenharmony_ciCPropVariant& CPropVariant::operator=(bool bSrc) throw()
169370b324cSopenharmony_ci{
170370b324cSopenharmony_ci  if (vt != VT_BOOL)
171370b324cSopenharmony_ci  {
172370b324cSopenharmony_ci    InternalClear();
173370b324cSopenharmony_ci    vt = VT_BOOL;
174370b324cSopenharmony_ci  }
175370b324cSopenharmony_ci  boolVal = bSrc ? VARIANT_TRUE : VARIANT_FALSE;
176370b324cSopenharmony_ci  return *this;
177370b324cSopenharmony_ci}
178370b324cSopenharmony_ci
179370b324cSopenharmony_ciBSTR CPropVariant::AllocBstr(unsigned numChars)
180370b324cSopenharmony_ci{
181370b324cSopenharmony_ci  if (vt != VT_EMPTY)
182370b324cSopenharmony_ci    InternalClear();
183370b324cSopenharmony_ci  vt = VT_BSTR;
184370b324cSopenharmony_ci  wReserved1 = 0;
185370b324cSopenharmony_ci  bstrVal = ::SysAllocStringLen(NULL, numChars);
186370b324cSopenharmony_ci  if (!bstrVal)
187370b324cSopenharmony_ci  {
188370b324cSopenharmony_ci    throw kMemException;
189370b324cSopenharmony_ci    // vt = VT_ERROR;
190370b324cSopenharmony_ci    // scode = E_OUTOFMEMORY;
191370b324cSopenharmony_ci  }
192370b324cSopenharmony_ci  return bstrVal;
193370b324cSopenharmony_ci}
194370b324cSopenharmony_ci
195370b324cSopenharmony_ci#define SET_PROP_id_dest(id, dest) \
196370b324cSopenharmony_ci  if (vt != id) { InternalClear(); vt = id; } dest = value; wReserved1 = 0;
197370b324cSopenharmony_ci
198370b324cSopenharmony_civoid CPropVariant::Set_Int32(Int32 value) throw()
199370b324cSopenharmony_ci{
200370b324cSopenharmony_ci  SET_PROP_id_dest(VT_I4, lVal)
201370b324cSopenharmony_ci}
202370b324cSopenharmony_ci
203370b324cSopenharmony_civoid CPropVariant::Set_Int64(Int64 value) throw()
204370b324cSopenharmony_ci{
205370b324cSopenharmony_ci  SET_PROP_id_dest(VT_I8, hVal.QuadPart)
206370b324cSopenharmony_ci}
207370b324cSopenharmony_ci
208370b324cSopenharmony_ci#define SET_PROP_FUNC(type, id, dest) \
209370b324cSopenharmony_ci  CPropVariant& CPropVariant::operator=(type value) throw() \
210370b324cSopenharmony_ci  { SET_PROP_id_dest(id, dest)  return *this; }
211370b324cSopenharmony_ci
212370b324cSopenharmony_ciSET_PROP_FUNC(Byte, VT_UI1, bVal)
213370b324cSopenharmony_ci// SET_PROP_FUNC(Int16, VT_I2, iVal)
214370b324cSopenharmony_ci// SET_PROP_FUNC(Int32, VT_I4, lVal)
215370b324cSopenharmony_ciSET_PROP_FUNC(UInt32, VT_UI4, ulVal)
216370b324cSopenharmony_ciSET_PROP_FUNC(UInt64, VT_UI8, uhVal.QuadPart)
217370b324cSopenharmony_ci// SET_PROP_FUNC(Int64, VT_I8, hVal.QuadPart)
218370b324cSopenharmony_ciSET_PROP_FUNC(const FILETIME &, VT_FILETIME, filetime)
219370b324cSopenharmony_ci
220370b324cSopenharmony_ci#define CASE_SIMPLE_VT_VALUES \
221370b324cSopenharmony_ci    case VT_EMPTY:    \
222370b324cSopenharmony_ci    case VT_BOOL:     \
223370b324cSopenharmony_ci    case VT_FILETIME: \
224370b324cSopenharmony_ci    case VT_UI8:      \
225370b324cSopenharmony_ci    case VT_UI4:      \
226370b324cSopenharmony_ci    case VT_UI2:      \
227370b324cSopenharmony_ci    case VT_UI1:      \
228370b324cSopenharmony_ci    case VT_I8:       \
229370b324cSopenharmony_ci    case VT_I4:       \
230370b324cSopenharmony_ci    case VT_I2:       \
231370b324cSopenharmony_ci    case VT_I1:       \
232370b324cSopenharmony_ci    case VT_UINT:     \
233370b324cSopenharmony_ci    case VT_INT:      \
234370b324cSopenharmony_ci    case VT_NULL:     \
235370b324cSopenharmony_ci    case VT_ERROR:    \
236370b324cSopenharmony_ci    case VT_R4:       \
237370b324cSopenharmony_ci    case VT_R8:       \
238370b324cSopenharmony_ci    case VT_CY:       \
239370b324cSopenharmony_ci    case VT_DATE:     \
240370b324cSopenharmony_ci
241370b324cSopenharmony_ci
242370b324cSopenharmony_ci/*
243370b324cSopenharmony_ci  ::VariantClear() and ::VariantCopy() don't work, if (vt == VT_FILETIME)
244370b324cSopenharmony_ci  So we handle VT_FILETIME and another simple types directly
245370b324cSopenharmony_ci  we call system functions for VT_BSTR and for unknown typed
246370b324cSopenharmony_ci*/
247370b324cSopenharmony_ci
248370b324cSopenharmony_ciCPropVariant::~CPropVariant() throw()
249370b324cSopenharmony_ci{
250370b324cSopenharmony_ci  switch ((unsigned)vt)
251370b324cSopenharmony_ci  {
252370b324cSopenharmony_ci    CASE_SIMPLE_VT_VALUES
253370b324cSopenharmony_ci      // vt = VT_EMPTY; // it's optional
254370b324cSopenharmony_ci      return;
255370b324cSopenharmony_ci  }
256370b324cSopenharmony_ci  ::VariantClear((tagVARIANT *)this);
257370b324cSopenharmony_ci}
258370b324cSopenharmony_ci
259370b324cSopenharmony_ciHRESULT PropVariant_Clear(PROPVARIANT *prop) throw()
260370b324cSopenharmony_ci{
261370b324cSopenharmony_ci  switch ((unsigned)prop->vt)
262370b324cSopenharmony_ci  {
263370b324cSopenharmony_ci    CASE_SIMPLE_VT_VALUES
264370b324cSopenharmony_ci      prop->vt = VT_EMPTY;
265370b324cSopenharmony_ci      break;
266370b324cSopenharmony_ci    default:
267370b324cSopenharmony_ci    {
268370b324cSopenharmony_ci      const HRESULT res = ::VariantClear((VARIANTARG *)prop);
269370b324cSopenharmony_ci      if (res != S_OK || prop->vt != VT_EMPTY)
270370b324cSopenharmony_ci        return res;
271370b324cSopenharmony_ci      break;
272370b324cSopenharmony_ci    }
273370b324cSopenharmony_ci  }
274370b324cSopenharmony_ci  prop->wReserved1 = 0;
275370b324cSopenharmony_ci  prop->wReserved2 = 0;
276370b324cSopenharmony_ci  prop->wReserved3 = 0;
277370b324cSopenharmony_ci  prop->uhVal.QuadPart = 0;
278370b324cSopenharmony_ci  return S_OK;
279370b324cSopenharmony_ci}
280370b324cSopenharmony_ci
281370b324cSopenharmony_ciHRESULT CPropVariant::Clear() throw()
282370b324cSopenharmony_ci{
283370b324cSopenharmony_ci  if (vt == VT_EMPTY)
284370b324cSopenharmony_ci  {
285370b324cSopenharmony_ci    wReserved1 = 0;
286370b324cSopenharmony_ci    return S_OK;
287370b324cSopenharmony_ci  }
288370b324cSopenharmony_ci  return PropVariant_Clear(this);
289370b324cSopenharmony_ci}
290370b324cSopenharmony_ci
291370b324cSopenharmony_ciHRESULT CPropVariant::Copy(const PROPVARIANT* pSrc) throw()
292370b324cSopenharmony_ci{
293370b324cSopenharmony_ci  Clear();
294370b324cSopenharmony_ci  switch ((unsigned)pSrc->vt)
295370b324cSopenharmony_ci  {
296370b324cSopenharmony_ci    CASE_SIMPLE_VT_VALUES
297370b324cSopenharmony_ci      memmove((PROPVARIANT*)this, pSrc, sizeof(PROPVARIANT));
298370b324cSopenharmony_ci      return S_OK;
299370b324cSopenharmony_ci  }
300370b324cSopenharmony_ci  return ::VariantCopy((tagVARIANT *)this, (tagVARIANT *)const_cast<PROPVARIANT *>(pSrc));
301370b324cSopenharmony_ci}
302370b324cSopenharmony_ci
303370b324cSopenharmony_ci
304370b324cSopenharmony_ciHRESULT CPropVariant::Attach(PROPVARIANT *pSrc) throw()
305370b324cSopenharmony_ci{
306370b324cSopenharmony_ci  const HRESULT hr = Clear();
307370b324cSopenharmony_ci  if (FAILED(hr))
308370b324cSopenharmony_ci    return hr;
309370b324cSopenharmony_ci  // memcpy((PROPVARIANT *)this, pSrc, sizeof(PROPVARIANT));
310370b324cSopenharmony_ci  *(PROPVARIANT *)this = *pSrc;
311370b324cSopenharmony_ci  pSrc->vt = VT_EMPTY;
312370b324cSopenharmony_ci  pSrc->wReserved1 = 0;
313370b324cSopenharmony_ci  return S_OK;
314370b324cSopenharmony_ci}
315370b324cSopenharmony_ci
316370b324cSopenharmony_ciHRESULT CPropVariant::Detach(PROPVARIANT *pDest) throw()
317370b324cSopenharmony_ci{
318370b324cSopenharmony_ci  if (pDest->vt != VT_EMPTY)
319370b324cSopenharmony_ci  {
320370b324cSopenharmony_ci    const HRESULT hr = PropVariant_Clear(pDest);
321370b324cSopenharmony_ci    if (FAILED(hr))
322370b324cSopenharmony_ci      return hr;
323370b324cSopenharmony_ci  }
324370b324cSopenharmony_ci  // memcpy(pDest, this, sizeof(PROPVARIANT));
325370b324cSopenharmony_ci  *pDest = *(PROPVARIANT *)this;
326370b324cSopenharmony_ci  vt = VT_EMPTY;
327370b324cSopenharmony_ci  wReserved1 = 0;
328370b324cSopenharmony_ci  return S_OK;
329370b324cSopenharmony_ci}
330370b324cSopenharmony_ci
331370b324cSopenharmony_ciHRESULT CPropVariant::InternalClear() throw()
332370b324cSopenharmony_ci{
333370b324cSopenharmony_ci  if (vt == VT_EMPTY)
334370b324cSopenharmony_ci  {
335370b324cSopenharmony_ci    wReserved1 = 0;
336370b324cSopenharmony_ci    return S_OK;
337370b324cSopenharmony_ci  }
338370b324cSopenharmony_ci  const HRESULT hr = Clear();
339370b324cSopenharmony_ci  if (FAILED(hr))
340370b324cSopenharmony_ci  {
341370b324cSopenharmony_ci    vt = VT_ERROR;
342370b324cSopenharmony_ci    scode = hr;
343370b324cSopenharmony_ci  }
344370b324cSopenharmony_ci  return hr;
345370b324cSopenharmony_ci}
346370b324cSopenharmony_ci
347370b324cSopenharmony_civoid CPropVariant::InternalCopy(const PROPVARIANT *pSrc)
348370b324cSopenharmony_ci{
349370b324cSopenharmony_ci  const HRESULT hr = Copy(pSrc);
350370b324cSopenharmony_ci  if (FAILED(hr))
351370b324cSopenharmony_ci  {
352370b324cSopenharmony_ci    if (hr == E_OUTOFMEMORY)
353370b324cSopenharmony_ci      throw kMemException;
354370b324cSopenharmony_ci    vt = VT_ERROR;
355370b324cSopenharmony_ci    scode = hr;
356370b324cSopenharmony_ci  }
357370b324cSopenharmony_ci}
358370b324cSopenharmony_ci
359370b324cSopenharmony_ci
360370b324cSopenharmony_ciint CPropVariant::Compare(const CPropVariant &a) throw()
361370b324cSopenharmony_ci{
362370b324cSopenharmony_ci  if (vt != a.vt)
363370b324cSopenharmony_ci    return MyCompare(vt, a.vt);
364370b324cSopenharmony_ci  switch ((unsigned)vt)
365370b324cSopenharmony_ci  {
366370b324cSopenharmony_ci    case VT_EMPTY: return 0;
367370b324cSopenharmony_ci    // case VT_I1: return MyCompare(cVal, a.cVal);
368370b324cSopenharmony_ci    case VT_UI1: return MyCompare(bVal, a.bVal);
369370b324cSopenharmony_ci    case VT_I2: return MyCompare(iVal, a.iVal);
370370b324cSopenharmony_ci    case VT_UI2: return MyCompare(uiVal, a.uiVal);
371370b324cSopenharmony_ci    case VT_I4: return MyCompare(lVal, a.lVal);
372370b324cSopenharmony_ci    case VT_UI4: return MyCompare(ulVal, a.ulVal);
373370b324cSopenharmony_ci    // case VT_UINT: return MyCompare(uintVal, a.uintVal);
374370b324cSopenharmony_ci    case VT_I8: return MyCompare(hVal.QuadPart, a.hVal.QuadPart);
375370b324cSopenharmony_ci    case VT_UI8: return MyCompare(uhVal.QuadPart, a.uhVal.QuadPart);
376370b324cSopenharmony_ci    case VT_BOOL: return -MyCompare(boolVal, a.boolVal);
377370b324cSopenharmony_ci    case VT_FILETIME:
378370b324cSopenharmony_ci    {
379370b324cSopenharmony_ci      const int res = CompareFileTime(&filetime, &a.filetime);
380370b324cSopenharmony_ci      if (res != 0)
381370b324cSopenharmony_ci        return res;
382370b324cSopenharmony_ci      const unsigned v1 = Get_Ns100();
383370b324cSopenharmony_ci      const unsigned v2 = a.Get_Ns100();
384370b324cSopenharmony_ci      return MyCompare(v1, v2);
385370b324cSopenharmony_ci    }
386370b324cSopenharmony_ci    case VT_BSTR: return 0; // Not implemented
387370b324cSopenharmony_ci    default: return 0;
388370b324cSopenharmony_ci  }
389370b324cSopenharmony_ci}
390370b324cSopenharmony_ci
391370b324cSopenharmony_ci}}
392