3
* VBox frontends: Qt GUI ("VirtualBox"):
4
* Various COM definitions and COM wrapper class declarations
6
* This header is used in conjunction with the header generated from
7
* XIDL expressed interface definitions to provide cross-platform Qt-based
8
* interface wrapper classes.
12
* Copyright (C) 2006-2008 Sun Microsystems, Inc.
14
* This file is part of VirtualBox Open Source Edition (OSE), as
15
* available from http://www.virtualbox.org. This file is free software;
16
* you can redistribute it and/or modify it under the terms of the GNU
17
* General Public License (GPL) as published by the Free Software
18
* Foundation, in version 2 as it comes in the "COPYING" file of the
19
* VirtualBox OSE distribution. VirtualBox OSE is distributed in the
20
* hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
22
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
23
* Clara, CA 95054 USA or visit http://www.sun.com if you need
24
* additional information or have any questions.
30
/** @defgroup grp_QT_COM Qt-COM Support Layer
33
* The Qt-COM support layer provides a set of definitions and smart classes for
34
* writing simple, clean and platform-independent code to access COM/XPCOM
35
* components through exposed COM interfaces. This layer is based on the
36
* COM/XPCOM Abstraction Layer library (the VBoxCOM glue library defined in
37
* include/VBox/com and implemented in src/VBox/Main/glue).
41
* @defgroup grp_QT_COM_arrays Arrays
44
* COM/XPCOM arrays are mapped to QVector objects. QVector templates declared
45
* with a type that corresponds to the COM type of elements in the array using
46
* normal Qt-COM type mapping rules. Here is a code example that demonstrates
47
* how to call interface methods that take and return arrays (this example is
48
* based on examples given in @ref grp_COM_arrays):
55
QVector <LONG> in (3);
63
ret = component.TestArrays (in, out);
65
for (size_t i = 0; i < ret.size(); ++ i)
66
LogFlow (("*** ret[%u]=%d\n", i, ret [i]));
72
/* Both VBox/com/assert.h and qglobal.h contain a definition of ASSERT.
73
* Either of them can be already included here, so try to shut them up. */
76
#include <VBox/com/com.h>
77
#include <VBox/com/array.h>
78
#include <VBox/com/assert.h>
88
#include <iprt/memory> // for auto_copy_ptr
91
* Additional COM / XPCOM defines and includes
94
#if !defined (VBOX_WITH_XPCOM)
96
#else /* !defined (VBOX_WITH_XPCOM) */
100
#include <nsIComponentManager.h>
102
class XPCOMEventQSocketListener;
104
#endif /* !defined (VBOX_WITH_XPCOM) */
107
/* VirtualBox interfaces declarations */
108
#if !defined (VBOX_WITH_XPCOM)
109
#include <VirtualBox.h>
110
#else /* !defined (VBOX_WITH_XPCOM) */
111
#include <VirtualBox_XPCOM.h>
112
#endif /* !defined (VBOX_WITH_XPCOM) */
114
#include "VBoxDefs.h"
117
/////////////////////////////////////////////////////////////////////////////
119
class CVirtualBoxErrorInfo;
121
/** Represents extended error information */
128
, mIsBasicAvailable (false), mIsFullAvailable (false)
129
, mResultCode (S_OK) {}
131
COMErrorInfo (const CVirtualBoxErrorInfo &info) { init (info); }
133
/* the default copy ctor and assignment op are ok */
135
bool isNull() const { return mIsNull; }
137
bool isBasicAvailable() const { return mIsBasicAvailable; }
138
bool isFullAvailable() const { return mIsFullAvailable; }
140
HRESULT resultCode() const { return mResultCode; }
141
QUuid interfaceID() const { return mInterfaceID; }
142
QString component() const { return mComponent; }
143
QString text() const { return mText; }
145
const COMErrorInfo *next() const { return mNext.get(); }
147
QString interfaceName() const { return mInterfaceName; }
148
QUuid calleeIID() const { return mCalleeIID; }
149
QString calleeName() const { return mCalleeName; }
153
void init (const CVirtualBoxErrorInfo &info);
154
void fetchFromCurrentThread (IUnknown *callee, const GUID *calleeIID);
156
static QString getInterfaceNameFromIID (const QUuid &id);
159
bool mIsBasicAvailable : 1;
160
bool mIsFullAvailable : 1;
167
cppx::auto_copy_ptr <COMErrorInfo> mNext;
169
QString mInterfaceName;
173
friend class COMBaseWithEI;
176
/////////////////////////////////////////////////////////////////////////////
179
* Base COM class the CInterface template and all wrapper classes are derived
180
* from. Provides common functionality for all COM wrappers.
186
static HRESULT InitializeCOM();
187
static HRESULT CleanupCOM();
190
* Returns the result code of the last interface method called by the
191
* wrapper instance or the result of CInterface::createInstance()
194
HRESULT lastRC() const { return mRC; }
196
#if !defined (VBOX_WITH_XPCOM)
198
/** Converts a GUID value to QUuid */
199
static QUuid ToQUuid (const GUID &id)
201
return QUuid (id.Data1, id.Data2, id.Data3,
202
id.Data4[0], id.Data4[1], id.Data4[2], id.Data4[3],
203
id.Data4[4], id.Data4[5], id.Data4[6], id.Data4[7]);
206
#else /* !defined (VBOX_WITH_XPCOM) */
208
/** Converts a GUID value to QUuid */
209
static QUuid ToQUuid (const nsID &id)
211
return QUuid (id.m0, id.m1, id.m2,
212
id.m3[0], id.m3[1], id.m3[2], id.m3[3],
213
id.m3[4], id.m3[5], id.m3[6], id.m3[7]);
216
#endif /* !defined (VBOX_WITH_XPCOM) */
218
/* Arrays of arbitrary types */
220
template <typename QT, typename CT>
221
static void ToSafeArray (const QVector <QT> &aVec, com::SafeArray <CT> &aArr)
223
aArr.reset (aVec.size());
224
for (int i = 0; i < aVec.size(); ++i)
225
aArr [i] = static_cast<CT> (aVec.at (i));
228
template <typename CT, typename QT>
229
static void FromSafeArray (const com::SafeArray <CT> &aArr, QVector <QT> &aVec)
231
aVec.resize (static_cast<int> (aArr.size()));
232
for (int i = 0; i < aVec.size(); ++i)
233
aVec [i] = static_cast<QT> (aArr [i]);
236
template <typename QT, typename CT>
237
static void ToSafeArray (const QVector <QT *> &aVec, com::SafeArray <CT *> &aArr)
241
AssertMsgFailedReturnVoid (("No conversion!\n"));
244
template <typename CT, typename QT>
245
static void FromSafeArray (const com::SafeArray <CT *> &aArr, QVector <QT *> &aVec)
249
AssertMsgFailedReturnVoid (("No conversion!\n"));
252
/* Arrays of equal types */
254
template <typename T>
255
static void ToSafeArray (const QVector <T> &aVec, com::SafeArray <T> &aArr)
257
aArr.reset (aVec.size());
258
for (int i = 0; i < aVec.size(); ++i)
259
aArr [i] = aVec.at (i);
262
template <typename T>
263
static void FromSafeArray (const com::SafeArray <T> &aArr, QVector <T> &aVec)
265
aVec.resize (static_cast<int> (aArr.size()));
266
for (int i = 0; i < aVec.size(); ++i)
270
/* Arrays of strings */
272
static void ToSafeArray (const QVector <QString> &aVec,
273
com::SafeArray <BSTR> &aArr);
274
static void FromSafeArray (const com::SafeArray <BSTR> &aArr,
275
QVector <QString> &aVec);
279
static void ToSafeArray (const QVector <QUuid> &aVec,
280
com::SafeGUIDArray &aArr);
281
static void FromSafeArray (const com::SafeGUIDArray &aArr,
282
QVector <QUuid> &aVec);
284
/* Arrays of enums. Does a cast similar to what ENUMOut does. */
286
template <typename QE, typename CE>
287
static void ToSafeArray (const QVector <QE> &aVec,
288
com::SafeIfaceArray <CE> &aArr)
290
aArr.reset (static_cast <int> (aVec.size()));
291
for (int i = 0; i < aVec.size(); ++i)
292
aArr [i] = static_cast <CE> (aVec.at (i));
295
template <typename CE, typename QE>
296
static void FromSafeArray (const com::SafeIfaceArray <CE> &aArr,
299
aVec.resize (static_cast <int> (aArr.size()));
300
for (int i = 0; i < aVec.size(); ++i)
301
aVec [i] = static_cast <QE> (aArr [i]);
304
/* Arrays of interface pointers. Note: we need a separate pair of names
305
* only because the MSVC8 template matching algorithm is poor and tries to
306
* instantiate a com::SafeIfaceArray <BSTR> (!!!) template otherwise for
307
* *no* reason and fails. Note that it's also not possible to choose the
308
* correct function by specifying template arguments explicitly because then
309
* it starts to try to instantiate the com::SafeArray <I> template for
310
* *no* reason again and fails too. Definitely, broken. Works in GCC like a
313
template <class CI, class I>
314
static void ToSafeIfaceArray (const QVector <CI> &aVec,
315
com::SafeIfaceArray <I> &aArr)
317
aArr.reset (static_cast<int> (aVec.size()));
318
for (int i = 0; i < aVec.size(); ++i)
320
aArr [i] = aVec.at (i).raw();
326
template <class I, class CI>
327
static void FromSafeIfaceArray (const com::SafeIfaceArray <I> &aArr,
330
aVec.resize (static_cast<int> (aArr.size()));
331
for (int i = 0; i < aVec.size(); ++i)
332
aVec [i].attach (aArr [i]);
337
/* no arbitrary instance creations */
338
COMBase() : mRC (S_OK) {};
340
#if defined (VBOX_WITH_XPCOM)
341
static XPCOMEventQSocketListener *sSocketListener;
344
/** Adapter to pass QString as input BSTR params */
349
BSTRIn (const QString &s) : bstr (SysAllocString ((const OLECHAR *)
350
(s.isNull() ? 0 : s.utf16()))) {}
355
SysFreeString (bstr);
358
operator BSTR() const { return bstr; }
365
/** Adapter to pass QString as output BSTR params */
370
BSTROut (QString &s) : str (s), bstr (0) {}
375
str = QString::fromUtf16 (bstr);
376
SysFreeString (bstr);
380
operator BSTR *() { return &bstr; }
389
* Adapter to pass K* enums as output COM enum params (*_T).
392
* @param CE COM enum.
394
template <typename QE, typename CE>
399
ENUMOut (QE &e) : qe (e), ce ((CE) 0) {}
400
~ENUMOut() { qe = (QE) ce; }
401
operator CE *() { return &ce; }
409
#if !defined (VBOX_WITH_XPCOM)
411
/** Adapter to pass QUuid as input GUID params */
412
static GUID GUIDIn (const QUuid &uuid) { return uuid; }
414
/** Adapter to pass QUuid as output GUID params */
419
GUIDOut (QUuid &id) : uuid (id)
421
::memset (&guid, 0, sizeof (GUID));
427
guid.Data1, guid.Data2, guid.Data3,
428
guid.Data4[0], guid.Data4[1], guid.Data4[2], guid.Data4[3],
429
guid.Data4[4], guid.Data4[5], guid.Data4[6], guid.Data4[7]);
432
operator GUID *() { return &guid; }
440
#else /* !defined (VBOX_WITH_XPCOM) */
442
/** Adapter to pass QUuid as input GUID params */
443
static const nsID &GUIDIn (const QUuid &uuid)
445
return *(const nsID *) &uuid;
448
/** Adapter to pass QUuid as output GUID params */
453
GUIDOut (QUuid &id) : uuid (id), nsid (0) {}
460
nsid->m0, nsid->m1, nsid->m2,
461
nsid->m3[0], nsid->m3[1], nsid->m3[2], nsid->m3[3],
462
nsid->m3[4], nsid->m3[5], nsid->m3[6], nsid->m3[7]);
463
nsMemory::Free (nsid);
467
operator nsID **() { return &nsid; }
475
#endif /* !defined (VBOX_WITH_XPCOM) */
477
static void addref (IUnknown *aIface) { if (aIface) aIface->AddRef(); }
478
static void release (IUnknown *aIface) { if (aIface) aIface->Release(); }
484
friend class COMErrorInfo;
487
/////////////////////////////////////////////////////////////////////////////
490
* Alternative base class for the CInterface template that adds the errorInfo()
491
* method for providing extended error info about unsuccessful invocation of the
492
* last called interface method.
494
class COMBaseWithEI : public COMBase
499
* Returns error info set by the last unsuccessfully invoked interface
500
* method. Returned error info is useful only if CInterface::lastRC()
501
* represents a failure or a warning (i.e. CInterface::isReallyOk() is
504
const COMErrorInfo &errorInfo() const { return mErrInfo; }
508
/* no arbitrary instance creation */
509
COMBaseWithEI() : COMBase () {};
511
void setErrorInfo (const COMErrorInfo &aErrInfo) { mErrInfo = aErrInfo; }
513
void fetchErrorInfo (IUnknown *aCallee, const GUID *aCalleeIID) const
515
mErrInfo.fetchFromCurrentThread (aCallee, aCalleeIID);
518
mutable COMErrorInfo mErrInfo;
521
/////////////////////////////////////////////////////////////////////////////
524
* Simple class that encapsulates the result code and COMErrorInfo.
530
COMResult() : mRC (S_OK) {}
533
* Queries the current result code from the given component.
535
explicit COMResult (const COMBase &aComponent)
536
: mRC (aComponent.lastRC()) {}
539
* Queries the current result code and error info from the given component.
541
COMResult (const COMBaseWithEI &aComponent)
542
: mRC (aComponent.lastRC())
543
, mErrInfo (aComponent.errorInfo()) {}
546
* Queries the current result code from the given component.
548
COMResult &operator= (const COMBase &aComponent)
550
mRC = aComponent.lastRC();
555
* Queries the current result code and error info from the given component.
557
COMResult &operator= (const COMBaseWithEI &aComponent)
559
mRC = aComponent.lastRC();
560
mErrInfo = aComponent.errorInfo();
564
bool isNull() const { return mErrInfo.isNull(); }
567
* Returns @c true if the result code represents success (with or without
570
bool isOk() const { return SUCCEEDED (mRC); }
573
* Returns @c true if the result code represents success with one or more
576
bool isWarning() const { return SUCCEEDED_WARNING (mRC); }
579
* Returns @c true if the result code represents success with no warnings.
581
bool isReallyOk() const { return mRC == S_OK; }
583
COMErrorInfo errorInfo() const { return mErrInfo; }
584
HRESULT rc() const { return mRC; }
589
COMErrorInfo mErrInfo;
592
/////////////////////////////////////////////////////////////////////////////
595
* Wrapper template class for all interfaces.
597
* All interface methods named as they are in the original, i.e. starting
598
* with the capital letter. All utility non-interface methods are named
599
* starting with the small letter. Utility methods should be not normally
600
* called by the end-user client application.
602
* @param I Interface class (i.e. IUnknown/nsISupports derivant).
603
* @param B Base class, either COMBase (by default) or COMBaseWithEI.
605
template <class I, class B = COMBase>
606
class CInterface : public B
613
// constructors & destructor
615
CInterface() : mIface (NULL) {}
617
CInterface (const CInterface &that) : B (that), mIface (that.mIface)
622
CInterface (I *aIface) : mIface (aIface) { addref (mIface); }
624
virtual ~CInterface() { release (mIface); }
628
void createInstance (const CLSID &aClsId)
630
AssertMsg (!mIface, ("Instance is already non-NULL\n"));
633
#if !defined (VBOX_WITH_XPCOM)
635
B::mRC = CoCreateInstance (aClsId, NULL, CLSCTX_ALL,
636
_ATL_IIDOF (I), (void **) &mIface);
638
#else /* !defined (VBOX_WITH_XPCOM) */
640
nsCOMPtr <nsIComponentManager> manager;
641
B::mRC = NS_GetComponentManager (getter_AddRefs (manager));
642
if (SUCCEEDED (B::mRC))
643
B::mRC = manager->CreateInstance (aClsId, nsnull, NS_GET_IID (I),
646
#endif /* !defined (VBOX_WITH_XPCOM) */
648
/* fetch error info, but don't assert if it's missing -- many other
649
* reasons can lead to an error (w/o providing error info), not only
650
* the instance initialization code (that should always provide it) */
651
B::fetchErrorInfo (NULL, NULL);
656
* Attaches to the given foreign interface pointer by querying the own
657
* interface on it. The operation may fail.
660
void attach (OI *aIface)
662
/* be aware of self assignment */
668
#if !defined (VBOX_WITH_XPCOM)
669
B::mRC = aIface->QueryInterface (_ATL_IIDOF (I), (void **) &mIface);
670
#else /* !defined (VBOX_WITH_XPCOM) */
671
B::mRC = aIface->QueryInterface (NS_GET_IID (I), (void **) &mIface);
672
#endif /* !defined (VBOX_WITH_XPCOM) */
681
/** Specialization of attach() for our own interface I. Never fails. */
682
void attach (I *aIface)
684
/* be aware of self assignment */
691
/** Detaches from the underlying interface pointer. */
692
void detach() { release (mIface); mIface = NULL; }
694
/** Returns @c true if not attached to any interface pointer. */
695
bool isNull() const { return mIface == NULL; }
698
* Returns @c true if the result code represents success (with or without
701
bool isOk() const { return !isNull() && SUCCEEDED (B::mRC); }
704
* Returns @c true if the result code represents success with one or more
707
bool isWarning() const { return !isNull() && SUCCEEDED_WARNING (B::mRC); }
710
* Returns @c true if the result code represents success with no warnings.
712
bool isReallyOk() const { return !isNull() && B::mRC == S_OK; }
716
CInterface &operator= (const CInterface &that)
718
attach (that.mIface);
723
CInterface &operator= (I *aIface)
730
* Returns the raw interface pointer. Not intended to be used for anything
731
* else but in generated wrappers and for debugging. You've been warned.
733
I *raw() const { return mIface; }
735
bool operator== (const CInterface &that) const { return mIface == that.mIface; }
736
bool operator!= (const CInterface &that) const { return mIface != that.mIface; }
743
/////////////////////////////////////////////////////////////////////////////
745
class CUnknown : public CInterface <IUnknown, COMBaseWithEI>
749
typedef CInterface <IUnknown, COMBaseWithEI> Base;
753
/** Creates an instance given another CInterface-based instance. */
754
template <class OI, class OB>
755
explicit CUnknown (const CInterface <OI, OB> &that)
757
attach (that.mIface);
760
/* preserve old error info if any */
762
setErrorInfo (that.errorInfo());
766
/** Constructor specialization for IUnknown. */
767
CUnknown (const CUnknown &that) : Base (that) {}
769
/** Creates an instance given a foreign interface pointer. */
771
explicit CUnknown (OI *aIface)
776
/** Constructor specialization for IUnknown. */
777
explicit CUnknown (IUnknown *aIface) : Base (aIface) {}
779
/** Assigns from another CInterface-based instance. */
780
template <class OI, class OB>
781
CUnknown &operator= (const CInterface <OI, OB> &that)
783
attach (that.mIface);
786
/* preserve old error info if any */
788
setErrorInfo (that.errorInfo());
793
/** Assignment specialization for CUnknown. */
794
CUnknown &operator= (const CUnknown &that)
796
Base::operator= (that);
800
/** Assigns from a foreign interface pointer. */
802
CUnknown &operator= (OI *aIface)
808
/** Assignment specialization for IUnknown. */
809
CUnknown &operator= (IUnknown *aIface)
811
Base::operator= (aIface);
815
/* @internal Used in generated wrappers. Never use directly. */
816
IUnknown *&rawRef() { return mIface; };
819
/////////////////////////////////////////////////////////////////////////////
821
/* include the generated header containing concrete wrapper definitions */
822
#include "COMWrappers.h"
826
#endif // __COMDefs_h__