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