VirtualBox

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

Last change on this file since 102493 was 101567, checked in by vboxsync, 11 months ago

FE/Qt: bugref:10450: Get rid of Qt5 stuff; This one is about type changes.

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