VirtualBox

source: vbox/trunk/src/VBox/Frontends/VirtualBox/src/globals/COMDefs.h@ 100347

Last change on this file since 100347 was 100068, checked in by vboxsync, 20 months ago

FE/Qt and Debugger: bugref:10450: Qt6 compatibility bits for QString::fromUtf16 calls; ushort is replaced with char16_t.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 29.4 KB
Line 
1/* $Id: COMDefs.h 100068 2023-06-05 12:42:04Z vboxsync $ */
2/** @file
3 * VBox Qt GUI - Various COM definitions and COM wrapper class declarations.
4 *
5 * This header is used in conjunction with the header generated from
6 * XIDL expressed interface definitions to provide cross-platform Qt-based
7 * interface wrapper classes.
8 */
9
10/*
11 * Copyright (C) 2006-2023 Oracle and/or its affiliates.
12 *
13 * This file is part of VirtualBox base platform packages, as
14 * available from https://www.virtualbox.org.
15 *
16 * This program is free software; you can redistribute it and/or
17 * modify it under the terms of the GNU General Public License
18 * as published by the Free Software Foundation, in version 3 of the
19 * License.
20 *
21 * This program is distributed in the hope that it will be useful, but
22 * WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
24 * General Public License for more details.
25 *
26 * You should have received a copy of the GNU General Public License
27 * along with this program; if not, see <https://www.gnu.org/licenses>.
28 *
29 * SPDX-License-Identifier: GPL-3.0-only
30 */
31
32#ifndef FEQT_INCLUDED_SRC_globals_COMDefs_h
33#define FEQT_INCLUDED_SRC_globals_COMDefs_h
34#ifndef RT_WITHOUT_PRAGMA_ONCE
35# pragma once
36#endif
37
38/** @defgroup grp_QT_COM Qt-COM Support Layer
39 * @{
40 *
41 * The Qt-COM support layer provides a set of definitions and smart classes for
42 * writing simple, clean and platform-independent code to access COM/XPCOM
43 * components through exposed COM interfaces. This layer is based on the
44 * COM/XPCOM Abstraction Layer library (the VBoxCOM glue library defined in
45 * include/VBox/com and implemented in src/VBox/Main/glue).
46 *
47 * ...
48 *
49 * @defgroup grp_QT_COM_arrays Arrays
50 * @{
51 *
52 * COM/XPCOM arrays are mapped to QVector objects. QVector templates declared
53 * with a type that corresponds to the COM type of elements in the array using
54 * normal Qt-COM type mapping rules. Here is a code example that demonstrates
55 * how to call interface methods that take and return arrays (this example is
56 * based on examples given in @ref grp_COM_arrays):
57 * @code
58
59 CSomething component;
60
61 // ...
62
63 QVector<LONG> in(3);
64 in[0] = -1;
65 in[1] = -2;
66 in[2] = -3;
67
68 QVector<LONG> out;
69 QVector<LONG> ret;
70
71 ret = component.TestArrays(in, out);
72
73 for (size_t i = 0; i < ret.size(); ++ i)
74 LogFlow(("*** ret[%u]=%d\n", i, ret[i]));
75
76 * @endcode
77 * @}
78 */
79
80/* Both VBox/com/assert.h and qglobal.h contain a definition of ASSERT.
81 * Either of them can be already included here, so try to shut them up. */
82#undef ASSERT
83
84#include <VBox/com/com.h>
85#include <VBox/com/array.h>
86
87#undef ASSERT
88
89/* Qt includes */
90#include <QString>
91#include <QUuid>
92#include <QVector>
93
94/* GUI includes: */
95#include "UILibraryDefs.h"
96
97/*
98 * Additional COM / XPCOM defines and includes
99 */
100
101#if !defined(VBOX_WITH_XPCOM)
102
103#else /* !defined(VBOX_WITH_XPCOM) */
104
105#include <nsXPCOM.h>
106#include <nsMemory.h>
107#include <nsIComponentManager.h>
108
109class XPCOMEventQSocketListener;
110
111#endif /* !defined(VBOX_WITH_XPCOM) */
112
113/////////////////////////////////////////////////////////////////////////////
114
115class CVirtualBoxErrorInfo;
116
117/** Represents extended error information */
118class SHARED_LIBRARY_STUFF COMErrorInfo
119{
120public:
121
122 COMErrorInfo()
123 : mIsNull(true),
124 mIsBasicAvailable(false),
125 mIsFullAvailable(false),
126 mResultCode(S_OK),
127 m_pNext(NULL)
128 {}
129
130 COMErrorInfo(const COMErrorInfo &info)
131 {
132 copyFrom(info);
133 }
134
135 COMErrorInfo(const CVirtualBoxErrorInfo &info)
136 {
137 init(info);
138 }
139
140 ~COMErrorInfo()
141 {
142 cleanup();
143 }
144
145 COMErrorInfo& operator=(const COMErrorInfo &info)
146 {
147 cleanup();
148 copyFrom(info);
149 return *this;
150 }
151
152 bool isNull() const { return mIsNull; }
153
154 bool isBasicAvailable() const { return mIsBasicAvailable; }
155 bool isFullAvailable() const { return mIsFullAvailable; }
156
157 HRESULT resultCode() const { return mResultCode; }
158 QUuid interfaceID() const { return mInterfaceID; }
159 QString component() const { return mComponent; }
160 QString text() const { return mText; }
161
162 const COMErrorInfo *next() const { return m_pNext; }
163
164 QString interfaceName() const { return mInterfaceName; }
165 QUuid calleeIID() const { return mCalleeIID; }
166 QString calleeName() const { return mCalleeName; }
167
168private:
169 void init(const CVirtualBoxErrorInfo &info);
170 void copyFrom(const COMErrorInfo &x);
171 void cleanup();
172
173 void fetchFromCurrentThread(IUnknown *callee, const GUID *calleeIID);
174
175 static QString getInterfaceNameFromIID(const QUuid &id);
176
177 bool mIsNull : 1;
178 bool mIsBasicAvailable : 1;
179 bool mIsFullAvailable : 1;
180
181 HRESULT mResultCode;
182 QUuid mInterfaceID;
183 QString mComponent;
184 QString mText;
185
186 COMErrorInfo *m_pNext;
187
188 QString mInterfaceName;
189 QUuid mCalleeIID;
190 QString mCalleeName;
191
192 friend class COMBaseWithEI;
193};
194
195/////////////////////////////////////////////////////////////////////////////
196
197/**
198 * Base COM class the CInterface template and all wrapper classes are derived
199 * from. Provides common functionality for all COM wrappers.
200 */
201class SHARED_LIBRARY_STUFF COMBase
202{
203public:
204
205 static HRESULT InitializeCOM(bool fGui);
206 static HRESULT CleanupCOM();
207
208 /**
209 * Returns the result code of the last interface method called by the
210 * wrapper instance or the result of CInterface::createInstance()
211 * operation.
212 */
213 HRESULT lastRC() const { return mRC; }
214
215#if !defined(VBOX_WITH_XPCOM)
216
217 /** Converts a GUID value to QUuid */
218 static QUuid ToQUuid(const GUID &id)
219 {
220 return QUuid(id.Data1, id.Data2, id.Data3,
221 id.Data4[0], id.Data4[1], id.Data4[2], id.Data4[3],
222 id.Data4[4], id.Data4[5], id.Data4[6], id.Data4[7]);
223 }
224
225#else /* !defined(VBOX_WITH_XPCOM) */
226
227 /** Converts a GUID value to QUuid */
228 static QUuid ToQUuid(const nsID &id)
229 {
230 return QUuid(id.m0, id.m1, id.m2,
231 id.m3[0], id.m3[1], id.m3[2], id.m3[3],
232 id.m3[4], id.m3[5], id.m3[6], id.m3[7]);
233 }
234
235#endif /* !defined(VBOX_WITH_XPCOM) */
236
237 /* Arrays of arbitrary types */
238
239 template <typename QT, typename CT>
240 static void ToSafeArray(const QVector<QT> &aVec, com::SafeArray<CT> &aArr)
241 {
242 aArr.reset(aVec.size());
243 for (int i = 0; i < aVec.size(); ++i)
244 aArr[i] = static_cast<CT>(aVec.at(i));
245 }
246
247 template <typename CT, typename QT>
248 static void FromSafeArray(const com::SafeArray<CT> &aArr, QVector<QT> &aVec)
249 {
250 aVec.resize(static_cast<int>(aArr.size()));
251 for (int i = 0; i < aVec.size(); ++i)
252 aVec[i] = static_cast<QT>(aArr[i]);
253 }
254
255 template <typename QT, typename CT>
256 static void ToSafeArray(const QVector<QT *> &aVec, com::SafeArray<CT *> &aArr)
257 {
258 Q_UNUSED(aVec);
259 Q_UNUSED(aArr);
260 AssertMsgFailedReturnVoid(("No conversion!\n"));
261 }
262
263 template <typename CT, typename QT>
264 static void FromSafeArray(const com::SafeArray<CT *> &aArr, QVector<QT *> &aVec)
265 {
266 Q_UNUSED(aArr);
267 Q_UNUSED(aVec);
268 AssertMsgFailedReturnVoid(("No conversion!\n"));
269 }
270
271 /* Arrays of equal types */
272
273 template <typename T>
274 static void ToSafeArray(const QVector<T> &aVec, com::SafeArray<T> &aArr)
275 {
276 aArr.reset(aVec.size());
277 for (int i = 0; i < aVec.size(); ++i)
278 aArr[i] = aVec.at(i);
279 }
280
281 template <typename T>
282 static void FromSafeArray(const com::SafeArray<T> &aArr, QVector<T> &aVec)
283 {
284 aVec.resize(static_cast<int>(aArr.size()));
285 memcpy(&aVec[0], aArr.raw(), aArr.size() * sizeof(T));
286 }
287
288 /* Arrays of strings */
289
290 static void ToSafeArray(const QVector<QString> &aVec,
291 com::SafeArray<BSTR> &aArr);
292 static void FromSafeArray(const com::SafeArray<BSTR> &aArr,
293 QVector<QString> &aVec);
294
295 /* Arrays of GUID */
296
297 static void ToSafeArray(const QVector<QUuid> &aVec,
298 com::SafeGUIDArray &aArr);
299 static void FromSafeArray(const com::SafeGUIDArray &aArr,
300 QVector<QUuid> &aVec);
301
302 /* Arrays of GUID as BSTR */
303
304 static void ToSafeArray(const QVector<QUuid> &aVec,
305 com::SafeArray<BSTR> &aArr);
306 static void FromSafeArray(const com::SafeArray<BSTR> &aArr,
307 QVector<QUuid> &aVec);
308
309 /* Arrays of enums. Does a cast similar to what ENUMOut does. */
310
311 template <typename QE, typename CE>
312 static void ToSafeArray(const QVector<QE> &aVec,
313 com::SafeIfaceArray<CE> &aArr)
314 {
315 aArr.reset(static_cast<int>(aVec.size()));
316 for (int i = 0; i < aVec.size(); ++i)
317 aArr[i] = static_cast<CE>(aVec.at(i));
318 }
319
320 template <typename CE, typename QE>
321 static void FromSafeArray(const com::SafeIfaceArray<CE> &aArr,
322 QVector<QE> &aVec)
323 {
324 aVec.resize(static_cast<int>(aArr.size()));
325 for (int i = 0; i < aVec.size(); ++i)
326 aVec[i] = static_cast<QE>(aArr[i]);
327 }
328
329 /* Arrays of interface pointers. Note: we need a separate pair of names
330 * only because the MSVC8 template matching algorithm is poor and tries to
331 * instantiate a com::SafeIfaceArray<BSTR> (!!!) template otherwise for
332 * *no* reason and fails. Note that it's also not possible to choose the
333 * correct function by specifying template arguments explicitly because then
334 * it starts to try to instantiate the com::SafeArray<I> template for
335 * *no* reason again and fails too. Definitely, broken. Works in GCC like a
336 * charm. */
337
338 template <class CI, class I>
339 static void ToSafeIfaceArray(const QVector<CI> &aVec,
340 com::SafeIfaceArray<I> &aArr)
341 {
342 aArr.reset(static_cast<int>(aVec.size()));
343 for (int i = 0; i < aVec.size(); ++i)
344 {
345 aArr[i] = aVec.at(i).raw();
346 if (aArr[i])
347 aArr[i]->AddRef();
348 }
349 }
350
351 template <class I, class CI>
352 static void FromSafeIfaceArray(const com::SafeIfaceArray<I> &aArr,
353 QVector<CI> &aVec)
354 {
355 aVec.resize(static_cast<int>(aArr.size()));
356 for (int i = 0; i < aVec.size(); ++i)
357 aVec[i].attach(aArr[i]);
358 }
359
360protected:
361
362 /* no arbitrary instance creations */
363 COMBase() : mRC(S_OK) {}
364
365#if defined(VBOX_WITH_XPCOM)
366 static XPCOMEventQSocketListener *sSocketListener;
367#endif
368
369 /** Adapter to pass QString as input BSTR params */
370 class BSTRIn
371 {
372 public:
373
374 BSTRIn(const QString &s) : bstr(SysAllocString((const OLECHAR *)
375 (s.isNull() ? 0 : s.utf16()))) {}
376
377 ~BSTRIn()
378 {
379 if (bstr)
380 SysFreeString(bstr);
381 }
382
383 operator BSTR() const { return bstr; }
384
385 private:
386
387 BSTR bstr;
388 };
389
390 /** Adapter to pass QString as output BSTR params */
391 class BSTROut
392 {
393 public:
394
395 BSTROut(QString &s) : str(s), bstr(0) {}
396
397 ~BSTROut()
398 {
399 if (bstr) {
400#ifndef VBOX_IS_QT6_OR_LATER
401 str = QString::fromUtf16((const ushort *)bstr);
402#else
403 str = QString::fromUtf16((const char16_t *)bstr);
404#endif
405 SysFreeString(bstr);
406 }
407 }
408
409 operator BSTR *() { return &bstr; }
410
411 private:
412
413 QString &str;
414 BSTR bstr;
415 };
416
417 /** Adapter to pass QUuid as input BSTR params */
418 class GuidAsBStrIn
419 {
420 public:
421
422 GuidAsBStrIn(const QUuid &s) : bstr(SysAllocString((const OLECHAR *)
423 (s.isNull() ? 0 : s.toString().utf16()))) {}
424
425 ~GuidAsBStrIn()
426 {
427 if (bstr)
428 SysFreeString(bstr);
429 }
430
431 operator BSTR() const { return bstr; }
432
433 private:
434
435 BSTR bstr;
436 };
437
438 /** Adapter to pass QUuid as output BSTR params */
439 class GuidAsBStrOut
440 {
441 public:
442
443 GuidAsBStrOut(QUuid &s) : uuid(s), bstr(0) {}
444
445 ~GuidAsBStrOut()
446 {
447 if (bstr) {
448#ifndef VBOX_IS_QT6_OR_LATER
449 uuid = QUuid(QString::fromUtf16((const ushort *)bstr));
450#else
451 uuid = QUuid(QString::fromUtf16((const char16_t *)bstr));
452#endif
453 SysFreeString(bstr);
454 }
455 }
456
457 operator BSTR *() { return &bstr; }
458
459 private:
460
461 QUuid &uuid;
462 BSTR bstr;
463 };
464
465 /**
466 * Adapter to pass K* enums as output COM enum params (*_T).
467 *
468 * @param QE K* enum.
469 * @param CE COM enum.
470 */
471 template <typename QE, typename CE>
472 class ENUMOut
473 {
474 public:
475
476 ENUMOut(QE &e) : qe(e), ce((CE)0) {}
477 ~ENUMOut() { qe = (QE)ce; }
478 operator CE *() { return &ce; }
479
480 private:
481
482 QE &qe;
483 CE ce;
484 };
485
486#if !defined(VBOX_WITH_XPCOM)
487
488 /** Adapter to pass QUuid as input GUID params */
489 static GUID GUIDIn(const QUuid &uuid) { return uuid; }
490
491 /** Adapter to pass QUuid as output GUID params */
492 class GUIDOut
493 {
494 public:
495
496 GUIDOut(QUuid &id) : uuid(id)
497 {
498 ::memset(&guid, 0, sizeof(GUID));
499 }
500
501 ~GUIDOut()
502 {
503 uuid = QUuid(
504 guid.Data1, guid.Data2, guid.Data3,
505 guid.Data4[0], guid.Data4[1], guid.Data4[2], guid.Data4[3],
506 guid.Data4[4], guid.Data4[5], guid.Data4[6], guid.Data4[7]);
507 }
508
509 operator GUID *() { return &guid; }
510
511 private:
512
513 QUuid &uuid;
514 GUID guid;
515 };
516
517#else /* !defined(VBOX_WITH_XPCOM) */
518
519 /** Adapter to pass QUuid as input GUID params */
520 static const nsID &GUIDIn(const QUuid &uuid)
521 {
522 return *(const nsID *) &uuid;
523 }
524
525 /** Adapter to pass QUuid as output GUID params */
526 class GUIDOut
527 {
528 public:
529
530 GUIDOut(QUuid &id) : uuid(id), nsid(0) {}
531
532 ~GUIDOut()
533 {
534 if (nsid)
535 {
536 uuid = QUuid(
537 nsid->m0, nsid->m1, nsid->m2,
538 nsid->m3[0], nsid->m3[1], nsid->m3[2], nsid->m3[3],
539 nsid->m3[4], nsid->m3[5], nsid->m3[6], nsid->m3[7]);
540 nsMemory::Free(nsid);
541 }
542 }
543
544 operator nsID **() { return &nsid; }
545
546 private:
547
548 QUuid &uuid;
549 nsID *nsid;
550 };
551
552#endif /* !defined(VBOX_WITH_XPCOM) */
553
554 static void addref(IUnknown *aIface) { if (aIface) aIface->AddRef(); }
555 static void release(IUnknown *aIface) { if (aIface) aIface->Release(); }
556
557protected:
558
559 mutable HRESULT mRC;
560
561 friend class COMErrorInfo;
562};
563
564/////////////////////////////////////////////////////////////////////////////
565
566/**
567 * Alternative base class for the CInterface template that adds the errorInfo()
568 * method for providing extended error info about unsuccessful invocation of the
569 * last called interface method.
570 */
571class COMBaseWithEI : public COMBase
572{
573public:
574
575 /**
576 * Returns error info set by the last unsuccessfully invoked interface
577 * method. Returned error info is useful only if CInterface::lastRC()
578 * represents a failure or a warning (i.e. CInterface::isReallyOk() is
579 * false).
580 */
581 const COMErrorInfo &errorInfo() const { return mErrInfo; }
582
583protected:
584
585 /* no arbitrary instance creation */
586 COMBaseWithEI() : COMBase() {};
587
588 void setErrorInfo(const COMErrorInfo &aErrInfo) { mErrInfo = aErrInfo; }
589
590 void fetchErrorInfo(IUnknown *aCallee, const GUID *aCalleeIID) const
591 {
592 mErrInfo.fetchFromCurrentThread(aCallee, aCalleeIID);
593 }
594
595 mutable COMErrorInfo mErrInfo;
596};
597
598/////////////////////////////////////////////////////////////////////////////
599
600/**
601 * Simple class that encapsulates the result code and COMErrorInfo.
602 */
603class COMResult
604{
605public:
606
607 COMResult() : mRC(S_OK) {}
608
609 /**
610 * Queries the current result code from the given component.
611 */
612 explicit COMResult(const COMBase &aComponent)
613 : mRC(aComponent.lastRC()) {}
614
615 /**
616 * Queries the current result code and error info from the given component.
617 */
618 COMResult(const COMBaseWithEI &aComponent)
619 : mRC(aComponent.lastRC()),
620 mErrInfo(aComponent.errorInfo())
621 { }
622
623 /**
624 * Queries the current result code from the given component.
625 */
626 COMResult &operator=(const COMBase &aComponent)
627 {
628 mRC = aComponent.lastRC();
629 return *this;
630 }
631
632 /**
633 * Queries the current result code and error info from the given component.
634 */
635 COMResult &operator=(const COMBaseWithEI &aComponent)
636 {
637 mRC = aComponent.lastRC();
638 mErrInfo = aComponent.errorInfo();
639 return *this;
640 }
641
642 bool isNull() const { return mErrInfo.isNull(); }
643
644 /**
645 * Returns @c true if the result code represents success (with or without
646 * warnings).
647 */
648 bool isOk() const { return SUCCEEDED(mRC); }
649
650 /**
651 * Returns @c true if the result code represents success with one or more
652 * warnings.
653 */
654 bool isWarning() const { return SUCCEEDED_WARNING(mRC); }
655
656 /**
657 * Returns @c true if the result code represents success with no warnings.
658 */
659 bool isReallyOk() const { return mRC == S_OK; }
660
661 COMErrorInfo errorInfo() const { return mErrInfo; }
662 HRESULT rc() const { return mRC; }
663
664private:
665
666 HRESULT mRC;
667 COMErrorInfo mErrInfo;
668};
669
670/////////////////////////////////////////////////////////////////////////////
671
672/**
673 * Wrapper template class for all interfaces.
674 *
675 * All interface methods named as they are in the original, i.e. starting
676 * with the capital letter. All utility non-interface methods are named
677 * starting with the small letter. Utility methods should be not normally
678 * called by the end-user client application.
679 *
680 * @param I Interface class (i.e. derived from IUnknown/nsISupports).
681 * @param B Base class, either COMBase (by default) or COMBaseWithEI.
682 */
683template <class I, class B = COMBase>
684class CInterface : public B
685{
686public:
687
688 typedef B Base;
689 typedef I Iface;
690
691 // constructors & destructor
692
693 CInterface()
694 {
695 clear();
696 }
697
698 CInterface(const CInterface &that) : B(that)
699 {
700 clear();
701 mIface = that.mIface;
702 this->addref((IUnknown*)ptr());
703 }
704
705 CInterface(I *aIface)
706 {
707 clear();
708 setPtr(aIface);
709 this->addref((IUnknown*)aIface);
710 }
711
712 virtual ~CInterface()
713 {
714 detach();
715#ifdef RT_STRICT
716 mDead = true;
717#endif
718 }
719
720#ifdef VBOX_WITH_LESS_VIRTUALBOX_INCLUDING
721 virtual IID const &getIID() const = 0;
722#else
723 IID const &getIID() const { return COM_IIDOF(I); }
724#endif
725
726 // utility methods
727 void createInstance(const CLSID &aClsId)
728 {
729 AssertMsg(ptr() == NULL, ("Instance is already non-NULL\n"));
730 if (ptr() == NULL)
731 {
732 I* pObj = NULL;
733#if !defined(VBOX_WITH_XPCOM)
734 B::mRC = CoCreateInstance(aClsId, NULL, CLSCTX_ALL, getIID(), (void **)&pObj);
735#else
736 nsCOMPtr<nsIComponentManager> manager;
737 B::mRC = NS_GetComponentManager(getter_AddRefs(manager));
738 if (SUCCEEDED(B::mRC))
739 B::mRC = manager->CreateInstance(aClsId, nsnull, getIID(), (void **)&pObj);
740#endif
741
742 if (SUCCEEDED(B::mRC))
743 setPtr(pObj);
744 else
745 setPtr(NULL);
746
747 /* fetch error info, but don't assert if it's missing -- many other
748 * reasons can lead to an error (w/o providing error info), not only
749 * the instance initialization code (that should always provide it) */
750 B::fetchErrorInfo(NULL, NULL);
751 }
752 }
753
754 /**
755 * Attaches to the given foreign interface pointer by querying the own
756 * interface on it. The operation may fail.
757 */
758 template <class OI>
759 void attach(OI *aIface)
760 {
761 Assert(!mDead);
762 /* be aware of self assignment */
763 I* amIface = ptr();
764 this->addref((IUnknown*)aIface);
765 this->release((IUnknown*)amIface);
766 if (aIface)
767 {
768 amIface = NULL;
769 B::mRC = aIface->QueryInterface(getIID(), (void **)&amIface);
770 this->release((IUnknown*)aIface);
771 setPtr(amIface);
772 }
773 else
774 {
775 setPtr(NULL);
776 B::mRC = S_OK;
777 }
778 };
779
780 /** Specialization of attach() for our own interface I. Never fails. */
781 void attach(I *aIface)
782 {
783 Assert(!mDead);
784 /* be aware of self assignment */
785 this->addref((IUnknown*)aIface);
786 this->release((IUnknown*)ptr());
787 setPtr(aIface);
788 B::mRC = S_OK;
789 };
790
791 /** Detaches from the underlying interface pointer. */
792 void detach()
793 {
794 Assert(!mDead);
795 this->release((IUnknown*)ptr());
796 setPtr(NULL);
797 }
798
799 /** Returns @c true if not attached to any interface pointer. */
800 bool isNull() const
801 {
802 Assert(!mDead);
803 return mIface == NULL;
804 }
805
806 /** Returns @c true if attached to an interface pointer. */
807 bool isNotNull() const
808 {
809 Assert(!mDead);
810 return mIface != NULL;
811 }
812
813 /**
814 * Returns @c true if the result code represents success (with or without
815 * warnings).
816 */
817 bool isOk() const { return !isNull() && SUCCEEDED(B::mRC); }
818
819 /**
820 * Returns @c true if the result code represents success with one or more
821 * warnings.
822 */
823 bool isWarning() const { return !isNull() && SUCCEEDED_WARNING(B::mRC); }
824
825 /**
826 * Returns @c true if the result code represents success with no warnings.
827 */
828 bool isReallyOk() const { return !isNull() && B::mRC == S_OK; }
829
830 /**
831 * Returns the last result code of this interface.
832 */
833 HRESULT rc() const { return B::mRC; }
834
835 // utility operators
836
837 CInterface &operator=(const CInterface &that)
838 {
839 attach(that.ptr());
840 B::operator=(that);
841 return *this;
842 }
843
844 CInterface &operator=(I *aIface)
845 {
846 attach(aIface);
847 return *this;
848 }
849
850 /**
851 * Returns the raw interface pointer. Not intended to be used for anything
852 * else but in generated wrappers and for debugging. You've been warned.
853 */
854 I *raw() const
855 {
856 return ptr();
857 }
858
859 bool operator==(const CInterface &that) const { return ptr() == that.ptr(); }
860 bool operator!=(const CInterface &that) const { return ptr() != that.ptr(); }
861
862 I *ptr() const
863 {
864 Assert(!mDead);
865 return mIface;
866 }
867
868 void setPtr(I* aObj) const
869 {
870 Assert(!mDead);
871 mIface = aObj;
872 }
873
874private:
875#ifdef RT_STRICT
876 bool mDead;
877#endif
878 mutable I * mIface;
879
880 void clear()
881 {
882 mIface = NULL;
883#ifdef RT_STRICT
884 mDead = false;
885#endif
886 }
887};
888
889/**
890 * Partial specialization for CInterface template class above for a case when B == COMBase.
891 *
892 * We had to add it because on exporting template to a library at least on Windows there is
893 * an implicit instantiation of the createInstance() member (even if it's not used) which
894 * in case of base template uses API present in COMBaseWithEI class only, not in COMBase.
895 *
896 * @param I Brings the interface class (i.e. derived from IUnknown/nsISupports).
897 */
898template <class I>
899class CInterface<I, COMBase> : public COMBase
900{
901public:
902
903 typedef COMBase Base;
904 typedef I Iface;
905
906 // constructors & destructor
907
908 CInterface()
909 {
910 clear();
911 }
912
913 CInterface(const CInterface &that) : COMBase(that)
914 {
915 clear();
916 mIface = that.mIface;
917 this->addref((IUnknown*)ptr());
918 }
919
920 CInterface(I *pIface)
921 {
922 clear();
923 setPtr(pIface);
924 this->addref((IUnknown*)pIface);
925 }
926
927 virtual ~CInterface()
928 {
929 detach();
930#ifdef RT_STRICT
931 mDead = true;
932#endif
933 }
934
935#ifdef VBOX_WITH_LESS_VIRTUALBOX_INCLUDING
936 virtual IID const &getIID() const = 0;
937#else
938 IID const &getIID() const { return COM_IIDOF(I); }
939#endif
940
941 // utility methods
942
943 void createInstance(const CLSID &clsId)
944 {
945 AssertMsg(ptr() == NULL, ("Instance is already non-NULL\n"));
946 if (ptr() == NULL)
947 {
948 I* pObj = NULL;
949#if !defined(VBOX_WITH_XPCOM)
950 COMBase::mRC = CoCreateInstance(clsId, NULL, CLSCTX_ALL, getIID(), (void **)&pObj);
951#else
952 nsCOMPtr<nsIComponentManager> manager;
953 COMBase::mRC = NS_GetComponentManager(getter_AddRefs(manager));
954 if (SUCCEEDED(COMBase::mRC))
955 COMBase::mRC = manager->CreateInstance(clsId, nsnull, getIID(), (void **)&pObj);
956#endif
957
958 if (SUCCEEDED(COMBase::mRC))
959 setPtr(pObj);
960 else
961 setPtr(NULL);
962 }
963 }
964
965 /**
966 * Attaches to the given foreign interface pointer by querying the own
967 * interface on it. The operation may fail.
968 */
969 template <class OI>
970 void attach(OI *pIface)
971 {
972 Assert(!mDead);
973 /* Be aware of self assignment: */
974 I *pmIface = ptr();
975 this->addref((IUnknown*)pIface);
976 this->release((IUnknown*)pmIface);
977 if (pIface)
978 {
979 pmIface = NULL;
980 COMBase::mRC = pIface->QueryInterface(getIID(), (void **)&pmIface);
981 this->release((IUnknown*)pIface);
982 setPtr(pmIface);
983 }
984 else
985 {
986 setPtr(NULL);
987 COMBase::mRC = S_OK;
988 }
989 };
990
991 /** Specialization of attach() for our own interface I. Never fails. */
992 void attach(I *pIface)
993 {
994 Assert(!mDead);
995 /* Be aware of self assignment: */
996 this->addref((IUnknown*)pIface);
997 this->release((IUnknown*)ptr());
998 setPtr(pIface);
999 COMBase::mRC = S_OK;
1000 };
1001
1002 /** Detaches from the underlying interface pointer. */
1003 void detach()
1004 {
1005 Assert(!mDead);
1006 this->release((IUnknown*)ptr());
1007 setPtr(NULL);
1008 }
1009
1010 /** Returns @c true if not attached to any interface pointer. */
1011 bool isNull() const
1012 {
1013 Assert(!mDead);
1014 return mIface == NULL;
1015 }
1016
1017 /** Returns @c true if attached to an interface pointer. */
1018 bool isNotNull() const
1019 {
1020 Assert(!mDead);
1021 return mIface != NULL;
1022 }
1023
1024 /** Returns @c true if the result code represents success (with or without warnings). */
1025 bool isOk() const { return !isNull() && SUCCEEDED(COMBase::mRC); }
1026
1027 /** Returns @c true if the result code represents success with one or more warnings. */
1028 bool isWarning() const { return !isNull() && SUCCEEDED_WARNING(COMBase::mRC); }
1029
1030 /** Returns @c true if the result code represents success with no warnings. */
1031 bool isReallyOk() const { return !isNull() && COMBase::mRC == S_OK; }
1032
1033 // utility operators
1034
1035 CInterface &operator=(const CInterface &that)
1036 {
1037 attach(that.ptr());
1038 COMBase::operator=(that);
1039 return *this;
1040 }
1041
1042 CInterface &operator=(I *pIface)
1043 {
1044 attach(pIface);
1045 return *this;
1046 }
1047
1048 /**
1049 * Returns the raw interface pointer. Not intended to be used for anything
1050 * else but in generated wrappers and for debugging. You've been warned.
1051 */
1052 I *raw() const
1053 {
1054 return ptr();
1055 }
1056
1057 bool operator==(const CInterface &that) const { return ptr() == that.ptr(); }
1058 bool operator!=(const CInterface &that) const { return ptr() != that.ptr(); }
1059
1060 I *ptr() const
1061 {
1062 Assert(!mDead);
1063 return mIface;
1064 }
1065
1066 void setPtr(I* aObj) const
1067 {
1068 Assert(!mDead);
1069 mIface = aObj;
1070 }
1071
1072private:
1073
1074#ifdef RT_STRICT
1075 bool mDead;
1076#endif
1077 mutable I *mIface;
1078
1079 void clear()
1080 {
1081 mIface = NULL;
1082#ifdef RT_STRICT
1083 mDead = false;
1084#endif
1085 }
1086};
1087
1088/////////////////////////////////////////////////////////////////////////////
1089
1090class CUnknown : public CInterface<IUnknown, COMBaseWithEI>
1091{
1092public:
1093
1094 typedef CInterface<IUnknown, COMBaseWithEI> Base;
1095
1096 CUnknown() {}
1097
1098 /** Creates an instance given another CInterface-based instance. */
1099 template <class OI, class OB>
1100 explicit CUnknown(const CInterface<OI, OB> &that)
1101 {
1102 attach(that.ptr());
1103 if (SUCCEEDED(mRC))
1104 {
1105 /* preserve old error info if any */
1106 mRC = that.lastRC();
1107 setErrorInfo(that.errorInfo());
1108 }
1109 }
1110
1111 /** Constructor specialization for IUnknown. */
1112 CUnknown(const CUnknown &that) : Base(that) {}
1113
1114 /** Creates an instance given a foreign interface pointer. */
1115 template <class OI>
1116 explicit CUnknown(OI *aIface)
1117 {
1118 attach(aIface);
1119 }
1120
1121 /** Constructor specialization for IUnknown. */
1122 explicit CUnknown(IUnknown *aIface) : Base(aIface) {}
1123
1124 /** Assigns from another CInterface-based instance. */
1125 template <class OI, class OB>
1126 CUnknown &operator=(const CInterface<OI, OB> &that)
1127 {
1128 attach(that.ptr());
1129 if (SUCCEEDED(mRC))
1130 {
1131 /* preserve old error info if any */
1132 mRC = that.lastRC();
1133 setErrorInfo(that.errorInfo());
1134 }
1135 return *this;
1136 }
1137
1138 /** Assignment specialization for CUnknown. */
1139 CUnknown &operator=(const CUnknown &that)
1140 {
1141 Base::operator=(that);
1142 return *this;
1143 }
1144
1145 /** Assigns from a foreign interface pointer. */
1146 template <class OI>
1147 CUnknown &operator=(OI *aIface)
1148 {
1149 attach(aIface);
1150 return *this;
1151 }
1152
1153 /** Assignment specialization for IUnknown. */
1154 CUnknown &operator=(IUnknown *aIface)
1155 {
1156 Base::operator=(aIface);
1157 return *this;
1158 }
1159
1160#ifdef VBOX_WITH_LESS_VIRTUALBOX_INCLUDING
1161 IID const &getIID() const RT_OVERRIDE { return COM_IIDOF(IUnknown); }
1162#else
1163 IID const &getIID() const { return COM_IIDOF(IUnknown); }
1164#endif
1165};
1166
1167/** @} */
1168
1169#endif /* !FEQT_INCLUDED_SRC_globals_COMDefs_h */
1170
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette