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