VirtualBox

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

Last change on this file since 98262 was 98103, checked in by vboxsync, 23 months ago

Copyright year updates by scm.

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