[ATL] Add CComBSTR.Attach
[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 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