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