[25177] | 1 | /** @file
|
---|
| 2 | *
|
---|
| 3 | * VBox frontends: Qt GUI ("VirtualBox"):
|
---|
| 4 | * Various COM definitions and COM wrapper class declarations
|
---|
| 5 | *
|
---|
| 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.
|
---|
| 9 | */
|
---|
| 10 |
|
---|
| 11 | /*
|
---|
[28800] | 12 | * Copyright (C) 2006-2008 Oracle Corporation
|
---|
[25177] | 13 | *
|
---|
| 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.
|
---|
| 21 | */
|
---|
| 22 |
|
---|
| 23 | #ifndef __COMDefs_h__
|
---|
| 24 | #define __COMDefs_h__
|
---|
| 25 |
|
---|
| 26 | /** @defgroup grp_QT_COM Qt-COM Support Layer
|
---|
| 27 | * @{
|
---|
| 28 | *
|
---|
| 29 | * The Qt-COM support layer provides a set of definitions and smart classes for
|
---|
| 30 | * writing simple, clean and platform-independent code to access COM/XPCOM
|
---|
| 31 | * components through exposed COM interfaces. This layer is based on the
|
---|
| 32 | * COM/XPCOM Abstraction Layer library (the VBoxCOM glue library defined in
|
---|
| 33 | * include/VBox/com and implemented in src/VBox/Main/glue).
|
---|
| 34 | *
|
---|
| 35 | * ...
|
---|
| 36 | *
|
---|
| 37 | * @defgroup grp_QT_COM_arrays Arrays
|
---|
| 38 | * @{
|
---|
| 39 | *
|
---|
| 40 | * COM/XPCOM arrays are mapped to QVector objects. QVector templates declared
|
---|
| 41 | * with a type that corresponds to the COM type of elements in the array using
|
---|
| 42 | * normal Qt-COM type mapping rules. Here is a code example that demonstrates
|
---|
| 43 | * how to call interface methods that take and return arrays (this example is
|
---|
| 44 | * based on examples given in @ref grp_COM_arrays):
|
---|
| 45 | * @code
|
---|
| 46 |
|
---|
| 47 | CSomething component;
|
---|
| 48 |
|
---|
| 49 | // ...
|
---|
| 50 |
|
---|
| 51 | QVector <LONG> in (3);
|
---|
| 52 | in [0] = -1;
|
---|
| 53 | in [1] = -2;
|
---|
| 54 | in [2] = -3;
|
---|
| 55 |
|
---|
| 56 | QVector <LONG> out;
|
---|
| 57 | QVector <LONG> ret;
|
---|
| 58 |
|
---|
| 59 | ret = component.TestArrays (in, out);
|
---|
| 60 |
|
---|
| 61 | for (size_t i = 0; i < ret.size(); ++ i)
|
---|
| 62 | LogFlow (("*** ret[%u]=%d\n", i, ret [i]));
|
---|
| 63 |
|
---|
| 64 | * @endcode
|
---|
| 65 | * @}
|
---|
| 66 | */
|
---|
| 67 |
|
---|
| 68 | /* Both VBox/com/assert.h and qglobal.h contain a definition of ASSERT.
|
---|
| 69 | * Either of them can be already included here, so try to shut them up. */
|
---|
| 70 | #undef ASSERT
|
---|
| 71 |
|
---|
| 72 | #include <VBox/com/com.h>
|
---|
| 73 | #include <VBox/com/array.h>
|
---|
| 74 | #include <VBox/com/assert.h>
|
---|
| 75 |
|
---|
| 76 | #undef ASSERT
|
---|
| 77 |
|
---|
| 78 | /* Qt includes */
|
---|
| 79 | #include <QString>
|
---|
[30026] | 80 | #include <QRect>
|
---|
[25177] | 81 | #include <QUuid>
|
---|
| 82 | #include <QVector>
|
---|
[30867] | 83 | #include <QStringList>
|
---|
[25177] | 84 | #include <QMetaType>
|
---|
| 85 |
|
---|
| 86 | /*
|
---|
| 87 | * Additional COM / XPCOM defines and includes
|
---|
| 88 | */
|
---|
| 89 |
|
---|
| 90 | #if !defined (VBOX_WITH_XPCOM)
|
---|
| 91 |
|
---|
| 92 | #else /* !defined (VBOX_WITH_XPCOM) */
|
---|
| 93 |
|
---|
| 94 | #include <nsXPCOM.h>
|
---|
| 95 | #include <nsMemory.h>
|
---|
| 96 | #include <nsIComponentManager.h>
|
---|
| 97 |
|
---|
| 98 | class XPCOMEventQSocketListener;
|
---|
| 99 |
|
---|
| 100 | #endif /* !defined (VBOX_WITH_XPCOM) */
|
---|
| 101 |
|
---|
| 102 |
|
---|
| 103 | /* VirtualBox interfaces declarations */
|
---|
| 104 | #if !defined (VBOX_WITH_XPCOM)
|
---|
| 105 | #include <VirtualBox.h>
|
---|
| 106 | #else /* !defined (VBOX_WITH_XPCOM) */
|
---|
| 107 | #include <VirtualBox_XPCOM.h>
|
---|
| 108 | #endif /* !defined (VBOX_WITH_XPCOM) */
|
---|
| 109 |
|
---|
| 110 | /////////////////////////////////////////////////////////////////////////////
|
---|
| 111 |
|
---|
| 112 | class CVirtualBoxErrorInfo;
|
---|
| 113 |
|
---|
| 114 | /** Represents extended error information */
|
---|
| 115 | class COMErrorInfo
|
---|
| 116 | {
|
---|
| 117 | public:
|
---|
| 118 |
|
---|
| 119 | COMErrorInfo()
|
---|
[30681] | 120 | : mIsNull(true),
|
---|
| 121 | mIsBasicAvailable(false),
|
---|
| 122 | mIsFullAvailable(false),
|
---|
| 123 | mResultCode(S_OK),
|
---|
| 124 | m_pNext(NULL)
|
---|
| 125 | {}
|
---|
[25177] | 126 |
|
---|
[30681] | 127 | COMErrorInfo(const COMErrorInfo &info)
|
---|
| 128 | {
|
---|
| 129 | copyFrom(info);
|
---|
| 130 | }
|
---|
[25177] | 131 |
|
---|
[30681] | 132 | COMErrorInfo(const CVirtualBoxErrorInfo &info)
|
---|
| 133 | {
|
---|
| 134 | init(info);
|
---|
| 135 | }
|
---|
[25177] | 136 |
|
---|
[30681] | 137 | ~COMErrorInfo()
|
---|
| 138 | {
|
---|
| 139 | cleanup();
|
---|
| 140 | }
|
---|
| 141 |
|
---|
| 142 | COMErrorInfo& operator=(const COMErrorInfo &info)
|
---|
| 143 | {
|
---|
| 144 | cleanup();
|
---|
| 145 | copyFrom(info);
|
---|
| 146 | return *this;
|
---|
| 147 | }
|
---|
| 148 |
|
---|
[25177] | 149 | bool isNull() const { return mIsNull; }
|
---|
| 150 |
|
---|
| 151 | bool isBasicAvailable() const { return mIsBasicAvailable; }
|
---|
| 152 | bool isFullAvailable() const { return mIsFullAvailable; }
|
---|
| 153 |
|
---|
| 154 | HRESULT resultCode() const { return mResultCode; }
|
---|
| 155 | QUuid interfaceID() const { return mInterfaceID; }
|
---|
| 156 | QString component() const { return mComponent; }
|
---|
| 157 | QString text() const { return mText; }
|
---|
| 158 |
|
---|
[30681] | 159 | const COMErrorInfo *next() const { return m_pNext; }
|
---|
[25177] | 160 |
|
---|
| 161 | QString interfaceName() const { return mInterfaceName; }
|
---|
| 162 | QUuid calleeIID() const { return mCalleeIID; }
|
---|
| 163 | QString calleeName() const { return mCalleeName; }
|
---|
| 164 |
|
---|
| 165 | private:
|
---|
[30681] | 166 | void init(const CVirtualBoxErrorInfo &info);
|
---|
| 167 | void copyFrom(const COMErrorInfo &x);
|
---|
| 168 | void cleanup();
|
---|
[25177] | 169 |
|
---|
[30681] | 170 | void fetchFromCurrentThread(IUnknown *callee, const GUID *calleeIID);
|
---|
[30676] | 171 |
|
---|
[25177] | 172 | static QString getInterfaceNameFromIID (const QUuid &id);
|
---|
| 173 |
|
---|
| 174 | bool mIsNull : 1;
|
---|
| 175 | bool mIsBasicAvailable : 1;
|
---|
| 176 | bool mIsFullAvailable : 1;
|
---|
| 177 |
|
---|
| 178 | HRESULT mResultCode;
|
---|
| 179 | QUuid mInterfaceID;
|
---|
| 180 | QString mComponent;
|
---|
| 181 | QString mText;
|
---|
| 182 |
|
---|
[30681] | 183 | COMErrorInfo *m_pNext;
|
---|
[25177] | 184 |
|
---|
| 185 | QString mInterfaceName;
|
---|
| 186 | QUuid mCalleeIID;
|
---|
| 187 | QString mCalleeName;
|
---|
| 188 |
|
---|
| 189 | friend class COMBaseWithEI;
|
---|
| 190 | };
|
---|
| 191 |
|
---|
| 192 | /////////////////////////////////////////////////////////////////////////////
|
---|
| 193 |
|
---|
| 194 | /**
|
---|
| 195 | * Base COM class the CInterface template and all wrapper classes are derived
|
---|
| 196 | * from. Provides common functionality for all COM wrappers.
|
---|
| 197 | */
|
---|
| 198 | class COMBase
|
---|
| 199 | {
|
---|
| 200 | public:
|
---|
| 201 |
|
---|
[35638] | 202 | static HRESULT InitializeCOM(bool fGui);
|
---|
[25177] | 203 | static HRESULT CleanupCOM();
|
---|
| 204 |
|
---|
| 205 | /**
|
---|
| 206 | * Returns the result code of the last interface method called by the
|
---|
| 207 | * wrapper instance or the result of CInterface::createInstance()
|
---|
| 208 | * operation.
|
---|
| 209 | */
|
---|
| 210 | HRESULT lastRC() const { return mRC; }
|
---|
| 211 |
|
---|
| 212 | #if !defined (VBOX_WITH_XPCOM)
|
---|
| 213 |
|
---|
| 214 | /** Converts a GUID value to QUuid */
|
---|
| 215 | static QUuid ToQUuid (const GUID &id)
|
---|
| 216 | {
|
---|
| 217 | return QUuid (id.Data1, id.Data2, id.Data3,
|
---|
| 218 | id.Data4[0], id.Data4[1], id.Data4[2], id.Data4[3],
|
---|
| 219 | id.Data4[4], id.Data4[5], id.Data4[6], id.Data4[7]);
|
---|
| 220 | }
|
---|
| 221 |
|
---|
| 222 | #else /* !defined (VBOX_WITH_XPCOM) */
|
---|
| 223 |
|
---|
| 224 | /** Converts a GUID value to QUuid */
|
---|
| 225 | static QUuid ToQUuid (const nsID &id)
|
---|
| 226 | {
|
---|
| 227 | return QUuid (id.m0, id.m1, id.m2,
|
---|
| 228 | id.m3[0], id.m3[1], id.m3[2], id.m3[3],
|
---|
| 229 | id.m3[4], id.m3[5], id.m3[6], id.m3[7]);
|
---|
| 230 | }
|
---|
| 231 |
|
---|
| 232 | #endif /* !defined (VBOX_WITH_XPCOM) */
|
---|
| 233 |
|
---|
| 234 | /* Arrays of arbitrary types */
|
---|
| 235 |
|
---|
| 236 | template <typename QT, typename CT>
|
---|
| 237 | static void ToSafeArray (const QVector <QT> &aVec, com::SafeArray <CT> &aArr)
|
---|
| 238 | {
|
---|
| 239 | aArr.reset (aVec.size());
|
---|
| 240 | for (int i = 0; i < aVec.size(); ++i)
|
---|
| 241 | aArr [i] = static_cast<CT> (aVec.at (i));
|
---|
| 242 | }
|
---|
| 243 |
|
---|
| 244 | template <typename CT, typename QT>
|
---|
| 245 | static void FromSafeArray (const com::SafeArray <CT> &aArr, QVector <QT> &aVec)
|
---|
| 246 | {
|
---|
| 247 | aVec.resize (static_cast<int> (aArr.size()));
|
---|
| 248 | for (int i = 0; i < aVec.size(); ++i)
|
---|
| 249 | aVec [i] = static_cast<QT> (aArr [i]);
|
---|
| 250 | }
|
---|
| 251 |
|
---|
| 252 | template <typename QT, typename CT>
|
---|
| 253 | static void ToSafeArray (const QVector <QT *> &aVec, com::SafeArray <CT *> &aArr)
|
---|
| 254 | {
|
---|
| 255 | Q_UNUSED (aVec);
|
---|
| 256 | Q_UNUSED (aArr);
|
---|
| 257 | AssertMsgFailedReturnVoid (("No conversion!\n"));
|
---|
| 258 | }
|
---|
| 259 |
|
---|
| 260 | template <typename CT, typename QT>
|
---|
| 261 | static void FromSafeArray (const com::SafeArray <CT *> &aArr, QVector <QT *> &aVec)
|
---|
| 262 | {
|
---|
| 263 | Q_UNUSED (aArr);
|
---|
| 264 | Q_UNUSED (aVec);
|
---|
| 265 | AssertMsgFailedReturnVoid (("No conversion!\n"));
|
---|
| 266 | }
|
---|
| 267 |
|
---|
| 268 | /* Arrays of equal types */
|
---|
| 269 |
|
---|
| 270 | template <typename T>
|
---|
| 271 | static void ToSafeArray (const QVector <T> &aVec, com::SafeArray <T> &aArr)
|
---|
| 272 | {
|
---|
| 273 | aArr.reset (aVec.size());
|
---|
| 274 | for (int i = 0; i < aVec.size(); ++i)
|
---|
| 275 | aArr [i] = aVec.at (i);
|
---|
| 276 | }
|
---|
| 277 |
|
---|
| 278 | template <typename T>
|
---|
| 279 | static void FromSafeArray (const com::SafeArray <T> &aArr, QVector <T> &aVec)
|
---|
| 280 | {
|
---|
| 281 | aVec.resize (static_cast<int> (aArr.size()));
|
---|
| 282 | for (int i = 0; i < aVec.size(); ++i)
|
---|
| 283 | aVec [i] = aArr [i];
|
---|
| 284 | }
|
---|
| 285 |
|
---|
| 286 | /* Arrays of strings */
|
---|
| 287 |
|
---|
| 288 | static void ToSafeArray (const QVector <QString> &aVec,
|
---|
| 289 | com::SafeArray <BSTR> &aArr);
|
---|
| 290 | static void FromSafeArray (const com::SafeArray <BSTR> &aArr,
|
---|
| 291 | QVector <QString> &aVec);
|
---|
| 292 |
|
---|
| 293 | /* Arrays of GUID */
|
---|
| 294 |
|
---|
| 295 | static void ToSafeArray (const QVector <QUuid> &aVec,
|
---|
| 296 | com::SafeGUIDArray &aArr);
|
---|
| 297 | static void FromSafeArray (const com::SafeGUIDArray &aArr,
|
---|
| 298 | QVector <QUuid> &aVec);
|
---|
| 299 |
|
---|
| 300 | /* Arrays of enums. Does a cast similar to what ENUMOut does. */
|
---|
| 301 |
|
---|
| 302 | template <typename QE, typename CE>
|
---|
| 303 | static void ToSafeArray (const QVector <QE> &aVec,
|
---|
| 304 | com::SafeIfaceArray <CE> &aArr)
|
---|
| 305 | {
|
---|
| 306 | aArr.reset (static_cast <int> (aVec.size()));
|
---|
| 307 | for (int i = 0; i < aVec.size(); ++i)
|
---|
| 308 | aArr [i] = static_cast <CE> (aVec.at (i));
|
---|
| 309 | }
|
---|
| 310 |
|
---|
| 311 | template <typename CE, typename QE>
|
---|
| 312 | static void FromSafeArray (const com::SafeIfaceArray <CE> &aArr,
|
---|
| 313 | QVector <QE> &aVec)
|
---|
| 314 | {
|
---|
| 315 | aVec.resize (static_cast <int> (aArr.size()));
|
---|
| 316 | for (int i = 0; i < aVec.size(); ++i)
|
---|
| 317 | aVec [i] = static_cast <QE> (aArr [i]);
|
---|
| 318 | }
|
---|
| 319 |
|
---|
| 320 | /* Arrays of interface pointers. Note: we need a separate pair of names
|
---|
| 321 | * only because the MSVC8 template matching algorithm is poor and tries to
|
---|
| 322 | * instantiate a com::SafeIfaceArray <BSTR> (!!!) template otherwise for
|
---|
| 323 | * *no* reason and fails. Note that it's also not possible to choose the
|
---|
| 324 | * correct function by specifying template arguments explicitly because then
|
---|
| 325 | * it starts to try to instantiate the com::SafeArray <I> template for
|
---|
| 326 | * *no* reason again and fails too. Definitely, broken. Works in GCC like a
|
---|
| 327 | * charm. */
|
---|
| 328 |
|
---|
| 329 | template <class CI, class I>
|
---|
| 330 | static void ToSafeIfaceArray (const QVector <CI> &aVec,
|
---|
| 331 | com::SafeIfaceArray <I> &aArr)
|
---|
| 332 | {
|
---|
| 333 | aArr.reset (static_cast<int> (aVec.size()));
|
---|
| 334 | for (int i = 0; i < aVec.size(); ++i)
|
---|
| 335 | {
|
---|
| 336 | aArr [i] = aVec.at (i).raw();
|
---|
| 337 | if (aArr [i])
|
---|
| 338 | aArr [i]->AddRef();
|
---|
| 339 | }
|
---|
| 340 | }
|
---|
| 341 |
|
---|
| 342 | template <class I, class CI>
|
---|
| 343 | static void FromSafeIfaceArray (const com::SafeIfaceArray <I> &aArr,
|
---|
| 344 | QVector <CI> &aVec)
|
---|
| 345 | {
|
---|
| 346 | aVec.resize (static_cast<int> (aArr.size()));
|
---|
| 347 | for (int i = 0; i < aVec.size(); ++i)
|
---|
| 348 | aVec [i].attach (aArr [i]);
|
---|
| 349 | }
|
---|
| 350 |
|
---|
| 351 | protected:
|
---|
| 352 |
|
---|
| 353 | /* no arbitrary instance creations */
|
---|
[35638] | 354 | COMBase() : mRC (S_OK) {}
|
---|
[25177] | 355 |
|
---|
| 356 | #if defined (VBOX_WITH_XPCOM)
|
---|
| 357 | static XPCOMEventQSocketListener *sSocketListener;
|
---|
| 358 | #endif
|
---|
| 359 |
|
---|
| 360 | /** Adapter to pass QString as input BSTR params */
|
---|
| 361 | class BSTRIn
|
---|
| 362 | {
|
---|
| 363 | public:
|
---|
| 364 |
|
---|
| 365 | BSTRIn (const QString &s) : bstr (SysAllocString ((const OLECHAR *)
|
---|
| 366 | (s.isNull() ? 0 : s.utf16()))) {}
|
---|
| 367 |
|
---|
| 368 | ~BSTRIn()
|
---|
| 369 | {
|
---|
| 370 | if (bstr)
|
---|
| 371 | SysFreeString (bstr);
|
---|
| 372 | }
|
---|
| 373 |
|
---|
| 374 | operator BSTR() const { return bstr; }
|
---|
| 375 |
|
---|
| 376 | private:
|
---|
| 377 |
|
---|
| 378 | BSTR bstr;
|
---|
| 379 | };
|
---|
| 380 |
|
---|
| 381 | /** Adapter to pass QString as output BSTR params */
|
---|
| 382 | class BSTROut
|
---|
| 383 | {
|
---|
| 384 | public:
|
---|
| 385 |
|
---|
| 386 | BSTROut (QString &s) : str (s), bstr (0) {}
|
---|
| 387 |
|
---|
| 388 | ~BSTROut()
|
---|
| 389 | {
|
---|
| 390 | if (bstr) {
|
---|
| 391 | str = QString::fromUtf16 (bstr);
|
---|
| 392 | SysFreeString (bstr);
|
---|
| 393 | }
|
---|
| 394 | }
|
---|
| 395 |
|
---|
| 396 | operator BSTR *() { return &bstr; }
|
---|
| 397 |
|
---|
| 398 | private:
|
---|
| 399 |
|
---|
| 400 | QString &str;
|
---|
| 401 | BSTR bstr;
|
---|
| 402 | };
|
---|
| 403 |
|
---|
| 404 | /**
|
---|
| 405 | * Adapter to pass K* enums as output COM enum params (*_T).
|
---|
| 406 | *
|
---|
| 407 | * @param QE K* enum.
|
---|
| 408 | * @param CE COM enum.
|
---|
| 409 | */
|
---|
| 410 | template <typename QE, typename CE>
|
---|
| 411 | class ENUMOut
|
---|
| 412 | {
|
---|
| 413 | public:
|
---|
| 414 |
|
---|
| 415 | ENUMOut (QE &e) : qe (e), ce ((CE) 0) {}
|
---|
| 416 | ~ENUMOut() { qe = (QE) ce; }
|
---|
| 417 | operator CE *() { return &ce; }
|
---|
| 418 |
|
---|
| 419 | private:
|
---|
| 420 |
|
---|
| 421 | QE &qe;
|
---|
| 422 | CE ce;
|
---|
| 423 | };
|
---|
| 424 |
|
---|
| 425 | #if !defined (VBOX_WITH_XPCOM)
|
---|
| 426 |
|
---|
| 427 | /** Adapter to pass QUuid as input GUID params */
|
---|
| 428 | static GUID GUIDIn (const QUuid &uuid) { return uuid; }
|
---|
| 429 |
|
---|
| 430 | /** Adapter to pass QUuid as output GUID params */
|
---|
| 431 | class GUIDOut
|
---|
| 432 | {
|
---|
| 433 | public:
|
---|
| 434 |
|
---|
| 435 | GUIDOut (QUuid &id) : uuid (id)
|
---|
| 436 | {
|
---|
| 437 | ::memset (&guid, 0, sizeof (GUID));
|
---|
| 438 | }
|
---|
| 439 |
|
---|
| 440 | ~GUIDOut()
|
---|
| 441 | {
|
---|
| 442 | uuid = QUuid (
|
---|
| 443 | guid.Data1, guid.Data2, guid.Data3,
|
---|
| 444 | guid.Data4[0], guid.Data4[1], guid.Data4[2], guid.Data4[3],
|
---|
| 445 | guid.Data4[4], guid.Data4[5], guid.Data4[6], guid.Data4[7]);
|
---|
| 446 | }
|
---|
| 447 |
|
---|
| 448 | operator GUID *() { return &guid; }
|
---|
| 449 |
|
---|
| 450 | private:
|
---|
| 451 |
|
---|
| 452 | QUuid &uuid;
|
---|
| 453 | GUID guid;
|
---|
| 454 | };
|
---|
| 455 |
|
---|
| 456 | #else /* !defined (VBOX_WITH_XPCOM) */
|
---|
| 457 |
|
---|
| 458 | /** Adapter to pass QUuid as input GUID params */
|
---|
| 459 | static const nsID &GUIDIn (const QUuid &uuid)
|
---|
| 460 | {
|
---|
| 461 | return *(const nsID *) &uuid;
|
---|
| 462 | }
|
---|
| 463 |
|
---|
| 464 | /** Adapter to pass QUuid as output GUID params */
|
---|
| 465 | class GUIDOut
|
---|
| 466 | {
|
---|
| 467 | public:
|
---|
| 468 |
|
---|
| 469 | GUIDOut (QUuid &id) : uuid (id), nsid (0) {}
|
---|
| 470 |
|
---|
| 471 | ~GUIDOut()
|
---|
| 472 | {
|
---|
| 473 | if (nsid)
|
---|
| 474 | {
|
---|
| 475 | uuid = QUuid (
|
---|
| 476 | nsid->m0, nsid->m1, nsid->m2,
|
---|
| 477 | nsid->m3[0], nsid->m3[1], nsid->m3[2], nsid->m3[3],
|
---|
| 478 | nsid->m3[4], nsid->m3[5], nsid->m3[6], nsid->m3[7]);
|
---|
| 479 | nsMemory::Free (nsid);
|
---|
| 480 | }
|
---|
| 481 | }
|
---|
| 482 |
|
---|
| 483 | operator nsID **() { return &nsid; }
|
---|
| 484 |
|
---|
| 485 | private:
|
---|
| 486 |
|
---|
| 487 | QUuid &uuid;
|
---|
| 488 | nsID *nsid;
|
---|
| 489 | };
|
---|
| 490 |
|
---|
| 491 | #endif /* !defined (VBOX_WITH_XPCOM) */
|
---|
| 492 |
|
---|
| 493 | static void addref (IUnknown *aIface) { if (aIface) aIface->AddRef(); }
|
---|
| 494 | static void release (IUnknown *aIface) { if (aIface) aIface->Release(); }
|
---|
| 495 |
|
---|
| 496 | protected:
|
---|
| 497 |
|
---|
| 498 | mutable HRESULT mRC;
|
---|
| 499 |
|
---|
| 500 | friend class COMErrorInfo;
|
---|
| 501 | };
|
---|
| 502 |
|
---|
| 503 | /////////////////////////////////////////////////////////////////////////////
|
---|
| 504 |
|
---|
| 505 | /**
|
---|
| 506 | * Alternative base class for the CInterface template that adds the errorInfo()
|
---|
| 507 | * method for providing extended error info about unsuccessful invocation of the
|
---|
| 508 | * last called interface method.
|
---|
| 509 | */
|
---|
| 510 | class COMBaseWithEI : public COMBase
|
---|
| 511 | {
|
---|
| 512 | public:
|
---|
| 513 |
|
---|
| 514 | /**
|
---|
| 515 | * Returns error info set by the last unsuccessfully invoked interface
|
---|
| 516 | * method. Returned error info is useful only if CInterface::lastRC()
|
---|
| 517 | * represents a failure or a warning (i.e. CInterface::isReallyOk() is
|
---|
| 518 | * false).
|
---|
| 519 | */
|
---|
| 520 | const COMErrorInfo &errorInfo() const { return mErrInfo; }
|
---|
| 521 |
|
---|
| 522 | protected:
|
---|
| 523 |
|
---|
| 524 | /* no arbitrary instance creation */
|
---|
| 525 | COMBaseWithEI() : COMBase () {};
|
---|
| 526 |
|
---|
| 527 | void setErrorInfo (const COMErrorInfo &aErrInfo) { mErrInfo = aErrInfo; }
|
---|
| 528 |
|
---|
| 529 | void fetchErrorInfo (IUnknown *aCallee, const GUID *aCalleeIID) const
|
---|
| 530 | {
|
---|
| 531 | mErrInfo.fetchFromCurrentThread (aCallee, aCalleeIID);
|
---|
| 532 | }
|
---|
| 533 |
|
---|
| 534 | mutable COMErrorInfo mErrInfo;
|
---|
| 535 | };
|
---|
| 536 |
|
---|
| 537 | /////////////////////////////////////////////////////////////////////////////
|
---|
| 538 |
|
---|
| 539 | /**
|
---|
| 540 | * Simple class that encapsulates the result code and COMErrorInfo.
|
---|
| 541 | */
|
---|
| 542 | class COMResult
|
---|
| 543 | {
|
---|
| 544 | public:
|
---|
| 545 |
|
---|
| 546 | COMResult() : mRC (S_OK) {}
|
---|
| 547 |
|
---|
| 548 | /**
|
---|
| 549 | * Queries the current result code from the given component.
|
---|
| 550 | */
|
---|
| 551 | explicit COMResult (const COMBase &aComponent)
|
---|
| 552 | : mRC (aComponent.lastRC()) {}
|
---|
| 553 |
|
---|
| 554 | /**
|
---|
| 555 | * Queries the current result code and error info from the given component.
|
---|
| 556 | */
|
---|
[30681] | 557 | COMResult(const COMBaseWithEI &aComponent)
|
---|
| 558 | : mRC(aComponent.lastRC()),
|
---|
| 559 | mErrInfo(aComponent.errorInfo())
|
---|
| 560 | { }
|
---|
[25177] | 561 |
|
---|
| 562 | /**
|
---|
| 563 | * Queries the current result code from the given component.
|
---|
| 564 | */
|
---|
| 565 | COMResult &operator= (const COMBase &aComponent)
|
---|
| 566 | {
|
---|
| 567 | mRC = aComponent.lastRC();
|
---|
| 568 | return *this;
|
---|
| 569 | }
|
---|
| 570 |
|
---|
| 571 | /**
|
---|
| 572 | * Queries the current result code and error info from the given component.
|
---|
| 573 | */
|
---|
| 574 | COMResult &operator= (const COMBaseWithEI &aComponent)
|
---|
| 575 | {
|
---|
| 576 | mRC = aComponent.lastRC();
|
---|
| 577 | mErrInfo = aComponent.errorInfo();
|
---|
| 578 | return *this;
|
---|
| 579 | }
|
---|
| 580 |
|
---|
| 581 | bool isNull() const { return mErrInfo.isNull(); }
|
---|
| 582 |
|
---|
| 583 | /**
|
---|
| 584 | * Returns @c true if the result code represents success (with or without
|
---|
| 585 | * warnings).
|
---|
| 586 | */
|
---|
| 587 | bool isOk() const { return SUCCEEDED (mRC); }
|
---|
| 588 |
|
---|
| 589 | /**
|
---|
| 590 | * Returns @c true if the result code represents success with one or more
|
---|
| 591 | * warnings.
|
---|
| 592 | */
|
---|
| 593 | bool isWarning() const { return SUCCEEDED_WARNING (mRC); }
|
---|
| 594 |
|
---|
| 595 | /**
|
---|
| 596 | * Returns @c true if the result code represents success with no warnings.
|
---|
| 597 | */
|
---|
| 598 | bool isReallyOk() const { return mRC == S_OK; }
|
---|
| 599 |
|
---|
| 600 | COMErrorInfo errorInfo() const { return mErrInfo; }
|
---|
| 601 | HRESULT rc() const { return mRC; }
|
---|
| 602 |
|
---|
| 603 | private:
|
---|
| 604 |
|
---|
| 605 | HRESULT mRC;
|
---|
| 606 | COMErrorInfo mErrInfo;
|
---|
| 607 | };
|
---|
| 608 |
|
---|
| 609 | /////////////////////////////////////////////////////////////////////////////
|
---|
| 610 |
|
---|
| 611 | /**
|
---|
| 612 | * Wrapper template class for all interfaces.
|
---|
| 613 | *
|
---|
| 614 | * All interface methods named as they are in the original, i.e. starting
|
---|
| 615 | * with the capital letter. All utility non-interface methods are named
|
---|
| 616 | * starting with the small letter. Utility methods should be not normally
|
---|
| 617 | * called by the end-user client application.
|
---|
| 618 | *
|
---|
[33540] | 619 | * @param I Interface class (i.e. derived from IUnknown/nsISupports).
|
---|
[25177] | 620 | * @param B Base class, either COMBase (by default) or COMBaseWithEI.
|
---|
| 621 | */
|
---|
| 622 | template <class I, class B = COMBase>
|
---|
| 623 | class CInterface : public B
|
---|
| 624 | {
|
---|
| 625 | public:
|
---|
| 626 |
|
---|
| 627 | typedef B Base;
|
---|
| 628 | typedef I Iface;
|
---|
| 629 |
|
---|
| 630 | // constructors & destructor
|
---|
| 631 |
|
---|
[37331] | 632 | CInterface()
|
---|
[25177] | 633 | {
|
---|
[35638] | 634 | clear();
|
---|
[25177] | 635 | }
|
---|
| 636 |
|
---|
[35638] | 637 | CInterface (const CInterface &that) : B (that)
|
---|
[37331] | 638 | {
|
---|
| 639 | clear();
|
---|
[35638] | 640 | mIface = that.mIface;
|
---|
[40023] | 641 | this->addref(ptr());
|
---|
[35638] | 642 | }
|
---|
[25177] | 643 |
|
---|
[37331] | 644 | CInterface (I *aIface)
|
---|
| 645 | {
|
---|
[35638] | 646 | clear();
|
---|
| 647 | setPtr (aIface);
|
---|
[40023] | 648 | this->addref (aIface);
|
---|
[35638] | 649 | }
|
---|
[25177] | 650 |
|
---|
[37331] | 651 | virtual ~CInterface()
|
---|
| 652 | {
|
---|
[35638] | 653 | detach();
|
---|
| 654 | #ifdef DEBUG
|
---|
| 655 | mDead = true;
|
---|
| 656 | #endif
|
---|
| 657 | }
|
---|
| 658 |
|
---|
[25177] | 659 | // utility methods
|
---|
| 660 | void createInstance (const CLSID &aClsId)
|
---|
| 661 | {
|
---|
[35638] | 662 | AssertMsg (ptr() == NULL, ("Instance is already non-NULL\n"));
|
---|
| 663 | if (ptr() == NULL)
|
---|
[25177] | 664 | {
|
---|
[35638] | 665 | I* pObj = NULL;
|
---|
[25177] | 666 | #if !defined (VBOX_WITH_XPCOM)
|
---|
| 667 | B::mRC = CoCreateInstance (aClsId, NULL, CLSCTX_ALL,
|
---|
[35638] | 668 | _ATL_IIDOF (I), (void **) &pObj);
|
---|
| 669 | #else
|
---|
[25177] | 670 | nsCOMPtr <nsIComponentManager> manager;
|
---|
| 671 | B::mRC = NS_GetComponentManager (getter_AddRefs (manager));
|
---|
| 672 | if (SUCCEEDED (B::mRC))
|
---|
| 673 | B::mRC = manager->CreateInstance (aClsId, nsnull, NS_GET_IID (I),
|
---|
[35638] | 674 | (void **) &pObj);
|
---|
| 675 | #endif
|
---|
[37331] | 676 |
|
---|
[35638] | 677 | if (SUCCEEDED (B::mRC))
|
---|
| 678 | setPtr(pObj);
|
---|
| 679 | else
|
---|
| 680 | setPtr(NULL);
|
---|
[37331] | 681 |
|
---|
[25177] | 682 | /* fetch error info, but don't assert if it's missing -- many other
|
---|
| 683 | * reasons can lead to an error (w/o providing error info), not only
|
---|
| 684 | * the instance initialization code (that should always provide it) */
|
---|
| 685 | B::fetchErrorInfo (NULL, NULL);
|
---|
[35638] | 686 | }
|
---|
[25177] | 687 | }
|
---|
| 688 |
|
---|
| 689 | /**
|
---|
| 690 | * Attaches to the given foreign interface pointer by querying the own
|
---|
| 691 | * interface on it. The operation may fail.
|
---|
| 692 | */
|
---|
| 693 | template <class OI>
|
---|
| 694 | void attach (OI *aIface)
|
---|
| 695 | {
|
---|
[35638] | 696 | #ifdef DEBUG
|
---|
| 697 | Assert(!mDead);
|
---|
| 698 | #endif
|
---|
[25177] | 699 | /* be aware of self assignment */
|
---|
[35638] | 700 | I* amIface = ptr();
|
---|
[40023] | 701 | this->addref (aIface);
|
---|
| 702 | this->release (amIface);
|
---|
[25177] | 703 | if (aIface)
|
---|
| 704 | {
|
---|
[35638] | 705 | amIface = NULL;
|
---|
| 706 | B::mRC = aIface->QueryInterface (COM_IIDOF (I), (void **) &amIface);
|
---|
[40023] | 707 | this->release (aIface);
|
---|
[35638] | 708 | setPtr(amIface);
|
---|
[25177] | 709 | }
|
---|
| 710 | else
|
---|
| 711 | {
|
---|
[35638] | 712 | setPtr(NULL);
|
---|
[25177] | 713 | B::mRC = S_OK;
|
---|
| 714 | }
|
---|
| 715 | };
|
---|
| 716 |
|
---|
| 717 | /** Specialization of attach() for our own interface I. Never fails. */
|
---|
| 718 | void attach (I *aIface)
|
---|
| 719 | {
|
---|
[35638] | 720 | #ifdef DEBUG
|
---|
| 721 | Assert(!mDead);
|
---|
| 722 | #endif
|
---|
[25177] | 723 | /* be aware of self assignment */
|
---|
[40023] | 724 | this->addref (aIface);
|
---|
| 725 | this->release (ptr());
|
---|
[35638] | 726 | setPtr(aIface);
|
---|
[25177] | 727 | B::mRC = S_OK;
|
---|
| 728 | };
|
---|
| 729 |
|
---|
| 730 | /** Detaches from the underlying interface pointer. */
|
---|
[37331] | 731 | void detach()
|
---|
| 732 | {
|
---|
[35638] | 733 | #ifdef DEBUG
|
---|
| 734 | Assert(!mDead);
|
---|
| 735 | #endif
|
---|
[40023] | 736 | this->release (ptr());
|
---|
[37331] | 737 | setPtr(NULL);
|
---|
[35638] | 738 | }
|
---|
[25177] | 739 |
|
---|
| 740 | /** Returns @c true if not attached to any interface pointer. */
|
---|
[37331] | 741 | bool isNull() const
|
---|
| 742 | {
|
---|
[35638] | 743 | #ifdef DEBUG
|
---|
| 744 | Assert(!mDead);
|
---|
| 745 | #endif
|
---|
[37331] | 746 | return mIface == NULL;
|
---|
[35638] | 747 | }
|
---|
[25177] | 748 |
|
---|
| 749 | /**
|
---|
| 750 | * Returns @c true if the result code represents success (with or without
|
---|
| 751 | * warnings).
|
---|
| 752 | */
|
---|
| 753 | bool isOk() const { return !isNull() && SUCCEEDED (B::mRC); }
|
---|
| 754 |
|
---|
| 755 | /**
|
---|
| 756 | * Returns @c true if the result code represents success with one or more
|
---|
| 757 | * warnings.
|
---|
| 758 | */
|
---|
| 759 | bool isWarning() const { return !isNull() && SUCCEEDED_WARNING (B::mRC); }
|
---|
| 760 |
|
---|
| 761 | /**
|
---|
| 762 | * Returns @c true if the result code represents success with no warnings.
|
---|
| 763 | */
|
---|
| 764 | bool isReallyOk() const { return !isNull() && B::mRC == S_OK; }
|
---|
| 765 |
|
---|
| 766 | // utility operators
|
---|
| 767 |
|
---|
| 768 | CInterface &operator= (const CInterface &that)
|
---|
| 769 | {
|
---|
[35638] | 770 | attach (that.ptr());
|
---|
[25177] | 771 | B::operator= (that);
|
---|
| 772 | return *this;
|
---|
| 773 | }
|
---|
| 774 |
|
---|
| 775 | CInterface &operator= (I *aIface)
|
---|
| 776 | {
|
---|
| 777 | attach (aIface);
|
---|
| 778 | return *this;
|
---|
| 779 | }
|
---|
| 780 |
|
---|
| 781 | /**
|
---|
| 782 | * Returns the raw interface pointer. Not intended to be used for anything
|
---|
| 783 | * else but in generated wrappers and for debugging. You've been warned.
|
---|
| 784 | */
|
---|
[37331] | 785 | I *raw() const
|
---|
[35638] | 786 | {
|
---|
| 787 | return ptr();
|
---|
| 788 | }
|
---|
[25177] | 789 |
|
---|
[35638] | 790 | bool operator== (const CInterface &that) const { return ptr() == that.ptr(); }
|
---|
| 791 | bool operator!= (const CInterface &that) const { return ptr() != that.ptr(); }
|
---|
[25177] | 792 |
|
---|
[35638] | 793 | I* ptr() const
|
---|
| 794 | {
|
---|
| 795 | #ifdef DEBUG
|
---|
| 796 | Assert(!mDead);
|
---|
| 797 | #endif
|
---|
[25177] | 798 |
|
---|
[35638] | 799 | return mIface;
|
---|
| 800 | }
|
---|
| 801 |
|
---|
| 802 | void setPtr(I* aObj) const
|
---|
| 803 | {
|
---|
| 804 | #ifdef DEBUG
|
---|
| 805 | Assert(!mDead);
|
---|
| 806 | #endif
|
---|
| 807 | mIface = aObj;
|
---|
| 808 | }
|
---|
| 809 |
|
---|
| 810 | private:
|
---|
| 811 | #ifdef DEBUG
|
---|
| 812 | bool mDead;
|
---|
| 813 | #endif
|
---|
| 814 | mutable I * mIface;
|
---|
| 815 |
|
---|
| 816 | void clear()
|
---|
| 817 | {
|
---|
[37331] | 818 | mIface = NULL;
|
---|
[35638] | 819 | #ifdef DEBUG
|
---|
| 820 | mDead = false;
|
---|
| 821 | #endif
|
---|
| 822 | }
|
---|
[25177] | 823 | };
|
---|
| 824 |
|
---|
| 825 | /////////////////////////////////////////////////////////////////////////////
|
---|
| 826 |
|
---|
| 827 | class CUnknown : public CInterface <IUnknown, COMBaseWithEI>
|
---|
| 828 | {
|
---|
| 829 | public:
|
---|
| 830 |
|
---|
| 831 | typedef CInterface <IUnknown, COMBaseWithEI> Base;
|
---|
| 832 |
|
---|
| 833 | CUnknown() {}
|
---|
| 834 |
|
---|
| 835 | /** Creates an instance given another CInterface-based instance. */
|
---|
| 836 | template <class OI, class OB>
|
---|
| 837 | explicit CUnknown (const CInterface <OI, OB> &that)
|
---|
| 838 | {
|
---|
[35638] | 839 | attach (that.ptr());
|
---|
[25177] | 840 | if (SUCCEEDED (mRC))
|
---|
| 841 | {
|
---|
| 842 | /* preserve old error info if any */
|
---|
| 843 | mRC = that.lastRC();
|
---|
| 844 | setErrorInfo (that.errorInfo());
|
---|
| 845 | }
|
---|
| 846 | }
|
---|
| 847 |
|
---|
| 848 | /** Constructor specialization for IUnknown. */
|
---|
| 849 | CUnknown (const CUnknown &that) : Base (that) {}
|
---|
| 850 |
|
---|
| 851 | /** Creates an instance given a foreign interface pointer. */
|
---|
| 852 | template <class OI>
|
---|
| 853 | explicit CUnknown (OI *aIface)
|
---|
| 854 | {
|
---|
| 855 | attach (aIface);
|
---|
| 856 | }
|
---|
| 857 |
|
---|
| 858 | /** Constructor specialization for IUnknown. */
|
---|
| 859 | explicit CUnknown (IUnknown *aIface) : Base (aIface) {}
|
---|
| 860 |
|
---|
| 861 | /** Assigns from another CInterface-based instance. */
|
---|
| 862 | template <class OI, class OB>
|
---|
| 863 | CUnknown &operator= (const CInterface <OI, OB> &that)
|
---|
| 864 | {
|
---|
[35638] | 865 | attach (that.ptr());
|
---|
[25177] | 866 | if (SUCCEEDED (mRC))
|
---|
| 867 | {
|
---|
| 868 | /* preserve old error info if any */
|
---|
| 869 | mRC = that.lastRC();
|
---|
| 870 | setErrorInfo (that.errorInfo());
|
---|
| 871 | }
|
---|
| 872 | return *this;
|
---|
| 873 | }
|
---|
| 874 |
|
---|
| 875 | /** Assignment specialization for CUnknown. */
|
---|
| 876 | CUnknown &operator= (const CUnknown &that)
|
---|
| 877 | {
|
---|
| 878 | Base::operator= (that);
|
---|
| 879 | return *this;
|
---|
| 880 | }
|
---|
| 881 |
|
---|
| 882 | /** Assigns from a foreign interface pointer. */
|
---|
| 883 | template <class OI>
|
---|
| 884 | CUnknown &operator= (OI *aIface)
|
---|
| 885 | {
|
---|
| 886 | attach (aIface);
|
---|
| 887 | return *this;
|
---|
| 888 | }
|
---|
| 889 |
|
---|
| 890 | /** Assignment specialization for IUnknown. */
|
---|
| 891 | CUnknown &operator= (IUnknown *aIface)
|
---|
| 892 | {
|
---|
| 893 | Base::operator= (aIface);
|
---|
| 894 | return *this;
|
---|
| 895 | }
|
---|
| 896 | };
|
---|
| 897 |
|
---|
| 898 | /** @} */
|
---|
| 899 |
|
---|
| 900 | #endif // __COMDefs_h__
|
---|
[26714] | 901 |
|
---|