VirtualBox

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

Last change on this file since 56447 was 55988, checked in by vboxsync, 10 years ago

iprt/log.h,SUPDrv: Replaced the 'personal' logging groups with 6 more generic logging levels (7 thru 12) and a 'Warn' level. The 'Warn' level is enabled by 'group.e' together with level 1 logging. Modified the new RTLog[Rel][Get]DefaultInstanceEx functions to only take one 32-bit parameter to minimize call setup time and size. Major support driver version bump. LogAleksey=Log7, LogBird=Log8, LogSunlover=Log9, none of the other personal macros was used. Log*Warning got renamed to Log1*Warning so as to not confuse it with the LogWarn/LogRelWarn macros.

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