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