VirtualBox

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

Last change on this file since 2753 was 2671, checked in by vboxsync, 18 years ago

FE/Qt: Added support for displaying more than one COM error if several errors are returned after a method invocation.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 18.0 KB
Line 
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 InnoTek Systemberatung GmbH
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 as published by the Free Software Foundation,
18 * in version 2 as it comes in the "COPYING" file of the VirtualBox OSE
19 * distribution. VirtualBox OSE is distributed in the hope that it will
20 * be useful, but WITHOUT ANY WARRANTY of any kind.
21 *
22 * If you received this file as part of a commercial VirtualBox
23 * distribution, then only the terms of your commercial VirtualBox
24 * license agreement apply instead of the previous paragraph.
25 */
26
27#ifndef __COMDefs_h__
28#define __COMDefs_h__
29
30#include <qglobal.h>
31#include <qstring.h>
32#include <quuid.h>
33
34#include <iprt/memory> // for auto_copy_ptr
35
36/*
37 * common COM / XPCOM includes and defines
38 */
39
40#if defined(Q_OS_WIN32)
41
42 #include <objbase.h>
43 /* for _ATL_IIDOF */
44 #include <atldef.h>
45
46 #include <VBox/types.h>
47
48 /* these are XPCOM only */
49 #define NS_DECL_ISUPPORTS
50
51 /* makes interface getter/setter names (n must be capitalized) */
52 #define COMGETTER(n) get_##n
53 #define COMSETTER(n) put_##n
54
55 #define IN_BSTRPARAM BSTR
56 #define IN_GUIDPARAM GUID
57
58 /* const reference to IID of the interface */
59 #define COM_IIDOF(I) _ATL_IIDOF (I)
60
61#else
62
63 #include <VBox/types.h>
64
65 #include <nsMemory.h>
66 #include <nsIComponentManager.h>
67 #include <ipcIDConnectService.h>
68
69 class nsIComponentManager;
70 class nsIEventQueue;
71 class ipcIDConnectService;
72
73 typedef nsCID CLSID;
74 typedef nsIID IID;
75
76 class XPCOMEventQSocketListener;
77
78 #define STDMETHOD(a) NS_IMETHOD a
79 #define STDMETHODIMP NS_IMETHODIMP
80
81 #define HRESULT nsresult
82 #define SUCCEEDED NS_SUCCEEDED
83 #define FAILED NS_FAILED
84
85 /// @todo error code mappings
86 #define S_OK NS_OK
87 #define E_UNEXPECTED (HRESULT)0x8000FFFFL
88 #define E_NOTIMPL (HRESULT)0x80004001L
89 #define E_OUTOFMEMORY (HRESULT)0x8007000EL
90 #define E_INVALIDARG (HRESULT)0x80070057L
91 #define E_NOINTERFACE (HRESULT)0x80004002L
92 #define E_POINTER (HRESULT)0x80004003L
93 #define E_HANDLE (HRESULT)0x80070006L
94 #define E_ABORT (HRESULT)0x80004004L
95 #define E_FAIL (HRESULT)0x80004005L
96 #define E_ACCESSDENIED (HRESULT)0x80070005L
97
98 #define IUnknown nsISupports
99
100 #define BOOL PRBool
101 #define BYTE PRUint8
102 #define SHORT PRInt16
103 #define USHORT PRUint16
104 #define LONG PRInt32
105 #define ULONG PRUint32
106 #define LONG64 PRInt64
107 #define ULONG64 PRUint64
108
109 #define BSTR PRUnichar*
110 #define LPBSTR BSTR*
111 #define OLECHAR wchar_t
112 #define GUID nsID
113
114 #define IN_BSTRPARAM const BSTR
115 #define IN_GUIDPARAM const nsID &
116
117 /* makes interface getter/setter names (n must be capitalized) */
118 #define COMGETTER(n) Get##n
119 #define COMSETTER(n) Set##n
120
121 /* const reference to IID of the interface */
122 #define COM_IIDOF(I) NS_GET_IID (I)
123
124 /* helper functions (defined in the Runtime3 library) */
125 extern "C" {
126 BSTR SysAllocString (const OLECHAR* sz);
127 BSTR SysAllocStringByteLen (char *psz, unsigned int len);
128 BSTR SysAllocStringLen (const OLECHAR *pch, unsigned int cch);
129 void SysFreeString (BSTR bstr);
130 int SysReAllocString (BSTR *pbstr, const OLECHAR *psz);
131 int SysReAllocStringLen (BSTR *pbstr, const OLECHAR *psz, unsigned int cch);
132 unsigned int SysStringByteLen (BSTR bstr);
133 unsigned int SysStringLen (BSTR bstr);
134 }
135
136#endif
137
138/* VirtualBox interfaces declarations */
139#if defined(Q_OS_WIN32)
140 #include <VirtualBox.h>
141#else
142 #include <VirtualBox_XPCOM.h>
143#endif
144
145#include "VBoxDefs.h"
146
147/////////////////////////////////////////////////////////////////////////////
148
149class CVirtualBoxErrorInfo;
150
151/** Represents extended error information */
152class COMErrorInfo
153{
154public:
155
156 COMErrorInfo()
157 : mIsNull (true)
158 , mIsBasicAvailable (false), mIsFullAvailable (false)
159 , mResultCode (S_OK) {}
160
161 COMErrorInfo (const CVirtualBoxErrorInfo &info) { init (info); }
162
163 /* the default copy ctor and assignment op are ok */
164
165 bool isNull() const { return mIsNull; }
166
167 bool isBasicAvailable() const { return mIsBasicAvailable; }
168 bool isFullAvailable() const { return mIsFullAvailable; }
169
170 HRESULT resultCode() const { return mResultCode; }
171 QUuid interfaceID() const { return mInterfaceID; }
172 QString component() const { return mComponent; }
173 QString text() const { return mText; }
174
175 const COMErrorInfo *next() const { return mNext.get(); }
176
177 QString interfaceName() const { return mInterfaceName; }
178 QUuid calleeIID() const { return mCalleeIID; }
179 QString calleeName() const { return mCalleeName; }
180
181private:
182
183 void init (const CVirtualBoxErrorInfo &info);
184 void fetchFromCurrentThread (IUnknown *callee, const GUID *calleeIID);
185
186 static QString getInterfaceNameFromIID (const QUuid &id);
187
188 bool mIsNull : 1;
189 bool mIsBasicAvailable : 1;
190 bool mIsFullAvailable : 1;
191
192 HRESULT mResultCode;
193 QUuid mInterfaceID;
194 QString mComponent;
195 QString mText;
196
197 cppx::auto_copy_ptr <COMErrorInfo> mNext;
198
199 QString mInterfaceName;
200 QUuid mCalleeIID;
201 QString mCalleeName;
202
203 friend class COMBaseWithEI;
204};
205
206/////////////////////////////////////////////////////////////////////////////
207
208/**
209 * Base COM class the CInterface template and all wrapper classes are derived
210 * from. Provides common functionality for all COM wrappers.
211 */
212class COMBase
213{
214public:
215
216 static HRESULT initializeCOM();
217 static HRESULT cleanupCOM();
218
219 /** Converts a GUID value to QUuid */
220#if defined (Q_OS_WIN32)
221 static QUuid toQUuid (const GUID &id) {
222 return QUuid (id.Data1, id.Data2, id.Data3,
223 id.Data4[0], id.Data4[1], id.Data4[2], id.Data4[3],
224 id.Data4[4], id.Data4[5], id.Data4[6], id.Data4[7]);
225 }
226#else
227 static QUuid toQUuid (const nsID &id) {
228 return QUuid (id.m0, id.m1, id.m2,
229 id.m3[0], id.m3[1], id.m3[2], id.m3[3],
230 id.m3[4], id.m3[5], id.m3[6], id.m3[7]);
231 }
232#endif
233
234 /**
235 * Returns the result code of the last interface method called
236 * by the wrapper instance or the result of CInterface::createInstance()
237 * operation.
238 */
239 HRESULT lastRC() const { return mRC; }
240
241 /**
242 * Returns error info set by the last unsuccessfully invoked interface
243 * method. Returned error info is useful only if CInterface::lastRC()
244 * represents a failure (i.e. CInterface::isOk() is false).
245 */
246 virtual COMErrorInfo errorInfo() const { return COMErrorInfo(); }
247
248protected:
249
250 /* no arbitrary instance creations */
251 COMBase() : mRC (S_OK) {};
252
253#if !defined (Q_OS_WIN32)
254 static nsIComponentManager *gComponentManager;
255 static nsIEventQueue* gEventQ;
256 static ipcIDConnectService *gDConnectService;
257 static PRUint32 gVBoxServerID;
258
259 static XPCOMEventQSocketListener *gSocketListener;
260#endif
261
262 /** Adapter to pass QString as input BSTR params */
263 class BSTRIn
264 {
265 public:
266 BSTRIn (const QString &s) : bstr (SysAllocString ((const OLECHAR *) s.ucs2())) {}
267 ~BSTRIn() {
268 if (bstr)
269 SysFreeString (bstr);
270 }
271 operator BSTR() const { return bstr; }
272
273 private:
274 BSTR bstr;
275 };
276
277 /** Adapter to pass QString as output BSTR params */
278 class BSTROut
279 {
280 public:
281 BSTROut (QString &s) : str (s), bstr (0) {}
282 ~BSTROut() {
283 if (bstr) {
284 str = QString::fromUcs2 (bstr);
285 SysFreeString (bstr);
286 }
287 }
288 operator BSTR *() { return &bstr; }
289
290 private:
291 QString &str;
292 BSTR bstr;
293 };
294
295 /** Adapter to pass CEnums enums as output VirtualBox enum params (*_T) */
296 template <typename CE, typename VE>
297 class ENUMOut
298 {
299 public:
300 ENUMOut (CE &e) : ce (e), ve ((VE) 0) {}
301 ~ENUMOut() { ce = (CE) ve; }
302 operator VE *() { return &ve; }
303
304 private:
305 CE &ce;
306 VE ve;
307 };
308
309#if defined (Q_OS_WIN32)
310
311 /** Adapter to pass QUuid as input GUID params */
312 GUID GUIDIn (const QUuid &uuid) const { return uuid; }
313
314 /** Adapter to pass QUuid as output GUID params */
315 class GUIDOut
316 {
317 public:
318 GUIDOut (QUuid &id) : uuid (id) {
319 ::memset (&guid, 0, sizeof (GUID));
320 }
321 ~GUIDOut() {
322 uuid = QUuid (
323 guid.Data1, guid.Data2, guid.Data3,
324 guid.Data4[0], guid.Data4[1], guid.Data4[2], guid.Data4[3],
325 guid.Data4[4], guid.Data4[5], guid.Data4[6], guid.Data4[7]
326 );
327 }
328 operator GUID *() { return &guid; }
329
330 private:
331 QUuid &uuid;
332 GUID guid;
333 };
334
335#else
336
337 /** Adapter to pass QUuid as input GUID params */
338 static const nsID &GUIDIn (const QUuid &uuid) {
339 return *(const nsID *) &uuid;
340 }
341
342 /** Adapter to pass QUuid as output GUID params */
343 class GUIDOut
344 {
345 public:
346 GUIDOut (QUuid &id) : uuid (id), nsid (0) {}
347 ~GUIDOut() {
348 if (nsid) {
349 uuid = QUuid (
350 nsid->m0, nsid->m1, nsid->m2,
351 nsid->m3[0], nsid->m3[1], nsid->m3[2], nsid->m3[3],
352 nsid->m3[4], nsid->m3[5], nsid->m3[6], nsid->m3[7]
353 );
354 nsMemory::Free (nsid);
355 }
356 }
357 operator nsID **() { return &nsid; }
358
359 private:
360 QUuid &uuid;
361 nsID *nsid;
362 };
363
364#endif
365
366 void fetchErrorInfo (IUnknown * /*callee*/, const GUID * /*calleeIID*/) const {}
367
368 mutable HRESULT mRC;
369
370 friend class COMErrorInfo;
371};
372
373/////////////////////////////////////////////////////////////////////////////
374
375/**
376 * Alternative base class for the CInterface template that adds
377 * the errorInfo() method for providing extended error info about
378 * unsuccessful invocation of the last called interface method.
379 */
380class COMBaseWithEI : public COMBase
381{
382public:
383
384 /**
385 * Returns error info set by the last unsuccessfully invoked interface
386 * method. Returned error info is useful only if CInterface::lastRC()
387 * represents a failure (i.e. CInterface::isOk() is false).
388 */
389 COMErrorInfo errorInfo() const { return mErrInfo; }
390
391protected:
392
393 /* no arbitrary instance creations */
394 COMBaseWithEI() : COMBase () {};
395
396 void fetchErrorInfo (IUnknown *callee, const GUID *calleeIID) const {
397 mErrInfo.fetchFromCurrentThread (callee, calleeIID);
398 }
399
400 mutable COMErrorInfo mErrInfo;
401};
402
403/////////////////////////////////////////////////////////////////////////////
404
405/**
406 * Simple class that encapsulates the result code and COMErrorInfo.
407 */
408class COMResult
409{
410public:
411
412 COMResult() : mRC (S_OK) {}
413
414 /** Queries the current result code and error info from the given component */
415 COMResult (const COMBase &aComponent)
416 {
417 mErrInfo = aComponent.errorInfo();
418 mRC = aComponent.lastRC();
419 }
420
421 /** Queries the current result code and error info from the given component */
422 COMResult &operator= (const COMBase &aComponent)
423 {
424 mErrInfo = aComponent.errorInfo();
425 mRC = aComponent.lastRC();
426 return *this;
427 }
428
429 bool isNull() const { return mErrInfo.isNull(); }
430 bool isOk() const { return mErrInfo.isNull() && SUCCEEDED (mRC); }
431
432 COMErrorInfo errorInfo() const { return mErrInfo; }
433 HRESULT rc() const { return mRC; }
434
435private:
436
437 COMErrorInfo mErrInfo;
438 HRESULT mRC;
439};
440
441/////////////////////////////////////////////////////////////////////////////
442
443class CUnknown;
444
445/**
446 * Wrapper template class for all interfaces.
447 *
448 * All interface methods named as they are in the original, i.e. starting
449 * with the capital letter. All utility non-interface methods are named
450 * starting with the small letter. Utility methods should be not normally
451 * called by the end-user client application.
452 *
453 * @param I interface class (i.e. IUnknown/nsISupports derivant)
454 * @param B base class, either COMBase (by default) or COMBaseWithEI
455 */
456template <class I, class B = COMBase>
457class CInterface : public B
458{
459public:
460
461 typedef B Base;
462 typedef I Iface;
463
464 /* constructors & destructor */
465
466 CInterface() : mIface (NULL) {}
467
468 CInterface (const CInterface &that) : B (that), mIface (that.mIface)
469 {
470 addref (mIface);
471 }
472
473 CInterface (const CUnknown &that);
474
475 CInterface (I *i) : mIface (i) { addref (mIface); }
476
477 virtual ~CInterface() { release (mIface); }
478
479 /* utility methods */
480
481 void createInstance (const CLSID &clsid)
482 {
483 AssertMsg (!mIface, ("Instance is already non-NULL\n"));
484 if (!mIface)
485 {
486#if defined (Q_OS_WIN32)
487 B::mRC = CoCreateInstance (clsid, NULL, CLSCTX_ALL,
488 _ATL_IIDOF (I), (void**) &mIface);
489#else
490 /* first, try to create an instance within the in-proc server
491 * (for compatibility with Win32) */
492 B::mRC = B::gComponentManager->
493 CreateInstance (clsid, nsnull, NS_GET_IID (I), (void**) &mIface);
494 if (FAILED (B::mRC) && B::gDConnectService && B::gVBoxServerID)
495 {
496 /* now try the out-of-proc server if it exists */
497 B::mRC = B::gDConnectService->
498 CreateInstance (B::gVBoxServerID, clsid,
499 NS_GET_IID (I), (void**) &mIface);
500 }
501#endif
502 /* fetch error info, but don't assert if it's missing -- many other
503 * reasons can lead to an error (w/o providing error info), not only
504 * the instance initialization code (that should always provide it) */
505 B::fetchErrorInfo (NULL, NULL);
506 }
507 }
508
509 void attach (I *i)
510 {
511 /* be aware of self (from COM point of view) assignment */
512 I *old_iface = mIface;
513 mIface = i;
514 addref (mIface);
515 release (old_iface);
516 B::mRC = S_OK;
517 };
518
519 void attachUnknown (IUnknown *i)
520 {
521 /* be aware of self (from COM point of view) assignment */
522 I *old_iface = mIface;
523 mIface = NULL;
524 B::mRC = S_OK;
525 if (i)
526#if defined (Q_OS_WIN32)
527 B::mRC = i->QueryInterface (_ATL_IIDOF (I), (void**) &mIface);
528#else
529 B::mRC = i->QueryInterface (NS_GET_IID (I), (void**) &mIface);
530#endif
531 release (old_iface);
532 };
533
534 void detach() { release (mIface); mIface = NULL; }
535
536 bool isNull() const { return mIface == NULL; }
537
538 bool isOk() const { return !isNull() && SUCCEEDED (B::mRC); }
539
540 /* utility operators */
541
542 CInterface &operator= (const CInterface &that)
543 {
544 attach (that.mIface);
545 B::operator= (that);
546 return *this;
547 }
548
549 I *iface() const { return mIface; }
550
551 bool operator== (const CInterface &that) const { return mIface == that.mIface; }
552 bool operator!= (const CInterface &that) const { return mIface != that.mIface; }
553
554 CInterface &operator= (const CUnknown &that);
555
556protected:
557
558 static void addref (I *i) { if (i) i->AddRef(); }
559 static void release (I *i) { if (i) i->Release(); }
560
561 mutable I *mIface;
562};
563
564/////////////////////////////////////////////////////////////////////////////
565
566class CUnknown : public CInterface <IUnknown, COMBaseWithEI>
567{
568public:
569
570 CUnknown() : CInterface <IUnknown, COMBaseWithEI> () {}
571
572 template <class C>
573 explicit CUnknown (const C &that)
574 {
575 mIface = NULL;
576 if (that.mIface)
577#if defined (Q_OS_WIN32)
578 mRC = that.mIface->QueryInterface (_ATL_IIDOF (IUnknown), (void**) &mIface);
579#else
580 mRC = that.mIface->QueryInterface (NS_GET_IID (IUnknown), (void**) &mIface);
581#endif
582 if (SUCCEEDED (mRC)) {
583 mRC = that.lastRC();
584 mErrInfo = that.errorInfo();
585 }
586 }
587 /* specialization for CUnknown */
588 CUnknown (const CUnknown &that) : CInterface <IUnknown, COMBaseWithEI> () {
589 mIface = that.mIface;
590 addref (mIface);
591 COMBaseWithEI::operator= (that);
592 }
593
594 template <class C>
595 CUnknown &operator= (const C &that) {
596 /* be aware of self (from COM point of view) assignment */
597 IUnknown *old_iface = mIface;
598 mIface = NULL;
599 mRC = S_OK;
600#if defined (Q_OS_WIN32)
601 if (that.mIface)
602 mRC = that.mIface->QueryInterface (_ATL_IIDOF (IUnknown), (void**) &mIface);
603#else
604 if (that.mIface)
605 mRC = that.mIface->QueryInterface (NS_GET_IID (IUnknown), (void**) &mIface);
606#endif
607 if (SUCCEEDED (mRC)) {
608 mRC = that.lastRC();
609 mErrInfo = that.errorInfo();
610 }
611 release (old_iface);
612 return *this;
613 }
614 /* specialization for CUnknown */
615 CUnknown &operator= (const CUnknown &that) {
616 attach (that.mIface);
617 COMBaseWithEI::operator= (that);
618 return *this;
619 }
620
621 /* @internal Used in wrappers. */
622 IUnknown *&ifaceRef() { return mIface; };
623};
624
625/* inlined CInterface methods that use CUnknown */
626
627template <class I, class B>
628inline CInterface <I, B>::CInterface (const CUnknown &that)
629 : mIface (NULL)
630{
631 attachUnknown (that.iface());
632 if (SUCCEEDED (B::mRC))
633 B::operator= ((B &) that);
634}
635
636template <class I, class B>
637inline CInterface <I, B> &CInterface <I, B>::operator =(const CUnknown &that)
638{
639 attachUnknown (that.iface());
640 if (SUCCEEDED (B::mRC))
641 B::operator= ((B &) that);
642 return *this;
643}
644
645/////////////////////////////////////////////////////////////////////////////
646
647/* include the generated header containing concrete wrapper definitions */
648#include "COMWrappers.h"
649
650#endif // __COMDefs_h__
Note: See TracBrowser for help on using the repository browser.

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