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