/** @file * * ErrorInfo class definition */ /* * Copyright (C) 2006-2007 innotek GmbH * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; * you can redistribute it and/or modify it under the terms of the GNU * General Public License as published by the Free Software Foundation, * in version 2 as it comes in the "COPYING" file of the VirtualBox OSE * distribution. VirtualBox OSE is distributed in the hope that it will * be useful, but WITHOUT ANY WARRANTY of any kind. */ #if !defined (VBOX_WITH_XPCOM) #else #include #include #include #endif #include "VBox/com/VirtualBox.h" #include "VBox/com/ErrorInfo.h" #include "VBox/com/assert.h" #include "VBox/com/com.h" #include #include #include namespace com { // ErrorInfo class //////////////////////////////////////////////////////////////////////////////// void ErrorInfo::init (bool aKeepObj /* = false */) { HRESULT rc = E_FAIL; #if !defined (VBOX_WITH_XPCOM) ComPtr err; rc = ::GetErrorInfo (0, err.asOutParam()); if (rc == S_OK && err) { if (aKeepObj) mErrorInfo = err; ComPtr info; rc = err.queryInterfaceTo (info.asOutParam()); if (SUCCEEDED (rc) && info) init (info); if (!mIsFullAvailable) { bool gotSomething = false; rc = err->GetGUID (mInterfaceID.asOutParam()); gotSomething |= SUCCEEDED (rc); if (SUCCEEDED (rc)) GetInterfaceNameByIID (mInterfaceID, mInterfaceName.asOutParam()); rc = err->GetSource (mComponent.asOutParam()); gotSomething |= SUCCEEDED (rc); rc = err->GetDescription (mText.asOutParam()); gotSomething |= SUCCEEDED (rc); if (gotSomething) mIsBasicAvailable = true; AssertMsg (gotSomething, ("Nothing to fetch!\n")); } } #else // !defined (VBOX_WITH_XPCOM) nsCOMPtr es; es = do_GetService (NS_EXCEPTIONSERVICE_CONTRACTID, &rc); if (NS_SUCCEEDED (rc)) { nsCOMPtr em; rc = es->GetCurrentExceptionManager (getter_AddRefs (em)); if (NS_SUCCEEDED (rc)) { ComPtr ex; rc = em->GetCurrentException (ex.asOutParam()); if (NS_SUCCEEDED (rc) && ex) { if (aKeepObj) mErrorInfo = ex; ComPtr info; rc = ex.queryInterfaceTo (info.asOutParam()); if (NS_SUCCEEDED (rc) && info) init (info); if (!mIsFullAvailable) { bool gotSomething = false; rc = ex->GetResult (&mResultCode); gotSomething |= NS_SUCCEEDED (rc); Utf8Str message; rc = ex->GetMessage (message.asOutParam()); gotSomething |= NS_SUCCEEDED (rc); if (NS_SUCCEEDED (rc)) mText = message; if (gotSomething) mIsBasicAvailable = true; AssertMsg (gotSomething, ("Nothing to fetch!\n")); } // set the exception to NULL (to emulate Win32 behavior) em->SetCurrentException (NULL); rc = NS_OK; } } } AssertComRC (rc); #endif // !defined (VBOX_WITH_XPCOM) } void ErrorInfo::init (IUnknown *aI, const GUID &aIID, bool aKeepObj /* = false */) { Assert (aI); if (!aI) return; #if !defined (VBOX_WITH_XPCOM) ComPtr iface = aI; ComPtr serr; HRESULT rc = iface.queryInterfaceTo (serr.asOutParam()); if (SUCCEEDED (rc)) { rc = serr->InterfaceSupportsErrorInfo (aIID); if (SUCCEEDED (rc)) init (aKeepObj); } #else init (aKeepObj); #endif if (mIsBasicAvailable) { mCalleeIID = aIID; GetInterfaceNameByIID (aIID, mCalleeName.asOutParam()); } } void ErrorInfo::init (IVirtualBoxErrorInfo *info) { AssertReturnVoid (info); HRESULT rc = E_FAIL; bool gotSomething = false; bool gotAll = true; rc = info->COMGETTER(ResultCode) (&mResultCode); gotSomething |= SUCCEEDED (rc); gotAll &= SUCCEEDED (rc); rc = info->COMGETTER(InterfaceID) (mInterfaceID.asOutParam()); gotSomething |= SUCCEEDED (rc); gotAll &= SUCCEEDED (rc); if (SUCCEEDED (rc)) GetInterfaceNameByIID (mInterfaceID, mInterfaceName.asOutParam()); rc = info->COMGETTER(Component) (mComponent.asOutParam()); gotSomething |= SUCCEEDED (rc); gotAll &= SUCCEEDED (rc); rc = info->COMGETTER(Text) (mText.asOutParam()); gotSomething |= SUCCEEDED (rc); gotAll &= SUCCEEDED (rc); ComPtr next; rc = info->COMGETTER(Next) (next.asOutParam()); if (SUCCEEDED (rc) && !next.isNull()) { mNext.reset (new ErrorInfo (next)); Assert (mNext.get()); if (!mNext.get()) rc = E_OUTOFMEMORY; } else mNext.reset(); gotSomething |= SUCCEEDED (rc); gotAll &= SUCCEEDED (rc); mIsBasicAvailable = gotSomething; mIsFullAvailable = gotAll; AssertMsg (gotSomething, ("Nothing to fetch!\n")); } ErrorInfo::~ErrorInfo() { } void ErrorInfo::print (const char *aPrefix /* = NULL */) { if (aPrefix == NULL) aPrefix = ""; RTPrintf ("%sFull error info present: %RTbool, basic error info present: %RTbool\n", aPrefix, mIsFullAvailable, mIsBasicAvailable); if (mIsFullAvailable || mIsBasicAvailable) { RTPrintf ("%sResult Code = %Rwa\n", aPrefix, mResultCode); RTPrintf ("%sText = %ls\n", aPrefix, mText.raw()); RTPrintf ("%sComponent = %ls, Interface: %ls, {%s}\n", aPrefix, mComponent.raw(), mInterfaceName.raw(), mInterfaceID.toString().raw()); RTPrintf ("%sCallee = %ls, {%s}\n", aPrefix, mCalleeName.raw(), mCalleeIID.toString().raw()); } } /** * Sets the given error info object for the current thread. If @a aPreserve * is @c true, then the current error info set on the thread before this * method is called will be preserved in the IVirtualBoxErrorInfo::next * attribute of the new error info object that will be then set as the * current error info object. */ //static HRESULT setError (IVirtualBoxErrorInfo *aInfo); // ProgressErrorInfo class //////////////////////////////////////////////////////////////////////////////// ProgressErrorInfo::ProgressErrorInfo (IProgress *progress) : ErrorInfo (false /* aDummy */) { Assert (progress); if (!progress) return; ComPtr info; HRESULT rc = progress->COMGETTER(ErrorInfo) (info.asOutParam()); if (SUCCEEDED (rc) && info) init (info); } // ErrorInfoKeeper class //////////////////////////////////////////////////////////////////////////////// HRESULT ErrorInfoKeeper::restore() { if (mForgot) return S_OK; HRESULT rc = S_OK; #if !defined (VBOX_WITH_XPCOM) ComPtr err; if (!mErrorInfo.isNull()) { rc = mErrorInfo.queryInterfaceTo (err.asOutParam()); AssertComRC (rc); } rc = ::SetErrorInfo (0, err); #else // !defined (VBOX_WITH_XPCOM) nsCOMPtr es; es = do_GetService (NS_EXCEPTIONSERVICE_CONTRACTID, &rc); if (NS_SUCCEEDED (rc)) { nsCOMPtr em; rc = es->GetCurrentExceptionManager (getter_AddRefs (em)); if (NS_SUCCEEDED (rc)) { ComPtr ex; if (!mErrorInfo.isNull()) { rc = mErrorInfo.queryInterfaceTo (ex.asOutParam()); AssertComRC (rc); } rc = em->SetCurrentException (ex); } } #endif // !defined (VBOX_WITH_XPCOM) if (SUCCEEDED (rc)) { mErrorInfo.setNull(); mForgot = true; } return rc; } }; // namespace com