VirtualBox

root/trunk/include/VBox/com/ErrorInfo.h

Revision 13856, 14.7 kB (checked in by vboxsync, 2 months ago)

Main: typos

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
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
41 struct IProgress;
42 struct IVirtualBoxErrorInfo;
43
44 namespace 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 sense 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  */
101 class ErrorInfo
102 {
103 public:
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      *  Resets all collected error information. #isNull() will
253      *  return @c true after this method is called.
254      */
255     void setNull()
256     {
257         mIsBasicAvailable = false;
258         mIsFullAvailable = false;
259
260         mResultCode = S_OK;
261         mInterfaceID.clear();
262         mComponent.setNull();
263         mText.setNull();
264         mNext.reset();
265         mInterfaceName.setNull();
266         mCalleeIID.clear();
267         mCalleeName.setNull();
268         mErrorInfo.setNull();
269     }
270
271 protected:
272
273     ErrorInfo (bool aDummy)
274         : mIsBasicAvailable (false), mIsFullAvailable (false)
275         , mResultCode (S_OK)
276         {}
277
278     void init (bool aKeepObj = false);
279     void init (IUnknown *aUnk, const GUID &aIID, bool aKeepObj = false);
280     void init (IVirtualBoxErrorInfo *aInfo);
281
282     bool mIsBasicAvailable : 1;
283     bool mIsFullAvailable : 1;
284
285     HRESULT mResultCode;
286     Guid mInterfaceID;
287     Bstr mComponent;
288     Bstr mText;
289
290     cppx::auto_copy_ptr <ErrorInfo> mNext;
291
292     Bstr mInterfaceName;
293     Guid mCalleeIID;
294     Bstr mCalleeName;
295
296     ComPtr <IUnknown> mErrorInfo;
297 };
298
299 /**
300  *  A convenience subclass of ErrorInfo that, given an IProgress interface
301  *  pointer, reads its errorInfo attribute and uses the returned
302  *  IVirtualBoxErrorInfo instance to construct itself.
303  */
304 class ProgressErrorInfo : public ErrorInfo
305 {
306 public:
307
308     /**
309      *  Constructs a new instance by fetching error information from the
310      *  IProgress interface pointer. If the progress object is not NULL,
311      *  its completed attribute is true, resultCode represents a failure,
312      *  and the errorInfo attribute returns a valid IVirtualBoxErrorInfo pointer,
313      *  both #isFullAvailable() and #isBasicAvailable() will return true.
314      *
315      *  @param  progress    the progress object representing a failed operation
316      */
317     ProgressErrorInfo (IProgress *progress);
318 };
319
320 /**
321  *  A convenience subclass of ErrorInfo that allows to preserve the current
322  *  error info. Instances of this class fetch an error info object set on the
323  *  current thread and keep a reference to it, which allows to restore it
324  *  later using the #restore() method. This is useful to preserve error
325  *  information returned by some method for the duration of making another COM
326  *  call that may set its own error info and overwrite the existing
327  *  one. Preserving and restoring error information makes sense when some
328  *  method wants to return error information set by other call as its own
329  *  error information while it still needs to make another call before return.
330  *
331  *  Instead of calling #restore() explicitly you may let the object destructor
332  *  do it for you, if you correctly limit the object's lifetime.
333  *
334  *  The usage pattern is:
335  *  <code>
336  *      rc = foo->method();
337  *      if (FAILED (rc))
338  *      {
339  *           ErrorInfoKeeper eik;
340  *           ...
341  *           // bar may return error info as well
342  *           bar->method();
343  *           ...
344  *           // no need to call #restore() explicitly here because the eik's
345  *           // destructor will restore error info fetched after the failed
346  *           // call to foo before returning to the caller
347  *           return rc;
348  *      }
349  *  </code>
350  */
351 class ErrorInfoKeeper : public ErrorInfo
352 {
353 public:
354
355     /**
356      *  Constructs a new instance that will fetch the current error info if
357      *  @a aIsNull is @c false (by default) or remain uninitialized (null)
358      *  otherwise.
359      *
360      *  @param aIsNull  @true to prevent fetching error info and leave
361      *                  the instance uninitialized.
362      */
363     ErrorInfoKeeper (bool aIsNull = false)
364         : ErrorInfo (false), mForgot (aIsNull)
365     {
366         if (!aIsNull)
367             init (true /* aKeepObj */);
368     }
369
370     /**
371      *  Destroys this instance and automatically calls #restore() which will
372      *  either restore error info fetched by the constructor or do nothing
373      *  if #forget() was called before destruction.
374      */
375     ~ErrorInfoKeeper() { if (!mForgot) restore(); }
376
377     /**
378      *  Tries to (re-)fetch error info set on the current thread.  On success,
379      *  the previous error information, if any, will be overwritten with the
380      *  new error information. On failure, or if there is no error information
381      *  available, this instance will be reset to null.
382      */
383     void fetch()
384     {
385         setNull();
386         mForgot = false;
387         init (true /* aKeepObj */);
388     }
389
390     /**
391      *  Restores error info fetched by the constructor and forgets it
392      *  afterwards. Does nothing if the error info was forgotten by #forget().
393      *
394      *  @return COM result of the restore operation.
395      */
396     HRESULT restore();
397
398     /**
399      *  Forgets error info fetched by the constructor to prevent it from
400      *  being restored by #restore() or by the destructor.
401      */
402     void forget() { mForgot = true; }
403
404     /**
405      *  Forgets error info fetched by the constructor to prevent it from
406      *  being restored by #restore() or by the destructor, and returns the
407      *  stored error info object to the caller.
408      */
409     ComPtr <IUnknown> takeError() { mForgot = true; return mErrorInfo; }
410
411 private:
412
413     bool mForgot : 1;
414 };
415
416 } /* namespace com */
417
418 #endif
419
Note: See TracBrowser for help on using the browser.

© 2008 Sun Microsystems, Inc.
ContactPrivacy policy