VirtualBox

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

Last change on this file since 94359 was 93115, checked in by vboxsync, 3 years ago

scm --update-copyright-year

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