GuestProcessImpl.h revision 5050fc8de0b121eab1b738d7c1007cde4903284d
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/* $Id$ */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/** @file
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * VirtualBox Main - XXX.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync/*
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Copyright (C) 2012 Oracle Corporation
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync *
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * available from http://www.virtualbox.org. This file is free software;
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * you can redistribute it and/or modify it under the terms of the GNU
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * General Public License (GPL) as published by the Free Software
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync */
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync#ifndef ____H_GUESTPROCESSIMPL
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#define ____H_GUESTPROCESSIMPL
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#include "VirtualBoxBase.h"
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#include "GuestCtrlImplPrivate.h"
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncclass Console;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncclass GuestSession;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/**
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * TODO
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync */
7e960d3a0a8a3a84d7aba2cca45d72b1c31cc97bvboxsyncclass ATL_NO_VTABLE GuestProcess :
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync public VirtualBoxBase,
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync VBOX_SCRIPTABLE_IMPL(IGuestProcess)
d31ded334a29f575e23dc889b603b1a586759348vboxsync{
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncpublic:
d31ded334a29f575e23dc889b603b1a586759348vboxsync /** @name COM and internal init/term/mapping cruft.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @{ */
61fa69e2bc9fc9e7490feed1c020273f3ddb238dvboxsync VIRTUALBOXBASE_ADD_ERRORINFO_SUPPORT(GuestProcess, IGuestProcess)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync DECLARE_NOT_AGGREGATABLE(GuestProcess)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync DECLARE_PROTECT_FINAL_CONSTRUCT()
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync BEGIN_COM_MAP(GuestProcess)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync VBOX_DEFAULT_INTERFACE_ENTRIES(IGuestProcess)
b74ca013e5f201a2dd371e6c438433ceac12af30vboxsync COM_INTERFACE_ENTRY(IProcess)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync END_COM_MAP()
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync DECLARE_EMPTY_CTOR_DTOR(GuestProcess)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync int init(Console *aConsole, GuestSession *aSession, ULONG aProcessID, const GuestProcessStartupInfo &aProcInfo);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync void uninit(void);
590bfe12ce22cd3716448fbb9f4dc51664bfe5e2vboxsync HRESULT FinalConstruct(void);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync void FinalRelease(void);
223cf005b18af2c21352a70693ebaf0582f68ebcvboxsync /** @} */
223cf005b18af2c21352a70693ebaf0582f68ebcvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /** @name IProcess interface.
afed5ab737f4aacfae3fe73776f40e989190a7cavboxsync * @{ */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync STDMETHOD(COMGETTER(Arguments))(ComSafeArrayOut(BSTR, aArguments));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync STDMETHOD(COMGETTER(Environment))(ComSafeArrayOut(BSTR, aEnvironment));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync STDMETHOD(COMGETTER(ExecutablePath))(BSTR *aExecutablePath);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync STDMETHOD(COMGETTER(ExitCode))(LONG *aExitCode);
0174432b2b1a760b89840ba696f7ba51def65dddvboxsync STDMETHOD(COMGETTER(Name))(BSTR *aName);
2daaccf68be3773aee600c5c3e48bcf5401418a6vboxsync STDMETHOD(COMGETTER(PID))(ULONG *aPID);
0174432b2b1a760b89840ba696f7ba51def65dddvboxsync STDMETHOD(COMGETTER(Status))(ProcessStatus_T *aStatus);
614cbe11a7e5588dc8d369e223174b1441a09359vboxsync
614cbe11a7e5588dc8d369e223174b1441a09359vboxsync STDMETHOD(Read)(ULONG aHandle, ULONG aToRead, ULONG aTimeoutMS, ComSafeArrayOut(BYTE, aData));
614cbe11a7e5588dc8d369e223174b1441a09359vboxsync STDMETHOD(Terminate)(void);
7666082b743c5e146a8cee6cc794ff4bc3fd0ffdvboxsync STDMETHOD(WaitFor)(ULONG aWaitFlags, ULONG aTimeoutMS, ProcessWaitResult_T *aReason);
7666082b743c5e146a8cee6cc794ff4bc3fd0ffdvboxsync STDMETHOD(WaitForArray)(ComSafeArrayIn(ProcessWaitForFlag_T, aFlags), ULONG aTimeoutMS, ProcessWaitResult_T *aReason);
7666082b743c5e146a8cee6cc794ff4bc3fd0ffdvboxsync STDMETHOD(Write)(ULONG aHandle, ULONG aFlags, ComSafeArrayIn(BYTE, aData), ULONG aTimeoutMS, ULONG *aWritten);
7666082b743c5e146a8cee6cc794ff4bc3fd0ffdvboxsync STDMETHOD(WriteArray)(ULONG aHandle, ComSafeArrayIn(ProcessInputFlag_T, aFlags), ComSafeArrayIn(BYTE, aData), ULONG aTimeoutMS, ULONG *aWritten);
7666082b743c5e146a8cee6cc794ff4bc3fd0ffdvboxsync /** @} */
7666082b743c5e146a8cee6cc794ff4bc3fd0ffdvboxsync
590bfe12ce22cd3716448fbb9f4dc51664bfe5e2vboxsyncpublic:
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /** @name Public internal methods.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @{ */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync int callbackDispatcher(uint32_t uContextID, uint32_t uFunction, void *pvData, size_t cbData);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync inline bool callbackExists(uint32_t uContextID);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync inline int checkPID(uint32_t uPID);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync static Utf8Str guestErrorToString(int guestRc);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync bool isReady(void);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync ULONG getProcessID(void) { return mData.mProcessID; }
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync int readData(uint32_t uHandle, uint32_t uSize, uint32_t uTimeoutMS, void *pvData, size_t cbData, size_t *pcbRead, int *pGuestRc);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync static HRESULT setErrorExternal(VirtualBoxBase *pInterface, int guestRc);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync int startProcess(int *pGuestRc);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync int startProcessAsync(void);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync int terminateProcess(void);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync int waitFor(uint32_t fWaitFlags, ULONG uTimeoutMS, ProcessWaitResult_T &waitResult, int *pGuestRc);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync int writeData(uint32_t uHandle, uint32_t uFlags, void *pvData, size_t cbData, uint32_t uTimeoutMS, uint32_t *puWritten, int *pGuestRc);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /** @} */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncprotected:
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /** @name Protected internal methods.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @{ */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync inline int callbackAdd(GuestCtrlCallback *pCallback, uint32_t *puContextID);
22e281e75ed636601178296c6daebda8f1d17c59vboxsync inline int callbackRemove(uint32_t uContextID);
22e281e75ed636601178296c6daebda8f1d17c59vboxsync inline bool isAlive(void);
22e281e75ed636601178296c6daebda8f1d17c59vboxsync int onGuestDisconnected(GuestCtrlCallback *pCallback, PCALLBACKDATACLIENTDISCONNECTED pData);
22e281e75ed636601178296c6daebda8f1d17c59vboxsync int onProcessInputStatus(GuestCtrlCallback *pCallback, PCALLBACKDATAEXECINSTATUS pData);
22e281e75ed636601178296c6daebda8f1d17c59vboxsync int onProcessNotifyIO(GuestCtrlCallback *pCallback, PCALLBACKDATAEXECSTATUS pData);
22e281e75ed636601178296c6daebda8f1d17c59vboxsync int onProcessStatusChange(GuestCtrlCallback *pCallback, PCALLBACKDATAEXECSTATUS pData);
22e281e75ed636601178296c6daebda8f1d17c59vboxsync int onProcessOutput(GuestCtrlCallback *pCallback, PCALLBACKDATAEXECOUT pData);
22e281e75ed636601178296c6daebda8f1d17c59vboxsync int prepareExecuteEnv(const char *pszEnv, void **ppvList, ULONG *pcbList, ULONG *pcEnvVars);
22e281e75ed636601178296c6daebda8f1d17c59vboxsync int sendCommand(uint32_t uFunction, uint32_t uParms, PVBOXHGCMSVCPARM paParms);
22e281e75ed636601178296c6daebda8f1d17c59vboxsync int setProcessStatus(ProcessStatus_T procStatus, int procRc);
22e281e75ed636601178296c6daebda8f1d17c59vboxsync int signalWaiters(ProcessWaitResult_T enmWaitResult, int rc = VINF_SUCCESS);
22e281e75ed636601178296c6daebda8f1d17c59vboxsync static DECLCALLBACK(int) startProcessThread(RTTHREAD Thread, void *pvUser);
22e281e75ed636601178296c6daebda8f1d17c59vboxsync /** @} */
22e281e75ed636601178296c6daebda8f1d17c59vboxsync
22e281e75ed636601178296c6daebda8f1d17c59vboxsyncprivate:
22e281e75ed636601178296c6daebda8f1d17c59vboxsync
22e281e75ed636601178296c6daebda8f1d17c59vboxsync struct Data
22e281e75ed636601178296c6daebda8f1d17c59vboxsync {
22e281e75ed636601178296c6daebda8f1d17c59vboxsync /** Pointer to parent session. Per definition
22e281e75ed636601178296c6daebda8f1d17c59vboxsync * this objects *always* lives shorter than the
22e281e75ed636601178296c6daebda8f1d17c59vboxsync * parent. */
22e281e75ed636601178296c6daebda8f1d17c59vboxsync GuestSession *mParent;
22e281e75ed636601178296c6daebda8f1d17c59vboxsync /** Pointer to the console object. Needed
7b80828e5760a8814fe6cd494d2715a4544fbddcvboxsync * for HGCM (VMMDev) communication. */
22e281e75ed636601178296c6daebda8f1d17c59vboxsync Console *mConsole;
22e281e75ed636601178296c6daebda8f1d17c59vboxsync /** All related callbacks to this process. */
22e281e75ed636601178296c6daebda8f1d17c59vboxsync GuestCtrlCallbacks mCallbacks;
22e281e75ed636601178296c6daebda8f1d17c59vboxsync /** The process start information. */
22e281e75ed636601178296c6daebda8f1d17c59vboxsync GuestProcessStartupInfo mProcess;
22e281e75ed636601178296c6daebda8f1d17c59vboxsync /** Exit code if process has been terminated. */
22e281e75ed636601178296c6daebda8f1d17c59vboxsync LONG mExitCode;
22e281e75ed636601178296c6daebda8f1d17c59vboxsync /** PID reported from the guest. */
22e281e75ed636601178296c6daebda8f1d17c59vboxsync ULONG mPID;
22e281e75ed636601178296c6daebda8f1d17c59vboxsync /** Internal, host-side process ID. */
22e281e75ed636601178296c6daebda8f1d17c59vboxsync ULONG mProcessID;
22e281e75ed636601178296c6daebda8f1d17c59vboxsync /** The current process status. */
22e281e75ed636601178296c6daebda8f1d17c59vboxsync ProcessStatus_T mStatus;
22e281e75ed636601178296c6daebda8f1d17c59vboxsync int mRC;
22e281e75ed636601178296c6daebda8f1d17c59vboxsync /** The next upcoming context ID. */
22e281e75ed636601178296c6daebda8f1d17c59vboxsync ULONG mNextContextID;
22e281e75ed636601178296c6daebda8f1d17c59vboxsync /** The mutex for protecting the waiter(s). */
d1cbbd799d8912978f5146960b6780f387bb414bvboxsync RTSEMMUTEX mWaitMutex;
22e281e75ed636601178296c6daebda8f1d17c59vboxsync /** How many waiters? At the moment there can only
22e281e75ed636601178296c6daebda8f1d17c59vboxsync * be one. */
c17f5c90f2cb60b38ecabebce128724c6ff2d036vboxsync uint32_t mWaitCount;
22e281e75ed636601178296c6daebda8f1d17c59vboxsync /** The actual process event for doing the waits.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * At the moment we only support one wait a time. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync GuestProcessWaitEvent *mWaitEvent;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync } mData;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync};
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/**
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Guest process tool flags.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/** No flags specified. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#define GUESTPROCESSTOOL_FLAG_NONE 0
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/** Run until next stream block from stdout has been
b1c3cdef473df2fbc621d5da81acc82dbfb8a11avboxsync * read in completely, then return.
a11c569636fa6838bd423f4631a9660a5a84204bvboxsync */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#define GUESTPROCESSTOOL_FLAG_STDOUT_BLOCK RT_BIT(0)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/**
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Internal class for handling a VBoxService tool ("vbox_ls", vbox_stat", ...).
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncclass GuestProcessTool
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync{
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncpublic:
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync GuestProcessTool(void);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync virtual ~GuestProcessTool(void);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncpublic:
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
3ecf9412133496b2aeb090cfd33a286404ec59fbvboxsync int Init(GuestSession *pGuestSession, const GuestProcessStartupInfo &startupInfo, bool fAsync, int *pGuestRc);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync GuestProcessStream &GetStdOut(void) { return mStdOut; }
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync GuestProcessStream &GetStdErr(void) { return mStdErr; }
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync int Wait(uint32_t fFlags, int *pGuestRc);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync int WaitEx(uint32_t fFlags, GuestProcessStreamBlock *pStreamBlock, int *pGuestRc);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
750d4d0506a38b2e80c997075d40aad474e675fbvboxsync int GetCurrentBlock(uint32_t uHandle, GuestProcessStreamBlock &strmBlock);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync bool IsRunning(void);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync int TerminatedOk(LONG *pExitCode);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync void Terminate(void);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncprotected:
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync GuestSession *pSession;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync ComObjPtr<GuestProcess> pProcess;
aaeb2e2f6ed5b164f1dec9a16a7adeb84f64cf31vboxsync GuestProcessStartupInfo mStartupInfo;
223cf005b18af2c21352a70693ebaf0582f68ebcvboxsync GuestProcessStream mStdOut;
b74ca013e5f201a2dd371e6c438433ceac12af30vboxsync GuestProcessStream mStdErr;
b74ca013e5f201a2dd371e6c438433ceac12af30vboxsync};
b74ca013e5f201a2dd371e6c438433ceac12af30vboxsync
b74ca013e5f201a2dd371e6c438433ceac12af30vboxsync#endif /* !____H_GUESTPROCESSIMPL */
b74ca013e5f201a2dd371e6c438433ceac12af30vboxsync
b74ca013e5f201a2dd371e6c438433ceac12af30vboxsync