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
AtlHresultFromLastError()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:
CComPtr()76 CComPtr()
77 {
78 p = NULL;
79 }
80
CComPtr(T * lp)81 CComPtr(T *lp)
82 {
83 p = lp;
84 if (p != NULL)
85 p->AddRef();
86 }
87
CComPtr(const CComPtr<T> & lp)88 CComPtr(const CComPtr<T> &lp)
89 {
90 p = lp.p;
91 if (p != NULL)
92 p->AddRef();
93 }
94
~CComPtr()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
Release()170 void Release()
171 {
172 if (p != NULL)
173 {
174 p->Release();
175 p = NULL;
176 }
177 }
178
Attach(T * lp)179 void Attach(T *lp)
180 {
181 if (p != NULL)
182 p->Release();
183 p = lp;
184 }
185
Detach()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
CComQIIDPtr()225 CComQIIDPtr()
226 {
227 }
CComQIIDPtr(_Inout_opt_ T * lp)228 CComQIIDPtr(_Inout_opt_ T* lp) :
229 CComPtr<T>(lp)
230 {
231 }
CComQIIDPtr(_Inout_ const CComQIIDPtr<T,piid> & lp)232 CComQIIDPtr(_Inout_ const CComQIIDPtr<T,piid>& lp):
233 CComPtr<T>(lp.p)
234 {
235 }
CComQIIDPtr(_Inout_opt_ IUnknown * lp)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:
CComBSTR()292 CComBSTR() :
293 m_str(NULL)
294 {
295 }
296
CComBSTR(LPCOLESTR pSrc)297 CComBSTR(LPCOLESTR pSrc)
298 {
299 if (pSrc == NULL)
300 m_str = NULL;
301 else
302 m_str = ::SysAllocString(pSrc);
303 }
304
CComBSTR(int length)305 CComBSTR(int length)
306 {
307 if (length == 0)
308 m_str = NULL;
309 else
310 m_str = ::SysAllocStringLen(NULL, length);
311 }
312
CComBSTR(int length,LPCOLESTR pSrc)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
CComBSTR(PCSTR pSrc)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
CComBSTR(const CComBSTR & other)344 CComBSTR(const CComBSTR &other)
345 {
346 m_str = other.Copy();
347 }
348
CComBSTR(REFGUID guid)349 CComBSTR(REFGUID guid)
350 {
351 OLECHAR szGuid[40];
352 ::StringFromGUID2(guid, szGuid, 40);
353 m_str = ::SysAllocString(szGuid);
354 }
355
~CComBSTR()356 ~CComBSTR()
357 {
358 ::SysFreeString(m_str);
359 m_str = NULL;
360 }
361
BSTR()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
Attach(BSTR bstr)379 void Attach(BSTR bstr)
380 {
381 ::SysFreeString(m_str);
382 m_str = bstr;
383 }
384
Detach()385 BSTR Detach()
386 {
387 BSTR str = m_str;
388 m_str = NULL;
389 return str;
390 }
391
Copy()392 BSTR Copy() const
393 {
394 if (!m_str)
395 return NULL;
396 return ::SysAllocStringLen(m_str, ::SysStringLen(m_str));
397 }
398
CopyTo(BSTR * other)399 HRESULT CopyTo(BSTR *other) const
400 {
401 if (!other)
402 return E_POINTER;
403 *other = Copy();
404 return S_OK;
405 }
406
LoadString(HMODULE module,DWORD uID)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
Length()418 unsigned int Length() const
419 {
420 return ::SysStringLen(m_str);
421 }
422
ByteLength()423 unsigned int ByteLength() const
424 {
425 return ::SysStringByteLen(m_str);
426 }
427 };
428
429
430 class CComVariant : public tagVARIANT
431 {
432 public:
CComVariant()433 CComVariant()
434 {
435 ::VariantInit(this);
436 }
437
CComVariant(const CComVariant & other)438 CComVariant(const CComVariant& other)
439 {
440 V_VT(this) = VT_EMPTY;
441 Copy(&other);
442 }
443
~CComVariant()444 ~CComVariant()
445 {
446 Clear();
447 }
448
CComVariant(LPCOLESTR lpStr)449 CComVariant(LPCOLESTR lpStr)
450 {
451 V_VT(this) = VT_BSTR;
452 V_BSTR(this) = ::SysAllocString(lpStr);
453 }
454
CComVariant(LPCSTR lpStr)455 CComVariant(LPCSTR lpStr)
456 {
457 V_VT(this) = VT_BSTR;
458 CComBSTR str(lpStr);
459 V_BSTR(this) = str.Detach();
460 }
461
CComVariant(bool value)462 CComVariant(bool value)
463 {
464 V_VT(this) = VT_BOOL;
465 V_BOOL(this) = value ? VARIANT_TRUE : VARIANT_FALSE;
466 }
467
CComVariant(char value)468 CComVariant(char value)
469 {
470 V_VT(this) = VT_I1;
471 V_I1(this) = value;
472 }
473
CComVariant(BYTE value)474 CComVariant(BYTE value)
475 {
476 V_VT(this) = VT_UI1;
477 V_UI1(this) = value;
478 }
479
CComVariant(short value)480 CComVariant(short value)
481 {
482 V_VT(this) = VT_I2;
483 V_I2(this) = value;
484 }
485
CComVariant(unsigned short value)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
CComVariant(unsigned long value)534 CComVariant(unsigned long value)
535 {
536 V_VT(this) = VT_UI4;
537 V_UI4(this) = value;
538 }
539
CComVariant(float value)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
CComVariant(const LONGLONG & value)560 CComVariant(const LONGLONG& value)
561 {
562 V_VT(this) = VT_I8;
563 V_I8(this) = value;
564 }
565
CComVariant(const ULONGLONG & value)566 CComVariant(const ULONGLONG& value)
567 {
568 V_VT(this) = VT_UI8;
569 V_UI8(this) = value;
570 }
571
CComVariant(const CY & value)572 CComVariant(const CY& value)
573 {
574 V_VT(this) = VT_CY;
575 V_I8(this) = value.int64;
576 }
577
578
Clear()579 HRESULT Clear()
580 {
581 return ::VariantClear(this);
582 }
583
Copy(_In_ const VARIANT * src)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