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