VirtualBox

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

Last change on this file since 38508 was 38508, checked in by vboxsync, 13 years ago

Main/glue/ErrorInfo: fix regression of r67420 (preserve error chain)

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 8.4 KB
Line 
1/* $Id: ErrorInfo.cpp 38508 2011-08-23 14:48:39Z vboxsync $ */
2
3/** @file
4 *
5 * ErrorInfo class definition
6 */
7
8/*
9 * Copyright (C) 2006-2010 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 AssertMsg(gotSomething, ("Nothing to fetch!\n"));
270}
271
272////////////////////////////////////////////////////////////////////////////////
273//
274// ProgressErrorInfo class
275//
276////////////////////////////////////////////////////////////////////////////////
277
278ProgressErrorInfo::ProgressErrorInfo(IProgress *progress) :
279 ErrorInfo(false /* aDummy */)
280{
281 Assert(progress);
282 if (!progress)
283 return;
284
285 ComPtr<IVirtualBoxErrorInfo> info;
286 HRESULT rc = progress->COMGETTER(ErrorInfo)(info.asOutParam());
287 if (SUCCEEDED(rc) && info)
288 init(info);
289}
290
291////////////////////////////////////////////////////////////////////////////////
292//
293// ErrorInfoKeeper class
294//
295////////////////////////////////////////////////////////////////////////////////
296
297HRESULT ErrorInfoKeeper::restore()
298{
299 if (mForgot)
300 return S_OK;
301
302 HRESULT rc = S_OK;
303
304#if !defined(VBOX_WITH_XPCOM)
305
306 ComPtr<IErrorInfo> err;
307 if (!mErrorInfo.isNull())
308 {
309 rc = mErrorInfo.queryInterfaceTo(err.asOutParam());
310 AssertComRC(rc);
311 }
312 rc = ::SetErrorInfo(0, err);
313
314#else // defined(VBOX_WITH_XPCOM)
315
316 nsCOMPtr <nsIExceptionService> es;
317 es = do_GetService(NS_EXCEPTIONSERVICE_CONTRACTID, &rc);
318 if (NS_SUCCEEDED(rc))
319 {
320 nsCOMPtr <nsIExceptionManager> em;
321 rc = es->GetCurrentExceptionManager(getter_AddRefs(em));
322 if (NS_SUCCEEDED(rc))
323 {
324 ComPtr<nsIException> ex;
325 if (!mErrorInfo.isNull())
326 {
327 rc = mErrorInfo.queryInterfaceTo(ex.asOutParam());
328 AssertComRC(rc);
329 }
330 rc = em->SetCurrentException(ex);
331 }
332 }
333
334#endif // defined(VBOX_WITH_XPCOM)
335
336 if (SUCCEEDED(rc))
337 {
338 mErrorInfo.setNull();
339 mForgot = true;
340 }
341
342 return rc;
343}
344
345} /* namespace com */
346
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