1 /* 2 * ReactOS ATL 3 * 4 * Copyright 2009 Andrew Hill <ash77@reactos.org> 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public 8 * License as published by the Free Software Foundation; either 9 * version 2.1 of the License, or (at your option) any later version. 10 * 11 * This library is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 19 */ 20 21 #pragma once 22 23 #include "atlcore.h" 24 25 26 #ifdef _MSC_VER 27 // It is common to use this in ATL constructors. They only store this for later use, so the usage is safe. 28 #pragma warning(disable:4355) 29 #endif 30 31 #ifndef _ATL_PACKING 32 #define _ATL_PACKING 8 33 #endif 34 35 #ifndef _ATL_FREE_THREADED 36 #ifndef _ATL_APARTMENT_THREADED 37 #ifndef _ATL_SINGLE_THREADED 38 #define _ATL_FREE_THREADED 39 #endif 40 #endif 41 #endif 42 43 #ifndef ATLTRY 44 #define ATLTRY(x) x; 45 #endif 46 47 #ifdef _ATL_DISABLE_NO_VTABLE 48 #define ATL_NO_VTABLE 49 #else 50 #define ATL_NO_VTABLE __declspec(novtable) 51 #endif 52 53 namespace ATL 54 { 55 56 57 template<class T> 58 class CComPtr 59 { 60 public: 61 T *p; 62 public: 63 CComPtr() 64 { 65 p = NULL; 66 } 67 68 CComPtr(T *lp) 69 { 70 p = lp; 71 if (p != NULL) 72 p->AddRef(); 73 } 74 75 CComPtr(const CComPtr<T> &lp) 76 { 77 p = lp.p; 78 if (p != NULL) 79 p->AddRef(); 80 } 81 82 ~CComPtr() 83 { 84 if (p != NULL) 85 p->Release(); 86 } 87 88 T *operator = (T *lp) 89 { 90 T* pOld = p; 91 92 p = lp; 93 if (p != NULL) 94 p->AddRef(); 95 96 if (pOld != NULL) 97 pOld->Release(); 98 99 return *this; 100 } 101 102 T *operator = (const CComPtr<T> &lp) 103 { 104 T* pOld = p; 105 106 p = lp.p; 107 if (p != NULL) 108 p->AddRef(); 109 110 if (pOld != NULL) 111 pOld->Release(); 112 113 return *this; 114 } 115 116 // We cannot enable this until gcc starts supporting __uuidof 117 // See CORE-12710 118 #if 0 119 template <typename Q> 120 T* operator=(const CComPtr<Q>& lp) 121 { 122 T* pOld = p; 123 124 if (!lp.p || FAILED(lp.p->QueryInterface(__uuidof(T), (void**)(IUnknown**)&p))) 125 p = NULL; 126 127 if (pOld != NULL) 128 pOld->Release(); 129 130 return *this; 131 } 132 #endif 133 134 void Release() 135 { 136 if (p != NULL) 137 { 138 p->Release(); 139 p = NULL; 140 } 141 } 142 143 void Attach(T *lp) 144 { 145 if (p != NULL) 146 p->Release(); 147 p = lp; 148 } 149 150 T *Detach() 151 { 152 T *saveP; 153 154 saveP = p; 155 p = NULL; 156 return saveP; 157 } 158 159 T **operator & () 160 { 161 ATLASSERT(p == NULL); 162 return &p; 163 } 164 165 operator T * () 166 { 167 return p; 168 } 169 170 T *operator -> () 171 { 172 ATLASSERT(p != NULL); 173 return p; 174 } 175 }; 176 177 178 //CComQIIDPtr<I_ID(Itype)> is the gcc compatible version of CComQIPtr<Itype> 179 #define I_ID(Itype) Itype,&IID_##Itype 180 181 template <class T, const IID* piid> 182 class CComQIIDPtr : 183 public CComPtr<T> 184 { 185 public: 186 // Let's tell GCC how to find a symbol. 187 using CComPtr<T>::p; 188 189 CComQIIDPtr() 190 { 191 } 192 CComQIIDPtr(_Inout_opt_ T* lp) : 193 CComPtr<T>(lp) 194 { 195 } 196 CComQIIDPtr(_Inout_ const CComQIIDPtr<T,piid>& lp): 197 CComPtr<T>(lp.p) 198 { 199 } 200 CComQIIDPtr(_Inout_opt_ IUnknown* lp) 201 { 202 if (lp != NULL) 203 { 204 if (FAILED(lp->QueryInterface(*piid, (void**)(IUnknown**)&p))) 205 p = NULL; 206 } 207 } 208 T *operator = (T *lp) 209 { 210 T* pOld = p; 211 212 p = lp; 213 if (p != NULL) 214 p->AddRef(); 215 216 if (pOld != NULL) 217 pOld->Release(); 218 219 return *this; 220 } 221 222 T *operator = (const CComQIIDPtr<T,piid> &lp) 223 { 224 T* pOld = p; 225 226 p = lp.p; 227 if (p != NULL) 228 p->AddRef(); 229 230 if (pOld != NULL) 231 pOld->Release(); 232 233 return *this; 234 } 235 236 T * operator=(IUnknown* lp) 237 { 238 T* pOld = p; 239 240 if (!lp || FAILED(lp->QueryInterface(*piid, (void**)(IUnknown**)&p))) 241 p = NULL; 242 243 if (pOld != NULL) 244 pOld->Release(); 245 246 return *this; 247 } 248 }; 249 250 251 class CComBSTR 252 { 253 public: 254 BSTR m_str; 255 public: 256 CComBSTR() : 257 m_str(NULL) 258 { 259 } 260 261 CComBSTR(LPCOLESTR pSrc) 262 { 263 if (pSrc == NULL) 264 m_str = NULL; 265 else 266 m_str = ::SysAllocString(pSrc); 267 } 268 269 CComBSTR(int length) 270 { 271 if (length == 0) 272 m_str = NULL; 273 else 274 m_str = ::SysAllocStringLen(NULL, length); 275 } 276 277 CComBSTR(int length, LPCOLESTR pSrc) 278 { 279 if (length == 0) 280 m_str = NULL; 281 else 282 m_str = ::SysAllocStringLen(pSrc, length); 283 } 284 285 CComBSTR(PCSTR pSrc) 286 { 287 if (pSrc) 288 { 289 int len = MultiByteToWideChar(CP_THREAD_ACP, 0, pSrc, -1, NULL, 0); 290 m_str = ::SysAllocStringLen(NULL, len - 1); 291 if (m_str) 292 { 293 int res = MultiByteToWideChar(CP_THREAD_ACP, 0, pSrc, -1, m_str, len); 294 ATLASSERT(res == len); 295 if (res != len) 296 { 297 ::SysFreeString(m_str); 298 m_str = NULL; 299 } 300 } 301 } 302 else 303 { 304 m_str = NULL; 305 } 306 } 307 308 CComBSTR(const CComBSTR &other) 309 { 310 m_str = other.Copy(); 311 } 312 313 CComBSTR(REFGUID guid) 314 { 315 OLECHAR szGuid[40]; 316 ::StringFromGUID2(guid, szGuid, 40); 317 m_str = ::SysAllocString(szGuid); 318 } 319 320 ~CComBSTR() 321 { 322 ::SysFreeString(m_str); 323 m_str = NULL; 324 } 325 326 operator BSTR () const 327 { 328 return m_str; 329 } 330 331 BSTR *operator & () 332 { 333 return &m_str; 334 } 335 336 CComBSTR &operator = (const CComBSTR &other) 337 { 338 ::SysFreeString(m_str); 339 m_str = other.Copy(); 340 return *this; 341 } 342 343 void Attach(BSTR bstr) 344 { 345 ::SysFreeString(m_str); 346 m_str = bstr; 347 } 348 349 BSTR Detach() 350 { 351 BSTR str = m_str; 352 m_str = NULL; 353 return str; 354 } 355 356 BSTR Copy() const 357 { 358 if (!m_str) 359 return NULL; 360 return ::SysAllocStringLen(m_str, ::SysStringLen(m_str)); 361 } 362 363 HRESULT CopyTo(BSTR *other) const 364 { 365 if (!other) 366 return E_POINTER; 367 *other = Copy(); 368 return S_OK; 369 } 370 371 bool LoadString(HMODULE module, DWORD uID) 372 { 373 ::SysFreeString(m_str); 374 m_str = NULL; 375 const wchar_t *ptr = NULL; 376 int len = ::LoadStringW(module, uID, (PWSTR)&ptr, 0); 377 if (len) 378 m_str = ::SysAllocStringLen(ptr, len); 379 return m_str != NULL; 380 } 381 382 unsigned int Length() const 383 { 384 return ::SysStringLen(m_str); 385 } 386 387 unsigned int ByteLength() const 388 { 389 return ::SysStringByteLen(m_str); 390 } 391 }; 392 393 394 class CComVariant : public tagVARIANT 395 { 396 public: 397 CComVariant() 398 { 399 ::VariantInit(this); 400 } 401 402 CComVariant(const CComVariant& other) 403 { 404 V_VT(this) = VT_EMPTY; 405 Copy(&other); 406 } 407 408 ~CComVariant() 409 { 410 Clear(); 411 } 412 413 CComVariant(LPCOLESTR lpStr) 414 { 415 V_VT(this) = VT_BSTR; 416 V_BSTR(this) = ::SysAllocString(lpStr); 417 } 418 419 CComVariant(LPCSTR lpStr) 420 { 421 V_VT(this) = VT_BSTR; 422 CComBSTR str(lpStr); 423 V_BSTR(this) = str.Detach(); 424 } 425 426 CComVariant(bool value) 427 { 428 V_VT(this) = VT_BOOL; 429 V_BOOL(this) = value ? VARIANT_TRUE : VARIANT_FALSE; 430 } 431 432 CComVariant(char value) 433 { 434 V_VT(this) = VT_I1; 435 V_I1(this) = value; 436 } 437 438 CComVariant(BYTE value) 439 { 440 V_VT(this) = VT_UI1; 441 V_UI1(this) = value; 442 } 443 444 CComVariant(short value) 445 { 446 V_VT(this) = VT_I2; 447 V_I2(this) = value; 448 } 449 450 CComVariant(unsigned short value) 451 { 452 V_VT(this) = VT_UI2; 453 V_UI2(this) = value; 454 } 455 456 CComVariant(int value, VARENUM type = VT_I4) 457 { 458 if (type == VT_I4 || type == VT_INT) 459 { 460 V_VT(this) = type; 461 V_I4(this) = value; 462 } 463 else 464 { 465 V_VT(this) = VT_ERROR; 466 V_ERROR(this) = E_INVALIDARG; 467 } 468 } 469 470 CComVariant(unsigned int value, VARENUM type = VT_UI4) 471 { 472 if (type == VT_UI4 || type == VT_UINT) 473 { 474 V_VT(this) = type; 475 V_UI4(this) = value; 476 } 477 else 478 { 479 V_VT(this) = VT_ERROR; 480 V_ERROR(this) = E_INVALIDARG; 481 } 482 } 483 484 CComVariant(long value, VARENUM type = VT_I4) 485 { 486 if (type == VT_I4 || type == VT_ERROR) 487 { 488 V_VT(this) = type; 489 V_I4(this) = value; 490 } 491 else 492 { 493 V_VT(this) = VT_ERROR; 494 V_ERROR(this) = E_INVALIDARG; 495 } 496 } 497 498 CComVariant(unsigned long value) 499 { 500 V_VT(this) = VT_UI4; 501 V_UI4(this) = value; 502 } 503 504 CComVariant(float value) 505 { 506 V_VT(this) = VT_R4; 507 V_R4(this) = value; 508 } 509 510 CComVariant(double value, VARENUM type = VT_R8) 511 { 512 if (type == VT_R8 || type == VT_DATE) 513 { 514 V_VT(this) = type; 515 V_R8(this) = value; 516 } 517 else 518 { 519 V_VT(this) = VT_ERROR; 520 V_ERROR(this) = E_INVALIDARG; 521 } 522 } 523 524 CComVariant(const LONGLONG& value) 525 { 526 V_VT(this) = VT_I8; 527 V_I8(this) = value; 528 } 529 530 CComVariant(const ULONGLONG& value) 531 { 532 V_VT(this) = VT_UI8; 533 V_UI8(this) = value; 534 } 535 536 CComVariant(const CY& value) 537 { 538 V_VT(this) = VT_CY; 539 V_I8(this) = value.int64; 540 } 541 542 543 HRESULT Clear() 544 { 545 return ::VariantClear(this); 546 } 547 548 HRESULT Copy(_In_ const VARIANT* src) 549 { 550 return ::VariantCopy(this, const_cast<VARIANT*>(src)); 551 } 552 553 HRESULT ChangeType(_In_ VARTYPE newType, _In_opt_ const LPVARIANT src = NULL) 554 { 555 const LPVARIANT lpSrc = src ? src : this; 556 return ::VariantChangeType(this, lpSrc, 0, newType); 557 } 558 }; 559 560 561 562 }; // namespace ATL 563 564 #ifndef _ATL_NO_AUTOMATIC_NAMESPACE 565 using namespace ATL; 566 #endif //!_ATL_NO_AUTOMATIC_NAMESPACE 567 568