[SDK][ATL] Independence day of ReactOS ATL (#1473)
[reactos.git] / sdk / lib / atl / atlcomcli.h
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