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