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