GuestProcessImpl.cpp revision f044158ee9eb7045a43f2c4ef2fbc07cb11329ae
4a5d1cb72abd351221a0d5bdce3a01b071f697a9vboxsync * VirtualBox Main - Guest process handling.
4a5d1cb72abd351221a0d5bdce3a01b071f697a9vboxsync * Copyright (C) 2012-2013 Oracle Corporation
4a5d1cb72abd351221a0d5bdce3a01b071f697a9vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
4a5d1cb72abd351221a0d5bdce3a01b071f697a9vboxsync * available from http://www.virtualbox.org. This file is free software;
4a5d1cb72abd351221a0d5bdce3a01b071f697a9vboxsync * you can redistribute it and/or modify it under the terms of the GNU
4a5d1cb72abd351221a0d5bdce3a01b071f697a9vboxsync * General Public License (GPL) as published by the Free Software
4a5d1cb72abd351221a0d5bdce3a01b071f697a9vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
4a5d1cb72abd351221a0d5bdce3a01b071f697a9vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
4a5d1cb72abd351221a0d5bdce3a01b071f697a9vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
4a5d1cb72abd351221a0d5bdce3a01b071f697a9vboxsync * Locking rules:
4a5d1cb72abd351221a0d5bdce3a01b071f697a9vboxsync * - When the main dispatcher (callbackDispatcher) is called it takes the
4a5d1cb72abd351221a0d5bdce3a01b071f697a9vboxsync * WriteLock while dispatching to the various on* methods.
4a5d1cb72abd351221a0d5bdce3a01b071f697a9vboxsync * - All other outer functions (accessible by Main) must not own a lock
4a5d1cb72abd351221a0d5bdce3a01b071f697a9vboxsync * while waiting for a callback or for an event.
4a5d1cb72abd351221a0d5bdce3a01b071f697a9vboxsync * - Only keep Read/WriteLocks as short as possible and only when necessary.
4a5d1cb72abd351221a0d5bdce3a01b071f697a9vboxsync/*******************************************************************************
4a5d1cb72abd351221a0d5bdce3a01b071f697a9vboxsync* Header Files *
4a5d1cb72abd351221a0d5bdce3a01b071f697a9vboxsync*******************************************************************************/
4a5d1cb72abd351221a0d5bdce3a01b071f697a9vboxsync virtual ~GuestProcessTask(void) { }
4a5d1cb72abd351221a0d5bdce3a01b071f697a9vboxsync const ComObjPtr<GuestProcess> &Process(void) const { return mProcess; }
4a5d1cb72abd351221a0d5bdce3a01b071f697a9vboxsyncclass GuestProcessStartTask : public GuestProcessTask
4a5d1cb72abd351221a0d5bdce3a01b071f697a9vboxsync * Internal listener class to serve events in an
4a5d1cb72abd351221a0d5bdce3a01b071f697a9vboxsync * active manner, e.g. without polling delays.
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;
LogFlowFunc(("Stale guest process (PID=%RU32) sent data to a newly started process (pProcesS=%p, PID=%RU32, status=%RU32)\n",
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::onGuestDisconnected(PVBOXGUESTCTRLHOSTCBCTX pCbCtx, PVBOXGUESTCTRLHOSTCALLBACK pSvcCbData)
return vrc;
int GuestProcess::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::onProcessNotifyIO(PVBOXGUESTCTRLHOSTCBCTX pCbCtx, PVBOXGUESTCTRLHOSTCALLBACK pSvcCbData)
return VERR_NOT_IMPLEMENTED;
int GuestProcess::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::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;
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;
AssertMsg(RT_FAILURE(mData.mLastError), ("No error rc (%Rrc) set when guest process indicated an error\n", mData.mLastError));
if (pGuestRc)
return VERR_GSTCTL_GUEST_ERROR;
if (pGuestRc)
if (!uTimeoutMS)
int vrc;
return vrc;
#ifdef DEBUG
return vrc;
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;
LogFlowThisFunc(("uPID=%RU32, uHandle=%RU32, uFlags=%RU32, pvData=%p, cbData=%RU32, uTimeoutMS=%RU32, puWritten=%p, pGuestRc=%p\n",
if (puWritten)
*puWritten = 0;
if (pGuestRc)
int vrc;
return vrc;
if (puWritten)
return vrc;
STDMETHODIMP GuestProcess::Read(ULONG aHandle, ULONG aToRead, ULONG aTimeoutMS, ComSafeArrayOut(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;
STDMETHODIMP GuestProcess::WaitFor(ULONG aWaitFlags, ULONG aTimeoutMS, ProcessWaitResult_T *aReason)
#ifndef VBOX_WITH_GUEST_CONTROL
switch (vrc)
case VERR_GSTCTL_GUEST_ERROR:
case VERR_TIMEOUT:
return hr;
STDMETHODIMP GuestProcess::WaitForArray(ComSafeArrayIn(ProcessWaitForFlag_T, aFlags), ULONG aTimeoutMS, ProcessWaitResult_T *aReason)
#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 (!IsRunning())
if (pExitCode)
return vrc;
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;