GuestSessionImpl.cpp revision a2681b6f21b225939d0e598990588bf3a800dc32
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync * VirtualBox Main - Guest session handling.
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync * Copyright (C) 2012-2014 Oracle Corporation
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync * available from http://www.virtualbox.org. This file is free software;
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync * you can redistribute it and/or modify it under the terms of the GNU
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync * General Public License (GPL) as published by the Free Software
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync/*******************************************************************************
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync* Header Files *
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync*******************************************************************************/
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync * Base class representing an internal
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync * asynchronous session task.
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync virtual ~GuestSessionTaskInternal(void) { }
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync const ComObjPtr<GuestSession> &Session(void) const { return mSession; }
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync * Class for asynchronously opening a guest session.
ee5869bb73f07de9c139dc6a608836a7b5767933vboxsyncclass GuestSessionTaskInternalOpen : public GuestSessionTaskInternal
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync GuestSessionTaskInternalOpen(GuestSession *pSession)
482a222498aae619afda0255a7edf4ebda97268cvboxsync * Internal listener class to serve events in an
a96ed55e8e1b248965a3d29d6e4c3116979e887bvboxsync * active manner, e.g. without polling delays.
4831e82ecaa3c813398d2f343e9d38ee34a3acf4vboxsync STDMETHOD(HandleEvent)(VBoxEventType_T aType, IEvent *aEvent)
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync int rc2 = mSession->signalWaitEvent(aType, aEvent);
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync LogFlowFunc(("Signalling events of type=%RU32, session=%p resulted in rc=%Rrc\n",
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync AssertMsgFailed(("Unhandled event %RU32\n", aType));
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsynctypedef ListenerImpl<GuestSessionListener, GuestSession*> GuestSessionListenerImpl;
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync// constructor / destructor
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync/////////////////////////////////////////////////////////////////////////////
611af5c9fc04865215e86b6e4906c9dfdfb6a381vboxsync// public initializer/uninitializer for internal purposes only
611af5c9fc04865215e86b6e4906c9dfdfb6a381vboxsync/////////////////////////////////////////////////////////////////////////////
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync * Initializes a guest session but does *not* open in on the guest side
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync * yet. This needs to be done via the openSession() / openSessionAsync calls.
f9cac318205d74ee5b35dabcf2bd39118f6293d7vboxsync * @return IPRT status code.
4831e82ecaa3c813398d2f343e9d38ee34a3acf4vboxsync ** @todo Docs!
4831e82ecaa3c813398d2f343e9d38ee34a3acf4vboxsyncint GuestSession::init(Guest *pGuest, const GuestSessionStartupInfo &ssInfo,
611af5c9fc04865215e86b6e4906c9dfdfb6a381vboxsync LogFlowThisFunc(("pGuest=%p, ssInfo=%p, guestCreds=%p\n",
4831e82ecaa3c813398d2f343e9d38ee34a3acf4vboxsync /* Enclose the state transition NotReady->InInit->Ready. */
8184f68cdef3c26869cdebc6a18829c854d0d17dvboxsync AssertReturn(autoInitSpan.isOk(), VERR_OBJECT_DESTROYED);
return rc;
#ifdef VBOX_WITH_GUEST_CONTROL
baseUninit();
#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;
#ifndef VBOX_WITH_GUEST_CONTROL
return S_OK;
#ifndef VBOX_WITH_GUEST_CONTROL
return S_OK;
#ifndef VBOX_WITH_GUEST_CONTROL
return hr;
#ifndef VBOX_WITH_GUEST_CONTROL
size_t i = 0;
++it, ++i)
return S_OK;
#ifndef VBOX_WITH_GUEST_CONTROL
size_t i = 0;
++it, ++i)
return S_OK;
#ifndef VBOX_WITH_GUEST_CONTROL
size_t i = 0;
return S_OK;
#ifndef VBOX_WITH_GUEST_CONTROL
return S_OK;
LogFlowThisFunc(("Installed Guest Additions don't support closing dedicated sessions, skipping\n"));
return VINF_SUCCESS;
return VINF_SUCCESS;
int vrc;
return vrc;
return vrc;
if (uFlags)
procInfo.mArguments.push_back(Utf8Str("--parents")); /* We also want to create the parent directories. */
if (uMode)
return vrc;
if (pDir)
int GuestSession::i_directoryQueryInfoInternal(const Utf8Str &strPath, GuestFsObjData &objData, int *pGuestRc)
return vrc;
LogFlowFunc(("Removing directory \"%s\" (Session: %RU32) (now total %zu processes, %RU32 objects)\n",
Utf8Str(strName).c_str(), mData.mSession.mID, mData.mDirectories.size() - 1, mData.mNumObjects - 1));
itDirs++;
return rc;
int *pGuestRc)
&pEvent);
return vrc;
&& pGuestRc)
return vrc;
if (fDirectory)
&guestRc);
if (pGuestRc)
return vrc;
return rc;
uNewDirID++;
uNewDirID = 0;
return rc;
return VERR_COM_UNEXPECTED;
return vrc;
LogFlowFunc(("Added new guest directory \"%s\" (Session: %RU32) (now total %zu dirs, %RU32 objects)\n",
if (pGuestRc)
return vrc;
int GuestSession::i_dispatchToDirectory(PVBOXGUESTCTRLHOSTCBCTX pCtxCb, PVBOXGUESTCTRLHOSTCALLBACK pSvcCb)
return VERR_INVALID_PARAMETER;
#ifdef DEBUG
int rc;
return rc;
int GuestSession::i_dispatchToFile(PVBOXGUESTCTRLHOSTCBCTX pCtxCb, PVBOXGUESTCTRLHOSTCALLBACK pSvcCb)
#ifdef DEBUG
int rc;
return rc;
int GuestSession::i_dispatchToObject(PVBOXGUESTCTRLHOSTCBCTX pCtxCb, PVBOXGUESTCTRLHOSTCALLBACK pSvcCb)
int rc;
return rc;
int GuestSession::i_dispatchToProcess(PVBOXGUESTCTRLHOSTCBCTX pCtxCb, PVBOXGUESTCTRLHOSTCALLBACK pSvcCb)
#ifdef DEBUG
int rc;
#ifdef DEBUG_andy
return rc;
int GuestSession::i_dispatchToThis(PVBOXGUESTCTRLHOSTCBCTX pCbCtx, PVBOXGUESTCTRLHOSTCALLBACK pSvcCb)
#ifdef DEBUG
int rc;
case GUEST_DISCONNECTED:
return rc;
if (pFile)
LogFlowThisFunc(("Removing guest file \"%s\" (Session: %RU32) (now total %zu files, %RU32 objects)\n",
itFiles++;
return rc;
return vrc;
LogFlowThisFunc(("strPath=%s, strOpenMode=%s, strDisposition=%s, uCreationMode=%x, uOffset=%RU64\n",
return VERR_NOT_SUPPORTED;
return rc;
uNewFileID++;
uNewFileID = 0;
return rc;
return VERR_COM_UNEXPECTED;
return rc;
int guestRc;
&& pGuestRc)
return rc;
int GuestSession::i_fileQueryInfoInternal(const Utf8Str &strPath, GuestFsObjData &objData, int *pGuestRc)
return vrc;
return vrc;
int GuestSession::i_fsQueryInfoInternal(const Utf8Str &strPath, GuestFsObjData &objData, int *pGuestRc)
&guestRc);
&& pGuestRc)
return vrc;
switch (guestRc)
case VERR_INVALID_VM_HANDLE:
case VERR_TIMEOUT:
case VERR_CANCELLED:
case VERR_PERMISSION_DENIED:
case VERR_MAX_PROCS_REACHED:
case VERR_NOT_FOUND:
return strError;
return S_OK;
return vrc;
int GuestSession::i_onSessionStatusChange(PVBOXGUESTCTRLHOSTCBCTX pCbCtx, PVBOXGUESTCTRLHOSTCALLBACK pSvcCbData)
return VERR_INVALID_PARAMETER;
return vrc;
LogFlowThisFunc(("mID=%RU32, mName=%s, uProtocolVersion=%RU32, openFlags=%x, openTimeoutMS=%RU32\n",
LogFlowThisFunc(("Installed Guest Additions don't support opening dedicated sessions, skipping\n"));
return VINF_SUCCESS;
return VINF_SUCCESS;
int vrc;
return vrc;
return vrc;
int vrc;
return vrc;
std::auto_ptr<GuestSessionTaskInternalOpen> pTask(static_cast<GuestSessionTaskInternalOpen*>(pvUser));
return vrc;
&pEvent);
return vrc;
&& pGuestRc)
return vrc;
#ifdef DEBUG_andy
LogFlowFunc(("Removing process ID=%RU32 (Session: %RU32), guest PID=%RU32 (now total %zu processes, %RU32 objects)\n",
pProcess->getObjectID(), mData.mSession.mID, uPID, mData.mProcesses.size() - 1, mData.mNumObjects - 1));
itProcs++;
return rc;
int GuestSession::i_processCreateExInteral(GuestProcessStartupInfo &procInfo, ComObjPtr<GuestProcess> &pProcess)
#ifdef DEBUG
it++;
return VERR_INVALID_PARAMETER;
return VERR_INVALID_PARAMETER;
return rc;
uNewProcessID = 0;
return rc;
return VERR_COM_UNEXPECTED;
return rc;
LogFlowFunc(("Added new process (Session: %RU32) with process ID=%RU32 (now total %zu processes, %RU32 objects)\n",
return rc;
if (pProcess)
return VERR_COM_INVALID_OBJECT_STATE;
if (pProcess)
return VINF_SUCCESS;
return VERR_NOT_FOUND;
#ifndef VBOX_GUESTCTRL_TEST_CASE
return vrc;
return pInterface->setError(VBOX_E_IPRT_ERROR, GuestSession::i_guestErrorToString(guestRc).c_str());
return VINF_SUCCESS;
int GuestSession::i_signalWaiters(GuestSessionWaitResult_T enmWaitResult, int rc /*= VINF_SUCCESS */)
return vrc;
return VERR_COM_UNEXPECTED;
return VERR_COM_UNEXPECTED;
return rc;
return rc;
#ifdef DEBUG_andy
static short s_gctrlLegacyWarning = 0;
LogRel((tr("Warning: Guest Additions are older (%ld.%ld) than host capabilities for guest control, please upgrade them. Using protocol version %ld now\n"),
return VINF_SUCCESS;
int GuestSession::i_waitFor(uint32_t fWaitFlags, ULONG uTimeoutMS, GuestSessionWaitResult_T &waitResult, int *pGuestRc)
/*LogFlowThisFunc(("fWaitFlags=0x%x, uTimeoutMS=%RU32, mStatus=%RU32, mWaitCount=%RU32, mWaitEvent=%p, pGuestRc=%p\n",
AssertMsg(RT_FAILURE(mData.mRC), ("No error rc (%Rrc) set when guest session indicated an error\n", mData.mRC));
if (pGuestRc)
return VERR_GSTCTL_GUEST_ERROR;
LogFlowThisFunc(("Installed Guest Additions don't support waiting for dedicated sessions, skipping\n"));
return VINF_SUCCESS;
case GuestSessionStatus_Down:
case GuestSessionStatus_Error:
return VERR_NOT_IMPLEMENTED;
case GuestSessionStatus_Down:
case GuestSessionStatus_Error:
return VERR_NOT_IMPLEMENTED;
if (pGuestRc)
int vrc;
return vrc;
switch (sessionStatus)
case GuestSessionStatus_Down:
case GuestSessionStatus_Error:
return vrc;
int GuestSession::i_waitForStatusChange(GuestWaitEvent *pEvent, uint32_t fWaitFlags, uint32_t uTimeoutMS,
if (pSessionStatus)
if (pGuestRc)
return vrc;
#ifndef VBOX_WITH_GUEST_CONTROL
&guestRc);
return S_OK;
#ifndef VBOX_WITH_GUEST_CONTROL
int rc = i_startTaskAsync(Utf8StrFmt(tr("Copying \"%s\" from guest to \"%s\" on the host"), aSource.c_str(),
return hr;
HRESULT GuestSession::copyTo(const com::Utf8Str &aSource, const com::Utf8Str &aDest, const std::vector<CopyFileFlag_T> &aFlags,
#ifndef VBOX_WITH_GUEST_CONTROL
int rc = i_startTaskAsync(Utf8StrFmt(tr("Copying \"%s\" from host to \"%s\" on the guest"), aSource.c_str(),
return hr;
#ifndef VBOX_WITH_GUEST_CONTROL
if (fFlags)
switch (rc)
case VERR_GSTCTL_GUEST_ERROR:
case VERR_INVALID_PARAMETER:
case VERR_BROKEN_PIPE:
return hr;
HRESULT GuestSession::directoryCreateTemp(const com::Utf8Str &aTemplateName, ULONG aMode, const com::Utf8Str &aPath,
#ifndef VBOX_WITH_GUEST_CONTROL
int guestRc;
switch (rc)
case VERR_GSTCTL_GUEST_ERROR:
hr = setError(VBOX_E_IPRT_ERROR, tr("Temporary directory creation \"%s\" with template \"%s\" failed: %Rrc"),
return hr;
#ifndef VBOX_WITH_GUEST_CONTROL
switch (rc)
case VERR_GSTCTL_GUEST_ERROR:
return hr;
#ifndef VBOX_WITH_GUEST_CONTROL
if (fFlags)
switch (rc)
case VERR_INVALID_PARAMETER:
case VERR_GSTCTL_GUEST_ERROR:
return hr;
#ifndef VBOX_WITH_GUEST_CONTROL
switch (vrc)
case VERR_GSTCTL_GUEST_ERROR:
case VERR_NOT_A_DIRECTORY:
return hr;
#ifndef VBOX_WITH_GUEST_CONTROL
return hr;
int guestRc;
switch (vrc)
case VERR_NOT_SUPPORTED:
case VERR_GSTCTL_GUEST_ERROR:
return hr;
HRESULT GuestSession::directoryRemoveRecursive(const com::Utf8Str &aPath, const std::vector<DirectoryRemoveRecFlag_T> &aFlags,
#ifndef VBOX_WITH_GUEST_CONTROL
return hr;
return hr;
return hr;
int guestRc;
switch (vrc)
case VERR_NOT_SUPPORTED:
case VERR_GSTCTL_GUEST_ERROR:
return hr;
#ifndef VBOX_WITH_GUEST_CONTROL
return hr;
int guestRc;
switch (vrc)
case VERR_NOT_SUPPORTED:
case VERR_GSTCTL_GUEST_ERROR:
return hr;
#ifndef VBOX_WITH_GUEST_CONTROL
#ifndef VBOX_WITH_GUEST_CONTROL
return S_OK;
#ifndef VBOX_WITH_GUEST_CONTROL
return S_OK;
#ifndef VBOX_WITH_GUEST_CONTROL
return hr;
#ifndef VBOX_WITH_GUEST_CONTROL
return S_OK;
HRESULT GuestSession::fileCreateTemp(const com::Utf8Str &aTemplateName, ULONG aMode, const com::Utf8Str &aPath, BOOL aSecure,
#ifndef VBOX_WITH_GUEST_CONTROL
#ifndef VBOX_WITH_GUEST_CONTROL
return S_OK;
switch (vrc)
case VERR_GSTCTL_GUEST_ERROR:
case VERR_NOT_A_FILE:
return hr;
#ifndef VBOX_WITH_GUEST_CONTROL
int guestRc;
switch (vrc)
case VERR_GSTCTL_GUEST_ERROR:
return hr;
HRESULT GuestSession::fileOpen(const com::Utf8Str &aPath, const com::Utf8Str &aOpenMode, const com::Utf8Str &aDisposition,
#ifndef VBOX_WITH_GUEST_CONTROL
HRESULT GuestSession::fileOpenEx(const com::Utf8Str &aPath, const com::Utf8Str &aOpenMode, const com::Utf8Str &aDisposition,
#ifndef VBOX_WITH_GUEST_CONTROL
return hr;
switch (vrc)
case VERR_NOT_SUPPORTED:
case VERR_GSTCTL_GUEST_ERROR:
return hr;
#ifndef VBOX_WITH_GUEST_CONTROL
switch (vrc)
case VERR_GSTCTL_GUEST_ERROR:
case VERR_NOT_A_FILE:
return hr;
#ifndef VBOX_WITH_GUEST_CONTROL
switch (vrc)
case VERR_GSTCTL_GUEST_ERROR:
return hr;
#ifndef VBOX_WITH_GUEST_CONTROL
return hr;
int guestRc;
switch (vrc)
case VERR_NOT_SUPPORTED:
case VERR_GSTCTL_GUEST_ERROR:
return hr;
#ifndef VBOX_WITH_GUEST_CONTROL
HRESULT GuestSession::processCreate(const com::Utf8Str &aCommand, const std::vector<com::Utf8Str> &aArguments,
#ifndef VBOX_WITH_GUEST_CONTROL
return processCreateEx(aCommand, aArguments, aEnvironment, aFlags, aTimeoutMS, ProcessPriority_Default,
HRESULT GuestSession::processCreateEx(const com::Utf8Str &aCommand, const std::vector<com::Utf8Str> &aArguments,
#ifndef VBOX_WITH_GUEST_CONTROL
return hr;
* have the chance of overwriting/deleting session entries.
if (aAffinity[i])
switch (rc)
case VERR_MAX_PROCS_REACHED:
hr = setError(VBOX_E_IPRT_ERROR, tr("Maximum number of concurrent guest processes per session (%ld) reached"),
return hr;
#ifndef VBOX_WITH_GUEST_CONTROL
if (aPid == 0)
return hr;
HRESULT GuestSession::symlinkCreate(const com::Utf8Str &aSource, const com::Utf8Str &aTarget, SymlinkType_T aType)
#ifndef VBOX_WITH_GUEST_CONTROL
#ifndef VBOX_WITH_GUEST_CONTROL
HRESULT GuestSession::symlinkRead(const com::Utf8Str &aSymlink, const std::vector<SymlinkReadFlag_T> &aFlags,
#ifndef VBOX_WITH_GUEST_CONTROL
#ifndef VBOX_WITH_GUEST_CONTROL
#ifndef VBOX_WITH_GUEST_CONTROL
#ifndef VBOX_WITH_GUEST_CONTROL
switch (vrc)
case VERR_GSTCTL_GUEST_ERROR:
case VERR_TIMEOUT:
return hr;
HRESULT GuestSession::waitForArray(const std::vector<GuestSessionWaitForFlag_T> &aWaitFor, ULONG aTimeoutMS,
#ifndef VBOX_WITH_GUEST_CONTROL