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