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