VirtualBox

source: vbox/trunk/include/VBox/com/ErrorInfo.h@ 3044

Last change on this file since 3044 was 3044, checked in by vboxsync, 17 years ago

Main: Added ErrorInfoKeeper::takeError().

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 13.0 KB
Line 
1/** @file
2 *
3 * MS COM / XPCOM Abstraction Layer:
4 * ErrorInfo class declaration
5 */
6
7/*
8 * Copyright (C) 2006-2007 innotek GmbH
9 *
10 * This file is part of VirtualBox Open Source Edition (OSE), as
11 * available from http://www.virtualbox.org. This file is free software;
12 * you can redistribute it and/or modify it under the terms of the GNU
13 * General Public License as published by the Free Software Foundation,
14 * in version 2 as it comes in the "COPYING" file of the VirtualBox OSE
15 * distribution. VirtualBox OSE is distributed in the hope that it will
16 * be useful, but WITHOUT ANY WARRANTY of any kind.
17 *
18 * If you received this file as part of a commercial VirtualBox
19 * distribution, then only the terms of your commercial VirtualBox
20 * license agreement apply instead of the previous paragraph.
21 */
22
23#ifndef __VBox_com_ErrorInfo_h__
24#define __VBox_com_ErrorInfo_h__
25
26#include "VBox/com/ptr.h"
27#include "VBox/com/string.h"
28#include "VBox/com/Guid.h"
29#include "VBox/com/assert.h"
30
31#include <iprt/memory> // for auto_copy_ptr
32
33struct IProgress;
34struct IVirtualBoxErrorInfo;
35
36namespace com
37{
38
39/**
40 * The ErrorInfo class provides a convenient way to retrieve error
41 * information set by the most recent interface method, that was invoked on
42 * the current thread and returned an unsuccessful result code.
43 *
44 * Once the instance of this class is created, the error information for
45 * the current thread is cleared.
46 *
47 * There is no sence to use instances of this class after the last
48 * invoked interface method returns a success.
49 *
50 * The class usage pattern is as follows:
51 * <code>
52 * IFoo *foo;
53 * ...
54 * HRESULT rc = foo->SomeMethod();
55 * if (FAILED (rc)) {
56 * ErrorInfo info (foo);
57 * if (info.isFullAvailable()) {
58 * printf ("error message = %ls\n", info.getText().raw());
59 * }
60 * }
61 * </code>
62 *
63 * This class fetches error information using the IErrorInfo interface on
64 * Win32 (MS COM) or the nsIException interface on other platforms (XPCOM),
65 * or the extended IVirtualBoxErrorInfo interface when when it is available
66 * (i.e. a given IErrorInfo or nsIException instance implements it).
67 * Currently, IVirtualBoxErrorInfo is only available for VirtualBox components.
68 *
69 * ErrorInfo::isFullAvailable() and ErrorInfo::isBasicAvailable() determine
70 * what level of error information is available. If #isBasicAvailable()
71 * returns true, it means that only IErrorInfo or nsIException is available as
72 * the source of information (depending on the platform), but not
73 * IVirtualBoxErrorInfo. If #isFullAvailable() returns true, it means that all
74 * three interfaces are available. If both methods return false, no error info
75 * is available at all.
76 *
77 * Here is a table of correspondence between this class methods and
78 * and IErrorInfo/nsIException/IVirtualBoxErrorInfo attributes/methods:
79 *
80 * ErrorInfo IErrorInfo nsIException IVirtualBoxErrorInfo
81 * --------------------------------------------------------------------
82 * getResultCode -- result resultCode
83 * getIID GetGUID -- interfaceID
84 * getComponent GetSource -- component
85 * getText GetDescription message text
86 *
87 * '--' means that this interface does not provide the corresponding portion
88 * of information, therefore it is useless to query it if only
89 * #isBasicAvailable() returns true. As it can be seen, the amount of
90 * information provided at the basic level, depends on the platform
91 * (MS COM or XPCOM).
92 */
93class ErrorInfo
94{
95public:
96
97 /**
98 * Constructs a new, "interfaceless" ErrorInfo instance that takes
99 * the error information possibly set on the current thread by an
100 * interface method of some COM component or by the COM subsystem.
101 *
102 * This constructor is useful, for example, after an unsuccessful attempt
103 * to instantiate (create) a component, so there is no any valid interface
104 * pointer available.
105 */
106 explicit ErrorInfo()
107 : mIsBasicAvailable (false), mIsFullAvailable (false)
108 , mResultCode (S_OK)
109 { init(); }
110
111 /**
112 * Constructs a new, "interfaceless" ErrorInfo instance that takes
113 * the error information possibly set on the current thread by an
114 * interface method of the given interface pointer.
115
116 * If the given interface does not support providing error information or,
117 * for some reason didn't set any error information, both
118 * #isFullAvailable() and #isBasicAvailable() will return |false|.
119 *
120 * @param aPtr pointer to the interface whose method returned an
121 * error
122 */
123 template <class I> ErrorInfo (I *aPtr)
124 : mIsBasicAvailable (false), mIsFullAvailable (false)
125 , mResultCode (S_OK)
126 { init (aPtr, COM_IIDOF(I)); }
127
128 /**
129 * Constructs a new ErrorInfo instance from the smart interface pointer.
130 * See template <class I> ErrorInfo (I *aPtr) for details
131 *
132 * @param aPtr smart pointer to the interface whose method returned
133 * an error
134 */
135 template <class I> ErrorInfo (const ComPtr <I> &aPtr)
136 : mIsBasicAvailable (false), mIsFullAvailable (false)
137 , mResultCode (S_OK)
138 { init (static_cast <I*> (aPtr), COM_IIDOF(I)); }
139
140 /** Specialization for the IVirtualBoxErrorInfo smart pointer */
141 ErrorInfo (const ComPtr <IVirtualBoxErrorInfo> &aPtr)
142 : mIsBasicAvailable (false), mIsFullAvailable (false)
143 , mResultCode (S_OK)
144 { init (aPtr); }
145
146 /**
147 * Constructs a new ErrorInfo instance from the IVirtualBoxErrorInfo
148 * interface pointer. If this pointer is not NULL, both #isFullAvailable()
149 * and #isBasicAvailable() will return |true|.
150 *
151 * @param aInfo pointer to the IVirtualBoxErrorInfo interface that
152 * holds error info to be fetched by this instance
153 */
154 ErrorInfo (IVirtualBoxErrorInfo *aInfo)
155 : mIsBasicAvailable (false), mIsFullAvailable (false)
156 , mResultCode (S_OK)
157 { init (aInfo); }
158
159 virtual ~ErrorInfo();
160
161 /**
162 * Returns whether basic error info is actually available for the current
163 * thread. If the instance was created from an interface pointer that
164 * supports basic error info and successfully provided it, or if it is an
165 * "interfaceless" instance and there is some error info for the current
166 * thread, the returned value will be true.
167 *
168 * See the class description for details about the basic error info level.
169 *
170 * The appropriate methods of this class provide meaningful info only when
171 * this method returns true (otherwise they simply return NULL-like values).
172 */
173 bool isBasicAvailable() const { return mIsBasicAvailable; }
174
175 /**
176 * Returns whether full error info is actually available for the current
177 * thread. If the instance was created from an interface pointer that
178 * supports full error info and successfully provided it, or if it is an
179 * "interfaceless" instance and there is some error info for the current
180 * thread, the returned value will be true.
181 *
182 * See the class description for details about the full error info level.
183 *
184 * The appropriate methods of this class provide meaningful info only when
185 * this method returns true (otherwise they simply return NULL-like values).
186 */
187 bool isFullAvailable() const { return mIsFullAvailable; }
188
189 /**
190 * Returns the COM result code of the failed operation.
191 */
192 HRESULT getResultCode() const { return mResultCode; }
193
194 /**
195 * Returns the IID of the interface that defined the error.
196 */
197 const Guid &getInterfaceID() const { return mInterfaceID; }
198
199 /**
200 * Returns the name of the component that generated the error.
201 */
202 const Bstr &getComponent() const { return mComponent; }
203
204 /**
205 * Returns the textual description of the error.
206 */
207 const Bstr &getText() const { return mText; }
208
209 /**
210 * Returns the next error information object or @c NULL if there is none.
211 */
212 const ErrorInfo *getNext() const { return mNext.get(); }
213
214 /**
215 * Returns the name of the interface that defined the error
216 */
217 const Bstr &getInterfaceName() const { return mInterfaceName; }
218
219 /**
220 * Returns the IID of the interface that returned the error.
221 *
222 * This method returns a non-null IID only if the instance was created
223 * using #template <class I> ErrorInfo (I *i) or
224 * template <class I> ErrorInfo (const ComPtr <I> &i) constructor.
225 */
226 const Guid &getCalleeIID() const { return mCalleeIID; }
227
228 /**
229 * Returns the name of the interface that returned the error
230 *
231 * This method returns a non-null name only if the instance was created
232 * using #template <class I> ErrorInfo (I *i) or
233 * template <class I> ErrorInfo (const ComPtr <I> &i) constructor.
234 */
235 const Bstr &getCalleeName() const { return mCalleeName; }
236
237 /**
238 * Prints error information stored in this instance to the console.
239 * Intended mainly for debugging and for simple command-line tools.
240 *
241 * @param aPrefix optional prefix
242 */
243 void print (const char *aPrefix = NULL);
244
245protected:
246
247 ErrorInfo (bool aDummy)
248 : mIsBasicAvailable (false), mIsFullAvailable (false)
249 , mResultCode (S_OK)
250 {}
251
252 void init (bool aKeepObj = false);
253 void init (IUnknown *aUnk, const GUID &aIID, bool aKeepObj = false);
254 void init (IVirtualBoxErrorInfo *aInfo);
255
256 bool mIsBasicAvailable : 1;
257 bool mIsFullAvailable : 1;
258
259 HRESULT mResultCode;
260 Guid mInterfaceID;
261 Bstr mComponent;
262 Bstr mText;
263
264 cppx::auto_copy_ptr <ErrorInfo> mNext;
265
266 Bstr mInterfaceName;
267 Guid mCalleeIID;
268 Bstr mCalleeName;
269
270 ComPtr <IUnknown> mErrorInfo;
271};
272
273/**
274 * A convenience subclass of ErrorInfo that, given an IProgress interface
275 * pointer, reads its errorInfo attribute and uses the returned
276 * IVirtualBoxErrorInfo instance to construct itself.
277 */
278class ProgressErrorInfo : public ErrorInfo
279{
280public:
281
282 /**
283 * Constructs a new instance by fetchig error information from the
284 * IProgress interface pointer. If the progress object is not NULL,
285 * its completed attribute is true, resultCode represents a failure,
286 * and the errorInfo attribute returns a valid IVirtualBoxErrorInfo pointer,
287 * both #isFullAvailable() and #isBasicAvailable() will return true.
288 *
289 * @param progress the progress object representing a failed operation
290 */
291 ProgressErrorInfo (IProgress *progress);
292};
293
294/**
295 * A convenience subclass of ErrorInfo that allows to preserve the current
296 * error info. Instances of this class fetch an error info object set on the
297 * current thread and keep a reference to it, which allows to restore it
298 * later using the #restore() method. This is useful to preserve error
299 * information returned by some method for the duration of making another COM
300 * call that may set its own error info and overwrite the existing
301 * one. Preserving and restoring error information makes sense when some
302 * method wants to return error information set by other call as its own
303 * error information while it still needs to make another call before return.
304 *
305 * Instead of calling #restore() explicitly you may let the object destructor
306 * do it for you, if you correctly limit the object's lifeime.
307 *
308 * The usage pattern is:
309 * <code>
310 * rc = foo->method();
311 * if (FAILED (rc))
312 * {
313 * ErrorInfoKeeper eik;
314 * ...
315 * // bar may return error info as well
316 * bar->method();
317 * ...
318 * // no need to call #restore() explicitly here because the eik's
319 * // destructor will restore error info fetched after the failed
320 * // call to foo before returning to the caller
321 * return rc;
322 * }
323 * </code>
324 */
325class ErrorInfoKeeper : public ErrorInfo
326{
327public:
328
329 /** Constructs a new instance that will fetch the current error info. */
330 ErrorInfoKeeper() : ErrorInfo (false), mForgot (false)
331 { init (true /* aKeepObj */); }
332
333 /**
334 * Destroys this instance and automatically calls #restore() which will
335 * either restore error info fetched by the constructor or do nothing
336 * if #forget() was called before destruction. */
337 ~ErrorInfoKeeper() { if (!mForgot) restore(); }
338
339 /**
340 * Restores error info fetched by the constructor and forgets it
341 * afterwards.
342 *
343 * @return COM result of the restore operation.
344 */
345 HRESULT restore();
346
347 /**
348 * Forgets error info fetched by the constructor to prevent it from
349 * being restored by #restore() or by the destructor.
350 */
351 void forget() { mForgot = 0; }
352
353 /**
354 * Forgets error info fetched by the constructor to prevent it from
355 * being restored by #restore() or by the destructor, and returns the
356 * stored error info object to the caller.
357 */
358 ComPtr <IUnknown> takeError() { mForgot = 0; return mErrorInfo; }
359
360private:
361
362 bool mForgot : 1;
363};
364
365}; // namespace com
366
367#endif // __VBox_com_ErrorInfo_h__
368
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