VirtualBox

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

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

Biggest check-in ever. New source code headers for all (C) innotek files.

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