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 inline HRESULT AtlHresultFromLastError() noexcept 57 { 58 DWORD dwError = ::GetLastError(); 59 return HRESULT_FROM_WIN32(dwError); 60 } 61 62 template <class T> 63 class _NoAddRefReleaseOnCComPtr : public T 64 { 65 private: 66 virtual ULONG STDMETHODCALLTYPE AddRef() = 0; 67 virtual ULONG STDMETHODCALLTYPE Release() = 0; 68 }; 69 70 template<class T> 71 class CComPtr 72 { 73 public: 74 T *p; 75 public: 76 CComPtr() 77 { 78 p = NULL; 79 } 80 81 CComPtr(T *lp) 82 { 83 p = lp; 84 if (p != NULL) 85 p->AddRef(); 86 } 87 88 CComPtr(const CComPtr<T> &lp) 89 { 90 p = lp.p; 91 if (p != NULL) 92 p->AddRef(); 93 } 94 95 ~CComPtr() 96 { 97 if (p != NULL) 98 p->Release(); 99 } 100 101 HRESULT CoCreateInstance(REFCLSID rclsid, REFIID riid, LPUNKNOWN pOuter = NULL, DWORD ClsCtx = CLSCTX_ALL) 102 { 103 ATLASSERT(!p); 104 return ::CoCreateInstance(rclsid, pOuter, ClsCtx, riid, (void**)&p); 105 } 106 107 HRESULT CoCreateInstance(LPCOLESTR ProgID, REFIID riid, LPUNKNOWN pOuter = NULL, DWORD ClsCtx = CLSCTX_ALL) 108 { 109 CLSID clsid; 110 HRESULT hr = CLSIDFromProgID(ProgID, &clsid); 111 return FAILED(hr) ? hr : CoCreateInstance(clsid, riid, pOuter, ClsCtx); 112 } 113 114 T *operator = (T *lp) 115 { 116 T* pOld = p; 117 118 p = lp; 119 if (p != NULL) 120 p->AddRef(); 121 122 if (pOld != NULL) 123 pOld->Release(); 124 125 return *this; 126 } 127 128 T *operator = (const CComPtr<T> &lp) 129 { 130 T* pOld = p; 131 132 p = lp.p; 133 if (p != NULL) 134 p->AddRef(); 135 136 if (pOld != NULL) 137 pOld->Release(); 138 139 return *this; 140 } 141 142 // We cannot enable this until gcc starts supporting __uuidof 143 // See CORE-12710 144 #if 0 145 template <typename Q> 146 T* operator=(const CComPtr<Q>& lp) 147 { 148 T* pOld = p; 149 150 if (!lp.p || FAILED(lp.p->QueryInterface(__uuidof(T), (void**)(IUnknown**)&p))) 151 p = NULL; 152 153 if (pOld != NULL) 154 pOld->Release(); 155 156 return *this; 157 } 158 159 HRESULT CoCreateInstance(REFCLSID rclsid, LPUNKNOWN pOuter = NULL, DWORD ClsCtx = CLSCTX_ALL) 160 { 161 return CoCreateInstance(rclsid, __uuidof(T), pOuter, ClsCtx); 162 } 163 164 HRESULT CoCreateInstance(LPCOLESTR ProgID, LPUNKNOWN pOuter = NULL, DWORD ClsCtx = CLSCTX_ALL) 165 { 166 return CoCreateInstance(ProgID, __uuidof(T), pOuter, ClsCtx); 167 } 168 #endif 169 170 void Release() 171 { 172 if (p != NULL) 173 { 174 p->Release(); 175 p = NULL; 176 } 177 } 178 179 void Attach(T *lp) 180 { 181 if (p != NULL) 182 p->Release(); 183 p = lp; 184 } 185 186 T *Detach() 187 { 188 T *saveP; 189 190 saveP = p; 191 p = NULL; 192 return saveP; 193 } 194 195 T **operator & () 196 { 197 ATLASSERT(p == NULL); 198 return &p; 199 } 200 201 operator T * () 202 { 203 return p; 204 } 205 206 _NoAddRefReleaseOnCComPtr<T> *operator -> () const 207 { 208 ATLASSERT(p != NULL); 209 return (_NoAddRefReleaseOnCComPtr<T> *)p; 210 } 211 }; 212 213 214 //CComQIIDPtr<I_ID(Itype)> is the gcc compatible version of CComQIPtr<Itype> 215 #define I_ID(Itype) Itype,&IID_##Itype 216 217 template <class T, const IID* piid> 218 class CComQIIDPtr : 219 public CComPtr<T> 220 { 221 public: 222 // Let's tell GCC how to find a symbol. 223 using CComPtr<T>::p; 224 225 CComQIIDPtr() 226 { 227 } 228 CComQIIDPtr(_Inout_opt_ T* lp) : 229 CComPtr<T>(lp) 230 { 231 } 232 CComQIIDPtr(_Inout_ const CComQIIDPtr<T,piid>& lp): 233 CComPtr<T>(lp.p) 234 { 235 } 236 CComQIIDPtr(_Inout_opt_ IUnknown* lp) 237 { 238 if (lp != NULL) 239 { 240 if (FAILED(lp->QueryInterface(*piid, (void**)(IUnknown**)&p))) 241 p = NULL; 242 } 243 } 244 T *operator = (T *lp) 245 { 246 T* pOld = p; 247 248 p = lp; 249 if (p != NULL) 250 p->AddRef(); 251 252 if (pOld != NULL) 253 pOld->Release(); 254 255 return *this; 256 } 257 258 T *operator = (const CComQIIDPtr<T,piid> &lp) 259 { 260 T* pOld = p; 261 262 p = lp.p; 263 if (p != NULL) 264 p->AddRef(); 265 266 if (pOld != NULL) 267 pOld->Release(); 268 269 return *this; 270 } 271 272 T * operator=(IUnknown* lp) 273 { 274 T* pOld = p; 275 276 if (!lp || FAILED(lp->QueryInterface(*piid, (void**)(IUnknown**)&p))) 277 p = NULL; 278 279 if (pOld != NULL) 280 pOld->Release(); 281 282 return *this; 283 } 284 }; 285 286 287 class CComBSTR 288 { 289 public: 290 BSTR m_str; 291 public: 292 CComBSTR() : 293 m_str(NULL) 294 { 295 } 296 297 CComBSTR(LPCOLESTR pSrc) 298 { 299 if (pSrc == NULL) 300 m_str = NULL; 301 else 302 m_str = ::SysAllocString(pSrc); 303 } 304 305 CComBSTR(int length) 306 { 307 if (length == 0) 308 m_str = NULL; 309 else 310 m_str = ::SysAllocStringLen(NULL, length); 311 } 312 313 CComBSTR(int length, LPCOLESTR pSrc) 314 { 315 if (length == 0) 316 m_str = NULL; 317 else 318 m_str = ::SysAllocStringLen(pSrc, length); 319 } 320 321 CComBSTR(PCSTR pSrc) 322 { 323 if (pSrc) 324 { 325 int len = MultiByteToWideChar(CP_THREAD_ACP, 0, pSrc, -1, NULL, 0); 326 m_str = ::SysAllocStringLen(NULL, len - 1); 327 if (m_str) 328 { 329 int res = MultiByteToWideChar(CP_THREAD_ACP, 0, pSrc, -1, m_str, len); 330 ATLASSERT(res == len); 331 if (res != len) 332 { 333 ::SysFreeString(m_str); 334 m_str = NULL; 335 } 336 } 337 } 338 else 339 { 340 m_str = NULL; 341 } 342 } 343 344 CComBSTR(const CComBSTR &other) 345 { 346 m_str = other.Copy(); 347 } 348 349 CComBSTR(REFGUID guid) 350 { 351 OLECHAR szGuid[40]; 352 ::StringFromGUID2(guid, szGuid, 40); 353 m_str = ::SysAllocString(szGuid); 354 } 355 356 ~CComBSTR() 357 { 358 ::SysFreeString(m_str); 359 m_str = NULL; 360 } 361 362 operator BSTR () const 363 { 364 return m_str; 365 } 366 367 BSTR *operator & () 368 { 369 return &m_str; 370 } 371 372 CComBSTR &operator = (const CComBSTR &other) 373 { 374 ::SysFreeString(m_str); 375 m_str = other.Copy(); 376 return *this; 377 } 378 379 void Attach(BSTR bstr) 380 { 381 ::SysFreeString(m_str); 382 m_str = bstr; 383 } 384 385 BSTR Detach() 386 { 387 BSTR str = m_str; 388 m_str = NULL; 389 return str; 390 } 391 392 BSTR Copy() const 393 { 394 if (!m_str) 395 return NULL; 396 return ::SysAllocStringLen(m_str, ::SysStringLen(m_str)); 397 } 398 399 HRESULT CopyTo(BSTR *other) const 400 { 401 if (!other) 402 return E_POINTER; 403 *other = Copy(); 404 return S_OK; 405 } 406 407 bool LoadString(HMODULE module, DWORD uID) 408 { 409 ::SysFreeString(m_str); 410 m_str = NULL; 411 const wchar_t *ptr = NULL; 412 int len = ::LoadStringW(module, uID, (PWSTR)&ptr, 0); 413 if (len) 414 m_str = ::SysAllocStringLen(ptr, len); 415 return m_str != NULL; 416 } 417 418 unsigned int Length() const 419 { 420 return ::SysStringLen(m_str); 421 } 422 423 unsigned int ByteLength() const 424 { 425 return ::SysStringByteLen(m_str); 426 } 427 }; 428 429 430 class CComVariant : public tagVARIANT 431 { 432 public: 433 CComVariant() 434 { 435 ::VariantInit(this); 436 } 437 438 CComVariant(const CComVariant& other) 439 { 440 V_VT(this) = VT_EMPTY; 441 Copy(&other); 442 } 443 444 ~CComVariant() 445 { 446 Clear(); 447 } 448 449 CComVariant(LPCOLESTR lpStr) 450 { 451 V_VT(this) = VT_BSTR; 452 V_BSTR(this) = ::SysAllocString(lpStr); 453 } 454 455 CComVariant(LPCSTR lpStr) 456 { 457 V_VT(this) = VT_BSTR; 458 CComBSTR str(lpStr); 459 V_BSTR(this) = str.Detach(); 460 } 461 462 CComVariant(bool value) 463 { 464 V_VT(this) = VT_BOOL; 465 V_BOOL(this) = value ? VARIANT_TRUE : VARIANT_FALSE; 466 } 467 468 CComVariant(char value) 469 { 470 V_VT(this) = VT_I1; 471 V_I1(this) = value; 472 } 473 474 CComVariant(BYTE value) 475 { 476 V_VT(this) = VT_UI1; 477 V_UI1(this) = value; 478 } 479 480 CComVariant(short value) 481 { 482 V_VT(this) = VT_I2; 483 V_I2(this) = value; 484 } 485 486 CComVariant(unsigned short value) 487 { 488 V_VT(this) = VT_UI2; 489 V_UI2(this) = value; 490 } 491 492 CComVariant(int value, VARENUM type = VT_I4) 493 { 494 if (type == VT_I4 || type == VT_INT) 495 { 496 V_VT(this) = type; 497 V_I4(this) = value; 498 } 499 else 500 { 501 V_VT(this) = VT_ERROR; 502 V_ERROR(this) = E_INVALIDARG; 503 } 504 } 505 506 CComVariant(unsigned int value, VARENUM type = VT_UI4) 507 { 508 if (type == VT_UI4 || type == VT_UINT) 509 { 510 V_VT(this) = type; 511 V_UI4(this) = value; 512 } 513 else 514 { 515 V_VT(this) = VT_ERROR; 516 V_ERROR(this) = E_INVALIDARG; 517 } 518 } 519 520 CComVariant(long value, VARENUM type = VT_I4) 521 { 522 if (type == VT_I4 || type == VT_ERROR) 523 { 524 V_VT(this) = type; 525 V_I4(this) = value; 526 } 527 else 528 { 529 V_VT(this) = VT_ERROR; 530 V_ERROR(this) = E_INVALIDARG; 531 } 532 } 533 534 CComVariant(unsigned long value) 535 { 536 V_VT(this) = VT_UI4; 537 V_UI4(this) = value; 538 } 539 540 CComVariant(float value) 541 { 542 V_VT(this) = VT_R4; 543 V_R4(this) = value; 544 } 545 546 CComVariant(double value, VARENUM type = VT_R8) 547 { 548 if (type == VT_R8 || type == VT_DATE) 549 { 550 V_VT(this) = type; 551 V_R8(this) = value; 552 } 553 else 554 { 555 V_VT(this) = VT_ERROR; 556 V_ERROR(this) = E_INVALIDARG; 557 } 558 } 559 560 CComVariant(const LONGLONG& value) 561 { 562 V_VT(this) = VT_I8; 563 V_I8(this) = value; 564 } 565 566 CComVariant(const ULONGLONG& value) 567 { 568 V_VT(this) = VT_UI8; 569 V_UI8(this) = value; 570 } 571 572 CComVariant(const CY& value) 573 { 574 V_VT(this) = VT_CY; 575 V_I8(this) = value.int64; 576 } 577 578 579 HRESULT Clear() 580 { 581 return ::VariantClear(this); 582 } 583 584 HRESULT Copy(_In_ const VARIANT* src) 585 { 586 return ::VariantCopy(this, const_cast<VARIANT*>(src)); 587 } 588 589 HRESULT ChangeType(_In_ VARTYPE newType, _In_opt_ const LPVARIANT src = NULL) 590 { 591 const LPVARIANT lpSrc = src ? src : this; 592 return ::VariantChangeType(this, lpSrc, 0, newType); 593 } 594 }; 595 596 597 598 }; // namespace ATL 599 600 #ifndef _ATL_NO_AUTOMATIC_NAMESPACE 601 using namespace ATL; 602 #endif //!_ATL_NO_AUTOMATIC_NAMESPACE 603 604