OLD | NEW |
| (Empty) |
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "base/win/scoped_variant.h" | |
6 #include "base/logging.h" | |
7 | |
8 namespace base { | |
9 namespace win { | |
10 | |
11 // Global, const instance of an empty variant. | |
12 const VARIANT ScopedVariant::kEmptyVariant = { VT_EMPTY }; | |
13 | |
14 ScopedVariant::~ScopedVariant() { | |
15 COMPILE_ASSERT(sizeof(ScopedVariant) == sizeof(VARIANT), ScopedVariantSize); | |
16 ::VariantClear(&var_); | |
17 } | |
18 | |
19 ScopedVariant::ScopedVariant(const wchar_t* str) { | |
20 var_.vt = VT_EMPTY; | |
21 Set(str); | |
22 } | |
23 | |
24 ScopedVariant::ScopedVariant(const wchar_t* str, UINT length) { | |
25 var_.vt = VT_BSTR; | |
26 var_.bstrVal = ::SysAllocStringLen(str, length); | |
27 } | |
28 | |
29 ScopedVariant::ScopedVariant(int value, VARTYPE vt) { | |
30 var_.vt = vt; | |
31 var_.lVal = value; | |
32 } | |
33 | |
34 ScopedVariant::ScopedVariant(double value, VARTYPE vt) { | |
35 DCHECK(vt == VT_R8 || vt == VT_DATE); | |
36 var_.vt = vt; | |
37 var_.dblVal = value; | |
38 } | |
39 | |
40 ScopedVariant::ScopedVariant(IDispatch* dispatch) { | |
41 var_.vt = VT_EMPTY; | |
42 Set(dispatch); | |
43 } | |
44 | |
45 ScopedVariant::ScopedVariant(IUnknown* unknown) { | |
46 var_.vt = VT_EMPTY; | |
47 Set(unknown); | |
48 } | |
49 | |
50 ScopedVariant::ScopedVariant(SAFEARRAY* safearray) { | |
51 var_.vt = VT_EMPTY; | |
52 Set(safearray); | |
53 } | |
54 | |
55 ScopedVariant::ScopedVariant(const VARIANT& var) { | |
56 var_.vt = VT_EMPTY; | |
57 Set(var); | |
58 } | |
59 | |
60 void ScopedVariant::Reset(const VARIANT& var) { | |
61 if (&var != &var_) { | |
62 ::VariantClear(&var_); | |
63 var_ = var; | |
64 } | |
65 } | |
66 | |
67 VARIANT ScopedVariant::Release() { | |
68 VARIANT var = var_; | |
69 var_.vt = VT_EMPTY; | |
70 return var; | |
71 } | |
72 | |
73 void ScopedVariant::Swap(ScopedVariant& var) { | |
74 VARIANT tmp = var_; | |
75 var_ = var.var_; | |
76 var.var_ = tmp; | |
77 } | |
78 | |
79 VARIANT* ScopedVariant::Receive() { | |
80 DCHECK(!IsLeakableVarType(var_.vt)) << "variant leak. type: " << var_.vt; | |
81 return &var_; | |
82 } | |
83 | |
84 VARIANT ScopedVariant::Copy() const { | |
85 VARIANT ret = { VT_EMPTY }; | |
86 ::VariantCopy(&ret, &var_); | |
87 return ret; | |
88 } | |
89 | |
90 int ScopedVariant::Compare(const VARIANT& var, bool ignore_case) const { | |
91 ULONG flags = ignore_case ? NORM_IGNORECASE : 0; | |
92 HRESULT hr = ::VarCmp(const_cast<VARIANT*>(&var_), const_cast<VARIANT*>(&var), | |
93 LOCALE_USER_DEFAULT, flags); | |
94 int ret = 0; | |
95 | |
96 switch (hr) { | |
97 case VARCMP_LT: | |
98 ret = -1; | |
99 break; | |
100 | |
101 case VARCMP_GT: | |
102 case VARCMP_NULL: | |
103 ret = 1; | |
104 break; | |
105 | |
106 default: | |
107 // Equal. | |
108 break; | |
109 } | |
110 | |
111 return ret; | |
112 } | |
113 | |
114 void ScopedVariant::Set(const wchar_t* str) { | |
115 DCHECK(!IsLeakableVarType(var_.vt)) << "leaking variant: " << var_.vt; | |
116 var_.vt = VT_BSTR; | |
117 var_.bstrVal = ::SysAllocString(str); | |
118 } | |
119 | |
120 void ScopedVariant::Set(int8 i8) { | |
121 DCHECK(!IsLeakableVarType(var_.vt)) << "leaking variant: " << var_.vt; | |
122 var_.vt = VT_I1; | |
123 var_.cVal = i8; | |
124 } | |
125 | |
126 void ScopedVariant::Set(uint8 ui8) { | |
127 DCHECK(!IsLeakableVarType(var_.vt)) << "leaking variant: " << var_.vt; | |
128 var_.vt = VT_UI1; | |
129 var_.bVal = ui8; | |
130 } | |
131 | |
132 void ScopedVariant::Set(int16 i16) { | |
133 DCHECK(!IsLeakableVarType(var_.vt)) << "leaking variant: " << var_.vt; | |
134 var_.vt = VT_I2; | |
135 var_.iVal = i16; | |
136 } | |
137 | |
138 void ScopedVariant::Set(uint16 ui16) { | |
139 DCHECK(!IsLeakableVarType(var_.vt)) << "leaking variant: " << var_.vt; | |
140 var_.vt = VT_UI2; | |
141 var_.uiVal = ui16; | |
142 } | |
143 | |
144 void ScopedVariant::Set(int32 i32) { | |
145 DCHECK(!IsLeakableVarType(var_.vt)) << "leaking variant: " << var_.vt; | |
146 var_.vt = VT_I4; | |
147 var_.lVal = i32; | |
148 } | |
149 | |
150 void ScopedVariant::Set(uint32 ui32) { | |
151 DCHECK(!IsLeakableVarType(var_.vt)) << "leaking variant: " << var_.vt; | |
152 var_.vt = VT_UI4; | |
153 var_.ulVal = ui32; | |
154 } | |
155 | |
156 void ScopedVariant::Set(int64 i64) { | |
157 DCHECK(!IsLeakableVarType(var_.vt)) << "leaking variant: " << var_.vt; | |
158 var_.vt = VT_I8; | |
159 var_.llVal = i64; | |
160 } | |
161 | |
162 void ScopedVariant::Set(uint64 ui64) { | |
163 DCHECK(!IsLeakableVarType(var_.vt)) << "leaking variant: " << var_.vt; | |
164 var_.vt = VT_UI8; | |
165 var_.ullVal = ui64; | |
166 } | |
167 | |
168 void ScopedVariant::Set(float r32) { | |
169 DCHECK(!IsLeakableVarType(var_.vt)) << "leaking variant: " << var_.vt; | |
170 var_.vt = VT_R4; | |
171 var_.fltVal = r32; | |
172 } | |
173 | |
174 void ScopedVariant::Set(double r64) { | |
175 DCHECK(!IsLeakableVarType(var_.vt)) << "leaking variant: " << var_.vt; | |
176 var_.vt = VT_R8; | |
177 var_.dblVal = r64; | |
178 } | |
179 | |
180 void ScopedVariant::SetDate(DATE date) { | |
181 DCHECK(!IsLeakableVarType(var_.vt)) << "leaking variant: " << var_.vt; | |
182 var_.vt = VT_DATE; | |
183 var_.date = date; | |
184 } | |
185 | |
186 void ScopedVariant::Set(IDispatch* disp) { | |
187 DCHECK(!IsLeakableVarType(var_.vt)) << "leaking variant: " << var_.vt; | |
188 var_.vt = VT_DISPATCH; | |
189 var_.pdispVal = disp; | |
190 if (disp) | |
191 disp->AddRef(); | |
192 } | |
193 | |
194 void ScopedVariant::Set(bool b) { | |
195 DCHECK(!IsLeakableVarType(var_.vt)) << "leaking variant: " << var_.vt; | |
196 var_.vt = VT_BOOL; | |
197 var_.boolVal = b ? VARIANT_TRUE : VARIANT_FALSE; | |
198 } | |
199 | |
200 void ScopedVariant::Set(IUnknown* unk) { | |
201 DCHECK(!IsLeakableVarType(var_.vt)) << "leaking variant: " << var_.vt; | |
202 var_.vt = VT_UNKNOWN; | |
203 var_.punkVal = unk; | |
204 if (unk) | |
205 unk->AddRef(); | |
206 } | |
207 | |
208 void ScopedVariant::Set(SAFEARRAY* array) { | |
209 DCHECK(!IsLeakableVarType(var_.vt)) << "leaking variant: " << var_.vt; | |
210 if (SUCCEEDED(::SafeArrayGetVartype(array, &var_.vt))) { | |
211 var_.vt |= VT_ARRAY; | |
212 var_.parray = array; | |
213 } else { | |
214 DCHECK(!array) << "Unable to determine safearray vartype"; | |
215 var_.vt = VT_EMPTY; | |
216 } | |
217 } | |
218 | |
219 void ScopedVariant::Set(const VARIANT& var) { | |
220 DCHECK(!IsLeakableVarType(var_.vt)) << "leaking variant: " << var_.vt; | |
221 if (FAILED(::VariantCopy(&var_, &var))) { | |
222 DLOG(ERROR) << "VariantCopy failed"; | |
223 var_.vt = VT_EMPTY; | |
224 } | |
225 } | |
226 | |
227 ScopedVariant& ScopedVariant::operator=(const VARIANT& var) { | |
228 if (&var != &var_) { | |
229 VariantClear(&var_); | |
230 Set(var); | |
231 } | |
232 return *this; | |
233 } | |
234 | |
235 bool ScopedVariant::IsLeakableVarType(VARTYPE vt) { | |
236 bool leakable = false; | |
237 switch (vt & VT_TYPEMASK) { | |
238 case VT_BSTR: | |
239 case VT_DISPATCH: | |
240 // we treat VT_VARIANT as leakable to err on the safe side. | |
241 case VT_VARIANT: | |
242 case VT_UNKNOWN: | |
243 case VT_SAFEARRAY: | |
244 | |
245 // very rarely used stuff (if ever): | |
246 case VT_VOID: | |
247 case VT_PTR: | |
248 case VT_CARRAY: | |
249 case VT_USERDEFINED: | |
250 case VT_LPSTR: | |
251 case VT_LPWSTR: | |
252 case VT_RECORD: | |
253 case VT_INT_PTR: | |
254 case VT_UINT_PTR: | |
255 case VT_FILETIME: | |
256 case VT_BLOB: | |
257 case VT_STREAM: | |
258 case VT_STORAGE: | |
259 case VT_STREAMED_OBJECT: | |
260 case VT_STORED_OBJECT: | |
261 case VT_BLOB_OBJECT: | |
262 case VT_VERSIONED_STREAM: | |
263 case VT_BSTR_BLOB: | |
264 leakable = true; | |
265 break; | |
266 } | |
267 | |
268 if (!leakable && (vt & VT_ARRAY) != 0) { | |
269 leakable = true; | |
270 } | |
271 | |
272 return leakable; | |
273 } | |
274 | |
275 } // namespace win | |
276 } // namespace base | |
OLD | NEW |