VirtualBox

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

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

The Giant CDDL Dual-License Header Change.

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