VirtualBox

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

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

VBox_hdr_h -> _VBox_hdr_h

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