Adding upstream version 7.0.20-dfsg.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
This commit is contained in:
parent
d0c7daf57c
commit
df1bda4fe9
26643 changed files with 10005219 additions and 0 deletions
545
include/VBox/com/ErrorInfo.h
Normal file
545
include/VBox/com/ErrorInfo.h
Normal file
|
@ -0,0 +1,545 @@
|
|||
/** @file
|
||||
* MS COM / XPCOM Abstraction Layer - ErrorInfo class declaration.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2006-2023 Oracle and/or its affiliates.
|
||||
*
|
||||
* This file is part of VirtualBox base platform packages, as
|
||||
* available from https://www.virtualbox.org.
|
||||
*
|
||||
* This program 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 3 of the
|
||||
* License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <https://www.gnu.org/licenses>.
|
||||
*
|
||||
* The contents of this file may alternatively be used under the terms
|
||||
* of the Common Development and Distribution License Version 1.0
|
||||
* (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
|
||||
* in the VirtualBox distribution, in which case the provisions of the
|
||||
* CDDL are applicable instead of those of the GPL.
|
||||
*
|
||||
* You may elect to license modified versions of this file under the
|
||||
* terms and conditions of either the GPL or the CDDL or both.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
|
||||
*/
|
||||
|
||||
#ifndef VBOX_INCLUDED_com_ErrorInfo_h
|
||||
#define VBOX_INCLUDED_com_ErrorInfo_h
|
||||
#ifndef RT_WITHOUT_PRAGMA_ONCE
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include "VBox/com/ptr.h"
|
||||
#include "VBox/com/string.h"
|
||||
#include "VBox/com/Guid.h"
|
||||
#include "VBox/com/assert.h"
|
||||
|
||||
|
||||
/** @defgroup grp_com_errinfo ErrorInfo Classes
|
||||
* @ingroup grp_com
|
||||
* @{
|
||||
*/
|
||||
|
||||
COM_STRUCT_OR_CLASS(IProgress);
|
||||
COM_STRUCT_OR_CLASS(IVirtualBoxErrorInfo);
|
||||
|
||||
namespace com
|
||||
{
|
||||
|
||||
/**
|
||||
* General discussion:
|
||||
*
|
||||
* In COM all errors are stored on a per thread basis. In general this means
|
||||
* only _one_ active error is possible per thread. A new error will overwrite
|
||||
* the previous one. To prevent this use MultiResult or ErrorInfoKeeper (see
|
||||
* below). The implementations in MSCOM/XPCOM differ slightly, but the details
|
||||
* are handled by this glue code.
|
||||
*
|
||||
* We have different classes which are involved in the error management. I try
|
||||
* to describe them separately to make clear what they are there for.
|
||||
*
|
||||
* ErrorInfo:
|
||||
*
|
||||
* This class is able to retrieve the per thread error and store it into its
|
||||
* member variables. This class can also handle non-VirtualBox errors (like
|
||||
* standard COM errors).
|
||||
*
|
||||
* ProgressErrorInfo:
|
||||
*
|
||||
* This is just a simple wrapper class to get the ErrorInfo stored within an
|
||||
* IProgress object. That is the error which was stored when the progress
|
||||
* object was in use and not an error produced by IProgress itself.
|
||||
*
|
||||
* IVirtualBoxErrorInfo:
|
||||
*
|
||||
* The VirtualBox interface class for accessing error information from Main
|
||||
* clients. This class is also used for storing the error information in the
|
||||
* thread context.
|
||||
*
|
||||
* ErrorInfoKeeper:
|
||||
*
|
||||
* A helper class which stores the current per thread info internally. After
|
||||
* calling methods which may produce other errors it is possible to restore
|
||||
* the previous error and therefore restore the situation before calling the
|
||||
* other methods.
|
||||
*
|
||||
* MultiResult:
|
||||
*
|
||||
* Creating an instance of MultiResult turns error chain saving on. All errors
|
||||
* which follow will be saved in a chain for later access.
|
||||
*
|
||||
* COMErrorInfo (Qt/Gui only):
|
||||
*
|
||||
* The Qt GUI does some additional work for saving errors. Because we create
|
||||
* wrappers for _every_ COM call, it is possible to automatically save the
|
||||
* error info after the execution. This allow some additional info like saving
|
||||
* the callee. Please note that this error info is saved on the client side
|
||||
* and therefore locally to the object instance. See COMBaseWithEI,
|
||||
* COMErrorInfo and the generated COMWrappers.cpp in the GUI.
|
||||
*
|
||||
* Errors itself are set in VirtualBoxBase::setErrorInternal. First a
|
||||
* IVirtualBoxErrorInfo object is created and the given error is saved within.
|
||||
* If MultiResult is active the current per thread error is fetched and
|
||||
* attached to the new created IVirtualBoxErrorInfo object. Next this object is
|
||||
* set as the new per thread error.
|
||||
*
|
||||
* Some general hints:
|
||||
*
|
||||
* - Always use setError, especially when you are working in an asynchronous thread
|
||||
* to indicate an error. Otherwise the error information itself will not make
|
||||
* it into the client.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* The ErrorInfo class provides a convenient way to retrieve error
|
||||
* information set by the most recent interface method, that was invoked on
|
||||
* the current thread and returned an unsuccessful result code.
|
||||
*
|
||||
* Once the instance of this class is created, the error information for
|
||||
* the current thread is cleared.
|
||||
*
|
||||
* There is no sense to use instances of this class after the last
|
||||
* invoked interface method returns a success.
|
||||
*
|
||||
* The class usage pattern is as follows:
|
||||
* <code>
|
||||
* IFoo *foo;
|
||||
* ...
|
||||
* HRESULT rc = foo->SomeMethod();
|
||||
* if (FAILED(rc)) {
|
||||
* ErrorInfo info(foo);
|
||||
* if (info.isFullAvailable()) {
|
||||
* printf("error message = %ls\n", info.getText().raw());
|
||||
* }
|
||||
* }
|
||||
* </code>
|
||||
*
|
||||
* This class fetches error information using the IErrorInfo interface on
|
||||
* Win32 (MS COM) or the nsIException interface on other platforms (XPCOM),
|
||||
* or the extended IVirtualBoxErrorInfo interface when when it is available
|
||||
* (i.e. a given IErrorInfo or nsIException instance implements it).
|
||||
* Currently, IVirtualBoxErrorInfo is only available for VirtualBox components.
|
||||
*
|
||||
* ErrorInfo::isFullAvailable() and ErrorInfo::isBasicAvailable() determine
|
||||
* what level of error information is available. If #isBasicAvailable()
|
||||
* returns true, it means that only IErrorInfo or nsIException is available as
|
||||
* the source of information (depending on the platform), but not
|
||||
* IVirtualBoxErrorInfo. If #isFullAvailable() returns true, it means that all
|
||||
* three interfaces are available. If both methods return false, no error info
|
||||
* is available at all.
|
||||
*
|
||||
* Here is a table of correspondence between this class methods and
|
||||
* and IErrorInfo/nsIException/IVirtualBoxErrorInfo attributes/methods:
|
||||
*
|
||||
* ErrorInfo IErrorInfo nsIException IVirtualBoxErrorInfo
|
||||
* --------------------------------------------------------------------
|
||||
* getResultCode -- result resultCode
|
||||
* getIID GetGUID -- interfaceID
|
||||
* getComponent GetSource -- component
|
||||
* getText GetDescription message text
|
||||
*
|
||||
* '--' means that this interface does not provide the corresponding portion
|
||||
* of information, therefore it is useless to query it if only
|
||||
* #isBasicAvailable() returns true. As it can be seen, the amount of
|
||||
* information provided at the basic level, depends on the platform
|
||||
* (MS COM or XPCOM).
|
||||
*/
|
||||
class ErrorInfo
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructs a new, "interfaceless" ErrorInfo instance that takes
|
||||
* the error information possibly set on the current thread by an
|
||||
* interface method of some COM component or by the COM subsystem.
|
||||
*
|
||||
* This constructor is useful, for example, after an unsuccessful attempt
|
||||
* to instantiate (create) a component, so there is no any valid interface
|
||||
* pointer available.
|
||||
*/
|
||||
explicit ErrorInfo()
|
||||
: mIsBasicAvailable(false),
|
||||
mIsFullAvailable(false),
|
||||
mResultCode(S_OK),
|
||||
mResultDetail(0),
|
||||
m_pNext(NULL)
|
||||
{
|
||||
init();
|
||||
}
|
||||
|
||||
ErrorInfo(IUnknown *pObj, const GUID &aIID)
|
||||
: mIsBasicAvailable(false),
|
||||
mIsFullAvailable(false),
|
||||
mResultCode(S_OK),
|
||||
mResultDetail(0),
|
||||
m_pNext(NULL)
|
||||
{
|
||||
init(pObj, aIID);
|
||||
}
|
||||
|
||||
/** Specialization for the IVirtualBoxErrorInfo smart pointer */
|
||||
ErrorInfo(const ComPtr<IVirtualBoxErrorInfo> &aPtr)
|
||||
: mIsBasicAvailable(false), mIsFullAvailable(false)
|
||||
, mResultCode(S_OK), mResultDetail(0)
|
||||
{ init(aPtr); }
|
||||
|
||||
/**
|
||||
* Constructs a new ErrorInfo instance from the IVirtualBoxErrorInfo
|
||||
* interface pointer. If this pointer is not NULL, both #isFullAvailable()
|
||||
* and #isBasicAvailable() will return |true|.
|
||||
*
|
||||
* @param aInfo pointer to the IVirtualBoxErrorInfo interface that
|
||||
* holds error info to be fetched by this instance
|
||||
*/
|
||||
ErrorInfo(IVirtualBoxErrorInfo *aInfo)
|
||||
: mIsBasicAvailable(false), mIsFullAvailable(false)
|
||||
, mResultCode(S_OK), mResultDetail(0)
|
||||
{ init(aInfo); }
|
||||
|
||||
ErrorInfo(const ErrorInfo &x)
|
||||
{
|
||||
copyFrom(x);
|
||||
}
|
||||
|
||||
virtual ~ErrorInfo()
|
||||
{
|
||||
cleanup();
|
||||
}
|
||||
|
||||
ErrorInfo& operator=(const ErrorInfo& x)
|
||||
{
|
||||
cleanup();
|
||||
copyFrom(x);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether basic error info is actually available for the current
|
||||
* thread. If the instance was created from an interface pointer that
|
||||
* supports basic error info and successfully provided it, or if it is an
|
||||
* "interfaceless" instance and there is some error info for the current
|
||||
* thread, the returned value will be true.
|
||||
*
|
||||
* See the class description for details about the basic error info level.
|
||||
*
|
||||
* The appropriate methods of this class provide meaningful info only when
|
||||
* this method returns true (otherwise they simply return NULL-like values).
|
||||
*/
|
||||
bool isBasicAvailable() const
|
||||
{
|
||||
return mIsBasicAvailable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether full error info is actually available for the current
|
||||
* thread. If the instance was created from an interface pointer that
|
||||
* supports full error info and successfully provided it, or if it is an
|
||||
* "interfaceless" instance and there is some error info for the current
|
||||
* thread, the returned value will be true.
|
||||
*
|
||||
* See the class description for details about the full error info level.
|
||||
*
|
||||
* The appropriate methods of this class provide meaningful info only when
|
||||
* this method returns true (otherwise they simply return NULL-like values).
|
||||
*/
|
||||
bool isFullAvailable() const
|
||||
{
|
||||
return mIsFullAvailable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the COM result code of the failed operation.
|
||||
*/
|
||||
HRESULT getResultCode() const
|
||||
{
|
||||
return mResultCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the (optional) result detail code of the failed operation.
|
||||
*/
|
||||
LONG getResultDetail() const
|
||||
{
|
||||
return mResultDetail;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the IID of the interface that defined the error.
|
||||
*/
|
||||
const Guid& getInterfaceID() const
|
||||
{
|
||||
return mInterfaceID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of the component that generated the error.
|
||||
*/
|
||||
const Bstr& getComponent() const
|
||||
{
|
||||
return mComponent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the textual description of the error.
|
||||
*/
|
||||
const Bstr& getText() const
|
||||
{
|
||||
return mText;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the next error information object or @c NULL if there is none.
|
||||
*/
|
||||
const ErrorInfo* getNext() const
|
||||
{
|
||||
return m_pNext;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of the interface that defined the error
|
||||
*/
|
||||
const Bstr& getInterfaceName() const
|
||||
{
|
||||
return mInterfaceName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the IID of the interface that returned the error.
|
||||
*
|
||||
* This method returns a non-null IID only if the instance was created
|
||||
* using template \<class I\> ErrorInfo(I *i) or
|
||||
* template \<class I\> ErrorInfo(const ComPtr<I> &i) constructor.
|
||||
*
|
||||
* @todo broken ErrorInfo documentation links, possibly misleading.
|
||||
*/
|
||||
const Guid& getCalleeIID() const
|
||||
{
|
||||
return mCalleeIID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of the interface that returned the error
|
||||
*
|
||||
* This method returns a non-null name only if the instance was created
|
||||
* using template \<class I\> ErrorInfo(I *i) or
|
||||
* template \<class I\> ErrorInfo(const ComPtr<I> &i) constructor.
|
||||
*
|
||||
* @todo broken ErrorInfo documentation links, possibly misleading.
|
||||
*/
|
||||
const Bstr& getCalleeName() const
|
||||
{
|
||||
return mCalleeName;
|
||||
}
|
||||
|
||||
HRESULT getVirtualBoxErrorInfo(ComPtr<IVirtualBoxErrorInfo> &pVirtualBoxErrorInfo);
|
||||
|
||||
/**
|
||||
* Resets all collected error information. #isBasicAvailable() and
|
||||
* #isFullAvailable will return @c true after this method is called.
|
||||
*/
|
||||
void setNull()
|
||||
{
|
||||
cleanup();
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
ErrorInfo(bool /* aDummy */)
|
||||
: mIsBasicAvailable(false),
|
||||
mIsFullAvailable(false),
|
||||
mResultCode(S_OK),
|
||||
m_pNext(NULL)
|
||||
{ }
|
||||
|
||||
void copyFrom(const ErrorInfo &x);
|
||||
void cleanup();
|
||||
|
||||
void init(bool aKeepObj = false);
|
||||
void init(IUnknown *aUnk, const GUID &aIID, bool aKeepObj = false);
|
||||
void init(IVirtualBoxErrorInfo *aInfo);
|
||||
|
||||
bool mIsBasicAvailable : 1;
|
||||
bool mIsFullAvailable : 1;
|
||||
|
||||
HRESULT mResultCode;
|
||||
LONG mResultDetail;
|
||||
Guid mInterfaceID;
|
||||
Bstr mComponent;
|
||||
Bstr mText;
|
||||
|
||||
ErrorInfo *m_pNext;
|
||||
|
||||
Bstr mInterfaceName;
|
||||
Guid mCalleeIID;
|
||||
Bstr mCalleeName;
|
||||
|
||||
ComPtr<IUnknown> mErrorInfo;
|
||||
};
|
||||
|
||||
/**
|
||||
* A convenience subclass of ErrorInfo that, given an IProgress interface
|
||||
* pointer, reads its errorInfo attribute and uses the returned
|
||||
* IVirtualBoxErrorInfo instance to construct itself.
|
||||
*/
|
||||
class ProgressErrorInfo : public ErrorInfo
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructs a new instance by fetching error information from the
|
||||
* IProgress interface pointer. If the progress object is not NULL,
|
||||
* its completed attribute is true, resultCode represents a failure,
|
||||
* and the errorInfo attribute returns a valid IVirtualBoxErrorInfo pointer,
|
||||
* both #isFullAvailable() and #isBasicAvailable() will return true.
|
||||
*
|
||||
* @param progress the progress object representing a failed operation
|
||||
*/
|
||||
ProgressErrorInfo(IProgress *progress);
|
||||
};
|
||||
|
||||
/**
|
||||
* A convenience subclass of ErrorInfo that allows to preserve the current
|
||||
* error info. Instances of this class fetch an error info object set on the
|
||||
* current thread and keep a reference to it, which allows to restore it
|
||||
* later using the #restore() method. This is useful to preserve error
|
||||
* information returned by some method for the duration of making another COM
|
||||
* call that may set its own error info and overwrite the existing
|
||||
* one. Preserving and restoring error information makes sense when some
|
||||
* method wants to return error information set by other call as its own
|
||||
* error information while it still needs to make another call before return.
|
||||
*
|
||||
* Instead of calling #restore() explicitly you may let the object destructor
|
||||
* do it for you, if you correctly limit the object's lifetime.
|
||||
*
|
||||
* The usage pattern is:
|
||||
* <code>
|
||||
* rc = foo->method();
|
||||
* if (FAILED(rc))
|
||||
* {
|
||||
* ErrorInfoKeeper eik;
|
||||
* ...
|
||||
* // bar may return error info as well
|
||||
* bar->method();
|
||||
* ...
|
||||
* // no need to call #restore() explicitly here because the eik's
|
||||
* // destructor will restore error info fetched after the failed
|
||||
* // call to foo before returning to the caller
|
||||
* return rc;
|
||||
* }
|
||||
* </code>
|
||||
*/
|
||||
class ErrorInfoKeeper : public ErrorInfo
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructs a new instance that will fetch the current error info if
|
||||
* @a aIsNull is @c false (by default) or remain uninitialized (null)
|
||||
* otherwise.
|
||||
*
|
||||
* @param aIsNull @c true to prevent fetching error info and leave
|
||||
* the instance uninitialized.
|
||||
*/
|
||||
ErrorInfoKeeper(bool aIsNull = false)
|
||||
: ErrorInfo(false), mForgot(aIsNull)
|
||||
{
|
||||
if (!aIsNull)
|
||||
init(true /* aKeepObj */);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new instance from an ErrorInfo object, to inject a full
|
||||
* error info created elsewhere.
|
||||
*
|
||||
* @param aInfo @c true to prevent fetching error info and leave
|
||||
* the instance uninitialized.
|
||||
*/
|
||||
ErrorInfoKeeper(const ErrorInfo &aInfo)
|
||||
: ErrorInfo(false), mForgot(false)
|
||||
{
|
||||
copyFrom(aInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroys this instance and automatically calls #restore() which will
|
||||
* either restore error info fetched by the constructor or do nothing
|
||||
* if #forget() was called before destruction.
|
||||
*/
|
||||
~ErrorInfoKeeper() { if (!mForgot) restore(); }
|
||||
|
||||
/**
|
||||
* Tries to (re-)fetch error info set on the current thread. On success,
|
||||
* the previous error information, if any, will be overwritten with the
|
||||
* new error information. On failure, or if there is no error information
|
||||
* available, this instance will be reset to null.
|
||||
*/
|
||||
void fetch()
|
||||
{
|
||||
setNull();
|
||||
mForgot = false;
|
||||
init(true /* aKeepObj */);
|
||||
}
|
||||
|
||||
/**
|
||||
* Restores error info fetched by the constructor and forgets it
|
||||
* afterwards. Does nothing if the error info was forgotten by #forget().
|
||||
*
|
||||
* @return COM result of the restore operation.
|
||||
*/
|
||||
HRESULT restore();
|
||||
|
||||
/**
|
||||
* Forgets error info fetched by the constructor to prevent it from
|
||||
* being restored by #restore() or by the destructor.
|
||||
*/
|
||||
void forget() { mForgot = true; }
|
||||
|
||||
/**
|
||||
* Forgets error info fetched by the constructor to prevent it from
|
||||
* being restored by #restore() or by the destructor, and returns the
|
||||
* stored error info object to the caller.
|
||||
*/
|
||||
ComPtr<IUnknown> takeError() { mForgot = true; return mErrorInfo; }
|
||||
|
||||
private:
|
||||
|
||||
bool mForgot : 1;
|
||||
};
|
||||
|
||||
} /* namespace com */
|
||||
|
||||
/** @} */
|
||||
|
||||
#endif /* !VBOX_INCLUDED_com_ErrorInfo_h */
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue