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