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