VirtualBox

source: vbox/trunk/src/VBox/Main/src-all/VirtualBoxBase.cpp@ 55784

Last change on this file since 55784 was 55582, checked in by vboxsync, 10 years ago

VirtualBoxBase.cpp: Added setErrorVrc(vrc) and setErrorBoth(hrc,vrc...) and passed the vrc on via IVirtualBoxErrorInfo::resultDetail. This is for better understand user problems, not necessarily for dragging include/*/err.h into the Main API definition. Fact is though, that several areas in main have poor error reporting, in some places it's almost unavoidable. (Btw. include/*/err.h is solidly stable within release due to extension packs, so there is no stability issues here.)

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 24.6 KB
Line 
1/* $Id: VirtualBoxBase.cpp 55582 2015-05-01 18:26:59Z vboxsync $ */
2
3/** @file
4 *
5 * VirtualBox COM base classes implementation
6 */
7
8/*
9 * Copyright (C) 2006-2014 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#include <iprt/semaphore.h>
21#include <iprt/asm.h>
22#include <iprt/cpp/exception.h>
23
24#include <typeinfo>
25
26#if !defined(VBOX_WITH_XPCOM)
27#include <windows.h>
28#include <dbghelp.h>
29#else /* !defined(VBOX_WITH_XPCOM) */
30/// @todo remove when VirtualBoxErrorInfo goes away from here
31#include <nsIServiceManager.h>
32#include <nsIExceptionService.h>
33#endif /* !defined(VBOX_WITH_XPCOM) */
34
35#include "VirtualBoxBase.h"
36#include "AutoCaller.h"
37#include "VirtualBoxErrorInfoImpl.h"
38#include "Logging.h"
39#include "Global.h"
40
41#include "VBox/com/ErrorInfo.h"
42#include "VBox/com/MultiResult.h"
43
44////////////////////////////////////////////////////////////////////////////////
45//
46// VirtualBoxBase
47//
48////////////////////////////////////////////////////////////////////////////////
49
50VirtualBoxBase::VirtualBoxBase() : mState(this)
51{
52 mObjectLock = NULL;
53}
54
55VirtualBoxBase::~VirtualBoxBase()
56{
57 if (mObjectLock)
58 delete mObjectLock;
59}
60
61/**
62 * This virtual method returns an RWLockHandle that can be used to
63 * protect instance data. This RWLockHandle is generally referred to
64 * as the "object lock"; its locking class (for lock order validation)
65 * must be returned by another virtual method, getLockingClass(), which
66 * by default returns LOCKCLASS_OTHEROBJECT but is overridden by several
67 * subclasses such as VirtualBox, Host, Machine and others.
68 *
69 * On the first call this method lazily creates the RWLockHandle.
70 *
71 * @return
72 */
73/* virtual */
74RWLockHandle *VirtualBoxBase::lockHandle() const
75{
76 /* lazy initialization */
77 if (RT_UNLIKELY(!mObjectLock))
78 {
79 AssertCompile(sizeof(RWLockHandle *) == sizeof(void *));
80
81 // getLockingClass() is overridden by many subclasses to return
82 // one of the locking classes listed at the top of AutoLock.h
83 RWLockHandle *objLock = new RWLockHandle(getLockingClass());
84 if (!ASMAtomicCmpXchgPtr(&mObjectLock, objLock, NULL))
85 {
86 delete objLock;
87 objLock = ASMAtomicReadPtrT(&mObjectLock, RWLockHandle *);
88 }
89 return objLock;
90 }
91 return mObjectLock;
92}
93
94/**
95 * Handles unexpected exceptions by turning them into COM errors in release
96 * builds or by hitting a breakpoint in the release builds.
97 *
98 * Usage pattern:
99 * @code
100 try
101 {
102 // ...
103 }
104 catch (LaLalA)
105 {
106 // ...
107 }
108 catch (...)
109 {
110 rc = VirtualBox::handleUnexpectedExceptions(this, RT_SRC_POS);
111 }
112 * @endcode
113 *
114 * @param aThis object where the exception happened
115 * @param RT_SRC_POS_DECL "RT_SRC_POS" macro instantiation.
116 * */
117/* static */
118HRESULT VirtualBoxBase::handleUnexpectedExceptions(VirtualBoxBase *const aThis, RT_SRC_POS_DECL)
119{
120 try
121 {
122 /* re-throw the current exception */
123 throw;
124 }
125 catch (const RTCError &err) // includes all XML exceptions
126 {
127 return setErrorInternal(E_FAIL, aThis->getClassIID(), aThis->getComponentName(),
128 Utf8StrFmt(tr("%s.\n%s[%d] (%s)"),
129 err.what(),
130 pszFile, iLine, pszFunction).c_str(),
131 false /* aWarning */,
132 true /* aLogIt */);
133 }
134 catch (const std::exception &err)
135 {
136 return setErrorInternal(E_FAIL, aThis->getClassIID(), aThis->getComponentName(),
137 Utf8StrFmt(tr("Unexpected exception: %s [%s]\n%s[%d] (%s)"),
138 err.what(), typeid(err).name(),
139 pszFile, iLine, pszFunction).c_str(),
140 false /* aWarning */,
141 true /* aLogIt */);
142 }
143 catch (...)
144 {
145 return setErrorInternal(E_FAIL, aThis->getClassIID(), aThis->getComponentName(),
146 Utf8StrFmt(tr("Unknown exception\n%s[%d] (%s)"),
147 pszFile, iLine, pszFunction).c_str(),
148 false /* aWarning */,
149 true /* aLogIt */);
150 }
151
152 /* should not get here */
153 AssertFailed();
154 return E_FAIL;
155}
156
157/**
158 * Sets error info for the current thread. This is an internal function that
159 * gets eventually called by all public variants. If @a aWarning is
160 * @c true, then the highest (31) bit in the @a aResultCode value which
161 * indicates the error severity is reset to zero to make sure the receiver will
162 * recognize that the created error info object represents a warning rather
163 * than an error.
164 */
165/* static */
166HRESULT VirtualBoxBase::setErrorInternal(HRESULT aResultCode,
167 const GUID &aIID,
168 const char *pcszComponent,
169 Utf8Str aText,
170 bool aWarning,
171 bool aLogIt,
172 LONG aResultDetail /* = 0*/)
173{
174 /* whether multi-error mode is turned on */
175 bool preserve = MultiResult::isMultiEnabled();
176
177 if (aLogIt)
178 LogRel(("%s [COM]: aRC=%Rhrc (%#08x) aIID={%RTuuid} aComponent={%s} aText={%s}, preserve=%RTbool aResultDetail=%d\n",
179 aWarning ? "WARNING" : "ERROR",
180 aResultCode,
181 aResultCode,
182 &aIID,
183 pcszComponent,
184 aText.c_str(),
185 aWarning,
186 preserve,
187 aResultDetail));
188
189 /* these are mandatory, others -- not */
190 AssertReturn((!aWarning && FAILED(aResultCode)) ||
191 (aWarning && aResultCode != S_OK),
192 E_FAIL);
193
194 /* reset the error severity bit if it's a warning */
195 if (aWarning)
196 aResultCode &= ~0x80000000;
197
198 HRESULT rc = S_OK;
199
200 if (aText.isEmpty())
201 {
202 /* Some default info */
203 switch (aResultCode)
204 {
205 case E_INVALIDARG: aText = "A parameter has an invalid value"; break;
206 case E_POINTER: aText = "A parameter is an invalid pointer"; break;
207 case E_UNEXPECTED: aText = "The result of the operation is unexpected"; break;
208 case E_ACCESSDENIED: aText = "The access to an object is not allowed"; break;
209 case E_OUTOFMEMORY: aText = "The allocation of new memory failed"; break;
210 case E_NOTIMPL: aText = "The requested operation is not implemented"; break;
211 case E_NOINTERFACE: aText = "The requested interface is not implemented"; break;
212 case E_FAIL: aText = "A general error occurred"; break;
213 case E_ABORT: aText = "The operation was canceled"; break;
214 case VBOX_E_OBJECT_NOT_FOUND: aText = "Object corresponding to the supplied arguments does not exist"; break;
215 case VBOX_E_INVALID_VM_STATE: aText = "Current virtual machine state prevents the operation"; break;
216 case VBOX_E_VM_ERROR: aText = "Virtual machine error occurred attempting the operation"; break;
217 case VBOX_E_FILE_ERROR: aText = "File not accessible or erroneous file contents"; break;
218 case VBOX_E_IPRT_ERROR: aText = "Runtime subsystem error"; break;
219 case VBOX_E_PDM_ERROR: aText = "Pluggable Device Manager error"; break;
220 case VBOX_E_INVALID_OBJECT_STATE: aText = "Current object state prohibits operation"; break;
221 case VBOX_E_HOST_ERROR: aText = "Host operating system related error"; break;
222 case VBOX_E_NOT_SUPPORTED: aText = "Requested operation is not supported"; break;
223 case VBOX_E_XML_ERROR: aText = "Invalid XML found"; break;
224 case VBOX_E_INVALID_SESSION_STATE: aText = "Current session state prohibits operation"; break;
225 case VBOX_E_OBJECT_IN_USE: aText = "Object being in use prohibits operation"; break;
226 default: aText = "Unknown error"; break;
227 }
228 }
229
230 do
231 {
232 ComObjPtr<VirtualBoxErrorInfo> info;
233 rc = info.createObject();
234 if (FAILED(rc)) break;
235
236#if !defined(VBOX_WITH_XPCOM)
237
238 ComPtr<IVirtualBoxErrorInfo> curInfo;
239 if (preserve)
240 {
241 /* get the current error info if any */
242 ComPtr<IErrorInfo> err;
243 rc = ::GetErrorInfo(0, err.asOutParam());
244 if (FAILED(rc)) break;
245 rc = err.queryInterfaceTo(curInfo.asOutParam());
246 if (FAILED(rc))
247 {
248 /* create a IVirtualBoxErrorInfo wrapper for the native
249 * IErrorInfo object */
250 ComObjPtr<VirtualBoxErrorInfo> wrapper;
251 rc = wrapper.createObject();
252 if (SUCCEEDED(rc))
253 {
254 rc = wrapper->init(err);
255 if (SUCCEEDED(rc))
256 curInfo = wrapper;
257 }
258 }
259 }
260 /* On failure, curInfo will stay null */
261 Assert(SUCCEEDED(rc) || curInfo.isNull());
262
263 /* set the current error info and preserve the previous one if any */
264 rc = info->initEx(aResultCode, aResultDetail, aIID, pcszComponent, aText, curInfo);
265 if (FAILED(rc)) break;
266
267 ComPtr<IErrorInfo> err;
268 rc = info.queryInterfaceTo(err.asOutParam());
269 if (SUCCEEDED(rc))
270 rc = ::SetErrorInfo(0, err);
271
272#else // !defined(VBOX_WITH_XPCOM)
273
274 nsCOMPtr <nsIExceptionService> es;
275 es = do_GetService(NS_EXCEPTIONSERVICE_CONTRACTID, &rc);
276 if (NS_SUCCEEDED(rc))
277 {
278 nsCOMPtr <nsIExceptionManager> em;
279 rc = es->GetCurrentExceptionManager(getter_AddRefs(em));
280 if (FAILED(rc)) break;
281
282 ComPtr<IVirtualBoxErrorInfo> curInfo;
283 if (preserve)
284 {
285 /* get the current error info if any */
286 ComPtr<nsIException> ex;
287 rc = em->GetCurrentException(ex.asOutParam());
288 if (FAILED(rc)) break;
289 rc = ex.queryInterfaceTo(curInfo.asOutParam());
290 if (FAILED(rc))
291 {
292 /* create a IVirtualBoxErrorInfo wrapper for the native
293 * nsIException object */
294 ComObjPtr<VirtualBoxErrorInfo> wrapper;
295 rc = wrapper.createObject();
296 if (SUCCEEDED(rc))
297 {
298 rc = wrapper->init(ex);
299 if (SUCCEEDED(rc))
300 curInfo = wrapper;
301 }
302 }
303 }
304 /* On failure, curInfo will stay null */
305 Assert(SUCCEEDED(rc) || curInfo.isNull());
306
307 /* set the current error info and preserve the previous one if any */
308 rc = info->initEx(aResultCode, aResultDetail, aIID, pcszComponent, Bstr(aText), curInfo);
309 if (FAILED(rc)) break;
310
311 ComPtr<nsIException> ex;
312 rc = info.queryInterfaceTo(ex.asOutParam());
313 if (SUCCEEDED(rc))
314 rc = em->SetCurrentException(ex);
315 }
316 else if (rc == NS_ERROR_UNEXPECTED)
317 {
318 /*
319 * It is possible that setError() is being called by the object
320 * after the XPCOM shutdown sequence has been initiated
321 * (for example, when XPCOM releases all instances it internally
322 * references, which can cause object's FinalConstruct() and then
323 * uninit()). In this case, do_GetService() above will return
324 * NS_ERROR_UNEXPECTED and it doesn't actually make sense to
325 * set the exception (nobody will be able to read it).
326 */
327 LogWarningFunc(("Will not set an exception because nsIExceptionService is not available "
328 "(NS_ERROR_UNEXPECTED). XPCOM is being shutdown?\n"));
329 rc = NS_OK;
330 }
331
332#endif // !defined(VBOX_WITH_XPCOM)
333 }
334 while (0);
335
336 AssertComRC(rc);
337
338 return SUCCEEDED(rc) ? aResultCode : rc;
339}
340
341/**
342 * Shortcut instance method to calling the static setErrorInternal with the
343 * class interface ID and component name inserted correctly. This uses the
344 * virtual getClassIID() and getComponentName() methods which are automatically
345 * defined by the VIRTUALBOXBASE_ADD_ERRORINFO_SUPPORT macro.
346 * @param aResultCode
347 * @param pcsz
348 * @return
349 */
350HRESULT VirtualBoxBase::setError(HRESULT aResultCode)
351{
352 return setErrorInternal(aResultCode,
353 this->getClassIID(),
354 this->getComponentName(),
355 "",
356 false /* aWarning */,
357 true /* aLogIt */);
358}
359
360/**
361 * Shortcut instance method to calling the static setErrorInternal with the
362 * class interface ID and component name inserted correctly. This uses the
363 * virtual getClassIID() and getComponentName() methods which are automatically
364 * defined by the VIRTUALBOXBASE_ADD_ERRORINFO_SUPPORT macro.
365 * @param aResultCode
366 * @return
367 */
368HRESULT VirtualBoxBase::setError(HRESULT aResultCode, const char *pcsz, ...)
369{
370 va_list args;
371 va_start(args, pcsz);
372 HRESULT rc = setErrorInternal(aResultCode,
373 this->getClassIID(),
374 this->getComponentName(),
375 Utf8Str(pcsz, args),
376 false /* aWarning */,
377 true /* aLogIt */);
378 va_end(args);
379 return rc;
380}
381
382/**
383 * Shortcut instance method to calling the static setErrorInternal with the
384 * class interface ID and component name inserted correctly. This uses the
385 * virtual getClassIID() and getComponentName() methods which are automatically
386 * defined by the VIRTUALBOXBASE_ADD_ERRORINFO_SUPPORT macro.
387 * @param ei
388 * @return
389 */
390HRESULT VirtualBoxBase::setError(const com::ErrorInfo &ei)
391{
392 /* whether multi-error mode is turned on */
393 bool preserve = MultiResult::isMultiEnabled();
394
395 HRESULT rc = S_OK;
396
397 do
398 {
399 ComObjPtr<VirtualBoxErrorInfo> info;
400 rc = info.createObject();
401 if (FAILED(rc)) break;
402
403#if !defined(VBOX_WITH_XPCOM)
404
405 ComPtr<IVirtualBoxErrorInfo> curInfo;
406 if (preserve)
407 {
408 /* get the current error info if any */
409 ComPtr<IErrorInfo> err;
410 rc = ::GetErrorInfo(0, err.asOutParam());
411 if (FAILED(rc)) break;
412 rc = err.queryInterfaceTo(curInfo.asOutParam());
413 if (FAILED(rc))
414 {
415 /* create a IVirtualBoxErrorInfo wrapper for the native
416 * IErrorInfo object */
417 ComObjPtr<VirtualBoxErrorInfo> wrapper;
418 rc = wrapper.createObject();
419 if (SUCCEEDED(rc))
420 {
421 rc = wrapper->init(err);
422 if (SUCCEEDED(rc))
423 curInfo = wrapper;
424 }
425 }
426 }
427 /* On failure, curInfo will stay null */
428 Assert(SUCCEEDED(rc) || curInfo.isNull());
429
430 /* set the current error info and preserve the previous one if any */
431 rc = info->init(ei, curInfo);
432 if (FAILED(rc)) break;
433
434 ComPtr<IErrorInfo> err;
435 rc = info.queryInterfaceTo(err.asOutParam());
436 if (SUCCEEDED(rc))
437 rc = ::SetErrorInfo(0, err);
438
439#else // !defined(VBOX_WITH_XPCOM)
440
441 nsCOMPtr <nsIExceptionService> es;
442 es = do_GetService(NS_EXCEPTIONSERVICE_CONTRACTID, &rc);
443 if (NS_SUCCEEDED(rc))
444 {
445 nsCOMPtr <nsIExceptionManager> em;
446 rc = es->GetCurrentExceptionManager(getter_AddRefs(em));
447 if (FAILED(rc)) break;
448
449 ComPtr<IVirtualBoxErrorInfo> curInfo;
450 if (preserve)
451 {
452 /* get the current error info if any */
453 ComPtr<nsIException> ex;
454 rc = em->GetCurrentException(ex.asOutParam());
455 if (FAILED(rc)) break;
456 rc = ex.queryInterfaceTo(curInfo.asOutParam());
457 if (FAILED(rc))
458 {
459 /* create a IVirtualBoxErrorInfo wrapper for the native
460 * nsIException object */
461 ComObjPtr<VirtualBoxErrorInfo> wrapper;
462 rc = wrapper.createObject();
463 if (SUCCEEDED(rc))
464 {
465 rc = wrapper->init(ex);
466 if (SUCCEEDED(rc))
467 curInfo = wrapper;
468 }
469 }
470 }
471 /* On failure, curInfo will stay null */
472 Assert(SUCCEEDED(rc) || curInfo.isNull());
473
474 /* set the current error info and preserve the previous one if any */
475 rc = info->init(ei, curInfo);
476 if (FAILED(rc)) break;
477
478 ComPtr<nsIException> ex;
479 rc = info.queryInterfaceTo(ex.asOutParam());
480 if (SUCCEEDED(rc))
481 rc = em->SetCurrentException(ex);
482 }
483 else if (rc == NS_ERROR_UNEXPECTED)
484 {
485 /*
486 * It is possible that setError() is being called by the object
487 * after the XPCOM shutdown sequence has been initiated
488 * (for example, when XPCOM releases all instances it internally
489 * references, which can cause object's FinalConstruct() and then
490 * uninit()). In this case, do_GetService() above will return
491 * NS_ERROR_UNEXPECTED and it doesn't actually make sense to
492 * set the exception (nobody will be able to read it).
493 */
494 LogWarningFunc(("Will not set an exception because nsIExceptionService is not available "
495 "(NS_ERROR_UNEXPECTED). XPCOM is being shutdown?\n"));
496 rc = NS_OK;
497 }
498
499#endif // !defined(VBOX_WITH_XPCOM)
500 }
501 while (0);
502
503 AssertComRC(rc);
504
505 return SUCCEEDED(rc) ? ei.getResultCode() : rc;
506}
507
508/**
509 * Converts the VBox status code a COM one and sets the error info.
510 *
511 * The VBox status code is made available to the API user via
512 * IVirtualBoxErrorInfo::resultDetail attribute.
513 *
514 * @param vrc The VBox status code.
515 * @return COM status code appropriate for @a vrc.
516 *
517 * @sa VirtualBoxBase::setError(HRESULT)
518 */
519HRESULT VirtualBoxBase::setErrorVrc(int vrc)
520{
521 return setErrorInternal(Global::vboxStatusCodeToCOM(vrc),
522 this->getClassIID(),
523 this->getComponentName(),
524 Utf8Str("%Rrc", vrc),
525 false /* aWarning */,
526 true /* aLogIt */,
527 vrc /* aResultDetail */);
528}
529
530/**
531 * Converts the VBox status code a COM one and sets the error info.
532 *
533 * @param vrc The VBox status code.
534 * @param pcszMsgFmt Error message format string.
535 * @param ... Argument specified in the @a pcszMsgFmt
536 * @return COM status code appropriate for @a vrc.
537 *
538 * @sa VirtualBoxBase::setError(HRESULT, const char *, ...)
539 */
540HRESULT VirtualBoxBase::setErrorVrc(int vrc, const char *pcszMsgFmt, ...)
541{
542 va_list va;
543 va_start(va, pcszMsgFmt);
544 HRESULT hrc = setErrorInternal(Global::vboxStatusCodeToCOM(vrc),
545 this->getClassIID(),
546 this->getComponentName(),
547 Utf8Str(pcszMsgFmt, va),
548 false /* aWarning */,
549 true /* aLogIt */,
550 vrc /* aResultDetail */);
551 va_end(va);
552 return hrc;
553}
554
555/**
556 * Sets error info with both a COM status and an VBox status code.
557 *
558 * The VBox status code is made available to the API user via
559 * IVirtualBoxErrorInfo::resultDetail attribute.
560 *
561 * @param hrc The COM status code to return.
562 * @param vrc The VBox status code.
563 * @return Most likely @hrc, see setErrorInternal.
564 *
565 * @sa VirtualBoxBase::setError(HRESULT)
566 */
567HRESULT VirtualBoxBase::setErrorBoth(HRESULT hrc, int vrc)
568{
569 return setErrorInternal(hrc,
570 this->getClassIID(),
571 this->getComponentName(),
572 Utf8Str("%Rrc", vrc),
573 false /* aWarning */,
574 true /* aLogIt */,
575 vrc /* aResultDetail */);
576}
577
578/**
579 * Sets error info with a message and both a COM status and an VBox status code.
580 *
581 * The VBox status code is made available to the API user via
582 * IVirtualBoxErrorInfo::resultDetail attribute.
583 *
584 * @param hrc The COM status code to return.
585 * @param vrc The VBox status code.
586 * @param pcszMsgFmt Error message format string.
587 * @param ... Argument specified in the @a pcszMsgFmt
588 * @return Most likely @hrc, see setErrorInternal.
589 *
590 * @sa VirtualBoxBase::setError(HRESULT, const char *, ...)
591 */
592HRESULT VirtualBoxBase::setErrorBoth(HRESULT hrc, int vrc, const char *pcszMsgFmt, ...)
593{
594 va_list va;
595 va_start(va, pcszMsgFmt);
596 hrc = setErrorInternal(hrc,
597 this->getClassIID(),
598 this->getComponentName(),
599 Utf8Str(pcszMsgFmt, va),
600 false /* aWarning */,
601 true /* aLogIt */,
602 vrc /* aResultDetail */);
603 va_end(va);
604 return hrc;
605}
606
607/**
608 * Like setError(), but sets the "warning" bit in the call to setErrorInternal().
609 * @param aResultCode
610 * @param pcsz
611 * @return
612 */
613HRESULT VirtualBoxBase::setWarning(HRESULT aResultCode, const char *pcsz, ...)
614{
615 va_list args;
616 va_start(args, pcsz);
617 HRESULT rc = setErrorInternal(aResultCode,
618 this->getClassIID(),
619 this->getComponentName(),
620 Utf8Str(pcsz, args),
621 true /* aWarning */,
622 true /* aLogIt */);
623 va_end(args);
624 return rc;
625}
626
627/**
628 * Like setError(), but disables the "log" flag in the call to setErrorInternal().
629 * @param aResultCode
630 * @param pcsz
631 * @return
632 */
633HRESULT VirtualBoxBase::setErrorNoLog(HRESULT aResultCode, const char *pcsz, ...)
634{
635 va_list args;
636 va_start(args, pcsz);
637 HRESULT rc = setErrorInternal(aResultCode,
638 this->getClassIID(),
639 this->getComponentName(),
640 Utf8Str(pcsz, args),
641 false /* aWarning */,
642 false /* aLogIt */);
643 va_end(args);
644 return rc;
645}
646
647/**
648 * Clear the current error information.
649 */
650/*static*/
651void VirtualBoxBase::clearError(void)
652{
653#if !defined(VBOX_WITH_XPCOM)
654 ::SetErrorInfo(0, NULL);
655#else
656 HRESULT rc = S_OK;
657 nsCOMPtr <nsIExceptionService> es;
658 es = do_GetService(NS_EXCEPTIONSERVICE_CONTRACTID, &rc);
659 if (NS_SUCCEEDED(rc))
660 {
661 nsCOMPtr <nsIExceptionManager> em;
662 rc = es->GetCurrentExceptionManager(getter_AddRefs(em));
663 if (SUCCEEDED(rc))
664 em->SetCurrentException(NULL);
665 }
666#endif
667}
668
669
670////////////////////////////////////////////////////////////////////////////////
671//
672// MultiResult methods
673//
674////////////////////////////////////////////////////////////////////////////////
675
676RTTLS MultiResult::sCounter = NIL_RTTLS;
677
678/*static*/
679void MultiResult::incCounter()
680{
681 if (sCounter == NIL_RTTLS)
682 {
683 sCounter = RTTlsAlloc();
684 AssertReturnVoid(sCounter != NIL_RTTLS);
685 }
686
687 uintptr_t counter = (uintptr_t)RTTlsGet(sCounter);
688 ++counter;
689 RTTlsSet(sCounter, (void*)counter);
690}
691
692/*static*/
693void MultiResult::decCounter()
694{
695 uintptr_t counter = (uintptr_t)RTTlsGet(sCounter);
696 AssertReturnVoid(counter != 0);
697 --counter;
698 RTTlsSet(sCounter, (void*)counter);
699}
700
701/*static*/
702bool MultiResult::isMultiEnabled()
703{
704 if (sCounter == NIL_RTTLS)
705 return false;
706
707 return ((uintptr_t)RTTlsGet(MultiResult::sCounter)) > 0;
708}
709
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