1 // Windows/PropVariant.cpp
2 
3 #include "StdAfx.h"
4 
5 #include "PropVariant.h"
6 
7 #include "../Common/Defs.h"
8 
9 namespace NWindows {
10 namespace NCOM {
11 
CPropVariant(const PROPVARIANT & varSrc)12 CPropVariant::CPropVariant(const PROPVARIANT &varSrc)
13 {
14   vt = VT_EMPTY;
15   InternalCopy(&varSrc);
16 }
17 
CPropVariant(const CPropVariant & varSrc)18 CPropVariant::CPropVariant(const CPropVariant &varSrc)
19 {
20   vt = VT_EMPTY;
21   InternalCopy(&varSrc);
22 }
23 
CPropVariant(BSTR bstrSrc)24 CPropVariant::CPropVariant(BSTR bstrSrc)
25 {
26   vt = VT_EMPTY;
27   *this = bstrSrc;
28 }
29 
CPropVariant(LPCOLESTR lpszSrc)30 CPropVariant::CPropVariant(LPCOLESTR lpszSrc)
31 {
32   vt = VT_EMPTY;
33   *this = lpszSrc;
34 }
35 
operator =(const CPropVariant & varSrc)36 CPropVariant& CPropVariant::operator=(const CPropVariant &varSrc)
37 {
38   InternalCopy(&varSrc);
39   return *this;
40 }
operator =(const PROPVARIANT & varSrc)41 CPropVariant& CPropVariant::operator=(const PROPVARIANT &varSrc)
42 {
43   InternalCopy(&varSrc);
44   return *this;
45 }
46 
operator =(BSTR bstrSrc)47 CPropVariant& CPropVariant::operator=(BSTR bstrSrc)
48 {
49   *this = (LPCOLESTR)bstrSrc;
50   return *this;
51 }
52 
53 static const char *kMemException = "out of memory";
54 
operator =(LPCOLESTR lpszSrc)55 CPropVariant& 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 
operator =(const char * s)71 CPropVariant& 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 
operator =(bool bSrc)92 CPropVariant& 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 
SET_PROP_FUNC(Byte,VT_UI1,bVal)108 SET_PROP_FUNC(Byte, VT_UI1, bVal)
109 SET_PROP_FUNC(Int16, VT_I2, iVal)
110 SET_PROP_FUNC(Int32, VT_I4, lVal)
111 SET_PROP_FUNC(UInt32, VT_UI4, ulVal)
112 SET_PROP_FUNC(UInt64, VT_UI8, uhVal.QuadPart)
113 SET_PROP_FUNC(const FILETIME &, VT_FILETIME, filetime)
114 
115 static 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 
Clear()142 HRESULT CPropVariant::Clear()
143 {
144   return MyPropVariantClear(this);
145 }
146 
Copy(const PROPVARIANT * pSrc)147 HRESULT 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 
Attach(PROPVARIANT * pSrc)175 HRESULT 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 
Detach(PROPVARIANT * pDest)185 HRESULT 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 
InternalClear()195 HRESULT 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 
InternalCopy(const PROPVARIANT * pSrc)206 void 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 
Compare(const CPropVariant & a)218 int 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