GuestProcessImpl.cpp revision b10a13ee0c4f4df2aa7cf2b164f0073fbd42e93c
65fea56f17cd614bc8908264df980a62e1931468vboxsync * VirtualBox Main - Guest process handling.
65fea56f17cd614bc8908264df980a62e1931468vboxsync * Copyright (C) 2012-2013 Oracle Corporation
65fea56f17cd614bc8908264df980a62e1931468vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
65fea56f17cd614bc8908264df980a62e1931468vboxsync * available from http://www.virtualbox.org. This file is free software;
65fea56f17cd614bc8908264df980a62e1931468vboxsync * you can redistribute it and/or modify it under the terms of the GNU
65fea56f17cd614bc8908264df980a62e1931468vboxsync * General Public License (GPL) as published by the Free Software
65fea56f17cd614bc8908264df980a62e1931468vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
65fea56f17cd614bc8908264df980a62e1931468vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
65fea56f17cd614bc8908264df980a62e1931468vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
65fea56f17cd614bc8908264df980a62e1931468vboxsync * Locking rules:
65fea56f17cd614bc8908264df980a62e1931468vboxsync * - When the main dispatcher (callbackDispatcher) is called it takes the
65fea56f17cd614bc8908264df980a62e1931468vboxsync * WriteLock while dispatching to the various on* methods.
65fea56f17cd614bc8908264df980a62e1931468vboxsync * - All other outer functions (accessible by Main) must not own a lock
65fea56f17cd614bc8908264df980a62e1931468vboxsync * while waiting for a callback or for an event.
65fea56f17cd614bc8908264df980a62e1931468vboxsync * - Only keep Read/WriteLocks as short as possible and only when necessary.
65fea56f17cd614bc8908264df980a62e1931468vboxsync/*******************************************************************************
65fea56f17cd614bc8908264df980a62e1931468vboxsync* Header Files *
65fea56f17cd614bc8908264df980a62e1931468vboxsync*******************************************************************************/
#ifdef LOG_GROUP
class GuestProcessTask
virtual ~GuestProcessTask(void) { }
int mRC;
class GuestProcessListener
GuestProcessListener(void)
return S_OK;
void uninit(void)
switch (aType)
#ifdef DEBUG
return S_OK;
return BaseFinalConstruct();
uninit();
// public initializer/uninitializer for internal purposes only
#ifndef VBOX_WITH_GUEST_CONTROL
return VINF_SUCCESS;
return vrc;
return vrc;
#ifdef VBOX_WITH_GUEST_CONTROL
baseUninit();
#ifndef VBOX_WITH_GUEST_CONTROL
size_t s = 0;
it++, s++)
return S_OK;
#ifndef VBOX_WITH_GUEST_CONTROL
return S_OK;
#ifndef VBOX_WITH_GUEST_CONTROL
return S_OK;
#ifndef VBOX_WITH_GUEST_CONTROL
return S_OK;
#ifndef VBOX_WITH_GUEST_CONTROL
return S_OK;
#ifndef VBOX_WITH_GUEST_CONTROL
return S_OK;
#ifndef VBOX_WITH_GUEST_CONTROL
return S_OK;
#ifndef VBOX_WITH_GUEST_CONTROL
return S_OK;
int GuestProcess::i_callbackDispatcher(PVBOXGUESTCTRLHOSTCBCTX pCbCtx, PVBOXGUESTCTRLHOSTCALLBACK pSvcCb)
#ifdef DEBUG
int vrc;
case GUEST_DISCONNECTED:
case GUEST_EXEC_STATUS:
case GUEST_EXEC_OUTPUT:
case GUEST_EXEC_INPUT_STATUS:
#ifdef DEBUG
return vrc;
return rc;
switch (guestRc)
case VERR_INVALID_VM_HANDLE:
case VERR_PATH_NOT_FOUND:
case VERR_BAD_EXE_FORMAT:
case VERR_INVALID_NAME:
case VERR_TIMEOUT:
case VERR_CANCELLED:
case VERR_PERMISSION_DENIED:
case VERR_MAX_PROCS_REACHED:
case VERR_NOT_FOUND:
return strError;
int GuestProcess::i_onGuestDisconnected(PVBOXGUESTCTRLHOSTCBCTX pCbCtx, PVBOXGUESTCTRLHOSTCALLBACK pSvcCbData)
return vrc;
int GuestProcess::i_onProcessInputStatus(PVBOXGUESTCTRLHOSTCBCTX pCbCtx, PVBOXGUESTCTRLHOSTCALLBACK pSvcCbData)
return VERR_INVALID_PARAMETER;
case INPUT_STS_WRITTEN:
case INPUT_STS_ERROR:
case INPUT_STS_TERMINATED:
case INPUT_STS_OVERFLOW:
case INPUT_STS_UNDEFINED:
return vrc;
int GuestProcess::i_onProcessNotifyIO(PVBOXGUESTCTRLHOSTCBCTX pCbCtx, PVBOXGUESTCTRLHOSTCALLBACK pSvcCbData)
return VERR_NOT_IMPLEMENTED;
int GuestProcess::i_onProcessStatusChange(PVBOXGUESTCTRLHOSTCBCTX pCbCtx, PVBOXGUESTCTRLHOSTCALLBACK pSvcCbData)
return VERR_INVALID_PARAMETER;
case PROC_STS_STARTED:
case PROC_STS_TEN:
case PROC_STS_TES:
case PROC_STS_TEA:
case PROC_STS_TOK:
case PROC_STS_TOA:
case PROC_STS_DWN:
case PROC_STS_ERROR:
case PROC_STS_UNDEFINED:
return vrc;
int GuestProcess::i_onProcessOutput(PVBOXGUESTCTRLHOSTCBCTX pCbCtx, PVBOXGUESTCTRLHOSTCALLBACK pSvcCbData)
return VERR_INVALID_PARAMETER;
return vrc;
return vrc;
LogFlowThisFunc(("uPID=%RU32, uHandle=%RU32, uSize=%RU32, uTimeoutMS=%RU32, pvData=%p, cbData=%RU32, pGuestRc=%p\n",
if (pcbRead)
*pcbRead = 0;
if (pGuestRc)
int vrc;
return vrc;
return vrc;
&& hasEnded())
return rc;
return pInterface->setError(VBOX_E_IPRT_ERROR, GuestProcess::i_guestErrorToString(guestRc).c_str());
LogFlowThisFunc(("uTimeoutMS=%RU32, procCmd=%s, procTimeoutMS=%RU32, procFlags=%x, sessionID=%RU32\n",
int vrc;
return vrc;
&& cArgs)
if (papszArgv)
size_t i = 0;
while (papszArgv[i])
paParms[i++].setPointer((void*)sessionCreds.mPassword.c_str(), (ULONG)sessionCreds.mPassword.length() + 1);
if (pszArgs)
return vrc;
int vrc;
return vrc;
return vrc;
return vrc;
return vrc;
switch (newStatus)
case ProcessStatus_Down:
case ProcessStatus_Started:
switch (oldStatus)
case ProcessStatus_Undefined:
case ProcessStatus_Starting:
case ProcessStatus_Started:
oldStatus));
case ProcessStatus_Error:
case ProcessStatus_Undefined:
case ProcessStatus_Starting:
#ifdef DEBUG
return waitResult;
if (pGuestRc)
return VERR_GSTCTL_GUEST_ERROR;
if (pGuestRc)
if (!uTimeoutMS)
int vrc;
return vrc;
#ifdef DEBUG
return vrc;
int GuestProcess::i_waitForInputNotify(GuestWaitEvent *pEvent, uint32_t uHandle, uint32_t uTimeoutMS,
if (pInputStatus)
if (pcbProcessed)
return vrc;
LogFlowThisFunc(("cEventTypes=%zu, pEvent=%p, uHandle=%RU32, uTimeoutMS=%RU32, pvData=%p, cbData=%zu, pcbRead=%p\n",
int vrc;
if (pvData)
if (cbRead)
&& pcbRead)
&& pcbRead)
*pcbRead = 0;
return vrc;
if (pProcessStatus)
if (pGuestRc)
return vrc;
bool fImplies;
switch (waitResult)
case ProcessWaitResult_Start:
fImplies = false;
return fImplies;
str = "uPID=%RU32, uHandle=%RU32, uFlags=%RU32, pvData=%p, cbData=%RU32, uTimeoutMS=%RU32, puWritten=%p, pGuestRc=%p\n";
LogFlowThisFunc((str.c_str(), mData.mPID, uHandle, uFlags, pvData, cbData, uTimeoutMS, puWritten, pGuestRc));
if (puWritten)
*puWritten = 0;
if (pGuestRc)
int vrc;
return vrc;
if (puWritten)
return vrc;
HRESULT GuestProcess::read(ULONG aHandle, ULONG aToRead, ULONG aTimeoutMS, std::vector<BYTE> &aData)
#ifndef VBOX_WITH_GUEST_CONTROL
if (aToRead == 0)
switch (vrc)
case VERR_GSTCTL_GUEST_ERROR:
return hr;
#ifndef VBOX_WITH_GUEST_CONTROL
int guestRc;
&guestRc);
switch (vrc)
case VERR_GSTCTL_GUEST_ERROR:
case VERR_NOT_SUPPORTED:
return hr;
#ifndef VBOX_WITH_GUEST_CONTROL
switch (vrc)
case VERR_GSTCTL_GUEST_ERROR:
case VERR_TIMEOUT:
return hr;
#ifndef VBOX_WITH_GUEST_CONTROL
#ifndef VBOX_WITH_GUEST_CONTROL
switch (vrc)
case VERR_GSTCTL_GUEST_ERROR:
return hr;
#ifndef VBOX_WITH_GUEST_CONTROL
&& !fAsync
&& ( pGuestRc
return vrc;
if (!pStream)
return VERR_INVALID_PARAMETER;
int vrc;
return vrc;
int *pGuestRc)
pGuestRc);
int *pGuestRc)
while (cStrmOutObjects--)
if (pStrmOutObjects)
if (pGuestRc)
return vrc;
int vrc;
if (!i_isRunning())
if (pExitCode)
return vrc;
int GuestProcessTool::i_waitEx(uint32_t fFlags, GuestProcessStreamBlock *pStrmBlkOut, int *pGuestRc)
int vrc;
return vrc;
int guestRc;
bool fDone = false;
bool fHandleStdOut = false;
bool fHandleStdErr = false;
#define UPDATE_AND_CHECK_ELAPSED_TIME() \
#define GET_REMAINING_TIME \
switch (waitRes)
case ProcessWaitResult_StdIn:
case ProcessWaitResult_StdOut:
fHandleStdOut = true;
case ProcessWaitResult_StdErr:
fHandleStdErr = true;
fHandleStdOut = true;
fHandleStdErr = true;
case ProcessWaitResult_Error:
fDone = true;
case ProcessWaitResult_Start:
case ProcessWaitResult_Status:
if (fHandleStdOut)
cbRead = 0;
if (cbRead)
fDone = true;
fHandleStdOut = false;
if (fHandleStdErr)
cbRead = 0;
if (cbRead)
fHandleStdErr = false;
if (pGuestRc)
return vrc;
return rc;