1// Windows/PropVariant.cpp
2
3#include "StdAfx.h"
4
5#include "PropVariant.h"
6
7#include "../Common/Defs.h"
8
9namespace NWindows {
10namespace NCOM {
11
12CPropVariant::CPropVariant(const PROPVARIANT &varSrc)
13{
14  vt = VT_EMPTY;
15  InternalCopy(&varSrc);
16}
17
18CPropVariant::CPropVariant(const CPropVariant &varSrc)
19{
20  vt = VT_EMPTY;
21  InternalCopy(&varSrc);
22}
23
24CPropVariant::CPropVariant(BSTR bstrSrc)
25{
26  vt = VT_EMPTY;
27  *this = bstrSrc;
28}
29
30CPropVariant::CPropVariant(LPCOLESTR lpszSrc)
31{
32  vt = VT_EMPTY;
33  *this = lpszSrc;
34}
35
36CPropVariant& CPropVariant::operator=(const CPropVariant &varSrc)
37{
38  InternalCopy(&varSrc);
39  return *this;
40}
41CPropVariant& CPropVariant::operator=(const PROPVARIANT &varSrc)
42{
43  InternalCopy(&varSrc);
44  return *this;
45}
46
47CPropVariant& CPropVariant::operator=(BSTR bstrSrc)
48{
49  *this = (LPCOLESTR)bstrSrc;
50  return *this;
51}
52
53static const char *kMemException = "out of memory";
54
55CPropVariant& CPropVariant::operator=(LPCOLESTR lpszSrc)
56{
57  InternalClear();
58  vt = VT_BSTR;
59  wReserved1 = 0;
60  bstrVal = ::SysAllocString(lpszSrc);
61  if (bstrVal == NULL && lpszSrc != NULL)
62  {
63    throw kMemException;
64    // vt = VT_ERROR;
65    // scode = E_OUTOFMEMORY;
66  }
67  return *this;
68}
69
70
71CPropVariant& CPropVariant::operator=(const char *s)
72{
73  InternalClear();
74  vt = VT_BSTR;
75  wReserved1 = 0;
76  UINT len = (UINT)strlen(s);
77  bstrVal = ::SysAllocStringByteLen(0, (UINT)len * sizeof(OLECHAR));
78  if (bstrVal == NULL)
79  {
80    throw kMemException;
81    // vt = VT_ERROR;
82    // scode = E_OUTOFMEMORY;
83  }
84  else
85  {
86    for (UINT i = 0; i <= len; i++)
87      bstrVal[i] = s[i];
88  }
89  return *this;
90}
91
92CPropVariant& CPropVariant::operator=(bool bSrc)
93{
94  if (vt != VT_BOOL)
95  {
96    InternalClear();
97    vt = VT_BOOL;
98  }
99  boolVal = bSrc ? VARIANT_TRUE : VARIANT_FALSE;
100  return *this;
101}
102
103#define SET_PROP_FUNC(type, id, dest) \
104  CPropVariant& CPropVariant::operator=(type value) \
105  { if (vt != id) { InternalClear(); vt = id; } \
106    dest = value; return *this; }
107
108SET_PROP_FUNC(Byte, VT_UI1, bVal)
109SET_PROP_FUNC(Int16, VT_I2, iVal)
110SET_PROP_FUNC(Int32, VT_I4, lVal)
111SET_PROP_FUNC(UInt32, VT_UI4, ulVal)
112SET_PROP_FUNC(UInt64, VT_UI8, uhVal.QuadPart)
113SET_PROP_FUNC(const FILETIME &, VT_FILETIME, filetime)
114
115static HRESULT MyPropVariantClear(PROPVARIANT *prop)
116{
117  switch(prop->vt)
118  {
119    case VT_UI1:
120    case VT_I1:
121    case VT_I2:
122    case VT_UI2:
123    case VT_BOOL:
124    case VT_I4:
125    case VT_UI4:
126    case VT_R4:
127    case VT_INT:
128    case VT_UINT:
129    case VT_ERROR:
130    case VT_FILETIME:
131    case VT_UI8:
132    case VT_R8:
133    case VT_CY:
134    case VT_DATE:
135      prop->vt = VT_EMPTY;
136      prop->wReserved1 = 0;
137      return S_OK;
138  }
139  return ::VariantClear((VARIANTARG *)prop);
140}
141
142HRESULT CPropVariant::Clear()
143{
144  return MyPropVariantClear(this);
145}
146
147HRESULT CPropVariant::Copy(const PROPVARIANT* pSrc)
148{
149  ::VariantClear((tagVARIANT *)this);
150  switch(pSrc->vt)
151  {
152    case VT_UI1:
153    case VT_I1:
154    case VT_I2:
155    case VT_UI2:
156    case VT_BOOL:
157    case VT_I4:
158    case VT_UI4:
159    case VT_R4:
160    case VT_INT:
161    case VT_UINT:
162    case VT_ERROR:
163    case VT_FILETIME:
164    case VT_UI8:
165    case VT_R8:
166    case VT_CY:
167    case VT_DATE:
168      memmove((PROPVARIANT*)this, pSrc, sizeof(PROPVARIANT));
169      return S_OK;
170  }
171  return ::VariantCopy((tagVARIANT *)this, (tagVARIANT *)const_cast<PROPVARIANT *>(pSrc));
172}
173
174
175HRESULT CPropVariant::Attach(PROPVARIANT *pSrc)
176{
177  HRESULT hr = Clear();
178  if (FAILED(hr))
179    return hr;
180  memcpy(this, pSrc, sizeof(PROPVARIANT));
181  pSrc->vt = VT_EMPTY;
182  return S_OK;
183}
184
185HRESULT CPropVariant::Detach(PROPVARIANT *pDest)
186{
187  HRESULT hr = MyPropVariantClear(pDest);
188  if (FAILED(hr))
189    return hr;
190  memcpy(pDest, this, sizeof(PROPVARIANT));
191  vt = VT_EMPTY;
192  return S_OK;
193}
194
195HRESULT CPropVariant::InternalClear()
196{
197  HRESULT hr = Clear();
198  if (FAILED(hr))
199  {
200    vt = VT_ERROR;
201    scode = hr;
202  }
203  return hr;
204}
205
206void CPropVariant::InternalCopy(const PROPVARIANT *pSrc)
207{
208  HRESULT hr = Copy(pSrc);
209  if (FAILED(hr))
210  {
211    if (hr == E_OUTOFMEMORY)
212      throw kMemException;
213    vt = VT_ERROR;
214    scode = hr;
215  }
216}
217
218int CPropVariant::Compare(const CPropVariant &a)
219{
220  if (vt != a.vt)
221    return MyCompare(vt, a.vt);
222  switch (vt)
223  {
224    case VT_EMPTY: return 0;
225    // case VT_I1: return MyCompare(cVal, a.cVal);
226    case VT_UI1: return MyCompare(bVal, a.bVal);
227    case VT_I2: return MyCompare(iVal, a.iVal);
228    case VT_UI2: return MyCompare(uiVal, a.uiVal);
229    case VT_I4: return MyCompare(lVal, a.lVal);
230    case VT_UI4: return MyCompare(ulVal, a.ulVal);
231    // case VT_UINT: return MyCompare(uintVal, a.uintVal);
232    case VT_I8: return MyCompare(hVal.QuadPart, a.hVal.QuadPart);
233    case VT_UI8: return MyCompare(uhVal.QuadPart, a.uhVal.QuadPart);
234    case VT_BOOL: return -MyCompare(boolVal, a.boolVal);
235    case VT_FILETIME: return ::CompareFileTime(&filetime, &a.filetime);
236    case VT_BSTR:
237      return 0; // Not implemented
238      // return MyCompare(aPropVarint.cVal);
239    default: return 0;
240  }
241}
242
243}}
244