VirtualBox

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

Last change on this file since 36254 was 35517, checked in by vboxsync, 14 years ago

Frontends/VBoxManage+glue/ErrorInfo: revert change which broke error reporting (4.0.0 regression), clean up on the way

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