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.
5 #include "base/win/scoped_variant.h"
6 #include "base/logging.h"
11 // Global, const instance of an empty variant.
12 const VARIANT ScopedVariant::kEmptyVariant = { VT_EMPTY };
14 ScopedVariant::~ScopedVariant() {
15 COMPILE_ASSERT(sizeof(ScopedVariant) == sizeof(VARIANT), ScopedVariantSize);
16 ::VariantClear(&var_);
19 ScopedVariant::ScopedVariant(const wchar_t* str) {
24 ScopedVariant::ScopedVariant(const wchar_t* str, UINT length) {
26 var_.bstrVal = ::SysAllocStringLen(str, length);
29 ScopedVariant::ScopedVariant(int value, VARTYPE vt) {
34 ScopedVariant::ScopedVariant(double value, VARTYPE vt) {
35 DCHECK(vt == VT_R8 || vt == VT_DATE);
40 ScopedVariant::ScopedVariant(IDispatch* dispatch) {
45 ScopedVariant::ScopedVariant(IUnknown* unknown) {
50 ScopedVariant::ScopedVariant(SAFEARRAY* safearray) {
55 ScopedVariant::ScopedVariant(const VARIANT& var) {
60 void ScopedVariant::Reset(const VARIANT& var) {
62 ::VariantClear(&var_);
67 VARIANT ScopedVariant::Release() {
73 void ScopedVariant::Swap(ScopedVariant& var) {
79 VARIANT* ScopedVariant::Receive() {
80 DCHECK(!IsLeakableVarType(var_.vt)) << "variant leak. type: " << var_.vt;
84 VARIANT ScopedVariant::Copy() const {
85 VARIANT ret = { VT_EMPTY };
86 ::VariantCopy(&ret, &var_);
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);
114 void ScopedVariant::Set(const wchar_t* str) {
115 DCHECK(!IsLeakableVarType(var_.vt)) << "leaking variant: " << var_.vt;
117 var_.bstrVal = ::SysAllocString(str);
120 void ScopedVariant::Set(int8 i8) {
121 DCHECK(!IsLeakableVarType(var_.vt)) << "leaking variant: " << var_.vt;
126 void ScopedVariant::Set(uint8 ui8) {
127 DCHECK(!IsLeakableVarType(var_.vt)) << "leaking variant: " << var_.vt;
132 void ScopedVariant::Set(int16 i16) {
133 DCHECK(!IsLeakableVarType(var_.vt)) << "leaking variant: " << var_.vt;
138 void ScopedVariant::Set(uint16 ui16) {
139 DCHECK(!IsLeakableVarType(var_.vt)) << "leaking variant: " << var_.vt;
144 void ScopedVariant::Set(int32 i32) {
145 DCHECK(!IsLeakableVarType(var_.vt)) << "leaking variant: " << var_.vt;
150 void ScopedVariant::Set(uint32 ui32) {
151 DCHECK(!IsLeakableVarType(var_.vt)) << "leaking variant: " << var_.vt;
156 void ScopedVariant::Set(int64 i64) {
157 DCHECK(!IsLeakableVarType(var_.vt)) << "leaking variant: " << var_.vt;
162 void ScopedVariant::Set(uint64 ui64) {
163 DCHECK(!IsLeakableVarType(var_.vt)) << "leaking variant: " << var_.vt;
168 void ScopedVariant::Set(float r32) {
169 DCHECK(!IsLeakableVarType(var_.vt)) << "leaking variant: " << var_.vt;
174 void ScopedVariant::Set(double r64) {
175 DCHECK(!IsLeakableVarType(var_.vt)) << "leaking variant: " << var_.vt;
180 void ScopedVariant::SetDate(DATE date) {
181 DCHECK(!IsLeakableVarType(var_.vt)) << "leaking variant: " << var_.vt;
186 void ScopedVariant::Set(IDispatch* disp) {
187 DCHECK(!IsLeakableVarType(var_.vt)) << "leaking variant: " << var_.vt;
188 var_.vt = VT_DISPATCH;
189 var_.pdispVal = disp;
194 void ScopedVariant::Set(bool b) {
195 DCHECK(!IsLeakableVarType(var_.vt)) << "leaking variant: " << var_.vt;
197 var_.boolVal = b ? VARIANT_TRUE : VARIANT_FALSE;
200 void ScopedVariant::Set(IUnknown* unk) {
201 DCHECK(!IsLeakableVarType(var_.vt)) << "leaking variant: " << var_.vt;
202 var_.vt = VT_UNKNOWN;
208 void ScopedVariant::Set(SAFEARRAY* array) {
209 DCHECK(!IsLeakableVarType(var_.vt)) << "leaking variant: " << var_.vt;
210 if (SUCCEEDED(::SafeArrayGetVartype(array, &var_.vt))) {
214 DCHECK(!array) << "Unable to determine safearray vartype";
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";
227 ScopedVariant& ScopedVariant::operator=(const VARIANT& var) {
235 bool ScopedVariant::IsLeakableVarType(VARTYPE vt) {
236 bool leakable = false;
237 switch (vt & VT_TYPEMASK) {
240 // we treat VT_VARIANT as leakable to err on the safe side.
245 // very rarely used stuff (if ever):
259 case VT_STREAMED_OBJECT:
260 case VT_STORED_OBJECT:
262 case VT_VERSIONED_STREAM:
268 if (!leakable && (vt & VT_ARRAY) != 0) {