VirtualBox

source: vbox/trunk/src/VBox/Main/glue/ErrorInfo.cpp@ 45500

Last change on this file since 45500 was 44970, checked in by vboxsync, 12 years ago

Main/VirtualBoxClient: add method to perform VM error checking which simplifies client code
com/ErrorInfo: small bugfix (the object where the error information originated was always lost), added a way to inject whole error object structures which needed the bugfix
Frontends/VBoxSDL: sample code how to use the new method

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 8.5 KB
Line 
1/* $Id: ErrorInfo.cpp 44970 2013-03-11 09:59:05Z vboxsync $ */
2
3/** @file
4 *
5 * ErrorInfo class definition
6 */
7
8/*
9 * Copyright (C) 2006-2013 Oracle Corporation
10 *
11 * This file is part of VirtualBox Open Source Edition (OSE), as
12 * available from http://www.virtualbox.org. This file is free software;
13 * you can redistribute it and/or modify it under the terms of the GNU
14 * General Public License (GPL) as published by the Free Software
15 * Foundation, in version 2 as it comes in the "COPYING" file of the
16 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
17 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
18 */
19
20#if defined(VBOX_WITH_XPCOM)
21# include <nsIServiceManager.h>
22# include <nsIExceptionService.h>
23# include <nsCOMPtr.h>
24#endif
25
26#include "VBox/com/VirtualBox.h"
27#include "VBox/com/ErrorInfo.h"
28#include "VBox/com/assert.h"
29#include "VBox/com/com.h"
30#include "VBox/com/MultiResult.h"
31
32#include <iprt/stream.h>
33#include <iprt/string.h>
34
35#include <VBox/err.h>
36
37namespace com
38{
39
40////////////////////////////////////////////////////////////////////////////////
41//
42// ErrorInfo class
43//
44////////////////////////////////////////////////////////////////////////////////
45
46void ErrorInfo::copyFrom(const ErrorInfo &x)
47{
48 mIsBasicAvailable = x.mIsBasicAvailable;
49 mIsFullAvailable = x.mIsFullAvailable;
50
51 mResultCode = x.mResultCode;
52 mInterfaceID = x.mInterfaceID;
53 mComponent = x.mComponent;
54 mText = x.mText;
55
56 if (x.m_pNext != NULL)
57 m_pNext = new ErrorInfo(*x.m_pNext);
58 else
59 m_pNext = NULL;
60
61 mInterfaceName = x.mInterfaceName;
62 mCalleeIID = x.mCalleeIID;
63 mCalleeName = x.mCalleeName;
64
65 mErrorInfo = x.mErrorInfo;
66}
67
68void ErrorInfo::cleanup()
69{
70 mIsBasicAvailable = false;
71 mIsFullAvailable = false;
72
73 if (m_pNext)
74 {
75 delete m_pNext;
76 m_pNext = NULL;
77 }
78
79 mResultCode = S_OK;
80 mInterfaceID.clear();
81 mComponent.setNull();
82 mText.setNull();
83 mInterfaceName.setNull();
84 mCalleeIID.clear();
85 mCalleeName.setNull();
86 mErrorInfo.setNull();
87}
88
89void ErrorInfo::init(bool aKeepObj /* = false */)
90{
91 HRESULT rc = E_FAIL;
92
93#if !defined(VBOX_WITH_XPCOM)
94
95 ComPtr<IErrorInfo> err;
96 rc = ::GetErrorInfo(0, err.asOutParam());
97 if (rc == S_OK && err)
98 {
99 if (aKeepObj)
100 mErrorInfo = err;
101
102 ComPtr<IVirtualBoxErrorInfo> info;
103 rc = err.queryInterfaceTo(info.asOutParam());
104 if (SUCCEEDED(rc) && info)
105 init(info);
106
107 if (!mIsFullAvailable)
108 {
109 bool gotSomething = false;
110
111 rc = err->GetGUID(mInterfaceID.asOutParam());
112 gotSomething |= SUCCEEDED(rc);
113 if (SUCCEEDED(rc))
114 GetInterfaceNameByIID(mInterfaceID.ref(), mInterfaceName.asOutParam());
115
116 rc = err->GetSource(mComponent.asOutParam());
117 gotSomething |= SUCCEEDED(rc);
118
119 rc = err->GetDescription(mText.asOutParam());
120 gotSomething |= SUCCEEDED(rc);
121
122 if (gotSomething)
123 mIsBasicAvailable = true;
124
125 AssertMsg(gotSomething, ("Nothing to fetch!\n"));
126 }
127 }
128
129#else // defined(VBOX_WITH_XPCOM)
130
131 nsCOMPtr<nsIExceptionService> es;
132 es = do_GetService(NS_EXCEPTIONSERVICE_CONTRACTID, &rc);
133 if (NS_SUCCEEDED(rc))
134 {
135 nsCOMPtr<nsIExceptionManager> em;
136 rc = es->GetCurrentExceptionManager(getter_AddRefs(em));
137 if (NS_SUCCEEDED(rc))
138 {
139 ComPtr<nsIException> ex;
140 rc = em->GetCurrentException(ex.asOutParam());
141 if (NS_SUCCEEDED(rc) && ex)
142 {
143 if (aKeepObj)
144 mErrorInfo = ex;
145
146 ComPtr<IVirtualBoxErrorInfo> info;
147 rc = ex.queryInterfaceTo(info.asOutParam());
148 if (NS_SUCCEEDED(rc) && info)
149 init(info);
150
151 if (!mIsFullAvailable)
152 {
153 bool gotSomething = false;
154
155 rc = ex->GetResult(&mResultCode);
156 gotSomething |= NS_SUCCEEDED(rc);
157
158 char *pszMsg;
159 rc = ex->GetMessage(&pszMsg);
160 gotSomething |= NS_SUCCEEDED(rc);
161 if (NS_SUCCEEDED(rc))
162 {
163 mText = Bstr(pszMsg);
164 nsMemory::Free(pszMsg);
165 }
166
167 if (gotSomething)
168 mIsBasicAvailable = true;
169
170 AssertMsg(gotSomething, ("Nothing to fetch!\n"));
171 }
172
173 // set the exception to NULL (to emulate Win32 behavior)
174 em->SetCurrentException(NULL);
175
176 rc = NS_OK;
177 }
178 }
179 }
180 /* Ignore failure when called after nsComponentManagerImpl::Shutdown(). */
181 else if (rc == NS_ERROR_UNEXPECTED)
182 rc = NS_OK;
183
184 AssertComRC(rc);
185
186#endif // defined(VBOX_WITH_XPCOM)
187}
188
189void ErrorInfo::init(IUnknown *aI,
190 const GUID &aIID,
191 bool aKeepObj /* = false */)
192{
193 AssertReturnVoid(aI);
194
195#if !defined(VBOX_WITH_XPCOM)
196
197 ComPtr<IUnknown> iface = aI;
198 ComPtr<ISupportErrorInfo> serr;
199 HRESULT rc = iface.queryInterfaceTo(serr.asOutParam());
200 if (SUCCEEDED(rc))
201 {
202 rc = serr->InterfaceSupportsErrorInfo(aIID);
203 if (SUCCEEDED(rc))
204 init(aKeepObj);
205 }
206
207#else
208
209 init(aKeepObj);
210
211#endif
212
213 if (mIsBasicAvailable)
214 {
215 mCalleeIID = aIID;
216 GetInterfaceNameByIID(aIID, mCalleeName.asOutParam());
217 }
218}
219
220void ErrorInfo::init(IVirtualBoxErrorInfo *info)
221{
222 AssertReturnVoid(info);
223
224 HRESULT rc = E_FAIL;
225 bool gotSomething = false;
226 bool gotAll = true;
227 LONG lrc;
228
229 rc = info->COMGETTER(ResultCode)(&lrc); mResultCode = lrc;
230 gotSomething |= SUCCEEDED(rc);
231 gotAll &= SUCCEEDED(rc);
232
233 Bstr iid;
234 rc = info->COMGETTER(InterfaceID)(iid.asOutParam());
235 gotSomething |= SUCCEEDED(rc);
236 gotAll &= SUCCEEDED(rc);
237 if (SUCCEEDED(rc))
238 {
239 mInterfaceID = iid;
240 GetInterfaceNameByIID(mInterfaceID.ref(), mInterfaceName.asOutParam());
241 }
242
243 rc = info->COMGETTER(Component)(mComponent.asOutParam());
244 gotSomething |= SUCCEEDED(rc);
245 gotAll &= SUCCEEDED(rc);
246
247 rc = info->COMGETTER(Text)(mText.asOutParam());
248 gotSomething |= SUCCEEDED(rc);
249 gotAll &= SUCCEEDED(rc);
250
251 m_pNext = NULL;
252
253 ComPtr<IVirtualBoxErrorInfo> next;
254 rc = info->COMGETTER(Next)(next.asOutParam());
255 if (SUCCEEDED(rc) && !next.isNull())
256 {
257 m_pNext = new ErrorInfo(next);
258 Assert(m_pNext != NULL);
259 if (!m_pNext)
260 rc = E_OUTOFMEMORY;
261 }
262
263 gotSomething |= SUCCEEDED(rc);
264 gotAll &= SUCCEEDED(rc);
265
266 mIsBasicAvailable = gotSomething;
267 mIsFullAvailable = gotAll;
268
269 mErrorInfo = info;
270
271 AssertMsg(gotSomething, ("Nothing to fetch!\n"));
272}
273
274////////////////////////////////////////////////////////////////////////////////
275//
276// ProgressErrorInfo class
277//
278////////////////////////////////////////////////////////////////////////////////
279
280ProgressErrorInfo::ProgressErrorInfo(IProgress *progress) :
281 ErrorInfo(false /* aDummy */)
282{
283 Assert(progress);
284 if (!progress)
285 return;
286
287 ComPtr<IVirtualBoxErrorInfo> info;
288 HRESULT rc = progress->COMGETTER(ErrorInfo)(info.asOutParam());
289 if (SUCCEEDED(rc) && info)
290 init(info);
291}
292
293////////////////////////////////////////////////////////////////////////////////
294//
295// ErrorInfoKeeper class
296//
297////////////////////////////////////////////////////////////////////////////////
298
299HRESULT ErrorInfoKeeper::restore()
300{
301 if (mForgot)
302 return S_OK;
303
304 HRESULT rc = S_OK;
305
306#if !defined(VBOX_WITH_XPCOM)
307
308 ComPtr<IErrorInfo> err;
309 if (!mErrorInfo.isNull())
310 {
311 rc = mErrorInfo.queryInterfaceTo(err.asOutParam());
312 AssertComRC(rc);
313 }
314 rc = ::SetErrorInfo(0, err);
315
316#else // defined(VBOX_WITH_XPCOM)
317
318 nsCOMPtr <nsIExceptionService> es;
319 es = do_GetService(NS_EXCEPTIONSERVICE_CONTRACTID, &rc);
320 if (NS_SUCCEEDED(rc))
321 {
322 nsCOMPtr <nsIExceptionManager> em;
323 rc = es->GetCurrentExceptionManager(getter_AddRefs(em));
324 if (NS_SUCCEEDED(rc))
325 {
326 ComPtr<nsIException> ex;
327 if (!mErrorInfo.isNull())
328 {
329 rc = mErrorInfo.queryInterfaceTo(ex.asOutParam());
330 AssertComRC(rc);
331 }
332 rc = em->SetCurrentException(ex);
333 }
334 }
335
336#endif // defined(VBOX_WITH_XPCOM)
337
338 if (SUCCEEDED(rc))
339 {
340 mErrorInfo.setNull();
341 mForgot = true;
342 }
343
344 return rc;
345}
346
347} /* namespace com */
348
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