/** @file * * MS COM / XPCOM Abstraction Layer: * ErrorInfo class declaration */ /* * Copyright (C) 2006 InnoTek Systemberatung 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 you received this file as part of a commercial VirtualBox * distribution, then only the terms of your commercial VirtualBox * license agreement apply instead of the previous paragraph. */ #ifndef __VBox_com_ErrorInfo_h__ #define __VBox_com_ErrorInfo_h__ #include "VBox/com/ptr.h" #include "VBox/com/string.h" #include "VBox/com/Guid.h" #include "VBox/com/assert.h" struct IProgress; struct IVirtualBoxErrorInfo; namespace com { /** * 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 sence to use instances of this class after the last * invoked interface method returns a success. * * The class usage pattern is as follows: * * IFoo *foo; * ... * HRESULT rc = foo->SomeMethod(); * if (FAILED (rc)) { * ErrorInfo info (foo); * if (info.isFullAvailable()) { * printf ("error message = %ls\n", info.getText().raw()); * } * } * * * 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) { init(); } /** * Constructs a new, "interfaceless" ErrorInfo instance that takes * the error information possibly set on the current thread by an * interface method of the given interface pointer. * If the given interface does not support providing error information or, * for some reason didn't set any error information, both * #isFullAvailable() and #isBasicAvailable() will return |false|. * * @param aPtr pointer to the interface whose method returned an * error */ template ErrorInfo (I *aPtr) : mIsBasicAvailable (false), mIsFullAvailable (false), mResultCode (S_OK) { init (aPtr, COM_IIDOF(I)); } /** * Constructs a new ErrorInfo instance from the smart interface pointer. * See template ErrorInfo (I *aPtr) for details * * @param aPtr smart pointer to the interface whose method returned * an error */ template ErrorInfo (const ComPtr &aPtr) : mIsBasicAvailable (false), mIsFullAvailable (false), mResultCode (S_OK) { init (static_cast (aPtr), COM_IIDOF(I)); } /** Specialization for the IVirtualBoxErrorInfo smart pointer */ ErrorInfo (const ComPtr &aPtr) : mIsBasicAvailable (false), mIsFullAvailable (false), mResultCode (S_OK) { 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) { init (aInfo); } ~ErrorInfo(); /** * 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 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 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 ErrorInfo (I *i) or * template ErrorInfo (const ComPtr &i) constructor. */ 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 ErrorInfo (I *i) or * template ErrorInfo (const ComPtr &i) constructor. */ const Bstr &getCalleeName() const { return mCalleeName; } /** * Prints error information stored in this instance to the console. * Intended mainly for debugging and for simple command-line tools. * * @param aPrefix optional prefix */ void print (const char *aPrefix = NULL); protected: ErrorInfo (bool dummy) : mIsBasicAvailable (false), mIsFullAvailable (false), mResultCode (S_OK) {} void init(); void init (IUnknown *i, const GUID &iid); void init (IVirtualBoxErrorInfo *info); private: bool mIsBasicAvailable; bool mIsFullAvailable; HRESULT mResultCode; Guid mInterfaceID; Bstr mComponent; Bstr mText; Bstr mInterfaceName; Guid mCalleeIID; Bstr mCalleeName; }; /** * 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 fetchig 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); }; }; // namespace com #endif // __VBox_com_ErrorInfo_h__