VirtualBox

source: vbox/trunk/src/VBox/Frontends/VirtualBox/src/globals/COMDefs.cpp@ 43138

Last change on this file since 43138 was 41689, checked in by vboxsync, 12 years ago

FE/Qt: VBoxDefs renamed to UIDefs and reworked into namespace. Corresponding files which were using VBoxDefs updated.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 11.3 KB
Line 
1/* $Id: COMDefs.cpp 41689 2012-06-13 17:13:36Z vboxsync $ */
2/** @file
3 *
4 * VBox frontends: Qt GUI ("VirtualBox"):
5 * CInterface implementation
6 */
7
8/*
9 * Copyright (C) 2006-2008 Oracle Corporation
10 *
11 * This file is part of VirtualBox Open Source Edition (OSE), as
12 * available from http://www.virtualbox.org. This file is free software;
13 * you can redistribute it and/or modify it under the terms of the GNU
14 * General Public License (GPL) as published by the Free Software
15 * Foundation, in version 2 as it comes in the "COPYING" file of the
16 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
17 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
18 */
19
20/* Qt includes: */
21#include <QObject>
22#include <QSocketNotifier>
23
24/* COM includes: */
25#include "COMDefs.h"
26#include "UIDefs.h"
27#include "CVirtualBoxErrorInfo.h"
28
29#if !defined (VBOX_WITH_XPCOM)
30
31#else /* !defined (VBOX_WITH_XPCOM) */
32
33/* Other VBox includes: */
34#include <iprt/env.h>
35#include <iprt/err.h>
36#include <iprt/path.h>
37#include <iprt/param.h>
38#include <nsEventQueueUtils.h>
39#include <nsIEventQueue.h>
40#include <nsIExceptionService.h>
41
42/* Mac OS X (Carbon mode) and OS/2 will notify the native queue
43 internally in plevent.c. Because moc doesn't seems to respect
44 #ifdefs, we still have to include the definition of the class.
45 very silly. */
46# if !defined (Q_OS_MAC) && !defined (Q_OS_OS2)
47XPCOMEventQSocketListener *COMBase::sSocketListener = 0;
48
49# endif
50
51/**
52 * Internal class to asynchronously handle IPC events on the GUI thread
53 * using the event queue socket FD and QSocketNotifier.
54 */
55class XPCOMEventQSocketListener : public QObject
56{
57 Q_OBJECT
58
59public:
60
61 XPCOMEventQSocketListener (nsIEventQueue *eq)
62 {
63 mEventQ = eq;
64 mNotifier = new QSocketNotifier (mEventQ->GetEventQueueSelectFD(),
65 QSocketNotifier::Read, this);
66 QObject::connect (mNotifier, SIGNAL (activated (int)),
67 this, SLOT (processEvents()));
68 }
69
70 virtual ~XPCOMEventQSocketListener()
71 {
72 delete mNotifier;
73 }
74
75public slots:
76
77 void processEvents() { mEventQ->ProcessPendingEvents(); }
78
79private:
80
81 QSocketNotifier *mNotifier;
82 nsCOMPtr <nsIEventQueue> mEventQ;
83};
84
85#endif /* !defined (VBOX_WITH_XPCOM) */
86
87/**
88 * Initializes COM/XPCOM.
89 */
90HRESULT COMBase::InitializeCOM(bool fGui)
91{
92 LogFlowFuncEnter();
93
94 HRESULT rc = com::Initialize(fGui);
95
96#if defined (VBOX_WITH_XPCOM)
97
98# if !defined (RT_OS_DARWIN) && !defined (RT_OS_OS2)
99
100 if (NS_SUCCEEDED (rc))
101 {
102 nsCOMPtr <nsIEventQueue> eventQ;
103 rc = NS_GetMainEventQ (getter_AddRefs (eventQ));
104 if (NS_SUCCEEDED (rc))
105 {
106# ifdef DEBUG
107 BOOL isNative = FALSE;
108 eventQ->IsQueueNative (&isNative);
109 AssertMsg (isNative, ("The event queue must be native"));
110# endif
111 BOOL isOnMainThread = FALSE;
112 rc = eventQ->IsOnCurrentThread (&isOnMainThread);
113 if (NS_SUCCEEDED (rc) && isOnMainThread)
114 {
115 sSocketListener = new XPCOMEventQSocketListener (eventQ);
116 }
117 }
118 }
119
120# endif /* !defined (RT_OS_DARWIN) && !defined (RT_OS_OS) */
121
122#endif /* defined (VBOX_WITH_XPCOM) */
123
124 if (FAILED (rc))
125 CleanupCOM();
126
127 AssertComRC (rc);
128
129 LogFlowFunc (("rc=%08X\n", rc));
130 LogFlowFuncLeave();
131 return rc;
132
133}
134
135/**
136 * Cleans up COM/XPCOM.
137 */
138HRESULT COMBase::CleanupCOM()
139{
140 LogFlowFuncEnter();
141
142 HRESULT rc = S_OK;
143
144#if defined (VBOX_WITH_XPCOM)
145
146 /* scope the code to make smart references are released before calling
147 * com::Shutdown() */
148 {
149 nsCOMPtr <nsIEventQueue> eventQ;
150 rc = NS_GetMainEventQ (getter_AddRefs (eventQ));
151 if (NS_SUCCEEDED (rc))
152 {
153 BOOL isOnMainThread = FALSE;
154 rc = eventQ->IsOnCurrentThread (&isOnMainThread);
155 if (NS_SUCCEEDED (rc) && isOnMainThread)
156 {
157# if !defined (RT_OS_DARWIN) && !defined (RT_OS_OS2)
158 if (sSocketListener)
159 {
160 delete sSocketListener;
161 sSocketListener = NULL;
162 }
163# endif
164 }
165 }
166 }
167
168#endif /* defined (VBOX_WITH_XPCOM) */
169
170 HRESULT rc2 = com::Shutdown();
171 if (SUCCEEDED (rc))
172 rc = rc2;
173
174 AssertComRC (rc);
175
176 LogFlowFunc (("rc=%08X\n", rc));
177 LogFlowFuncLeave();
178 return rc;
179}
180
181/* static */
182void COMBase::ToSafeArray (const QVector <QString> &aVec,
183 com::SafeArray <BSTR> &aArr)
184{
185 aArr.reset (aVec.size());
186 for (int i = 0; i < aVec.size(); ++ i)
187 aArr [i] = SysAllocString ((const OLECHAR *)
188 (aVec.at (i).isNull() ? 0 : aVec.at (i).utf16()));
189}
190
191/* static */
192void COMBase::FromSafeArray (const com::SafeArray <BSTR> &aArr,
193 QVector <QString> &aVec)
194{
195 aVec.resize (static_cast <int> (aArr.size()));
196 for (int i = 0; i < aVec.size(); ++ i)
197 aVec [i] = QString::fromUtf16 (aArr [i]);
198}
199
200/* static */
201void COMBase::ToSafeArray (const QVector <QUuid> &aVec,
202 com::SafeGUIDArray &aArr)
203{
204 AssertCompileSize (GUID, sizeof (QUuid));
205 aArr.reset (aVec.size());
206 for (int i = 0; i < aVec.size(); ++ i)
207 aArr [i] = *(GUID*) &aVec [i];
208}
209
210/* static */
211void COMBase::FromSafeArray (const com::SafeGUIDArray &aArr,
212 QVector <QUuid> &aVec)
213{
214 AssertCompileSize (GUID, sizeof (QUuid));
215 aVec.resize (static_cast <int> (aArr.size()));
216 for (int i = 0; i < aVec.size(); ++ i)
217 aVec [i] = *(QUuid*) &aArr [i];
218}
219
220////////////////////////////////////////////////////////////////////////////////
221
222void COMErrorInfo::init(const CVirtualBoxErrorInfo &info)
223{
224 if (info.isNull())
225 {
226 mIsNull = true;
227 mIsBasicAvailable = false;
228 mIsFullAvailable = false;
229 mResultCode = S_OK;
230 m_pNext = NULL;
231 AssertMsgFailedReturnVoid(("error info is NULL!\n"));
232 }
233
234 bool gotSomething = false;
235 bool gotAll = true;
236
237 mResultCode = info.GetResultCode();
238 gotSomething |= info.isOk();
239 gotAll &= info.isOk();
240
241 mInterfaceID = info.GetInterfaceID();
242 gotSomething |= info.isOk();
243 gotAll &= info.isOk();
244 if (info.isOk())
245 mInterfaceName = getInterfaceNameFromIID (mInterfaceID);
246
247 mComponent = info.GetComponent();
248 gotSomething |= info.isOk();
249 gotAll &= info.isOk();
250
251 mText = info.GetText();
252 gotSomething |= info.isOk();
253 gotAll &= info.isOk();
254
255 m_pNext = NULL;
256
257 CVirtualBoxErrorInfo next = info.GetNext();
258 if (info.isOk() && !next.isNull())
259 {
260 m_pNext = new COMErrorInfo(next);
261 Assert(m_pNext);
262 }
263
264 gotSomething |= info.isOk();
265 gotAll &= info.isOk();
266
267 mIsBasicAvailable = gotSomething;
268 mIsFullAvailable = gotAll;
269
270 mIsNull = !gotSomething;
271
272 AssertMsg (gotSomething, ("Nothing to fetch!\n"));
273}
274
275void COMErrorInfo::copyFrom(const COMErrorInfo &x)
276{
277 mIsNull = x.mIsNull;
278 mIsBasicAvailable = x.mIsBasicAvailable;
279 mIsFullAvailable = x.mIsFullAvailable;
280
281 mResultCode = x.mResultCode;
282 mInterfaceID = x.mInterfaceID;
283 mComponent = x.mComponent;
284 mText = x.mText;
285
286 if (x.m_pNext)
287 m_pNext = new COMErrorInfo(*x.m_pNext);
288 else
289 m_pNext = NULL;
290
291 mInterfaceName = x.mInterfaceName;
292 mCalleeIID = x.mCalleeIID;
293 mCalleeName = x.mCalleeName;
294}
295
296void COMErrorInfo::cleanup()
297{
298 if (m_pNext)
299 {
300 delete m_pNext;
301 m_pNext = NULL;
302 }
303}
304
305/**
306 * Fetches error info from the current thread.
307 * If callee is NULL, then error info is fetched in "interfaceless"
308 * manner (so calleeIID() and calleeName() will return null).
309 *
310 * @param callee
311 * pointer to the interface whose method returned an error
312 * @param calleeIID
313 * UUID of the callee's interface. Ignored when callee is NULL
314 */
315void COMErrorInfo::fetchFromCurrentThread(IUnknown *callee, const GUID *calleeIID)
316{
317 mIsNull = true;
318 mIsFullAvailable = mIsBasicAvailable = false;
319
320 AssertReturn (!callee || calleeIID, (void) 0);
321
322 HRESULT rc = E_FAIL;
323
324#if !defined (VBOX_WITH_XPCOM)
325
326 if (callee)
327 {
328 CComPtr <IUnknown> iface = callee;
329 CComQIPtr <ISupportErrorInfo> serr;
330 serr = callee;
331 if (!serr)
332 return;
333 rc = serr->InterfaceSupportsErrorInfo (*calleeIID);
334 if (!SUCCEEDED (rc))
335 return;
336 }
337
338 CComPtr <IErrorInfo> err;
339 rc = ::GetErrorInfo (0, &err);
340 if (rc == S_OK && err)
341 {
342 CComPtr <IVirtualBoxErrorInfo> info;
343 info = err;
344 if (info)
345 init (CVirtualBoxErrorInfo (info));
346
347 if (!mIsFullAvailable)
348 {
349 bool gotSomething = false;
350
351 rc = err->GetGUID (COMBase::GUIDOut (mInterfaceID));
352 gotSomething |= SUCCEEDED (rc);
353 if (SUCCEEDED (rc))
354 mInterfaceName = getInterfaceNameFromIID (mInterfaceID);
355
356 rc = err->GetSource (COMBase::BSTROut (mComponent));
357 gotSomething |= SUCCEEDED (rc);
358
359 rc = err->GetDescription (COMBase::BSTROut (mText));
360 gotSomething |= SUCCEEDED (rc);
361
362 if (gotSomething)
363 mIsBasicAvailable = true;
364
365 mIsNull = !gotSomething;
366
367 AssertMsg (gotSomething, ("Nothing to fetch!\n"));
368 }
369 }
370
371#else /* !defined (VBOX_WITH_XPCOM) */
372
373 nsCOMPtr <nsIExceptionService> es;
374 es = do_GetService (NS_EXCEPTIONSERVICE_CONTRACTID, &rc);
375 if (NS_SUCCEEDED (rc))
376 {
377 nsCOMPtr <nsIExceptionManager> em;
378 rc = es->GetCurrentExceptionManager (getter_AddRefs (em));
379 if (NS_SUCCEEDED (rc))
380 {
381 nsCOMPtr <nsIException> ex;
382 rc = em->GetCurrentException (getter_AddRefs(ex));
383 if (NS_SUCCEEDED (rc) && ex)
384 {
385 nsCOMPtr <IVirtualBoxErrorInfo> info;
386 info = do_QueryInterface (ex, &rc);
387 if (NS_SUCCEEDED (rc) && info)
388 init (CVirtualBoxErrorInfo (info));
389
390 if (!mIsFullAvailable)
391 {
392 bool gotSomething = false;
393
394 rc = ex->GetResult (&mResultCode);
395 gotSomething |= NS_SUCCEEDED (rc);
396
397 char *message = NULL; // utf8
398 rc = ex->GetMessage (&message);
399 gotSomething |= NS_SUCCEEDED (rc);
400 if (NS_SUCCEEDED (rc) && message)
401 {
402 mText = QString::fromUtf8 (message);
403 nsMemory::Free (message);
404 }
405
406 if (gotSomething)
407 mIsBasicAvailable = true;
408
409 mIsNull = !gotSomething;
410
411 AssertMsg (gotSomething, ("Nothing to fetch!\n"));
412 }
413
414 // set the exception to NULL (to emulate Win32 behavior)
415 em->SetCurrentException (NULL);
416
417 rc = NS_OK;
418 }
419 }
420 }
421
422 AssertComRC (rc);
423
424#endif /* !defined (VBOX_WITH_XPCOM) */
425
426 if (callee && calleeIID && mIsBasicAvailable)
427 {
428 mCalleeIID = COMBase::ToQUuid (*calleeIID);
429 mCalleeName = getInterfaceNameFromIID (mCalleeIID);
430 }
431}
432
433// static
434QString COMErrorInfo::getInterfaceNameFromIID (const QUuid &id)
435{
436 QString name;
437
438 com::GetInterfaceNameByIID (COMBase::GUIDIn (id), COMBase::BSTROut (name));
439
440 return name;
441}
442
443#if defined (VBOX_WITH_XPCOM)
444#include "COMDefs.moc"
445#endif
446
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use