ErrorInfo.cpp revision a97f26ece82a85f69a131fb74b057774c85db9c8
/* $Id$ */
/** @file
*
* ErrorInfo class definition
*/
/*
* Copyright (C) 2006-2007 Sun Microsystems, Inc.
*
* 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 (GPL) 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.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
* Clara, CA 95054 USA or visit http://www.sun.com if you need
* additional information or have any questions.
*/
#if !defined (VBOX_WITH_XPCOM)
#else
#include <nsIServiceManager.h>
#include <nsIExceptionService.h>
#include <nsCOMPtr.h>
#endif
#include "VBox/com/VirtualBox.h"
#include "VBox/com/ErrorInfo.h"
#include "VBox/com/assert.h"
#include "VBox/com/com.h"
#include <iprt/stream.h>
#include <iprt/string.h>
#include <VBox/err.h>
namespace com
{
// ErrorInfo class
////////////////////////////////////////////////////////////////////////////////
void ErrorInfo::init (bool aKeepObj /* = false */)
{
HRESULT rc = E_FAIL;
#if !defined (VBOX_WITH_XPCOM)
ComPtr<IErrorInfo> err;
rc = ::GetErrorInfo (0, err.asOutParam());
if (rc == S_OK && err)
{
if (aKeepObj)
mErrorInfo = err;
ComPtr<IVirtualBoxErrorInfo> 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 <nsIExceptionService> es;
es = do_GetService (NS_EXCEPTIONSERVICE_CONTRACTID, &rc);
if (NS_SUCCEEDED(rc))
{
nsCOMPtr <nsIExceptionManager> em;
rc = es->GetCurrentExceptionManager (getter_AddRefs (em));
if (NS_SUCCEEDED(rc))
{
ComPtr<nsIException> ex;
rc = em->GetCurrentException (ex.asOutParam());
if (NS_SUCCEEDED(rc) && ex)
{
if (aKeepObj)
mErrorInfo = ex;
ComPtr<IVirtualBoxErrorInfo> 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());
message.jolt();
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<IUnknown> iface = aI;
ComPtr<ISupportErrorInfo> 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;
LONG lrc;
rc = info->COMGETTER(ResultCode) (&lrc); mResultCode = lrc;
gotSomething |= SUCCEEDED(rc);
gotAll &= SUCCEEDED(rc);
Bstr iid;
rc = info->COMGETTER(InterfaceID) (iid.asOutParam());
gotSomething |= SUCCEEDED(rc);
gotAll &= SUCCEEDED(rc);
if (SUCCEEDED(rc))
{
mInterfaceID = iid;
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<IVirtualBoxErrorInfo> 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()
{
}
// ProgressErrorInfo class
////////////////////////////////////////////////////////////////////////////////
ProgressErrorInfo::ProgressErrorInfo (IProgress *progress) :
ErrorInfo (false /* aDummy */)
{
Assert(progress);
if (!progress)
return;
ComPtr<IVirtualBoxErrorInfo> 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<IErrorInfo> err;
if (!mErrorInfo.isNull())
{
rc = mErrorInfo.queryInterfaceTo(err.asOutParam());
AssertComRC (rc);
}
rc = ::SetErrorInfo (0, err);
#else // !defined (VBOX_WITH_XPCOM)
nsCOMPtr <nsIExceptionService> es;
es = do_GetService (NS_EXCEPTIONSERVICE_CONTRACTID, &rc);
if (NS_SUCCEEDED(rc))
{
nsCOMPtr <nsIExceptionManager> em;
rc = es->GetCurrentExceptionManager (getter_AddRefs (em));
if (NS_SUCCEEDED(rc))
{
ComPtr<nsIException> 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 */