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