xref: /reactos/sdk/lib/atl/atlcomcli.h (revision 565bf9e3)
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