15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2010 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/win/scoped_variant.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace base {
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace win {
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Global, const instance of an empty variant.
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const VARIANT ScopedVariant::kEmptyVariant = { VT_EMPTY };
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ScopedVariant::~ScopedVariant() {
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  COMPILE_ASSERT(sizeof(ScopedVariant) == sizeof(VARIANT), ScopedVariantSize);
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ::VariantClear(&var_);
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ScopedVariant::ScopedVariant(const wchar_t* str) {
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var_.vt = VT_EMPTY;
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Set(str);
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ScopedVariant::ScopedVariant(const wchar_t* str, UINT length) {
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var_.vt = VT_BSTR;
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var_.bstrVal = ::SysAllocStringLen(str, length);
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ScopedVariant::ScopedVariant(int value, VARTYPE vt) {
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var_.vt = vt;
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var_.lVal = value;
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ScopedVariant::ScopedVariant(double value, VARTYPE vt) {
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(vt == VT_R8 || vt == VT_DATE);
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var_.vt = vt;
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var_.dblVal = value;
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ScopedVariant::ScopedVariant(IDispatch* dispatch) {
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var_.vt = VT_EMPTY;
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Set(dispatch);
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ScopedVariant::ScopedVariant(IUnknown* unknown) {
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var_.vt = VT_EMPTY;
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Set(unknown);
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ScopedVariant::ScopedVariant(SAFEARRAY* safearray) {
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var_.vt = VT_EMPTY;
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Set(safearray);
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ScopedVariant::ScopedVariant(const VARIANT& var) {
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var_.vt = VT_EMPTY;
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Set(var);
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ScopedVariant::Reset(const VARIANT& var) {
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (&var != &var_) {
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ::VariantClear(&var_);
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var_ = var;
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)VARIANT ScopedVariant::Release() {
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VARIANT var = var_;
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var_.vt = VT_EMPTY;
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return var;
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ScopedVariant::Swap(ScopedVariant& var) {
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VARIANT tmp = var_;
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var_ = var.var_;
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var.var_ = tmp;
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)VARIANT* ScopedVariant::Receive() {
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!IsLeakableVarType(var_.vt)) << "variant leak. type: " << var_.vt;
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return &var_;
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)VARIANT ScopedVariant::Copy() const {
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VARIANT ret = { VT_EMPTY };
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ::VariantCopy(&ret, &var_);
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ret;
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int ScopedVariant::Compare(const VARIANT& var, bool ignore_case) const {
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ULONG flags = ignore_case ? NORM_IGNORECASE : 0;
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HRESULT hr = ::VarCmp(const_cast<VARIANT*>(&var_), const_cast<VARIANT*>(&var),
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        LOCALE_USER_DEFAULT, flags);
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int ret = 0;
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (hr) {
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case VARCMP_LT:
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ret = -1;
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case VARCMP_GT:
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case VARCMP_NULL:
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ret = 1;
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Equal.
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ret;
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ScopedVariant::Set(const wchar_t* str) {
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!IsLeakableVarType(var_.vt)) << "leaking variant: " << var_.vt;
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var_.vt = VT_BSTR;
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var_.bstrVal = ::SysAllocString(str);
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ScopedVariant::Set(int8 i8) {
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!IsLeakableVarType(var_.vt)) << "leaking variant: " << var_.vt;
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var_.vt = VT_I1;
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var_.cVal = i8;
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ScopedVariant::Set(uint8 ui8) {
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!IsLeakableVarType(var_.vt)) << "leaking variant: " << var_.vt;
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var_.vt = VT_UI1;
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var_.bVal = ui8;
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ScopedVariant::Set(int16 i16) {
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!IsLeakableVarType(var_.vt)) << "leaking variant: " << var_.vt;
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var_.vt = VT_I2;
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var_.iVal = i16;
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ScopedVariant::Set(uint16 ui16) {
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!IsLeakableVarType(var_.vt)) << "leaking variant: " << var_.vt;
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var_.vt = VT_UI2;
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var_.uiVal = ui16;
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ScopedVariant::Set(int32 i32) {
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!IsLeakableVarType(var_.vt)) << "leaking variant: " << var_.vt;
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var_.vt = VT_I4;
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var_.lVal = i32;
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ScopedVariant::Set(uint32 ui32) {
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!IsLeakableVarType(var_.vt)) << "leaking variant: " << var_.vt;
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var_.vt = VT_UI4;
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var_.ulVal = ui32;
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ScopedVariant::Set(int64 i64) {
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!IsLeakableVarType(var_.vt)) << "leaking variant: " << var_.vt;
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var_.vt = VT_I8;
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var_.llVal = i64;
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ScopedVariant::Set(uint64 ui64) {
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!IsLeakableVarType(var_.vt)) << "leaking variant: " << var_.vt;
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var_.vt = VT_UI8;
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var_.ullVal = ui64;
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ScopedVariant::Set(float r32) {
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!IsLeakableVarType(var_.vt)) << "leaking variant: " << var_.vt;
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var_.vt = VT_R4;
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var_.fltVal = r32;
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ScopedVariant::Set(double r64) {
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!IsLeakableVarType(var_.vt)) << "leaking variant: " << var_.vt;
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var_.vt = VT_R8;
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var_.dblVal = r64;
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ScopedVariant::SetDate(DATE date) {
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!IsLeakableVarType(var_.vt)) << "leaking variant: " << var_.vt;
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var_.vt = VT_DATE;
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var_.date = date;
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ScopedVariant::Set(IDispatch* disp) {
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!IsLeakableVarType(var_.vt)) << "leaking variant: " << var_.vt;
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var_.vt = VT_DISPATCH;
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var_.pdispVal = disp;
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (disp)
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    disp->AddRef();
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ScopedVariant::Set(bool b) {
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!IsLeakableVarType(var_.vt)) << "leaking variant: " << var_.vt;
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var_.vt = VT_BOOL;
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var_.boolVal = b ? VARIANT_TRUE : VARIANT_FALSE;
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ScopedVariant::Set(IUnknown* unk) {
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!IsLeakableVarType(var_.vt)) << "leaking variant: " << var_.vt;
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var_.vt = VT_UNKNOWN;
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var_.punkVal = unk;
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (unk)
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unk->AddRef();
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ScopedVariant::Set(SAFEARRAY* array) {
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!IsLeakableVarType(var_.vt)) << "leaking variant: " << var_.vt;
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (SUCCEEDED(::SafeArrayGetVartype(array, &var_.vt))) {
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var_.vt |= VT_ARRAY;
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var_.parray = array;
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(!array) << "Unable to determine safearray vartype";
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var_.vt = VT_EMPTY;
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ScopedVariant::Set(const VARIANT& var) {
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!IsLeakableVarType(var_.vt)) << "leaking variant: " << var_.vt;
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (FAILED(::VariantCopy(&var_, &var))) {
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DLOG(ERROR) << "VariantCopy failed";
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var_.vt = VT_EMPTY;
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ScopedVariant& ScopedVariant::operator=(const VARIANT& var) {
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (&var != &var_) {
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VariantClear(&var_);
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Set(var);
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return *this;
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ScopedVariant::IsLeakableVarType(VARTYPE vt) {
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool leakable = false;
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (vt & VT_TYPEMASK) {
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case VT_BSTR:
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case VT_DISPATCH:
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // we treat VT_VARIANT as leakable to err on the safe side.
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case VT_VARIANT:
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case VT_UNKNOWN:
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case VT_SAFEARRAY:
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // very rarely used stuff (if ever):
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case VT_VOID:
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case VT_PTR:
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case VT_CARRAY:
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case VT_USERDEFINED:
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case VT_LPSTR:
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case VT_LPWSTR:
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case VT_RECORD:
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case VT_INT_PTR:
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case VT_UINT_PTR:
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case VT_FILETIME:
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case VT_BLOB:
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case VT_STREAM:
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case VT_STORAGE:
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case VT_STREAMED_OBJECT:
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case VT_STORED_OBJECT:
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case VT_BLOB_OBJECT:
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case VT_VERSIONED_STREAM:
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case VT_BSTR_BLOB:
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      leakable = true;
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!leakable && (vt & VT_ARRAY) != 0) {
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    leakable = true;
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return leakable;
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace win
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace base
277