HRESULT Guest::taskCopyFileFromGuest(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? */
        BOOL fFileExists;
        rc = pGuest->FileExists(Bstr(aTask->strSource).raw(),
                                Bstr(aTask->strUserName).raw(), Bstr(aTask->strPassword).raw(),
                                &fFileExists);
        if (SUCCEEDED(rc))
        {
            if (!fFileExists)
                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
            rc = GuestTask::setProgressErrorInfo(rc, aTask->pProgress, pGuest);

        /* Query file size to make an estimate for our progress object. */
        if (SUCCEEDED(rc))
        {
            LONG64 lFileSize;
            rc = pGuest->FileQuerySize(Bstr(aTask->strSource).raw(),
                                       Bstr(aTask->strUserName).raw(), Bstr(aTask->strPassword).raw(),
                                       &lFileSize);
            if (FAILED(rc))
                rc = GuestTask::setProgressErrorInfo(rc, aTask->pProgress, pGuest);

            com::SafeArray<IN_BSTR> args;
            com::SafeArray<IN_BSTR> env;

            if (SUCCEEDED(rc))
            {
                /*
                 * Prepare tool command line.
                 */
                char szSource[RTPATH_MAX];
                if (RTStrPrintf(szSource, sizeof(szSource), "%s", aTask->strSource.c_str()) <= sizeof(szSource) - 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(szSource, true /* Force conversion. */);
                    }
                    else /* ... or something which isn't from Redmond ... */
                    {
                        RTPathChangeToUnixSlashes(szSource, true /* Force conversion. */);
                    }

                    args.push_back(Bstr(szSource).raw()); /* Tell our cat tool which file to output. */
                }
                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 host \"%s\" (%u bytes) ...\n",
                        aTask->strSource.c_str(), aTask->strDest.c_str(), lFileSize));

                /*
                 * 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 host").raw(),
                                                   ComSafeArrayAsInParam(args),
                                                   ComSafeArrayAsInParam(env),
                                                   Bstr(aTask->strUserName).raw(),
                                                   Bstr(aTask->strPassword).raw(),
                                                     ExecuteProcessFlag_WaitForProcessStartOnly
                                                   | ExecuteProcessFlag_WaitForStdOut,
                                                   NULL, NULL,
                                                   execProgress.asOutParam(), &uPID);
                if (FAILED(rc))
                    rc = GuestTask::setProgressErrorInfo(rc, aTask->pProgress, pGuest);
            }

            if (SUCCEEDED(rc))
            {
                BOOL fCompleted = FALSE;
                BOOL fCanceled = FALSE;

                RTFILE hFileDest;
                int vrc = RTFileOpen(&hFileDest, aTask->strDest.c_str(),
                                     RTFILE_O_WRITE | RTFILE_O_OPEN_CREATE | RTFILE_O_DENY_WRITE);
                if (RT_FAILURE(vrc))
                    rc = GuestTask::setProgressErrorInfo(VBOX_E_IPRT_ERROR, aTask->pProgress,
                                                         Guest::tr("Unable to create/open destination file \"%s\", rc=%Rrc"),
                                                         aTask->strDest.c_str(), vrc);
                else
                {
                    size_t cbToRead = lFileSize;
                    size_t cbTransfered = 0;
                    while (   SUCCEEDED(execProgress->COMGETTER(Completed(&fCompleted)))
                           && !fCompleted)
                    {
                        SafeArray<BYTE> aOutputData;
                        rc = pGuest->GetProcessOutput(uPID, ProcessOutputFlag_None /* StdOut */,
                                                      0 /* No timeout. */,
                                                      _64K, ComSafeArrayAsOutParam(aOutputData));
                        if (SUCCEEDED(rc))
                        {
                            if (aOutputData.size())
                            {
                                vrc = RTFileWrite(hFileDest, aOutputData.raw(), aOutputData.size(), NULL /* No partial writes */);
                                if (RT_FAILURE(vrc))
                                {
                                    rc = GuestTask::setProgressErrorInfo(VBOX_E_IPRT_ERROR, aTask->pProgress,
                                                                         Guest::tr("Error writing to file \"%s\" (%u bytes left), rc=%Rrc"),
                                                                         aTask->strSource.c_str(), cbToRead, vrc);
                                    break;
                                }

                                Assert(cbToRead >= aOutputData.size());
                                cbToRead -= aOutputData.size();
                                cbTransfered += aOutputData.size();

                                aTask->pProgress->SetCurrentOperationProgress(cbTransfered / (lFileSize / 100.0));
                            }

                            /* Nothing read this time; try next round. */
                        }
                        else
                        {
                            rc = GuestTask::setProgressErrorInfo(rc, aTask->pProgress, pGuest);
                            break;
                        }
                    }

                    RTFileClose(hFileDest);

                    if (SUCCEEDED(rc))
                    {
                        if (   cbTransfered
                            && (cbTransfered != lFileSize))
                        {
                            /*
                             * Only bitch about an unexpected end of a file when there already
                             * was data read from that file. If this was the very first read we can
                             * be (almost) sure that this file is not meant to be read by the specified user.
                             */
                            rc = GuestTask::setProgressErrorInfo(VBOX_E_IPRT_ERROR, aTask->pProgress,
                                                                 Guest::tr("Unexpected end of file \"%s\" (%u bytes total, %u bytes transferred)"),
                                                                 aTask->strSource.c_str(), lFileSize, cbTransfered);
                        }

                        if (SUCCEEDED(rc))
                            aTask->pProgress->notifyComplete(S_OK);
                    }
                }
            }
        }
    }
    catch (HRESULT aRC)
    {
        rc = aRC;
    }

    /* Clean up */
    aTask->rc = rc;

    LogFlowFunc(("rc=%Rhrc\n", rc));
    LogFlowFuncLeave();

    return VINF_SUCCESS;
}
int NetworkManager::processParameterReqList(const Client& client, const uint8_t *pu8ReqList,
                                            int cReqList, std::vector<RawOption>& extra)
{
    int rc;

    const Lease l = client.lease();

    const NetworkConfigEntity *pNetCfg = l.getConfig();

    /*
     * XXX: Brute-force.  Unfortunately, there's no notification event
     * for changes.  Should at least cache the options for a short
     * time, enough to last discover/offer/request/ack cycle.
     */
    typedef std::map< int, std::pair<std::string, int> > DhcpOptionMap;
    DhcpOptionMap OptMap;

    if (!m->m_DhcpServer.isNull())
    {
        com::SafeArray<BSTR> strings;
        com::Bstr str;
        HRESULT hrc;
        int OptCode, OptEncoding;
        char *pszOptText;

        strings.setNull();
        hrc = m->m_DhcpServer->COMGETTER(GlobalOptions)(ComSafeArrayAsOutParam(strings));
        AssertComRC(hrc);
        for (size_t i = 0; i < strings.size(); ++i)
        {
            com::Utf8Str encoded(strings[i]);
            rc = parseDhcpOptionText(encoded.c_str(),
                                     &OptCode, &pszOptText, &OptEncoding);
            if (!RT_SUCCESS(rc))
                continue;

            OptMap[OptCode] = std::make_pair(pszOptText, OptEncoding);
        }

        const RTMAC &mac = client.getMacAddress();
        char strMac[6*2+1] = "";
        RTStrPrintf(strMac, sizeof(strMac), "%02x%02x%02x%02x%02x%02x",
                    mac.au8[0], mac.au8[1], mac.au8[2],
                    mac.au8[3], mac.au8[4], mac.au8[5]);

        strings.setNull();
        hrc = m->m_DhcpServer->GetMacOptions(com::Bstr(strMac).raw(),
                                             ComSafeArrayAsOutParam(strings));
        AssertComRC(hrc);
        for (size_t i = 0; i < strings.size(); ++i)
        {
            com::Utf8Str text(strings[i]);
            rc = parseDhcpOptionText(text.c_str(),
                                     &OptCode, &pszOptText, &OptEncoding);
            if (!RT_SUCCESS(rc))
                continue;

            OptMap[OptCode] = std::make_pair(pszOptText, OptEncoding);
        }
    }

    /* request parameter list */
    RawOption opt;
    bool fIgnore;
    uint8_t u8Req;
    for (int idxParam = 0; idxParam < cReqList; ++idxParam)
    {
        fIgnore = false;
        RT_ZERO(opt);
        u8Req = opt.u8OptId = pu8ReqList[idxParam];

        switch(u8Req)
        {
            case RTNET_DHCP_OPT_SUBNET_MASK:
                ((PRTNETADDRIPV4)opt.au8RawOpt)->u = pNetCfg->netmask().u;
                opt.cbRawOpt = sizeof(RTNETADDRIPV4);

                break;

            case RTNET_DHCP_OPT_ROUTERS:
            case RTNET_DHCP_OPT_DNS:
                {
                    const Ipv4AddressContainer lst =
                      g_ConfigurationManager->getAddressList(u8Req);
                    PRTNETADDRIPV4 pAddresses = (PRTNETADDRIPV4)&opt.au8RawOpt[0];

                    for (Ipv4AddressConstIterator it = lst.begin();
                         it != lst.end();
                         ++it)
                    {
                        *pAddresses = (*it);
                        pAddresses++;
                        opt.cbRawOpt += sizeof(RTNETADDRIPV4);
                    }

                    if (lst.empty())
                        fIgnore = true;
                }
                break;
            case RTNET_DHCP_OPT_DOMAIN_NAME:
                {
                    std::string domainName = g_ConfigurationManager->getString(u8Req);
                    if (domainName == g_ConfigurationManager->m_noString)
                    {
                        fIgnore = true;
                        break;
                    }

                    char *pszDomainName = (char *)&opt.au8RawOpt[0];

                    strcpy(pszDomainName, domainName.c_str());
                    opt.cbRawOpt = domainName.length();
                }
                break;
            default:
                {
                    DhcpOptionMap::const_iterator it = OptMap.find((int)u8Req);
                    if (it == OptMap.end())
                    {
                        Log(("opt: %d is ignored\n", u8Req));
                        fIgnore = true;
                    }
                    else
                    {
                        std::string OptText((*it).second.first);
                        int OptEncoding((*it).second.second);

                        rc = fillDhcpOption(opt, OptText, OptEncoding);
                        if (!RT_SUCCESS(rc))
                        {
                            fIgnore = true;
                            break;
                        }
                    }
                }
                break;
        }

        if (!fIgnore)
            extra.push_back(opt);

    }

    return VINF_SUCCESS;
}
Esempio n. 3
0
/**
 * Handles the getregisters sub-command.
 *
 * @returns Suitable exit code.
 * @param   pArgs               The handler arguments.
 * @param   pDebugger           Pointer to the debugger interface.
 */
static RTEXITCODE handleDebugVM_GetRegisters(HandlerArg *pArgs, IMachineDebugger *pDebugger)
{
    /*
     * We take a list of register names (case insensitive).  If 'all' is
     * encountered we'll dump all registers.
     */
    ULONG                       idCpu = 0;
    unsigned                    cRegisters = 0;

    RTGETOPTSTATE               GetState;
    RTGETOPTUNION               ValueUnion;
    static const RTGETOPTDEF    s_aOptions[] =
    {
        { "--cpu", 'c', RTGETOPT_REQ_UINT32 },
    };
    int rc = RTGetOptInit(&GetState, pArgs->argc, pArgs->argv, s_aOptions, RT_ELEMENTS(s_aOptions), 2, RTGETOPTINIT_FLAGS_OPTS_FIRST);
    AssertRCReturn(rc, RTEXITCODE_FAILURE);

    while ((rc = RTGetOpt(&GetState, &ValueUnion)) != 0)
    {
        switch (rc)
        {
            case 'c':
                idCpu = ValueUnion.u32;
                break;

            case VINF_GETOPT_NOT_OPTION:
                if (!RTStrICmp(ValueUnion.psz, "all"))
                {
                    com::SafeArray<BSTR> aBstrNames;
                    com::SafeArray<BSTR> aBstrValues;
                    CHECK_ERROR2I_RET(pDebugger, GetRegisters(idCpu, ComSafeArrayAsOutParam(aBstrNames),
                                                              ComSafeArrayAsOutParam(aBstrValues)),
                                      RTEXITCODE_FAILURE);
                    Assert(aBstrNames.size() == aBstrValues.size());

                    size_t cchMaxName  = 8;
                    for (size_t i = 0; i < aBstrNames.size(); i++)
                    {
                        size_t cchName = RTUtf16Len(aBstrNames[i]);
                        if (cchName > cchMaxName)
                            cchMaxName = cchName;
                    }

                    for (size_t i = 0; i < aBstrNames.size(); i++)
                        RTPrintf("%-*ls = %ls\n", cchMaxName, aBstrNames[i], aBstrValues[i]);
                }
                else
                {
                    com::Bstr bstrName = ValueUnion.psz;
                    com::Bstr bstrValue;
                    CHECK_ERROR2I_RET(pDebugger, GetRegister(idCpu, bstrName.raw(), bstrValue.asOutParam()), RTEXITCODE_FAILURE);
                    RTPrintf("%s = %ls\n", ValueUnion.psz, bstrValue.raw());
                }
                cRegisters++;
                break;

            default:
                return errorGetOpt(rc, &ValueUnion);
        }
    }

    if (!cRegisters)
        return errorSyntax("The getregisters sub-command takes at least one register name");
    return RTEXITCODE_SUCCESS;
}