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; }
/** * 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; }