VirtualBox

source: vbox/trunk/src/VBox/Frontends/VirtualBox/include/COMDefs.h@ 6851

最後變更 在這個檔案從6851是 6851,由 vboxsync 提交於 17 年 前

Ported r27277:27975 (array support) from branches/dmik/s2.

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Author Date Id Revision
檔案大小: 19.6 KB
 
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/*
12 * Copyright (C) 2006-2007 innotek GmbH
13 *
14 * This file is part of VirtualBox Open Source Edition (OSE), as
15 * available from http://www.alldomusa.eu.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 defintions 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 Abstarction 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 QValueVector objects. QValueVector templates
41 * declared with a type that corresponds to the COM type of elements in the
42 * array using normal Qt-COM type mapping rules. Here is a code example that
43 * demonstrates how to call interface methods that take and return arrays (this
44 * example is based on examples given in @ref grp_COM_arrays):
45 * @code
46
47 CSomething component;
48
49 // ...
50
51 QValueVector <LONG> in (3);
52 in [0] = -1;
53 in [1] = -2;
54 in [2] = -3;
55
56 QValueVector <LONG> out;
57 QValueVector <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#include <qglobal.h>
79#include <qstring.h>
80#include <quuid.h>
81#include <qvaluevector.h>
82
83#include <iprt/memory> // for auto_copy_ptr
84
85/*
86 * Additional COM / XPCOM defines and includes
87 */
88
89#define IN_BSTRPARAM INPTR BSTR
90#define IN_GUIDPARAM INPTR GUIDPARAM
91
92#if !defined (VBOX_WITH_XPCOM)
93
94#else /* !defined (VBOX_WITH_XPCOM) */
95
96#include <nsXPCOM.h>
97#include <nsMemory.h>
98#include <nsIComponentManager.h>
99
100class XPCOMEventQSocketListener;
101
102#endif /* !defined (VBOX_WITH_XPCOM) */
103
104
105/* VirtualBox interfaces declarations */
106#if !defined (VBOX_WITH_XPCOM)
107 #include <VirtualBox.h>
108#else /* !defined (VBOX_WITH_XPCOM) */
109 #include <VirtualBox_XPCOM.h>
110#endif /* !defined (VBOX_WITH_XPCOM) */
111
112#include "VBoxDefs.h"
113
114
115/////////////////////////////////////////////////////////////////////////////
116
117class CVirtualBoxErrorInfo;
118
119/** Represents extended error information */
120class COMErrorInfo
121{
122public:
123
124 COMErrorInfo()
125 : mIsNull (true)
126 , mIsBasicAvailable (false), mIsFullAvailable (false)
127 , mResultCode (S_OK) {}
128
129 COMErrorInfo (const CVirtualBoxErrorInfo &info) { init (info); }
130
131 /* the default copy ctor and assignment op are ok */
132
133 bool isNull() const { return mIsNull; }
134
135 bool isBasicAvailable() const { return mIsBasicAvailable; }
136 bool isFullAvailable() const { return mIsFullAvailable; }
137
138 HRESULT resultCode() const { return mResultCode; }
139 QUuid interfaceID() const { return mInterfaceID; }
140 QString component() const { return mComponent; }
141 QString text() const { return mText; }
142
143 const COMErrorInfo *next() const { return mNext.get(); }
144
145 QString interfaceName() const { return mInterfaceName; }
146 QUuid calleeIID() const { return mCalleeIID; }
147 QString calleeName() const { return mCalleeName; }
148
149private:
150
151 void init (const CVirtualBoxErrorInfo &info);
152 void fetchFromCurrentThread (IUnknown *callee, const GUID *calleeIID);
153
154 static QString getInterfaceNameFromIID (const QUuid &id);
155
156 bool mIsNull : 1;
157 bool mIsBasicAvailable : 1;
158 bool mIsFullAvailable : 1;
159
160 HRESULT mResultCode;
161 QUuid mInterfaceID;
162 QString mComponent;
163 QString mText;
164
165 cppx::auto_copy_ptr <COMErrorInfo> mNext;
166
167 QString mInterfaceName;
168 QUuid mCalleeIID;
169 QString mCalleeName;
170
171 friend class COMBaseWithEI;
172};
173
174/////////////////////////////////////////////////////////////////////////////
175
176/**
177 * Base COM class the CInterface template and all wrapper classes are derived
178 * from. Provides common functionality for all COM wrappers.
179 */
180class COMBase
181{
182public:
183
184 static HRESULT InitializeCOM();
185 static HRESULT CleanupCOM();
186
187 /**
188 * Returns the result code of the last interface method called
189 * by the wrapper instance or the result of CInterface::createInstance()
190 * operation.
191 */
192 HRESULT lastRC() const { return mRC; }
193
194 /**
195 * Returns error info set by the last unsuccessfully invoked interface
196 * method. Returned error info is useful only if CInterface::lastRC()
197 * represents a failure (i.e. CInterface::isOk() is false).
198 */
199 virtual COMErrorInfo errorInfo() const { return COMErrorInfo(); }
200
201#if !defined (VBOX_WITH_XPCOM)
202
203 /** Converts a GUID value to QUuid */
204 static QUuid ToQUuid (const GUID &id)
205 {
206 return QUuid (id.Data1, id.Data2, id.Data3,
207 id.Data4[0], id.Data4[1], id.Data4[2], id.Data4[3],
208 id.Data4[4], id.Data4[5], id.Data4[6], id.Data4[7]);
209 }
210
211#else /* !defined (VBOX_WITH_XPCOM) */
212
213 /** Converts a GUID value to QUuid */
214 static QUuid ToQUuid (const nsID &id)
215 {
216 return QUuid (id.m0, id.m1, id.m2,
217 id.m3[0], id.m3[1], id.m3[2], id.m3[3],
218 id.m3[4], id.m3[5], id.m3[6], id.m3[7]);
219 }
220
221#endif /* !defined (VBOX_WITH_XPCOM) */
222
223 /* Arrays of arbitrary types */
224
225 template <typename QT, typename CT>
226 static void ToSafeArray (const QValueVector <QT> &aVec, com::SafeArray <CT> &aArr)
227 {
228 AssertMsgFailedReturnVoid (("No conversion!\n"));
229 }
230
231 template <typename CT, typename QT>
232 static void FromSafeArray (const com::SafeArray <CT> &aArr, QValueVector <QT> &aVec)
233 {
234 AssertMsgFailedReturnVoid (("No conversion!\n"));
235 }
236
237 template <typename QT, typename CT>
238 static void ToSafeArray (const QValueVector <QT *> &aVec, com::SafeArray <CT *> &aArr)
239 {
240 AssertMsgFailedReturnVoid (("No conversion!\n"));
241 }
242
243 template <typename CT, typename QT>
244 static void FromSafeArray (const com::SafeArray <CT *> &aArr, QValueVector <QT *> &aVec)
245 {
246 AssertMsgFailedReturnVoid (("No conversion!\n"));
247 }
248
249 /* Arrays of equal types */
250
251 template <typename T>
252 static void ToSafeArray (const QValueVector <T> &aVec, com::SafeArray <T> &aArr)
253 {
254 aArr.reset (aVec.size());
255 size_t i = 0;
256 for (typename QValueVector <T>::const_iterator it = aVec.begin();
257 it != aVec.end(); ++ it, ++ i)
258 aArr [i] = *it;
259 }
260
261 template <typename T>
262 static void FromSafeArray (const com::SafeArray <T> &aArr, QValueVector <T> &aVec)
263 {
264 aVec = QValueVector <T> (aArr.size());
265 size_t i = 0;
266 for (typename QValueVector <T>::iterator it = aVec.begin();
267 it != aVec.end(); ++ it, ++ i)
268 *it = aArr [i];
269 }
270
271 /* Arrays of interface pointers */
272
273 template <class CI, class I>
274 static void ToSafeArray (const QValueVector <CI> &aVec,
275 com::SafeArray <I *> &aArr)
276 {
277 aArr.reset (aVec.size());
278 size_t i = 0;
279 for (typename QValueVector <CI>::const_iterator it = aVec.begin();
280 it != aVec.end(); ++ it, ++ i)
281 {
282 aArr [i] = (*it).iface();
283 if (aArr [i])
284 aArr [i]->AddRef();
285 }
286 }
287
288 template <class I, class CI>
289 void FromSafeArray (const com::SafeArray <I *> &aArr,
290 QValueVector <CI> &aVec)
291 {
292 aVec = QValueVector <CI> (aArr.size());
293 size_t i = 0;
294 for (typename QValueVector <CI>::iterator it = aVec.begin();
295 it != aVec.end(); ++ it, ++ i)
296 (*it).attach (aArr [i]);
297 }
298
299 /* Arrays of strings */
300
301 static void ToSafeArray (const QValueVector <QString> &aVec,
302 com::SafeArray <BSTR> &aArr);
303 static void FromSafeArray (const com::SafeArray <BSTR> &aArr,
304 QValueVector <QString> &aVec);
305
306protected:
307
308 /* no arbitrary instance creations */
309 COMBase() : mRC (S_OK) {};
310
311#if defined (VBOX_WITH_XPCOM)
312 static XPCOMEventQSocketListener *sSocketListener;
313#endif
314
315 /** Adapter to pass QString as input BSTR params */
316 class BSTRIn
317 {
318 public:
319
320 BSTRIn (const QString &s) : bstr (SysAllocString ((const OLECHAR *) s.ucs2())) {}
321
322 ~BSTRIn()
323 {
324 if (bstr)
325 SysFreeString (bstr);
326 }
327
328 operator BSTR() const { return bstr; }
329
330 private:
331
332 BSTR bstr;
333 };
334
335 /** Adapter to pass QString as output BSTR params */
336 class BSTROut
337 {
338 public:
339
340 BSTROut (QString &s) : str (s), bstr (0) {}
341
342 ~BSTROut()
343 {
344 if (bstr) {
345 str = QString::fromUcs2 (bstr);
346 SysFreeString (bstr);
347 }
348 }
349
350 operator BSTR *() { return &bstr; }
351
352 private:
353
354 QString &str;
355 BSTR bstr;
356 };
357
358 /**
359 * Adapter to pass CEnums enums as output COM enum params (*_T).
360 *
361 * @param QE CEnums enum.
362 * @param CE COM enum.
363 */
364 template <typename QE, typename CE>
365 class ENUMOut
366 {
367 public:
368
369 ENUMOut (QE &e) : qe (e), ce ((CE) 0) {}
370 ~ENUMOut() { qe = (QE) ce; }
371 operator CE *() { return &ce; }
372
373 private:
374
375 QE &qe;
376 CE ce;
377 };
378
379#if !defined (VBOX_WITH_XPCOM)
380
381 /** Adapter to pass QUuid as input GUID params */
382 static GUID GUIDIn (const QUuid &uuid) { return uuid; }
383
384 /** Adapter to pass QUuid as output GUID params */
385 class GUIDOut
386 {
387 public:
388
389 GUIDOut (QUuid &id) : uuid (id)
390 {
391 ::memset (&guid, 0, sizeof (GUID));
392 }
393
394 ~GUIDOut()
395 {
396 uuid = QUuid (
397 guid.Data1, guid.Data2, guid.Data3,
398 guid.Data4[0], guid.Data4[1], guid.Data4[2], guid.Data4[3],
399 guid.Data4[4], guid.Data4[5], guid.Data4[6], guid.Data4[7]);
400 }
401
402 operator GUID *() { return &guid; }
403
404 private:
405
406 QUuid &uuid;
407 GUID guid;
408 };
409
410#else /* !defined (VBOX_WITH_XPCOM) */
411
412 /** Adapter to pass QUuid as input GUID params */
413 static const nsID &GUIDIn (const QUuid &uuid)
414 {
415 return *(const nsID *) &uuid;
416 }
417
418 /** Adapter to pass QUuid as output GUID params */
419 class GUIDOut
420 {
421 public:
422
423 GUIDOut (QUuid &id) : uuid (id), nsid (0) {}
424
425 ~GUIDOut()
426 {
427 if (nsid)
428 {
429 uuid = QUuid (
430 nsid->m0, nsid->m1, nsid->m2,
431 nsid->m3[0], nsid->m3[1], nsid->m3[2], nsid->m3[3],
432 nsid->m3[4], nsid->m3[5], nsid->m3[6], nsid->m3[7]);
433 nsMemory::Free (nsid);
434 }
435 }
436
437 operator nsID **() { return &nsid; }
438
439 private:
440
441 QUuid &uuid;
442 nsID *nsid;
443 };
444
445#endif /* !defined (VBOX_WITH_XPCOM) */
446
447 void fetchErrorInfo (IUnknown * /*callee*/, const GUID * /*calleeIID*/) const {}
448
449 mutable HRESULT mRC;
450
451 friend class COMErrorInfo;
452};
453
454/////////////////////////////////////////////////////////////////////////////
455
456/**
457 * Alternative base class for the CInterface template that adds
458 * the errorInfo() method for providing extended error info about
459 * unsuccessful invocation of the last called interface method.
460 */
461class COMBaseWithEI : public COMBase
462{
463public:
464
465 /**
466 * Returns error info set by the last unsuccessfully invoked interface
467 * method. Returned error info is useful only if CInterface::lastRC()
468 * represents a failure (i.e. CInterface::isOk() is false).
469 */
470 COMErrorInfo errorInfo() const { return mErrInfo; }
471
472protected:
473
474 /* no arbitrary instance creations */
475 COMBaseWithEI() : COMBase () {};
476
477 void fetchErrorInfo (IUnknown *callee, const GUID *calleeIID) const
478 {
479 mErrInfo.fetchFromCurrentThread (callee, calleeIID);
480 }
481
482 mutable COMErrorInfo mErrInfo;
483};
484
485/////////////////////////////////////////////////////////////////////////////
486
487/**
488 * Simple class that encapsulates the result code and COMErrorInfo.
489 */
490class COMResult
491{
492public:
493
494 COMResult() : mRC (S_OK) {}
495
496 /** Queries the current result code and error info from the given component */
497 COMResult (const COMBase &aComponent)
498 {
499 mErrInfo = aComponent.errorInfo();
500 mRC = aComponent.lastRC();
501 }
502
503 /** Queries the current result code and error info from the given component */
504 COMResult &operator= (const COMBase &aComponent)
505 {
506 mErrInfo = aComponent.errorInfo();
507 mRC = aComponent.lastRC();
508 return *this;
509 }
510
511 bool isNull() const { return mErrInfo.isNull(); }
512 bool isOk() const { return mErrInfo.isNull() && SUCCEEDED (mRC); }
513
514 COMErrorInfo errorInfo() const { return mErrInfo; }
515 HRESULT rc() const { return mRC; }
516
517private:
518
519 COMErrorInfo mErrInfo;
520 HRESULT mRC;
521};
522
523/////////////////////////////////////////////////////////////////////////////
524
525class CUnknown;
526
527/**
528 * Wrapper template class for all interfaces.
529 *
530 * All interface methods named as they are in the original, i.e. starting
531 * with the capital letter. All utility non-interface methods are named
532 * starting with the small letter. Utility methods should be not normally
533 * called by the end-user client application.
534 *
535 * @param I interface class (i.e. IUnknown/nsISupports derivant)
536 * @param B base class, either COMBase (by default) or COMBaseWithEI
537 */
538template <class I, class B = COMBase>
539class CInterface : public B
540{
541public:
542
543 typedef B Base;
544 typedef I Iface;
545
546 /* constructors & destructor */
547
548 CInterface() : mIface (NULL) {}
549
550 CInterface (const CInterface &that) : B (that), mIface (that.mIface)
551 {
552 addref (mIface);
553 }
554
555 CInterface (const CUnknown &that);
556
557 CInterface (I *i) : mIface (i) { addref (mIface); }
558
559 virtual ~CInterface() { release (mIface); }
560
561 /* utility methods */
562
563 void createInstance (const CLSID &clsid)
564 {
565 AssertMsg (!mIface, ("Instance is already non-NULL\n"));
566 if (!mIface)
567 {
568#if !defined (VBOX_WITH_XPCOM)
569
570 B::mRC = CoCreateInstance (clsid, NULL, CLSCTX_ALL,
571 _ATL_IIDOF (I), (void **) &mIface);
572
573#else /* !defined (VBOX_WITH_XPCOM) */
574
575 nsCOMPtr <nsIComponentManager> manager;
576 B::mRC = NS_GetComponentManager (getter_AddRefs (manager));
577 if (SUCCEEDED (B::mRC))
578 B::mRC = manager->CreateInstance (clsid, nsnull, NS_GET_IID (I),
579 (void **) &mIface);
580
581#endif /* !defined (VBOX_WITH_XPCOM) */
582
583 /* fetch error info, but don't assert if it's missing -- many other
584 * reasons can lead to an error (w/o providing error info), not only
585 * the instance initialization code (that should always provide it) */
586 B::fetchErrorInfo (NULL, NULL);
587 }
588 }
589
590 void attach (I *i)
591 {
592 /* be aware of self (from COM point of view) assignment */
593 I *old_iface = mIface;
594 mIface = i;
595 addref (mIface);
596 release (old_iface);
597 B::mRC = S_OK;
598 };
599
600 void attachUnknown (IUnknown *i)
601 {
602 /* be aware of self (from COM point of view) assignment */
603 I *old_iface = mIface;
604 mIface = NULL;
605 B::mRC = S_OK;
606 if (i)
607#if !defined (VBOX_WITH_XPCOM)
608 B::mRC = i->QueryInterface (_ATL_IIDOF (I), (void **) &mIface);
609#else /* !defined (VBOX_WITH_XPCOM) */
610 B::mRC = i->QueryInterface (NS_GET_IID (I), (void **) &mIface);
611#endif /* !defined (VBOX_WITH_XPCOM) */
612 release (old_iface);
613 };
614
615 void detach() { release (mIface); mIface = NULL; }
616
617 bool isNull() const { return mIface == NULL; }
618
619 bool isOk() const { return !isNull() && SUCCEEDED (B::mRC); }
620
621 /* utility operators */
622
623 CInterface &operator= (const CInterface &that)
624 {
625 attach (that.mIface);
626 B::operator= (that);
627 return *this;
628 }
629
630 I *iface() const { return mIface; }
631
632 bool operator== (const CInterface &that) const { return mIface == that.mIface; }
633 bool operator!= (const CInterface &that) const { return mIface != that.mIface; }
634
635 CInterface &operator= (const CUnknown &that);
636
637protected:
638
639 static void addref (I *i) { if (i) i->AddRef(); }
640 static void release (I *i) { if (i) i->Release(); }
641
642 mutable I *mIface;
643};
644
645/////////////////////////////////////////////////////////////////////////////
646
647class CUnknown : public CInterface <IUnknown, COMBaseWithEI>
648{
649public:
650
651 CUnknown() : CInterface <IUnknown, COMBaseWithEI> () {}
652
653 template <class C>
654 explicit CUnknown (const C &that)
655 {
656 mIface = NULL;
657 if (that.mIface)
658#if !defined (VBOX_WITH_XPCOM)
659 mRC = that.mIface->QueryInterface (_ATL_IIDOF (IUnknown), (void**) &mIface);
660#else /* !defined (VBOX_WITH_XPCOM) */
661 mRC = that.mIface->QueryInterface (NS_GET_IID (IUnknown), (void**) &mIface);
662#endif /* !defined (VBOX_WITH_XPCOM) */
663 if (SUCCEEDED (mRC))
664 {
665 mRC = that.lastRC();
666 mErrInfo = that.errorInfo();
667 }
668 }
669
670 /* specialization for CUnknown */
671 CUnknown (const CUnknown &that) : CInterface <IUnknown, COMBaseWithEI> ()
672 {
673 mIface = that.mIface;
674 addref (mIface);
675 COMBaseWithEI::operator= (that);
676 }
677
678 template <class C>
679 CUnknown &operator= (const C &that)
680 {
681 /* be aware of self (from COM point of view) assignment */
682 IUnknown *old_iface = mIface;
683 mIface = NULL;
684 mRC = S_OK;
685#if !defined (VBOX_WITH_XPCOM)
686 if (that.mIface)
687 mRC = that.mIface->QueryInterface (_ATL_IIDOF (IUnknown), (void**) &mIface);
688#else /* !defined (VBOX_WITH_XPCOM) */
689 if (that.mIface)
690 mRC = that.mIface->QueryInterface (NS_GET_IID (IUnknown), (void**) &mIface);
691#endif /* !defined (VBOX_WITH_XPCOM) */
692 if (SUCCEEDED (mRC))
693 {
694 mRC = that.lastRC();
695 mErrInfo = that.errorInfo();
696 }
697 release (old_iface);
698 return *this;
699 }
700
701 /* specialization for CUnknown */
702 CUnknown &operator= (const CUnknown &that)
703 {
704 attach (that.mIface);
705 COMBaseWithEI::operator= (that);
706 return *this;
707 }
708
709 /* @internal Used in wrappers. */
710 IUnknown *&ifaceRef() { return mIface; };
711};
712
713/* inlined CInterface methods that use CUnknown */
714
715template <class I, class B>
716inline CInterface <I, B>::CInterface (const CUnknown &that)
717 : mIface (NULL)
718{
719 attachUnknown (that.iface());
720 if (SUCCEEDED (B::mRC))
721 B::operator= ((B &) that);
722}
723
724template <class I, class B>
725inline CInterface <I, B> &CInterface <I, B>::operator =(const CUnknown &that)
726{
727 attachUnknown (that.iface());
728 if (SUCCEEDED (B::mRC))
729 B::operator= ((B &) that);
730 return *this;
731}
732
733/////////////////////////////////////////////////////////////////////////////
734
735/* include the generated header containing concrete wrapper definitions */
736#include "COMWrappers.h"
737
738/** @} */
739
740#endif // __COMDefs_h__
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

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