VirtualBox

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

Last change on this file since 104158 was 103803, checked in by vboxsync, 9 months ago

FE/Qt. bugref:10618. Splitting COMEnums.h file into individual enum header files.

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