/*static*/ HRESULT USBProxyService::setError(HRESULT aResultCode, const char *aText, ...) { va_list va; va_start(va, aText); HRESULT rc = VirtualBoxBase::setErrorInternal(aResultCode, COM_IIDOF(IHost), "USBProxyService", Utf8StrFmt(aText, va), false /* aWarning*/, true /* aLogIt*/); va_end(va); return rc; }
int NetIfRemoveHostOnlyNetworkInterface(VirtualBox *pVirtualBox, IN_GUID aId, IProgress **aProgress) { #if defined(RT_OS_LINUX) || defined(RT_OS_DARWIN) || defined(RT_OS_FREEBSD) /* create a progress object */ ComObjPtr<Progress> progress; progress.createObject(); ComPtr<IHost> host; int rc = VINF_SUCCESS; HRESULT hr = pVirtualBox->COMGETTER(Host)(host.asOutParam()); if (SUCCEEDED(hr)) { Bstr ifname; ComPtr<IHostNetworkInterface> iface; if (FAILED(host->FindHostNetworkInterfaceById(Guid(aId).toUtf16().raw(), iface.asOutParam()))) return VERR_INVALID_PARAMETER; iface->COMGETTER(Name)(ifname.asOutParam()); if (ifname.isEmpty()) return VERR_INTERNAL_ERROR; rc = progress->init(pVirtualBox, host, Bstr("Removing host network interface").raw(), FALSE /* aCancelable */); if (SUCCEEDED(rc)) { progress.queryInterfaceTo(aProgress); rc = NetIfAdpCtl(Utf8Str(ifname).c_str(), "remove", NULL, NULL); if (RT_FAILURE(rc)) progress->i_notifyComplete(E_FAIL, COM_IIDOF(IHostNetworkInterface), HostNetworkInterface::getStaticComponentName(), "Failed to execute '" VBOXNETADPCTL_NAME "' (exit status: %d)", rc); else progress->i_notifyComplete(S_OK); } } else { progress->i_notifyComplete(hr); rc = VERR_INTERNAL_ERROR; } return rc; #else NOREF(pVirtualBox); NOREF(aId); NOREF(aProgress); return VERR_NOT_IMPLEMENTED; #endif }
void GlueHandleComError(ComPtr<IUnknown> iface, const char *pcszContext, HRESULT rc, const char *pcszSourceFile, uint32_t ulLine) { /* If we have full error info, print something nice, and start with the * actual error message. */ com::ErrorInfo info(iface, COM_IIDOF(IUnknown)); glueHandleComErrorInternal(info, pcszContext, rc, pcszSourceFile, ulLine); }
int GuestFile::i_setFileStatus(FileStatus_T fileStatus, int fileRc) { LogFlowThisFuncEnter(); AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); LogFlowThisFunc(("oldStatus=%RU32, newStatus=%RU32, fileRc=%Rrc\n", mData.mStatus, fileStatus, fileRc)); #ifdef VBOX_STRICT if (fileStatus == FileStatus_Error) { AssertMsg(RT_FAILURE(fileRc), ("Guest rc must be an error (%Rrc)\n", fileRc)); } else AssertMsg(RT_SUCCESS(fileRc), ("Guest rc must not be an error (%Rrc)\n", fileRc)); #endif if (mData.mStatus != fileStatus) { mData.mStatus = fileStatus; mData.mLastError = fileRc; ComObjPtr<VirtualBoxErrorInfo> errorInfo; HRESULT hr = errorInfo.createObject(); ComAssertComRC(hr); if (RT_FAILURE(fileRc)) { hr = errorInfo->initEx(VBOX_E_IPRT_ERROR, fileRc, COM_IIDOF(IGuestFile), getComponentName(), i_guestErrorToString(fileRc)); ComAssertComRC(hr); } alock.release(); /* Release lock before firing off event. */ fireGuestFileStateChangedEvent(mEventSource, mSession, this, fileStatus, errorInfo); } return VINF_SUCCESS; }
HRESULT GuestSessionTask::setProgressErrorMsg(HRESULT hr, const Utf8Str &strMsg) { if (mProgress.isNull()) /* Progress is optional. */ return hr; /* Return original rc. */ BOOL fCanceled; BOOL fCompleted; if ( SUCCEEDED(mProgress->COMGETTER(Canceled(&fCanceled))) && !fCanceled && SUCCEEDED(mProgress->COMGETTER(Completed(&fCompleted))) && !fCompleted) { HRESULT hr2 = mProgress->notifyComplete(hr, COM_IIDOF(IGuestSession), GuestSession::getStaticComponentName(), strMsg.c_str()); if (FAILED(hr2)) return hr2; } return hr; /* Return original rc. */ }
/* static */ HRESULT GuestTask::setProgressErrorInfo(HRESULT hr, ComObjPtr<Progress> pProgress, const char *pszText, ...) { BOOL fCanceled; BOOL fCompleted; if ( SUCCEEDED(pProgress->COMGETTER(Canceled(&fCanceled))) && !fCanceled && SUCCEEDED(pProgress->COMGETTER(Completed(&fCompleted))) && !fCompleted) { va_list va; va_start(va, pszText); HRESULT hr2 = pProgress->notifyCompleteV(hr, COM_IIDOF(IGuest), Guest::getStaticComponentName(), pszText, va); va_end(va); if (hr2 == S_OK) /* If unable to retrieve error, return input error. */ hr2 = hr; return hr2; } return S_OK; }
int NetIfCreateHostOnlyNetworkInterface(VirtualBox *pVirtualBox, IHostNetworkInterface **aHostNetworkInterface, IProgress **aProgress, const char *pcszName) { #if defined(RT_OS_LINUX) || defined(RT_OS_DARWIN) || defined(RT_OS_FREEBSD) /* create a progress object */ ComObjPtr<Progress> progress; progress.createObject(); ComPtr<IHost> host; HRESULT hrc = pVirtualBox->COMGETTER(Host)(host.asOutParam()); if (SUCCEEDED(hrc)) { hrc = progress->init(pVirtualBox, host, Bstr("Creating host only network interface").raw(), FALSE /* aCancelable */); if (SUCCEEDED(hrc)) { progress.queryInterfaceTo(aProgress); char szAdpCtl[RTPATH_MAX]; int rc = RTPathExecDir(szAdpCtl, sizeof(szAdpCtl) - sizeof("/" VBOXNETADPCTL_NAME " add")); if (RT_FAILURE(rc)) { progress->i_notifyComplete(E_FAIL, COM_IIDOF(IHostNetworkInterface), HostNetworkInterface::getStaticComponentName(), "Failed to get program path, rc=%Rrc\n", rc); return rc; } strcat(szAdpCtl, "/" VBOXNETADPCTL_NAME " "); if (pcszName && strlen(pcszName) <= RTPATH_MAX - strlen(szAdpCtl) - sizeof(" add")) { strcat(szAdpCtl, pcszName); strcat(szAdpCtl, " add"); } else strcat(szAdpCtl, "add"); if (strlen(szAdpCtl) < RTPATH_MAX - sizeof(" 2>&1")) strcat(szAdpCtl, " 2>&1"); FILE *fp = popen(szAdpCtl, "r"); if (fp) { char szBuf[128]; /* We are not interested in long error messages. */ if (fgets(szBuf, sizeof(szBuf), fp)) { /* Remove trailing new line characters. */ char *pLast = szBuf + strlen(szBuf) - 1; if (pLast >= szBuf && *pLast == '\n') *pLast = 0; if (!strncmp(VBOXNETADPCTL_NAME ":", szBuf, sizeof(VBOXNETADPCTL_NAME))) { progress->i_notifyComplete(E_FAIL, COM_IIDOF(IHostNetworkInterface), HostNetworkInterface::getStaticComponentName(), "%s", szBuf); pclose(fp); return E_FAIL; } size_t cbNameLen = strlen(szBuf) + 1; PNETIFINFO pInfo = (PNETIFINFO)RTMemAllocZ(RT_OFFSETOF(NETIFINFO, szName[cbNameLen])); if (!pInfo) rc = VERR_NO_MEMORY; else { strcpy(pInfo->szShortName, szBuf); strcpy(pInfo->szName, szBuf); rc = NetIfGetConfigByName(pInfo); if (RT_FAILURE(rc)) { progress->i_notifyComplete(E_FAIL, COM_IIDOF(IHostNetworkInterface), HostNetworkInterface::getStaticComponentName(), "Failed to get config info for %s (as reported by '" VBOXNETADPCTL_NAME " add')\n", szBuf); } else { Bstr IfName(szBuf); /* create a new uninitialized host interface object */ ComObjPtr<HostNetworkInterface> iface; iface.createObject(); iface->init(IfName, HostNetworkInterfaceType_HostOnly, pInfo); iface->i_setVirtualBox(pVirtualBox); iface.queryInterfaceTo(aHostNetworkInterface); } RTMemFree(pInfo); } if ((rc = pclose(fp)) != 0) { progress->i_notifyComplete(E_FAIL, COM_IIDOF(IHostNetworkInterface), HostNetworkInterface::getStaticComponentName(), "Failed to execute '" VBOXNETADPCTL_NAME " add' (exit status: %d)", rc); rc = VERR_INTERNAL_ERROR; } } else { /* Failed to add an interface */ rc = VERR_PERMISSION_DENIED; progress->i_notifyComplete(E_FAIL, COM_IIDOF(IHostNetworkInterface), HostNetworkInterface::getStaticComponentName(), "Failed to execute '" VBOXNETADPCTL_NAME " add' (exit status: %d). Check permissions!", rc); pclose(fp); } } if (RT_SUCCESS(rc)) progress->i_notifyComplete(rc); else hrc = E_FAIL; } } return hrc; #else NOREF(pVirtualBox); NOREF(aHostNetworkInterface); NOREF(aProgress); NOREF(pcszName); return VERR_NOT_IMPLEMENTED; #endif }
/** * Called to copy over the progress information from @a pOtherProgress. * * @param pOtherProgress The source of the information. * @param fEarly Early copy. * * @note The caller owns the write lock and as cleared mptrOtherProgress * already (or we might recurse forever)! */ void ProgressProxy::copyProgressInfo(IProgress *pOtherProgress, bool fEarly) { HRESULT hrc; LogFlowThisFunc(("\n")); NOREF(fEarly); /* * No point in doing this if the progress object was canceled already. */ if (!mCanceled) { /* Detect if the other progress object was canceled. */ BOOL fCanceled; hrc = pOtherProgress->COMGETTER(Canceled)(&fCanceled); if (FAILED(hrc)) fCanceled = FALSE; if (fCanceled) { LogFlowThisFunc(("Canceled\n")); mCanceled = TRUE; if (m_pfnCancelCallback) m_pfnCancelCallback(m_pvCancelUserArg); } else { /* Has it completed? */ BOOL fCompleted; hrc = pOtherProgress->COMGETTER(Completed)(&fCompleted); if (FAILED(hrc)) fCompleted = TRUE; Assert(fCompleted || fEarly); if (fCompleted) { /* Check the result. */ LONG hrcResult; hrc = pOtherProgress->COMGETTER(ResultCode)(&hrcResult); if (FAILED(hrc)) hrcResult = hrc; if (SUCCEEDED((HRESULT)hrcResult)) LogFlowThisFunc(("Succeeded\n")); else { /* Get the error information. */ ComPtr<IVirtualBoxErrorInfo> ptrErrorInfo; hrc = pOtherProgress->COMGETTER(ErrorInfo)(ptrErrorInfo.asOutParam()); if (SUCCEEDED(hrc) && !ptrErrorInfo.isNull()) { Bstr bstrIID; hrc = ptrErrorInfo->COMGETTER(InterfaceID)(bstrIID.asOutParam()); AssertComRC(hrc); if (FAILED(hrc)) bstrIID.setNull(); Bstr bstrComponent; hrc = ptrErrorInfo->COMGETTER(Component)(bstrComponent.asOutParam()); AssertComRC(hrc); if (FAILED(hrc)) bstrComponent = "failed"; Bstr bstrText; hrc = ptrErrorInfo->COMGETTER(Text)(bstrText.asOutParam()); AssertComRC(hrc); if (FAILED(hrc)) bstrText = "<failed>"; Utf8Str strText(bstrText); LogFlowThisFunc(("Got ErrorInfo(%s); hrcResult=%Rhrc\n", strText.c_str(), hrcResult)); Progress::notifyComplete((HRESULT)hrcResult, Guid(bstrIID).ref(), Utf8Str(bstrComponent).c_str(), "%s", strText.c_str()); } else { LogFlowThisFunc(("ErrorInfo failed with hrc=%Rhrc; hrcResult=%Rhrc\n", hrc, hrcResult)); Progress::notifyComplete((HRESULT)hrcResult, COM_IIDOF(IProgress), "ProgressProxy", tr("No error info")); } } } else LogFlowThisFunc(("Not completed\n")); } } else LogFlowThisFunc(("Already canceled\n")); /* * Did cancelable state change (point of no return)? */ if (mCancelable && !mCompleted && !mCanceled) { BOOL fCancelable; hrc = pOtherProgress->COMGETTER(Cancelable)(&fCancelable); AssertComRC(hrc); if (SUCCEEDED(hrc) && !fCancelable) { LogFlowThisFunc(("point-of-no-return reached\n")); mCancelable = FALSE; } } }
int GuestDnDResponse::setProgress(unsigned uPercentage, uint32_t uStatus, int rcOp /* = VINF_SUCCESS */, const Utf8Str &strMsg /* = "" */) { LogFlowFunc(("uStatus=%RU32, uPercentage=%RU32, rcOp=%Rrc, strMsg=%s\n", uStatus, uPercentage, rcOp, strMsg.c_str())); int rc = VINF_SUCCESS; if (!m_progress.isNull()) { BOOL fCompleted; HRESULT hr = m_progress->COMGETTER(Completed)(&fCompleted); AssertComRC(hr); BOOL fCanceled; hr = m_progress->COMGETTER(Canceled)(&fCanceled); AssertComRC(hr); LogFlowFunc(("Current: fCompleted=%RTbool, fCanceled=%RTbool\n", fCompleted, fCanceled)); if (!fCompleted) { switch (uStatus) { case DragAndDropSvc::DND_PROGRESS_ERROR: { hr = m_progress->i_notifyComplete(VBOX_E_IPRT_ERROR, COM_IIDOF(IGuest), m_parent->getComponentName(), strMsg.c_str()); reset(); break; } case DragAndDropSvc::DND_PROGRESS_CANCELLED: { hr = m_progress->i_notifyComplete(S_OK); AssertComRC(hr); reset(); break; } case DragAndDropSvc::DND_PROGRESS_RUNNING: case DragAndDropSvc::DND_PROGRESS_COMPLETE: { if (!fCanceled) { hr = m_progress->SetCurrentOperationProgress(uPercentage); AssertComRC(hr); if ( uStatus == DragAndDropSvc::DND_PROGRESS_COMPLETE || uPercentage >= 100) { hr = m_progress->i_notifyComplete(S_OK); AssertComRC(hr); } } break; } default: break; } } hr = m_progress->COMGETTER(Completed)(&fCompleted); AssertComRC(hr); hr = m_progress->COMGETTER(Canceled)(&fCanceled); AssertComRC(hr); LogFlowFunc(("New: fCompleted=%RTbool, fCanceled=%RTbool\n", fCompleted, fCanceled)); } LogFlowFuncLeaveRC(rc); return rc; }
HRESULT Guest::taskCopyFileToGuest(GuestTask *aTask) { LogFlowFuncEnter(); AutoCaller autoCaller(this); if (FAILED(autoCaller.rc())) return autoCaller.rc(); /* * Do *not* take a write lock here since we don't (and won't) * touch any class-specific data (of IGuest) here - only the member functions * which get called here can do that. */ HRESULT rc = S_OK; try { ComObjPtr<Guest> pGuest = aTask->pGuest; /* Does our source file exist? */ if (!RTFileExists(aTask->strSource.c_str())) { rc = GuestTask::setProgressErrorInfo(VBOX_E_IPRT_ERROR, aTask->pProgress, Guest::tr("Source file \"%s\" does not exist, or is not a file"), aTask->strSource.c_str()); } else { RTFILE fileSource; int vrc = RTFileOpen(&fileSource, aTask->strSource.c_str(), RTFILE_O_OPEN | RTFILE_O_READ | RTFILE_O_DENY_WRITE); if (RT_FAILURE(vrc)) { rc = GuestTask::setProgressErrorInfo(VBOX_E_IPRT_ERROR, aTask->pProgress, Guest::tr("Could not open source file \"%s\" for reading (%Rrc)"), aTask->strSource.c_str(), vrc); } else { uint64_t cbSize; vrc = RTFileGetSize(fileSource, &cbSize); if (RT_FAILURE(vrc)) { rc = GuestTask::setProgressErrorInfo(VBOX_E_IPRT_ERROR, aTask->pProgress, Guest::tr("Could not query file size of \"%s\" (%Rrc)"), aTask->strSource.c_str(), vrc); } else { com::SafeArray<IN_BSTR> args; com::SafeArray<IN_BSTR> env; /* * Prepare tool command line. */ char szOutput[RTPATH_MAX]; if (RTStrPrintf(szOutput, sizeof(szOutput), "--output=%s", aTask->strDest.c_str()) <= sizeof(szOutput) - 1) { /* * Normalize path slashes, based on the detected guest. */ Utf8Str osType = mData.mOSTypeId; if ( osType.contains("Microsoft", Utf8Str::CaseInsensitive) || osType.contains("Windows", Utf8Str::CaseInsensitive)) { /* We have a Windows guest. */ RTPathChangeToDosSlashes(szOutput, true /* Force conversion. */); } else /* ... or something which isn't from Redmond ... */ { RTPathChangeToUnixSlashes(szOutput, true /* Force conversion. */); } args.push_back(Bstr(szOutput).raw()); /* We want to write a file ... */ } else { rc = GuestTask::setProgressErrorInfo(VBOX_E_IPRT_ERROR, aTask->pProgress, Guest::tr("Error preparing command line")); } ComPtr<IProgress> execProgress; ULONG uPID; if (SUCCEEDED(rc)) { LogRel(("Copying file \"%s\" to guest \"%s\" (%u bytes) ...\n", aTask->strSource.c_str(), aTask->strDest.c_str(), cbSize)); /* * Okay, since we gathered all stuff we need until now to start the * actual copying, start the guest part now. */ rc = pGuest->executeAndWaitForTool(Bstr(VBOXSERVICE_TOOL_CAT).raw(), Bstr("Copying file to guest").raw(), ComSafeArrayAsInParam(args), ComSafeArrayAsInParam(env), Bstr(aTask->strUserName).raw(), Bstr(aTask->strPassword).raw(), ExecuteProcessFlag_WaitForProcessStartOnly, NULL, NULL, execProgress.asOutParam(), &uPID); if (FAILED(rc)) rc = GuestTask::setProgressErrorInfo(rc, aTask->pProgress, pGuest); } if (SUCCEEDED(rc)) { BOOL fCompleted = FALSE; BOOL fCanceled = FALSE; uint64_t cbTransferedTotal = 0; SafeArray<BYTE> aInputData(_64K); while ( SUCCEEDED(execProgress->COMGETTER(Completed(&fCompleted))) && !fCompleted) { size_t cbToRead = cbSize; size_t cbRead = 0; if (cbSize) /* If we have nothing to read, take a shortcut. */ { /** @todo Not very efficient, but works for now. */ vrc = RTFileSeek(fileSource, cbTransferedTotal, RTFILE_SEEK_BEGIN, NULL /* poffActual */); if (RT_SUCCESS(vrc)) { vrc = RTFileRead(fileSource, (uint8_t*)aInputData.raw(), RT_MIN(cbToRead, _64K), &cbRead); /* * Some other error occured? There might be a chance that RTFileRead * could not resolve/map the native error code to an IPRT code, so just * print a generic error. */ if (RT_FAILURE(vrc)) { rc = GuestTask::setProgressErrorInfo(VBOX_E_IPRT_ERROR, aTask->pProgress, Guest::tr("Could not read from file \"%s\" (%Rrc)"), aTask->strSource.c_str(), vrc); break; } } else { rc = GuestTask::setProgressErrorInfo(VBOX_E_IPRT_ERROR, aTask->pProgress, Guest::tr("Seeking file \"%s\" failed; offset = %RU64 (%Rrc)"), aTask->strSource.c_str(), cbTransferedTotal, vrc); break; } } /* Resize buffer to reflect amount we just have read. * Size 0 is allowed! */ aInputData.resize(cbRead); ULONG uFlags = ProcessInputFlag_None; /* Did we reach the end of the content we want to transfer (last chunk)? */ if ( (cbRead < _64K) /* Did we reach the last block which is exactly _64K? */ || (cbToRead - cbRead == 0) /* ... or does the user want to cancel? */ || ( SUCCEEDED(aTask->pProgress->COMGETTER(Canceled(&fCanceled))) && fCanceled) ) { uFlags |= ProcessInputFlag_EndOfFile; } ULONG uBytesWritten = 0; rc = pGuest->SetProcessInput(uPID, uFlags, 0 /* Infinite timeout */, ComSafeArrayAsInParam(aInputData), &uBytesWritten); if (FAILED(rc)) { rc = GuestTask::setProgressErrorInfo(rc, aTask->pProgress, pGuest); break; } Assert(cbRead <= cbToRead); Assert(cbToRead >= cbRead); cbToRead -= cbRead; cbTransferedTotal += uBytesWritten; Assert(cbTransferedTotal <= cbSize); aTask->pProgress->SetCurrentOperationProgress(cbTransferedTotal / (cbSize / 100.0)); /* End of file reached? */ if (cbToRead == 0) break; /* Did the user cancel the operation above? */ if (fCanceled) break; /* Progress canceled by Main API? */ if ( SUCCEEDED(execProgress->COMGETTER(Canceled(&fCanceled))) && fCanceled) { rc = GuestTask::setProgressErrorInfo(VBOX_E_IPRT_ERROR, aTask->pProgress, Guest::tr("Copy operation of file \"%s\" was canceled on guest side"), aTask->strSource.c_str()); break; } } if (SUCCEEDED(rc)) { /* * If we got here this means the started process either was completed, * canceled or we simply got all stuff transferred. */ ExecuteProcessStatus_T retStatus; ULONG uRetExitCode; rc = executeWaitForExit(uPID, execProgress, 0 /* No timeout */, &retStatus, &uRetExitCode); if (FAILED(rc)) { rc = GuestTask::setProgressErrorInfo(rc, aTask->pProgress, pGuest); } else { if ( uRetExitCode != 0 || retStatus != ExecuteProcessStatus_TerminatedNormally) { rc = GuestTask::setProgressErrorInfo(VBOX_E_IPRT_ERROR, aTask->pProgress, Guest::tr("Guest process reported error %u (status: %u) while copying file \"%s\" to \"%s\""), uRetExitCode, retStatus, aTask->strSource.c_str(), aTask->strDest.c_str()); } } } if (SUCCEEDED(rc)) { if (fCanceled) { /* * In order to make the progress object to behave nicely, we also have to * notify the object with a complete event when it's canceled. */ aTask->pProgress->notifyComplete(VBOX_E_IPRT_ERROR, COM_IIDOF(IGuest), Guest::getStaticComponentName(), Guest::tr("Copying file \"%s\" canceled"), aTask->strSource.c_str()); } else { /* * Even if we succeeded until here make sure to check whether we really transfered * everything. */ if ( cbSize > 0 && cbTransferedTotal == 0) { /* If nothing was transfered but the file size was > 0 then "vbox_cat" wasn't able to write * to the destination -> access denied. */ rc = GuestTask::setProgressErrorInfo(VBOX_E_IPRT_ERROR, aTask->pProgress, Guest::tr("Access denied when copying file \"%s\" to \"%s\""), aTask->strSource.c_str(), aTask->strDest.c_str()); } else if (cbTransferedTotal < cbSize) { /* If we did not copy all let the user know. */ rc = GuestTask::setProgressErrorInfo(VBOX_E_IPRT_ERROR, aTask->pProgress, Guest::tr("Copying file \"%s\" failed (%u/%u bytes transfered)"), aTask->strSource.c_str(), cbTransferedTotal, cbSize); } else /* Yay, all went fine! */ aTask->pProgress->notifyComplete(S_OK); } } } } RTFileClose(fileSource); } } } catch (HRESULT aRC) { rc = aRC; } /* Clean up */ aTask->rc = rc; LogFlowFunc(("rc=%Rhrc\n", rc)); LogFlowFuncLeave(); return VINF_SUCCESS; }
/* static */ HRESULT GuestTask::setProgressErrorInfo(HRESULT hr, ComObjPtr<Progress> pProgress, ComObjPtr<Guest> pGuest) { return setProgressErrorInfo(hr, pProgress, Utf8Str(com::ErrorInfo((IGuest*)pGuest, COM_IIDOF(IGuest)).getText()).c_str()); }