Esempio n. 1
0
/* static */
Utf8Str GuestFile::i_guestErrorToString(int guestRc)
{
    Utf8Str strError;

    /** @todo pData->u32Flags: int vs. uint32 -- IPRT errors are *negative* !!! */
    switch (guestRc)
    {
        case VERR_ALREADY_EXISTS:
            strError += Utf8StrFmt(tr("File already exists"));
            break;

        case VERR_FILE_NOT_FOUND:
            strError += Utf8StrFmt(tr("File not found"));
            break;

        case VERR_NET_HOST_NOT_FOUND:
            strError += Utf8StrFmt(tr("Host name not found"));
            break;

        case VERR_SHARING_VIOLATION:
            strError += Utf8StrFmt(tr("Sharing violation"));
            break;

        default:
            strError += Utf8StrFmt("%Rrc", guestRc);
            break;
    }

    return strError;
}
HRESULT HostNetworkInterface::saveAdapterConfigIPv4(ULONG addr, ULONG mask)
{
    HRESULT hrc = saveAdapterConfigParameter("IPAddress", Utf8StrFmt("%RTnaipv4", addr));
    if (hrc == S_OK)
        hrc = saveAdapterConfigParameter("IPNetMask", Utf8StrFmt("%RTnaipv4", mask));
    return hrc;
}
HRESULT HostNetworkInterface::updateConfig()
{
    NETIFINFO info;
    int rc = NetIfGetConfig(this, &info);
    if (RT_SUCCESS(rc))
    {
        int iPrefixIPv6;

        m.realIPAddress = m.IPAddress = info.IPAddress.u;
        m.realNetworkMask = m.networkMask = info.IPNetMask.u;
        m.dhcpEnabled = info.fDhcpEnabled;
        if (info.IPv6Address.s.Lo || info.IPv6Address.s.Hi)
            m.realIPV6Address = m.IPV6Address = Utf8StrFmt("%RTnaipv6", &info.IPv6Address);
        else
            m.realIPV6Address = m.IPV6Address = Utf8Str::Empty;
        RTNetMaskToPrefixIPv6(&info.IPv6NetMask, &iPrefixIPv6);
        m.realIPV6PrefixLength = m.IPV6NetworkMaskPrefixLength = iPrefixIPv6;
        m.hardwareAddress = Utf8StrFmt("%RTmac", &info.MACAddress);
        AssertCompile((unsigned)NETIF_T_UNKNOWN == (unsigned)HostNetworkInterfaceMediumType_Unknown);
        m.mediumType = (HostNetworkInterfaceMediumType_T)info.enmMediumType;
        AssertCompile((unsigned)NETIF_S_UNKNOWN == (unsigned)HostNetworkInterfaceStatus_Unknown);
        m.status = (HostNetworkInterfaceStatus_T)info.enmStatus;
        m.speedMbits = info.uSpeedMbits;
        m.wireless = info.fWireless;
        return S_OK;
    }
    return rc == VERR_NOT_IMPLEMENTED ? E_NOTIMPL : E_FAIL;
}
/**
 * Initializes the host object.
 *
 * @returns COM result indicator
 * @param   aInterfaceName name of the network interface
 * @param   aGuid GUID of the host network interface
 */
HRESULT HostNetworkInterface::init(Utf8Str aInterfaceName, HostNetworkInterfaceType_T ifType, PNETIFINFO pIf)
{
//    LogFlowThisFunc(("aInterfaceName={%s}, aGuid={%s}\n",
//                      aInterfaceName.c_str(), aGuid.toString().c_str()));

//    ComAssertRet(aInterfaceName, E_INVALIDARG);
//    ComAssertRet(aGuid.isValid(), E_INVALIDARG);
    ComAssertRet(pIf, E_INVALIDARG);

    /* Enclose the state transition NotReady->InInit->Ready */
    AutoInitSpan autoInitSpan(this);
    AssertReturn(autoInitSpan.isOk(), E_FAIL);

    unconst(mInterfaceName) = aInterfaceName;
    unconst(mGuid) = pIf->Uuid;
    if (pIf->szShortName[0])
    {
        unconst(mNetworkName) = i_composeNetworkName(pIf->szShortName);
        unconst(mShortName)   = pIf->szShortName;
    }
    else
    {
        unconst(mNetworkName) = i_composeNetworkName(aInterfaceName);
        unconst(mShortName)   = aInterfaceName;
    }
    mIfType = ifType;

    int iPrefixIPv6;

    m.realIPAddress = m.IPAddress = pIf->IPAddress.u;
    m.realNetworkMask = m.networkMask = pIf->IPNetMask.u;
    if (pIf->IPv6Address.s.Lo || pIf->IPv6Address.s.Hi)
        m.realIPV6Address = m.IPV6Address = Utf8StrFmt("%RTnaipv6", &pIf->IPv6Address);
    else
        m.realIPV6Address = m.IPV6Address = Utf8Str::Empty;
    RTNetMaskToPrefixIPv6(&pIf->IPv6NetMask, &iPrefixIPv6);
    m.realIPV6PrefixLength = m.IPV6NetworkMaskPrefixLength = iPrefixIPv6;
    m.dhcpEnabled = pIf->fDhcpEnabled;
    m.hardwareAddress = Utf8StrFmt("%RTmac", &pIf->MACAddress);
    AssertCompile((unsigned)NETIF_T_UNKNOWN == (unsigned)HostNetworkInterfaceMediumType_Unknown);
    m.mediumType = (HostNetworkInterfaceMediumType_T)pIf->enmMediumType;
    AssertCompile((unsigned)NETIF_S_UNKNOWN == (unsigned)HostNetworkInterfaceStatus_Unknown);
    m.status = (HostNetworkInterfaceStatus_T)pIf->enmStatus;
    m.speedMbits = pIf->uSpeedMbits;
    m.wireless = pIf->fWireless;

    /* Confirm a successful initialization */
    autoInitSpan.setSucceeded();

    return S_OK;
}
Esempio n. 5
0
HRESULT DHCPServer::encodeOption(com::Utf8Str &aEncoded,
                                 uint32_t aOptCode,
                                 const settings::DhcpOptValue &aOptValue)
{
    switch (aOptValue.encoding)
    {
        case DhcpOptEncoding_Legacy:
        {
            /*
             * This is original encoding which assumed that for each
             * option we know its format and so we know how option
             * "value" text is to be interpreted.
             *
             *   "2:10800"           # integer 32
             *   "6:1.2.3.4 8.8.8.8" # array of ip-address
             */
            aEncoded = Utf8StrFmt("%d:%s", aOptCode, aOptValue.text.c_str());
            break;
        }

        case DhcpOptEncoding_Hex:
        {
            /*
             * This is a bypass for any option - preformatted value as
             * hex string with no semantic involved in formatting the
             * value for the DHCP reply.
             *
             *   234=68:65:6c:6c:6f:2c:20:77:6f:72:6c:64
             */
            aEncoded = Utf8StrFmt("%d=%s", aOptCode, aOptValue.text.c_str());
            break;
        }

        default:
        {
            /*
             * Try to be forward compatible.
             *
             *   "254@42=i hope you know what this means"
             */
            aEncoded = Utf8StrFmt("%d@%d=%s", aOptCode, (int)aOptValue.encoding,
                                  aOptValue.text.c_str());
            break;
        }
    }

    return S_OK;
}
Esempio n. 6
0
void GluePrintRCMessage(HRESULT rc)
{
    Utf8Str str = Utf8StrFmt("Code %Rhra (extended info not available)\n", rc);
    // print and log
    RTMsgError("%s", str.c_str());
    Log(("ERROR: %s", str.c_str()));
}
HRESULT HostNetworkInterface::saveAdapterConfigIPv6(const Utf8Str& addr, ULONG prefix)
{
    HRESULT hrc = saveAdapterConfigParameter("IPV6Address", addr);
    if (hrc == S_OK)
        hrc = saveAdapterConfigParameter("IPV6PrefixLen", Utf8StrFmt("%u", prefix));
    return hrc;
}
STDMETHODIMP SharedFolder::COMGETTER(Accessible) (BOOL *aAccessible)
{
    CheckComArgOutPointerValid(aAccessible);

    AutoCaller autoCaller(this);
    if (FAILED(autoCaller.rc())) return autoCaller.rc();

    /* mName and mHostPath are constant during life time, no need to lock */

    /* check whether the host path exists */
    Utf8Str hostPath = m->strHostPath;
    char hostPathFull[RTPATH_MAX];
    int vrc = RTPathExists(hostPath.c_str()) ? RTPathReal(hostPath.c_str(),
                                                          hostPathFull,
                                                          sizeof(hostPathFull))
                                      : VERR_PATH_NOT_FOUND;
    if (RT_SUCCESS(vrc))
    {
        *aAccessible = TRUE;
        return S_OK;
    }

    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);

    m->strLastAccessError = Utf8StrFmt(tr("'%s' is not accessible (%Rrc)"),
                                       m->strHostPath.c_str(),
                                       vrc);

    LogWarningThisFunc(("m.lastAccessError=\"%s\"\n", m->strLastAccessError.c_str()));

    *aAccessible = FALSE;
    return S_OK;
}
Esempio n. 9
0
void GluePrintErrorInfo(const com::ErrorInfo &info)
{
    bool haveResultCode = false;
#if defined (RT_OS_WIN)
    haveResultCode = info.isFullAvailable();
    bool haveComponent = true;
    bool haveInterfaceID = true;
#else /* defined (RT_OS_WIN) */
    haveResultCode = true;
    bool haveComponent = info.isFullAvailable();
    bool haveInterfaceID = info.isFullAvailable();
#endif

    Utf8Str str;
    RTCList<Utf8Str> comp;

    Bstr bstrDetailsText = info.getText();
    if (!bstrDetailsText.isEmpty())
        str = Utf8StrFmt("%ls\n",
                         bstrDetailsText.raw());
    if (haveResultCode)
        comp.append(Utf8StrFmt("code %Rhrc (0x%RX32)",
                               info.getResultCode(),
                               info.getResultCode()));
    if (haveComponent)
        comp.append(Utf8StrFmt("component %ls",
                               info.getComponent().raw()));
    if (haveInterfaceID)
        comp.append(Utf8StrFmt("interface %ls",
                               info.getInterfaceName().raw()));
    if (!info.getCalleeName().isEmpty())
        comp.append(Utf8StrFmt("callee %ls",
                               info.getCalleeName().raw()));

    if (comp.size() > 0)
    {
        str += "Details: ";
        for (size_t i = 0; i < comp.size() - 1; ++i)
            str += comp.at(i) + ", ";
        str += comp.last();
        str += "\n";
    }

    // print and log
    RTMsgError("%s", str.c_str());
    Log(("ERROR: %s", str.c_str()));
}
Esempio n. 10
0
STDMETHODIMP
NATEngine::AddRedirect(IN_BSTR aName, NATProtocol_T aProto, IN_BSTR aBindIp, USHORT aHostPort, IN_BSTR aGuestIP, USHORT aGuestPort)
{

    AutoCaller autoCaller(this);
    if (FAILED(autoCaller.rc())) return autoCaller.rc();

    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
    Utf8Str name = aName;
    settings::NATRule r;
    const char *proto;
    switch (aProto)
    {
        case NATProtocol_TCP:
            proto = "tcp";
            break;
        case NATProtocol_UDP:
            proto = "udp";
            break;
        default:
            return E_INVALIDARG;
    }
    if (name.isEmpty())
        name = Utf8StrFmt("%s_%d_%d", proto, aHostPort, aGuestPort);

    NATRuleMap::iterator it;
    for (it = mNATRules.begin(); it != mNATRules.end(); ++it)
    {
        r = it->second;
        if (it->first == name)
            return setError(E_INVALIDARG,
                            tr("A NAT rule of this name already exists"));
        if (   r.strHostIP == Utf8Str(aBindIp)
            && r.u16HostPort == aHostPort
            && r.proto == aProto)
            return setError(E_INVALIDARG,
                            tr("A NAT rule for this host port and this host IP already exists"));
    }

    r.strName = name.c_str();
    r.proto = aProto;
    r.strHostIP = aBindIp;
    r.u16HostPort = aHostPort;
    r.strGuestIP = aGuestIP;
    r.u16GuestPort = aGuestPort;
    mNATRules.insert(std::make_pair(name, r));
    mParent->setModified(Machine::IsModified_NetworkAdapters);
    m_fModified = true;

    ULONG ulSlot;
    mAdapter->COMGETTER(Slot)(&ulSlot);

    alock.release();
    mParent->onNATRedirectRuleChange(ulSlot, FALSE, Bstr(name).raw(), aProto, Bstr(r.strHostIP).raw(), r.u16HostPort, Bstr(r.strGuestIP).raw(), r.u16GuestPort);
    return S_OK;
}
void MediumAttachment::i_updateLogName()
{
    const char *pszName = m->bd->strControllerName.c_str();
    const char *pszEndNick = strpbrk(pszName, " \t:-");
    mLogName = Utf8StrFmt("MA%p[%.*s:%u:%u:%s%s]",
                          this,
                          pszEndNick ? pszEndNick - pszName : 4, pszName,
                          m->bd->mData.lPort, m->bd->mData.lDevice, Global::stringifyDeviceType(m->bd->mData.deviceType),
                          m->bd->fImplicit ? ":I" : "");
}
int GuestDirectory::init(GuestSession *aSession,
                         const Utf8Str &strPath, const Utf8Str &strFilter /*= ""*/, uint32_t uFlags /*= 0*/)
{
    LogFlowThisFunc(("strPath=%s, strFilter=%s, uFlags=%x\n",
                     strPath.c_str(), strFilter.c_str(), uFlags));

    /* Enclose the state transition NotReady->InInit->Ready. */
    AutoInitSpan autoInitSpan(this);
    AssertReturn(autoInitSpan.isOk(), E_FAIL);

    mData.mSession = aSession;
    mData.mName    = strPath;
    mData.mFilter  = strFilter;
    mData.mFlags   = uFlags;

    /* Start the directory process on the guest. */
    GuestProcessStartupInfo procInfo;
    procInfo.mName      = Utf8StrFmt(tr("Reading directory \"%s\"", strPath.c_str()));
    procInfo.mCommand   = Utf8Str(VBOXSERVICE_TOOL_LS);
    procInfo.mTimeoutMS = 0; /* No timeout. */
    procInfo.mFlags     = ProcessCreateFlag_Hidden | ProcessCreateFlag_WaitForStdOut;

    procInfo.mArguments.push_back(Utf8Str("--machinereadable"));
    /* We want the long output format which contains all the object details. */
    procInfo.mArguments.push_back(Utf8Str("-l"));
#if 0 /* Flags are not supported yet. */
    if (uFlags & DirectoryOpenFlag_NoSymlinks)
        procInfo.mArguments.push_back(Utf8Str("--nosymlinks")); /** @todo What does GNU here? */
#endif
    /** @todo Recursion support? */
    procInfo.mArguments.push_back(strPath); /* The directory we want to open. */

    /*
     * Start the process asynchronously and keep it around so that we can use
     * it later in subsequent read() calls.
     */
    ComObjPtr<GuestProcess> pProcess;
    int rc = mData.mSession->processCreateExInteral(procInfo, pProcess);
    if (RT_SUCCESS(rc))
        rc = pProcess->startProcessAsync();

    LogFlowThisFunc(("rc=%Rrc\n", rc));

    if (RT_SUCCESS(rc))
    {
        mData.mProcess = pProcess;

        /* Confirm a successful initialization when it's the case. */
        autoInitSpan.setSucceeded();
        return rc;
    }

    autoInitSpan.setFailed();
    return rc;
}
Esempio n. 13
0
int VFSExplorer::TaskVFSExplorer::startThread()
{
    int vrc = RTThreadCreate(NULL, VFSExplorer::TaskVFSExplorer::taskThread, this,
                             0, RTTHREADTYPE_MAIN_HEAVY_WORKER, 0,
                             "Explorer::Task");

    if (RT_FAILURE(vrc))
        return VFSExplorer::setErrorStatic(E_FAIL, Utf8StrFmt("Could not create taskThreadVFS (%Rrc)\n", vrc));

    return vrc;
}
Esempio n. 14
0
HRESULT DHCPServer::getVmConfigs(std::vector<com::Utf8Str> &aValues)
{
    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
    aValues.resize(m->VmSlot2Options.size());
    settings::VmSlot2OptionsMap::const_iterator it;
    size_t i = 0;
    for (it = m->VmSlot2Options.begin(); it != m->VmSlot2Options.end(); ++it, ++i)
    {
        aValues[i] = Utf8StrFmt("[%s]:%d", it->first.VmName.c_str(), it->first.Slot);
    }

    return S_OK;
}
Esempio n. 15
0
/*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;
}
Esempio n. 16
0
void GluePrintErrorContext(const char *pcszContext, const char *pcszSourceFile, uint32_t ulLine)
{
    // pcszSourceFile comes from __FILE__ macro, which always contains the full path,
    // which we don't want to see printed:
    Utf8Str strFilename(RTPathFilename(pcszSourceFile));
    Utf8Str str = Utf8StrFmt("Context: \"%s\" at line %d of file %s\n",
                             pcszContext,
                             ulLine,
                             strFilename.c_str());
    // print and log
    RTMsgError("%s", str.c_str());
    Log(("%s", str.c_str()));
}
bool HostNetworkInterface::isInConfigFile(void)
{
    /* We care about host-only adapters only */
    if (mIfType != HostNetworkInterfaceType_HostOnly)
        return true;

    Assert(mVirtualBox != NULL);
    if (mVirtualBox == NULL)
        return false; /* Trigger config update, which will fail with proper return code */
    Bstr tmpName;
    mVirtualBox->GetExtraData(Bstr(Utf8StrFmt("HostOnly/{%RTuuid}/Name", mGuid)).raw(), tmpName.asOutParam());
    return (tmpName.isNotEmpty() && tmpName == mInterfaceName);

}
/**
 *  Converts a USBFilter field into a string.
 *
 *  (This function is also used by HostUSBDeviceFilter.)
 *
 *  @param  aFilter     The filter.
 *  @param  aIdx        The field index.
 *  @param  aStr        The output string.
 */
static void i_usbFilterFieldToString(PCUSBFILTER aFilter, USBFILTERIDX aIdx, Utf8Str &rstrOut)
{
    const USBFILTERMATCH matchingMethod = USBFilterGetMatchingMethod(aFilter, aIdx);
    Assert(matchingMethod != USBFILTERMATCH_INVALID);

    if (USBFilterIsMethodNumeric(matchingMethod))
    {
        int value = USBFilterGetNum(aFilter, aIdx);
        Assert(value >= 0 && value <= 0xffff);

        rstrOut = Utf8StrFmt("%04RX16", (uint16_t)value);
    }
    else if (USBFilterIsMethodString(matchingMethod))
        rstrOut = USBFilterGetString(aFilter, aIdx);
    else
        rstrOut.setNull();
}
Esempio n. 19
0
HRESULT SystemProperties::i_setDefaultAdditionsISO(const com::Utf8Str &aPath)
{
    com::Utf8Str path(aPath);
    if (path.isEmpty())
    {
        char strTemp[RTPATH_MAX];
        int vrc = RTPathAppPrivateNoArch(strTemp, sizeof(strTemp));
        AssertRC(vrc);
        Utf8Str strSrc1 = Utf8Str(strTemp).append("/VBoxGuestAdditions.iso");

        vrc = RTPathExecDir(strTemp, sizeof(strTemp));
        AssertRC(vrc);
        Utf8Str strSrc2 = Utf8Str(strTemp).append("/additions/VBoxGuestAdditions.iso");

        vrc = RTPathUserHome(strTemp, sizeof(strTemp));
        AssertRC(vrc);
        Utf8Str strSrc3 = Utf8StrFmt("%s/VBoxGuestAdditions_%s.iso", strTemp, VirtualBox::i_getVersionNormalized().c_str());

        /* Check the standard image locations */
        if (RTFileExists(strSrc1.c_str()))
            path = strSrc1;
        else if (RTFileExists(strSrc2.c_str()))
            path = strSrc2;
        else if (RTFileExists(strSrc3.c_str()))
            path = strSrc3;
        else
            return setError(E_FAIL,
                            tr("Cannot determine default Guest Additions ISO location. Most likely they are not available"));
    }

    if (!RTPathStartsWithRoot(path.c_str()))
        return setError(E_INVALIDARG,
                        tr("Given default machine Guest Additions ISO file '%s' is not fully qualified"),
                        path.c_str());

    if (!RTFileExists(path.c_str()))
        return setError(E_INVALIDARG,
                        tr("Given default machine Guest Additions ISO file '%s' does not exist"),
                        path.c_str());

    m->strDefaultAdditionsISO = path;

    return S_OK;
}
Esempio n. 20
0
/**
 * Sets the Guest Additions version information details.
 *
 * Gets called by vmmdevUpdateGuestInfo2 and vmmdevUpdateGuestInfo (to clear the
 * state).
 *
 * @param   a_uFullVersion          VBoxGuestInfo2::additionsMajor,
 *                                  VBoxGuestInfo2::additionsMinor and
 *                                  VBoxGuestInfo2::additionsBuild combined into
 *                                  one value by VBOX_FULL_VERSION_MAKE.
 *
 *                                  When this is 0, it's vmmdevUpdateGuestInfo
 *                                  calling to reset the state.
 *
 * @param   a_pszName               Build type tag and/or publisher tag, empty
 *                                  string if neiter of those are present.
 * @param   a_uRevision             See VBoxGuestInfo2::additionsRevision.
 * @param   a_fFeatures             See VBoxGuestInfo2::additionsFeatures.
 */
void Guest::i_setAdditionsInfo2(uint32_t a_uFullVersion, const char *a_pszName, uint32_t a_uRevision, uint32_t a_fFeatures)
{
    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);

    if (a_uFullVersion)
    {
        mData.mAdditionsVersionNew  = Utf8StrFmt(*a_pszName ? "%u.%u.%u_%s" : "%u.%u.%u",
                                                 VBOX_FULL_VERSION_GET_MAJOR(a_uFullVersion),
                                                 VBOX_FULL_VERSION_GET_MINOR(a_uFullVersion),
                                                 VBOX_FULL_VERSION_GET_BUILD(a_uFullVersion),
                                                 a_pszName);
        mData.mAdditionsVersionFull = a_uFullVersion;
        mData.mAdditionsRevision    = a_uRevision;
        mData.mAdditionsFeatures    = a_fFeatures;
    }
    else
    {
        Assert(!a_fFeatures && !a_uRevision && !*a_pszName);
        mData.mAdditionsVersionNew.setNull();
        mData.mAdditionsVersionFull = 0;
        mData.mAdditionsRevision    = 0;
        mData.mAdditionsFeatures    = 0;
    }
}
Esempio n. 21
0
int SessionTaskUpdateAdditions::copyFileToGuest(GuestSession *pSession, PRTISOFSFILE pISO,
                                                Utf8Str const &strFileSource, const Utf8Str &strFileDest,
                                                bool fOptional, uint32_t *pcbSize)
{
    AssertPtrReturn(pSession, VERR_INVALID_POINTER);
    AssertPtrReturn(pISO, VERR_INVALID_POINTER);
    /* pcbSize is optional. */

    uint32_t cbOffset;
    size_t cbSize;

    int rc = RTIsoFsGetFileInfo(pISO, strFileSource.c_str(), &cbOffset, &cbSize);
    if (RT_FAILURE(rc))
    {
        if (fOptional)
            return VINF_SUCCESS;

        return rc;
    }

    Assert(cbOffset);
    Assert(cbSize);
    rc = RTFileSeek(pISO->file, cbOffset, RTFILE_SEEK_BEGIN, NULL);

    /* Copy over the Guest Additions file to the guest. */
    if (RT_SUCCESS(rc))
    {
        LogRel(("Copying Guest Additions installer file \"%s\" to \"%s\" on guest ...\n",
                strFileSource.c_str(), strFileDest.c_str()));

        if (RT_SUCCESS(rc))
        {
            SessionTaskCopyTo *pTask = new SessionTaskCopyTo(pSession /* GuestSession */,
                                                             &pISO->file, cbOffset, cbSize,
                                                             strFileDest, CopyFileFlag_None);
            AssertPtrReturn(pTask, VERR_NO_MEMORY);

            ComObjPtr<Progress> pProgressCopyTo;
            rc = pSession->startTaskAsync(Utf8StrFmt(GuestSession::tr("Copying Guest Additions installer file \"%s\" to \"%s\" on guest"),
                                                     mSource.c_str(), strFileDest.c_str()),
                                          pTask, pProgressCopyTo);
            if (RT_SUCCESS(rc))
            {
                BOOL fCanceled = FALSE;
                HRESULT hr = pProgressCopyTo->WaitForCompletion(-1);
                if (   SUCCEEDED(pProgressCopyTo->COMGETTER(Canceled)(&fCanceled))
                    && fCanceled)
                {
                    rc = VERR_GENERAL_FAILURE; /* Fudge. */
                }
                else if (FAILED(hr))
                {
                    Assert(FAILED(hr));
                    rc = VERR_GENERAL_FAILURE; /* Fudge. */
                }
            }
        }
    }

    /** @todo Note: Since there is no file locking involved at the moment, there can be modifications
     *              between finished copying, the verification and the actual execution. */

    /* Determine where the installer image ended up and if it has the correct size. */
    if (RT_SUCCESS(rc))
    {
        LogRel(("Verifying Guest Additions installer file \"%s\" ...\n", strFileDest.c_str()));

        GuestFsObjData objData;
        int64_t cbSizeOnGuest;
        rc = pSession->fileQuerySizeInternal(strFileDest, &cbSizeOnGuest);
#ifdef VBOX_SERVICE_ENVARG_BUG
        if (RT_FAILURE(rc))
        {
            /* Ugly hack: Because older Guest Additions have problems with environment variable
                          expansion in parameters we have to check an alternative location on Windows.
                          So check for "%TEMP%\" being "C:\\Windows\\system32\\EMP" actually. */
            if (strFileDest.startsWith("%TEMP%\\", RTCString::CaseSensitive))
            {
                Utf8Str strFileDestBug = "C:\\Windows\\system32\\EMP" + strFileDest.substr(sizeof("%TEMP%\\") - sizeof(char));
                rc = pSession->fileQuerySizeInternal(strFileDestBug, &cbSizeOnGuest);
            }
        }
#endif
        if (   RT_SUCCESS(rc)
            && cbSize == (uint64_t)cbSizeOnGuest)
        {
            LogRel(("Guest Additions installer file \"%s\" successfully verified\n",
                    strFileDest.c_str()));
        }
        else
        {
            if (RT_SUCCESS(rc)) /* Size does not match. */
                rc = VERR_BROKEN_PIPE; /** @todo FInd a better error. */
        }

        if (RT_SUCCESS(rc))
        {
            if (pcbSize)
                *pcbSize = cbSizeOnGuest;
        }
    }

    return rc;
}
Esempio n. 22
0
int SessionTaskUpdateAdditions::runFile(GuestSession *pSession, GuestProcessStartupInfo &procInfo)
{
    AssertPtrReturn(pSession, VERR_INVALID_POINTER);

#ifdef VBOX_SERVICE_ENVARG_BUG
    GuestFsObjData objData;
    int rc = pSession->fileQueryInfoInternal(procInfo.mCommand, objData);
    if (RT_FAILURE(rc))
        procInfo.mCommand = "C:\\Windows\\system32\\EMP" + procInfo.mCommand.substr(sizeof("%TEMP%\\") - sizeof(char));
#endif

    ComObjPtr<GuestProcess> pProcess;
    rc = pSession->processCreateExInteral(procInfo, pProcess);
    if (RT_SUCCESS(rc))
        rc = pProcess->startProcess();

    if (RT_SUCCESS(rc))
    {
        LogRel(("Running %s ...\n", procInfo.mName.c_str()));

        GuestProcessWaitResult waitRes;
        rc = pProcess->waitFor(ProcessWaitForFlag_Terminate,
                               10 * 60 * 1000 /* 10 mins Timeout */, waitRes);
        if (waitRes.mResult == ProcessWaitResult_Terminate)
        {
            ProcessStatus_T procStatus;
            LONG exitCode;
            if (   (   SUCCEEDED(pProcess->COMGETTER(Status(&procStatus)))
                    && procStatus != ProcessStatus_TerminatedNormally)
                || (   SUCCEEDED(pProcess->COMGETTER(ExitCode(&exitCode)))
                    && exitCode != 0)
               )
            {
                setProgressErrorMsg(VBOX_E_IPRT_ERROR,
                                    Utf8StrFmt(GuestSession::tr("Running %s failed with status %ld, exit code %ld"),
                                               procInfo.mName.c_str(), procStatus, exitCode));
                rc = VERR_GENERAL_FAILURE; /* Fudge. */
            }
            else /* Yay, success! */
            {
                LogRel(("%s successfully completed\n", procInfo.mName.c_str()));
            }
        }
        else
        {
            if (RT_FAILURE(rc))
                setProgressErrorMsg(VBOX_E_IPRT_ERROR,
                                    Utf8StrFmt(GuestSession::tr("Error while waiting running %s: %Rrc"),
                                               procInfo.mName.c_str(), rc));
            else
            {
                setProgressErrorMsg(VBOX_E_IPRT_ERROR, pProcess->errorMsg());
                rc = VERR_GENERAL_FAILURE; /* Fudge. */
            }
        }
    }

    if (!pProcess.isNull())
        pProcess->uninit();

    return rc;
}
Esempio n. 23
0
int SessionTaskUpdateAdditions::Run(void)
{
    LogFlowThisFuncEnter();

    ComObjPtr<GuestSession> pSession = mSession;
    Assert(!pSession.isNull());

    AutoCaller autoCaller(pSession);
    if (FAILED(autoCaller.rc())) return autoCaller.rc();

    int rc = setProgress(10);
    if (RT_FAILURE(rc))
        return rc;

    HRESULT hr = S_OK;

    LogRel(("Automatic update of Guest Additions started, using \"%s\"\n", mSource.c_str()));

    /*
     * Determine guest OS type and the required installer image.
     * At the moment only Windows guests are supported.
     */
    Utf8Str strInstallerImage;

    ComObjPtr<Guest> pGuest(mSession->getParent());
    Bstr osTypeId;
    if (   SUCCEEDED(pGuest->COMGETTER(OSTypeId(osTypeId.asOutParam())))
        && !osTypeId.isEmpty())
    {
        Utf8Str osTypeIdUtf8(osTypeId); /* Needed for .contains(). */
        if (   osTypeIdUtf8.contains("Microsoft", Utf8Str::CaseInsensitive)
            || osTypeIdUtf8.contains("Windows", Utf8Str::CaseInsensitive))
        {
            if (osTypeIdUtf8.contains("64", Utf8Str::CaseInsensitive))
                strInstallerImage = "VBOXWINDOWSADDITIONS_AMD64.EXE";
            else
                strInstallerImage = "VBOXWINDOWSADDITIONS_X86.EXE";
            /* Since the installers are located in the root directory,
             * no further path processing needs to be done (yet). */
        }
        else /* Everything else is not supported (yet). */
        {
            hr = setProgressErrorMsg(VBOX_E_IPRT_ERROR,
                                     Utf8StrFmt(GuestSession::tr("Detected guest OS (%s) does not support automatic Guest Additions updating, please update manually"),
                                     osTypeIdUtf8.c_str()));
            rc = VERR_GENERAL_FAILURE; /* Fudge. */
        }
    }
    else
    {
        hr = setProgressErrorMsg(VBOX_E_IPRT_ERROR,
                                 Utf8StrFmt(GuestSession::tr("Could not detected guest OS type/version, please update manually")));
        rc = VERR_GENERAL_FAILURE; /* Fudge. */
    }

    RTISOFSFILE iso;
    if (RT_SUCCESS(rc))
    {
        Assert(!strInstallerImage.isEmpty());

        /*
         * Try to open the .ISO file and locate the specified installer.
         */
        rc = RTIsoFsOpen(&iso, mSource.c_str());
        if (RT_FAILURE(rc))
        {
            hr = setProgressErrorMsg(VBOX_E_IPRT_ERROR,
                                     Utf8StrFmt(GuestSession::tr("Unable to open Guest Additions .ISO file \"%s\": %Rrc"),
                                     mSource.c_str(), rc));
        }
        else
        {
            rc = setProgress(5);

            /** @todo Add support for non-Windows as well! */
            Utf8Str strInstallerDest = "%TEMP%\\VBoxWindowsAdditions.exe";
            bool fInstallCertificates = false;

            if (RT_SUCCESS(rc))
            {
                /*
                 * Copy over main installer to the guest.
                 */
                rc = copyFileToGuest(pSession, &iso, strInstallerImage, strInstallerDest,
                                     false /* File is not optional */, NULL /* cbSize */);
                if (RT_SUCCESS(rc))
                    rc = setProgress(20);

                /*
                 * Install needed certificates for the WHQL crap.
                 ** @todo Only for Windows!
                 */
                if (RT_SUCCESS(rc))
                {
                    rc = copyFileToGuest(pSession, &iso, "CERT/ORACLE_VBOX.CER", "%TEMP%\\oracle-vbox.cer",
                                         true /* File is optional */, NULL /* cbSize */);
                    if (RT_SUCCESS(rc))
                    {
                        rc = setProgress(30);
                        if (RT_SUCCESS(rc))
                        {
                            rc = copyFileToGuest(pSession, &iso, "CERT/VBOXCERTUTIL.EXE", "%TEMP%\\VBoxCertUtil.exe",
                                                 true /* File is optional */, NULL /* cbSize */);
                            if (RT_SUCCESS(rc))
                            {
                                fInstallCertificates = true;
                                rc = setProgress(40);
                            }
                            else
                                hr = setProgressErrorMsg(VBOX_E_IPRT_ERROR,
                                                         Utf8StrFmt(GuestSession::tr("Error while copying certificate installation tool to the guest: %Rrc"), rc));
                        }
                    }
                    else
                        hr = setProgressErrorMsg(VBOX_E_IPRT_ERROR,
                                                 Utf8StrFmt(GuestSession::tr("Error while copying certificate to the guest: %Rrc"), rc));
                }
            }

            /*
             * Run VBoxCertUtil.exe to install the Oracle certificate.
             */
            if (   RT_SUCCESS(rc)
                && fInstallCertificates)
            {
                LogRel(("Installing certificates on the guest ...\n"));

                GuestProcessStartupInfo procInfo;
                procInfo.mName    = Utf8StrFmt(GuestSession::tr("VirtualBox Guest Additions Certificate Utility"));
                procInfo.mCommand = Utf8Str("%TEMP%\\VBoxCertUtil.exe");
                procInfo.mFlags   = ProcessCreateFlag_Hidden;

                /* Construct arguments. */
                /** @todo Remove hardcoded paths. */
                procInfo.mArguments.push_back(Utf8Str("add-trusted-publisher"));
                /* Ugly hack: Because older Guest Additions have problems with environment variable
                          expansion in parameters we have to check an alternative location on Windows.
                          So check for "%TEMP%\VBoxWindowsAdditions.exe" in a screwed up way. */
#ifdef VBOX_SERVICE_ENVARG_BUG
                GuestFsObjData objData;
                rc = pSession->fileQueryInfoInternal("%TEMP%\\oracle-vbox.cer", objData);
                if (RT_SUCCESS(rc))
#endif
                    procInfo.mArguments.push_back(Utf8Str("%TEMP%\\oracle-vbox.cer"));
#ifdef VBOX_SERVICE_ENVARG_BUG
                else
                    procInfo.mArguments.push_back(Utf8Str("C:\\Windows\\system32\\EMPoracle-vbox.cer"));
#endif
                /* Overwrite rc in any case. */
                rc = runFile(pSession, procInfo);
            }

            if (RT_SUCCESS(rc))
                rc = setProgress(60);

            if (RT_SUCCESS(rc))
            {
                LogRel(("Updating Guest Additions ...\n"));

                GuestProcessStartupInfo procInfo;
                procInfo.mName    = Utf8StrFmt(GuestSession::tr("VirtualBox Guest Additions Setup"));
                procInfo.mCommand = Utf8Str(strInstallerDest);
                procInfo.mFlags   = ProcessCreateFlag_Hidden;
                /* If the caller does not want to wait for out guest update process to end,
                 * complete the progress object now so that the caller can do other work. */
                if (mFlags & AdditionsUpdateFlag_WaitForUpdateStartOnly)
                    procInfo.mFlags |= ProcessCreateFlag_WaitForProcessStartOnly;

                /* Construct arguments. */
                procInfo.mArguments.push_back(Utf8Str("/S")); /* We want to install in silent mode. */
                procInfo.mArguments.push_back(Utf8Str("/l")); /* ... and logging enabled. */
                /* Don't quit VBoxService during upgrade because it still is used for this
                 * piece of code we're in right now (that is, here!) ... */
                procInfo.mArguments.push_back(Utf8Str("/no_vboxservice_exit"));
                /* Tell the installer to report its current installation status
                 * using a running VBoxTray instance via balloon messages in the
                 * Windows taskbar. */
                procInfo.mArguments.push_back(Utf8Str("/post_installstatus"));

                rc = runFile(pSession, procInfo);
                if (RT_SUCCESS(rc))
                    hr = setProgressSuccess();
            }
            RTIsoFsClose(&iso);
        }
    }

    LogFlowFuncLeaveRC(rc);
    return rc;
}
HRESULT HostNetworkInterface::eraseAdapterConfigParameter(const char *szParamName)
{
    AssertReturn(mVirtualBox != NULL, E_POINTER);
    return mVirtualBox->SetExtraData(Bstr(Utf8StrFmt("HostOnly/{%RTuuid}/%s", mGuid, szParamName)).raw(), NULL);
}
Esempio n. 25
0
int SessionTaskCopyFrom::Run(void)
{
    LogFlowThisFuncEnter();

    ComObjPtr<GuestSession> pSession = mSession;
    Assert(!pSession.isNull());

    AutoCaller autoCaller(pSession);
    if (FAILED(autoCaller.rc())) return autoCaller.rc();

    /*
     * Note: There will be races between querying file size + reading the guest file's
     *       content because we currently *do not* lock down the guest file when doing the
     *       actual operations.
     ** @todo Implement guest file locking!
     */
    GuestFsObjData objData;
    int rc = pSession->fileQueryInfoInternal(Utf8Str(mSource), objData);
    if (RT_FAILURE(rc))
    {
        setProgressErrorMsg(VBOX_E_IPRT_ERROR,
                            Utf8StrFmt(GuestSession::tr("Querying guest file information for \"%s\" failed: %Rrc"),
                            mSource.c_str(), rc));
    }
    else if (objData.mType != FsObjType_File) /* Only single files are supported at the moment. */
    {
        rc = setProgressErrorMsg(VBOX_E_IPRT_ERROR,
                                 Utf8StrFmt(GuestSession::tr("Object \"%s\" on the guest is not a file"), mSource.c_str()));
    }

    if (RT_SUCCESS(rc))
    {
        RTFILE fileDest;
        rc = RTFileOpen(&fileDest, mDest.c_str(),
                        RTFILE_O_WRITE | RTFILE_O_OPEN_CREATE | RTFILE_O_DENY_WRITE); /** @todo Use the correct open modes! */
        if (RT_FAILURE(rc))
        {
            setProgressErrorMsg(VBOX_E_IPRT_ERROR,
                                Utf8StrFmt(GuestSession::tr("Error opening destination file \"%s\": %Rrc"),
                                           mDest.c_str(), rc));
        }
        else
        {
            GuestProcessStartupInfo procInfo;
            procInfo.mName    = Utf8StrFmt(GuestSession::tr("Copying file \"%s\" from guest to the host to \"%s\" (%RI64 bytes)"),
                                                            mSource.c_str(), mDest.c_str(), objData.mObjectSize);
            procInfo.mCommand   = Utf8Str(VBOXSERVICE_TOOL_CAT);
            procInfo.mFlags     = ProcessCreateFlag_Hidden | ProcessCreateFlag_WaitForStdOut;

            /* Set arguments.*/
            procInfo.mArguments.push_back(mSource); /* Which file to output? */

            /* Startup process. */
            ComObjPtr<GuestProcess> pProcess;
            rc = pSession->processCreateExInteral(procInfo, pProcess);
            if (RT_SUCCESS(rc))
                rc = pProcess->startProcess();
            if (RT_FAILURE(rc))
            {
                setProgressErrorMsg(VBOX_E_IPRT_ERROR,
                                    Utf8StrFmt(GuestSession::tr("Unable to start guest process for copying data from guest to host: %Rrc"), rc));
            }
            else
            {
                GuestProcessWaitResult waitRes;
                BYTE byBuf[_64K];

                BOOL fCanceled = FALSE;
                uint64_t cbWrittenTotal = 0;
                uint64_t cbToRead = objData.mObjectSize;

                for (;;)
                {
                    rc = pProcess->waitFor(ProcessWaitForFlag_StdOut,
                                           30 * 1000 /* Timeout */, waitRes);
                    if (   waitRes.mResult == ProcessWaitResult_StdOut
                        || waitRes.mResult == ProcessWaitResult_WaitFlagNotSupported)
                    {
                        /* If the guest does not support waiting for stdin, we now yield in
                         * order to reduce the CPU load due to busy waiting. */
                        if (waitRes.mResult == ProcessWaitResult_WaitFlagNotSupported)
                            RTThreadYield(); /* Optional, don't check rc. */

                        size_t cbRead;
                        rc = pProcess->readData(OUTPUT_HANDLE_ID_STDOUT, sizeof(byBuf),
                                                30 * 1000 /* Timeout */, byBuf, sizeof(byBuf),
                                                &cbRead);
                        if (RT_FAILURE(rc))
                        {
                            setProgressErrorMsg(VBOX_E_IPRT_ERROR,
                                                Utf8StrFmt(GuestSession::tr("Reading from file \"%s\" (offset %RU64) failed: %Rrc"),
                                                mSource.c_str(), cbWrittenTotal, rc));
                            break;
                        }

                        if (cbRead)
                        {
                            rc = RTFileWrite(fileDest, byBuf, cbRead, NULL /* No partial writes */);
                            if (RT_FAILURE(rc))
                            {
                                setProgressErrorMsg(VBOX_E_IPRT_ERROR,
                                                    Utf8StrFmt(GuestSession::tr("Error writing to file \"%s\" (%RU64 bytes left): %Rrc"),
                                                    mDest.c_str(), cbToRead, rc));
                                break;
                            }

                            /* Only subtract bytes reported written by the guest. */
                            Assert(cbToRead >= cbRead);
                            cbToRead -= cbRead;

                            /* Update total bytes written to the guest. */
                            cbWrittenTotal += cbRead;
                            Assert(cbWrittenTotal <= (uint64_t)objData.mObjectSize);

                            /* Did the user cancel the operation above? */
                            if (   SUCCEEDED(mProgress->COMGETTER(Canceled(&fCanceled)))
                                && fCanceled)
                                break;

                            rc = setProgress((ULONG)(cbWrittenTotal / ((uint64_t)objData.mObjectSize / 100.0)));
                            if (RT_FAILURE(rc))
                                break;
                        }
                    }
                    else if (   RT_FAILURE(rc)
                             || waitRes.mResult == ProcessWaitResult_Terminate
                             || waitRes.mResult == ProcessWaitResult_Error
                             || waitRes.mResult == ProcessWaitResult_Timeout)
                    {
                        if (RT_FAILURE(waitRes.mRC))
                            rc = waitRes.mRC;
                        break;
                    }
                } /* for */

                LogFlowThisFunc(("rc=%Rrc, cbWrittenTotal=%RU64, cbSize=%RI64, cbToRead=%RU64\n",
                                 rc, cbWrittenTotal, objData.mObjectSize, cbToRead));

                if (   !fCanceled
                    || RT_SUCCESS(rc))
                {
                    /*
                     * Even if we succeeded until here make sure to check whether we really transfered
                     * everything.
                     */
                    if (   objData.mObjectSize > 0
                        && cbWrittenTotal == 0)
                    {
                        /* If nothing was transfered but the file size was > 0 then "vbox_cat" wasn't able to write
                         * to the destination -> access denied. */
                        setProgressErrorMsg(VBOX_E_IPRT_ERROR,
                                            Utf8StrFmt(GuestSession::tr("Access denied when copying file \"%s\" to \"%s\""),
                                            mSource.c_str(), mDest.c_str()));
                        rc = VERR_GENERAL_FAILURE; /* Fudge. */
                    }
                    else if (cbWrittenTotal < (uint64_t)objData.mObjectSize)
                    {
                        /* If we did not copy all let the user know. */
                        setProgressErrorMsg(VBOX_E_IPRT_ERROR,
                                            Utf8StrFmt(GuestSession::tr("Copying file \"%s\" failed (%RU64/%RI64 bytes transfered)"),
                                            mSource.c_str(), cbWrittenTotal, objData.mObjectSize));
                        rc = VERR_GENERAL_FAILURE; /* Fudge. */
                    }
                    else
                    {
                        ProcessStatus_T procStatus;
                        LONG exitCode;
                        if (   (   SUCCEEDED(pProcess->COMGETTER(Status(&procStatus)))
                                && procStatus != ProcessStatus_TerminatedNormally)
                            || (   SUCCEEDED(pProcess->COMGETTER(ExitCode(&exitCode)))
                                && exitCode != 0)
                           )
                        {
                            setProgressErrorMsg(VBOX_E_IPRT_ERROR,
                                                Utf8StrFmt(GuestSession::tr("Copying file \"%s\" failed with status %ld, exit code %d"),
                                                mSource.c_str(), procStatus, exitCode)); /**@todo Add stringify methods! */
                            rc = VERR_GENERAL_FAILURE; /* Fudge. */
                        }
                        else /* Yay, success! */
                            rc = setProgressSuccess();
                    }
                }

                if (!pProcess.isNull())
                    pProcess->uninit();
            }

            RTFileClose(fileDest);
        }
    }

    LogFlowFuncLeaveRC(rc);
    return rc;
}
/**
 *  Interprets a string and assigns it to a USBFilter field.
 *
 *  (This function is also used by HostUSBDeviceFilter.)
 *
 *  @param  aFilter     The filter.
 *  @param  aIdx        The field index.
 *  @param  aStr        The input string.
 *  @param  aName       The field name for use in the error string.
 *  @param  aErrStr     Where to return the error string on failure.
 *
 *  @return COM status code.
 *  @remark The idea was to have this as a static function, but tr() doesn't wanna work without a class :-/
 */
/*static*/ HRESULT USBDeviceFilter::i_usbFilterFieldFromString(PUSBFILTER aFilter,
                                                               USBFILTERIDX aIdx,
                                                               const Utf8Str &aValue,
                                                               Utf8Str &aErrStr)
{
    int vrc;
    if (aValue.isEmpty())
        vrc = USBFilterSetIgnore(aFilter, aIdx);
    else
    {
        const char *pcszValue = aValue.c_str();
        if (USBFilterIsNumericField(aIdx))
        {
            /* Is it a lonely number? */
            char *pszNext;
            uint64_t u64;
            vrc = RTStrToUInt64Ex(pcszValue, &pszNext, 16, &u64);
            if (RT_SUCCESS(vrc))
                pszNext = RTStrStripL(pszNext);
            if (    vrc == VINF_SUCCESS
                &&  !*pszNext)
            {
                if (u64 > 0xffff)
                {
                    // there was a bug writing out "-1" values in earlier versions, which got
                    // written as "FFFFFFFF"; make sure we don't fail on those
                    if (u64 == 0xffffffff)
                        u64 = 0xffff;
                    else
                    {
                        aErrStr = Utf8StrFmt(tr("The %s value '%s' is too big (max 0xFFFF)"),
                                             i_describeUSBFilterIdx(aIdx), pcszValue);
                        return E_INVALIDARG;
                    }
                }

                vrc = USBFilterSetNumExact(aFilter, aIdx, (uint16_t)u64, true /* fMustBePresent */);
            }
            else
                vrc = USBFilterSetNumExpression(aFilter, aIdx, pcszValue, true /* fMustBePresent */);
        }
        else
        {
            /* Any wildcard in the string? */
            Assert(USBFilterIsStringField(aIdx));
            if (    strchr(pcszValue, '*')
                ||  strchr(pcszValue, '?')
                /* || strchr (psz, '[') - later */
                )
                vrc = USBFilterSetStringPattern(aFilter, aIdx, pcszValue, true /*fMustBePresent*/);
            else
                vrc = USBFilterSetStringExact(aFilter, aIdx, pcszValue, true /*fMustBePresent*/, false /*fPurge*/);
        }
    }

    if (RT_FAILURE(vrc))
    {
        if (vrc == VERR_INVALID_PARAMETER)
        {
            aErrStr = Utf8StrFmt(tr("The %s filter expression '%s' is not valid"), i_describeUSBFilterIdx(aIdx), aValue.c_str());
            return E_INVALIDARG;
        }
        if (vrc == VERR_BUFFER_OVERFLOW)
        {
            aErrStr = Utf8StrFmt(tr("Insufficient expression space for the '%s' filter expression '%s'"),
                                 i_describeUSBFilterIdx(aIdx), aValue.c_str());
            return E_FAIL;
        }
        AssertRC(vrc);
        aErrStr = Utf8StrFmt(tr("Encountered unexpected status %Rrc when setting '%s' to '%s'"),
                             vrc, i_describeUSBFilterIdx(aIdx), aValue.c_str());
        return E_FAIL;
    }

    return S_OK;
}
Esempio n. 27
0
int SessionTaskCopyTo::Run(void)
{
    LogFlowThisFuncEnter();

    ComObjPtr<GuestSession> pSession = mSession;
    Assert(!pSession.isNull());

    AutoCaller autoCaller(pSession);
    if (FAILED(autoCaller.rc())) return autoCaller.rc();

    if (mCopyFileFlags)
    {
        setProgressErrorMsg(VBOX_E_IPRT_ERROR,
                            Utf8StrFmt(GuestSession::tr("Copy flags (%#x) not implemented yet"),
                            mCopyFileFlags));
        return VERR_INVALID_PARAMETER;
    }

    int rc;

    RTFILE fileLocal;
    PRTFILE pFile = &fileLocal;

    if (!mSourceFile)
    {
        /* Does our source file exist? */
        if (!RTFileExists(mSource.c_str()))
        {
            rc = setProgressErrorMsg(VBOX_E_IPRT_ERROR,
                                     Utf8StrFmt(GuestSession::tr("Source file \"%s\" does not exist or is not a file"),
                                                mSource.c_str()));
        }
        else
        {
            rc = RTFileOpen(pFile, mSource.c_str(),
                            RTFILE_O_OPEN | RTFILE_O_READ | RTFILE_O_DENY_WRITE);
            if (RT_FAILURE(rc))
            {
                rc = setProgressErrorMsg(VBOX_E_IPRT_ERROR,
                                         Utf8StrFmt(GuestSession::tr("Could not open source file \"%s\" for reading: %Rrc"),
                                                    mSource.c_str(), rc));
            }
            else
            {
                rc = RTFileGetSize(*pFile, &mSourceSize);
                if (RT_FAILURE(rc))
                {
                    setProgressErrorMsg(VBOX_E_IPRT_ERROR,
                                        Utf8StrFmt(GuestSession::tr("Could not query file size of \"%s\": %Rrc"),
                                                   mSource.c_str(), rc));
                }
            }
        }
    }
    else
    {
        pFile = mSourceFile;
        /* Size + offset are optional. */
    }

    GuestProcessStartupInfo procInfo;
    procInfo.mName    = Utf8StrFmt(GuestSession::tr("Copying file \"%s\" to the guest to \"%s\" (%RU64 bytes)"),
                                   mSource.c_str(), mDest.c_str(), mSourceSize);
    procInfo.mCommand = Utf8Str(VBOXSERVICE_TOOL_CAT);
    procInfo.mFlags   = ProcessCreateFlag_Hidden;

    /* Set arguments.*/
    procInfo.mArguments.push_back(Utf8StrFmt("--output=%s", mDest.c_str())); /** @todo Do we need path conversion? */

    /* Startup process. */
    ComObjPtr<GuestProcess> pProcess;
    rc = pSession->processCreateExInteral(procInfo, pProcess);
    if (RT_SUCCESS(rc))
        rc = pProcess->startProcess();
    if (RT_FAILURE(rc))
    {
        setProgressErrorMsg(VBOX_E_IPRT_ERROR,
                            Utf8StrFmt(GuestSession::tr("Unable to start guest process: %Rrc"), rc));
    }
    else
    {
        GuestProcessWaitResult waitRes;
        BYTE byBuf[_64K];

        BOOL fCanceled = FALSE;
        uint64_t cbWrittenTotal = 0;
        uint64_t cbToRead = mSourceSize;

        for (;;)
        {
            rc = pProcess->waitFor(ProcessWaitForFlag_StdIn,
                                   30 * 1000 /* Timeout */, waitRes);
            if (   RT_FAILURE(rc)
                || (   waitRes.mResult != ProcessWaitResult_StdIn
                    && waitRes.mResult != ProcessWaitResult_WaitFlagNotSupported))
            {
                break;
            }

            /* If the guest does not support waiting for stdin, we now yield in
             * order to reduce the CPU load due to busy waiting. */
            if (waitRes.mResult == ProcessWaitResult_WaitFlagNotSupported)
                RTThreadYield(); /* Optional, don't check rc. */

            size_t cbRead = 0;
            if (mSourceSize) /* If we have nothing to write, take a shortcut. */
            {
                /** @todo Not very efficient, but works for now. */
                rc = RTFileSeek(*pFile, mSourceOffset + cbWrittenTotal,
                                RTFILE_SEEK_BEGIN, NULL /* poffActual */);
                if (RT_SUCCESS(rc))
                {
                    rc = RTFileRead(*pFile, (uint8_t*)byBuf,
                                    RT_MIN(cbToRead, sizeof(byBuf)), &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(rc))
                    {
                        setProgressErrorMsg(VBOX_E_IPRT_ERROR,
                                            Utf8StrFmt(GuestSession::tr("Could not read from file \"%s\" (%Rrc)"),
                                                       mSource.c_str(), rc));
                        break;
                    }
                }
                else
                {
                    setProgressErrorMsg(VBOX_E_IPRT_ERROR,
                                        Utf8StrFmt(GuestSession::tr("Seeking file \"%s\" offset %RU64 failed: %Rrc"),
                                                   mSource.c_str(), cbWrittenTotal, rc));
                    break;
                }
            }

            uint32_t fFlags = ProcessInputFlag_None;

            /* Did we reach the end of the content we want to transfer (last chunk)? */
            if (   (cbRead < sizeof(byBuf))
                /* Did we reach the last block which is exactly _64K? */
                || (cbToRead - cbRead == 0)
                /* ... or does the user want to cancel? */
                || (   SUCCEEDED(mProgress->COMGETTER(Canceled(&fCanceled)))
                    && fCanceled)
               )
            {
                fFlags |= ProcessInputFlag_EndOfFile;
            }

            uint32_t cbWritten;
            Assert(sizeof(byBuf) >= cbRead);
            rc = pProcess->writeData(0 /* StdIn */, fFlags,
                                     byBuf, cbRead,
                                     30 * 1000 /* Timeout */, &cbWritten);
            if (RT_FAILURE(rc))
            {
                setProgressErrorMsg(VBOX_E_IPRT_ERROR,
                                    Utf8StrFmt(GuestSession::tr("Writing to file \"%s\" (offset %RU64) failed: %Rrc"),
                                               mDest.c_str(), cbWrittenTotal, rc));
                break;
            }

            LogFlowThisFunc(("cbWritten=%RU32, cbToRead=%RU64, cbWrittenTotal=%RU64, cbFileSize=%RU64\n",
                             cbWritten, cbToRead - cbWritten, cbWrittenTotal + cbWritten, mSourceSize));

            /* Only subtract bytes reported written by the guest. */
            Assert(cbToRead >= cbWritten);
            cbToRead -= cbWritten;

            /* Update total bytes written to the guest. */
            cbWrittenTotal += cbWritten;
            Assert(cbWrittenTotal <= mSourceSize);

            /* Did the user cancel the operation above? */
            if (fCanceled)
                break;

            /* Update the progress.
             * Watch out for division by zero. */
            mSourceSize > 0
                ? rc = setProgress((ULONG)(cbWrittenTotal * 100 / mSourceSize))
                : rc = setProgress(100);
            if (RT_FAILURE(rc))
                break;

            /* End of file reached? */
            if (!cbToRead)
                break;
        } /* for */

        if (   !fCanceled
            || RT_SUCCESS(rc))
        {
            /*
             * Even if we succeeded until here make sure to check whether we really transfered
             * everything.
             */
            if (   mSourceSize > 0
                && cbWrittenTotal == 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 = setProgressErrorMsg(VBOX_E_IPRT_ERROR,
                                         Utf8StrFmt(GuestSession::tr("Access denied when copying file \"%s\" to \"%s\""),
                                                    mSource.c_str(), mDest.c_str()));
            }
            else if (cbWrittenTotal < mSourceSize)
            {
                /* If we did not copy all let the user know. */
                rc = setProgressErrorMsg(VBOX_E_IPRT_ERROR,
                                         Utf8StrFmt(GuestSession::tr("Copying file \"%s\" failed (%RU64/%RU64 bytes transfered)"),
                                                    mSource.c_str(), cbWrittenTotal, mSourceSize));
            }
            else
            {
                rc = pProcess->waitFor(ProcessWaitForFlag_Terminate,
                                       30 * 1000 /* Timeout */, waitRes);
                if (   RT_FAILURE(rc)
                    || waitRes.mResult != ProcessWaitResult_Terminate)
                {
                    if (RT_FAILURE(rc))
                        rc = setProgressErrorMsg(VBOX_E_IPRT_ERROR,
                                                 Utf8StrFmt(GuestSession::tr("Waiting on termination for copying file \"%s\" failed: %Rrc"),
                                                            mSource.c_str(), rc));
                    else
                        rc = setProgressErrorMsg(VBOX_E_IPRT_ERROR,
                                                 Utf8StrFmt(GuestSession::tr("Waiting on termination for copying file \"%s\" failed with wait result %ld"),
                                                            mSource.c_str(), waitRes.mResult));
                }

                if (RT_SUCCESS(rc))
                {
                    ProcessStatus_T procStatus;
                    LONG exitCode;
                    if (   (   SUCCEEDED(pProcess->COMGETTER(Status(&procStatus)))
                            && procStatus != ProcessStatus_TerminatedNormally)
                        || (   SUCCEEDED(pProcess->COMGETTER(ExitCode(&exitCode)))
                            && exitCode != 0)
                       )
                    {
                        rc = setProgressErrorMsg(VBOX_E_IPRT_ERROR,
                                                 Utf8StrFmt(GuestSession::tr("Copying file \"%s\" failed with status %ld, exit code %ld"),
                                                            mSource.c_str(), procStatus, exitCode)); /**@todo Add stringify methods! */
                    }
                }

                if (RT_SUCCESS(rc))
                    rc = setProgressSuccess();
            }
        }

        if (!pProcess.isNull())
            pProcess->uninit();
    } /* processCreateExInteral */

    if (!mSourceFile) /* Only close locally opened files. */
        RTFileClose(*pFile);

    LogFlowFuncLeaveRC(rc);
    return rc;
}