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) {