9c19e3371c47bc7b4fc090be95aaedb44a64c9cf
[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 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 BSTR Detach()
305 {
306 BSTR str = m_str;
307 m_str = NULL;
308 return str;
309 }
310
311 BSTR Copy() const
312 {
313 if (!m_str)
314 return NULL;
315 return ::SysAllocStringLen(m_str, ::SysStringLen(m_str));
316 }
317
318 HRESULT CopyTo(BSTR *other) const
319 {
320 if (!other)
321 return E_POINTER;
322 *other = Copy();
323 return S_OK;
324 }
325
326 bool LoadString(HMODULE module, DWORD uID)
327 {
328 ::SysFreeString(m_str);
329 m_str = NULL;
330 const wchar_t *ptr = NULL;
331 int len = ::LoadStringW(module, uID, (PWSTR)&ptr, 0);
332 if (len)
333 m_str = ::SysAllocStringLen(ptr, len);
334 return m_str != NULL;
335 }
336
337 unsigned int Length() const
338 {
339 return ::SysStringLen(m_str);
340 }
341
342 unsigned int ByteLength() const
343 {
344 return ::SysStringByteLen(m_str);
345 }
346 };
347
348
349 class CComVariant : public tagVARIANT
350 {
351 public:
352 CComVariant()
353 {
354 ::VariantInit(this);
355 }
356
357 CComVariant(const CComVariant& other)
358 {
359 V_VT(this) = VT_EMPTY;
360 Copy(&other);
361 }
362
363 ~CComVariant()
364 {
365 Clear();
366 }
367
368 CComVariant(LPCOLESTR lpStr)
369 {
370 V_VT(this) = VT_BSTR;
371 V_BSTR(this) = ::SysAllocString(lpStr);
372 }
373
374 CComVariant(LPCSTR lpStr)
375 {
376 V_VT(this) = VT_BSTR;
377 CComBSTR str(lpStr);
378 V_BSTR(this) = str.Detach();
379 }
380
381 CComVariant(bool value)
382 {
383 V_VT(this) = VT_BOOL;
384 V_BOOL(this) = value ? VARIANT_TRUE : VARIANT_FALSE;
385 }
386
387 CComVariant(char value)
388 {
389 V_VT(this) = VT_I1;
390 V_I1(this) = value;
391 }
392
393 CComVariant(BYTE value)
394 {
395 V_VT(this) = VT_UI1;
396 V_UI1(this) = value;
397 }
398
399 CComVariant(short value)
400 {
401 V_VT(this) = VT_I2;
402 V_I2(this) = value;
403 }
404
405 CComVariant(unsigned short value)
406 {
407 V_VT(this) = VT_UI2;
408 V_UI2(this) = value;
409 }
410
411 CComVariant(int value, VARENUM type = VT_I4)
412 {
413 if (type == VT_I4 || type == VT_INT)
414 {
415 V_VT(this) = type;
416 V_I4(this) = value;
417 }
418 else
419 {
420 V_VT(this) = VT_ERROR;
421 V_ERROR(this) = E_INVALIDARG;
422 }
423 }
424
425 CComVariant(unsigned int value, VARENUM type = VT_UI4)
426 {
427 if (type == VT_UI4 || type == VT_UINT)
428 {
429 V_VT(this) = type;
430 V_UI4(this) = value;
431 }
432 else
433 {
434 V_VT(this) = VT_ERROR;
435 V_ERROR(this) = E_INVALIDARG;
436 }
437 }
438
439 CComVariant(long value, VARENUM type = VT_I4)
440 {
441 if (type == VT_I4 || type == VT_ERROR)
442 {
443 V_VT(this) = type;
444 V_I4(this) = value;
445 }
446 else
447 {
448 V_VT(this) = VT_ERROR;
449 V_ERROR(this) = E_INVALIDARG;
450 }
451 }
452
453 CComVariant(unsigned long value)
454 {
455 V_VT(this) = VT_UI4;
456 V_UI4(this) = value;
457 }
458
459 CComVariant(float value)
460 {
461 V_VT(this) = VT_R4;
462 V_R4(this) = value;
463 }
464
465 CComVariant(double value, VARENUM type = VT_R8)
466 {
467 if (type == VT_R8 || type == VT_DATE)
468 {
469 V_VT(this) = type;
470 V_R8(this) = value;
471 }
472 else
473 {
474 V_VT(this) = VT_ERROR;
475 V_ERROR(this) = E_INVALIDARG;
476 }
477 }
478
479 CComVariant(const LONGLONG& value)
480 {
481 V_VT(this) = VT_I8;
482 V_I8(this) = value;
483 }
484
485 CComVariant(const ULONGLONG& value)
486 {
487 V_VT(this) = VT_UI8;
488 V_UI8(this) = value;
489 }
490
491 CComVariant(const CY& value)
492 {
493 V_VT(this) = VT_CY;
494 V_I8(this) = value.int64;
495 }
496
497
498 HRESULT Clear()
499 {
500 return ::VariantClear(this);
501 }
502
503 HRESULT Copy(_In_ const VARIANT* src)
504 {
505 return ::VariantCopy(this, const_cast<VARIANT*>(src));
506 }
507
508 HRESULT ChangeType(_In_ VARTYPE newType, _In_opt_ const LPVARIANT src = NULL)
509 {
510 const LPVARIANT lpSrc = src ? src : this;
511 return ::VariantChangeType(this, lpSrc, 0, newType);
512 }
513 };
514
515
516
517 }; // namespace ATL
518
519 #ifndef _ATL_NO_AUTOMATIC_NAMESPACE
520 using namespace ATL;
521 #endif //!_ATL_NO_AUTOMATIC_NAMESPACE
522