VirtualBox

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

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

The Big Sun Rebranding Header Change

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