VirtualBox

儲存庫 vbox 的更動 42160


忽略:
時間撮記:
2012-7-16 上午11:41:10 (12 年 以前)
作者:
vboxsync
訊息:

Guest Control 2.0: Update.

位置:
trunk
檔案:
修改 11 筆資料
移動 1 筆資料

圖例:

未更動
新增
刪除
  • trunk/include/VBox/HostServices/GuestControlSvc.h

    r39906 r42160  
    44
    55/*
    6  * Copyright (C) 2011 Oracle Corporation
     6 * Copyright (C) 2011-2012 Oracle Corporation
    77 *
    88 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    7373 * Note: Has to match Main's ProcessInputFlag_* flags!
    7474 */
    75 #define INPUT_FLAG_NONE             0
    76 #define INPUT_FLAG_EOF              RT_BIT(0)
     75#define INPUT_FLAG_NONE                     0x0
     76#define INPUT_FLAG_EOF                      RT_BIT(0)
    7777
    7878/**
    7979 * Execution flags.
    80  * Note: Has to match Main's ExecuteProcessFlag_* flags!
     80 * Note: Has to match Main's CreateProcessFlag_* flags!
    8181 */
    8282#define EXECUTEPROCESSFLAG_NONE             0x0
  • trunk/src/VBox/Main/Makefile.kmk

    r42154 r42160  
    620620        src-client/GuestSessionImpl.cpp \
    621621        src-client/GuestCtrlImpl.cpp \
    622         src-client/GuestCtrlIO.cpp \
    623622        src-client/GuestCtrlImplDir.cpp \
    624623        src-client/GuestCtrlImplFile.cpp \
     
    641640ifdef VBOX_WITH_GUEST_CONTROL
    642641VBoxC_SOURCES += \
     642        src-client/GuestCtrlPrivate.cpp \
    643643        src-client/GuestCtrlImplTasks.cpp \
    644644        src-client/GuestDirEntryImpl.cpp
  • trunk/src/VBox/Main/include/GuestCtrlImplPrivate.h

    r40575 r42160  
    11/** @file
    22 *
    3  * VirtualBox Guest Control - Private data definitions / classes.
     3 * Internal helpers/structures for guest control functionality.
    44 */
    55
    66/*
    7  * Copyright (C) 2011 Oracle Corporation
     7 * Copyright (C) 2011-2012 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    1919#define ____H_GUESTIMPLPRIVATE
    2020
     21#include <iprt/semaphore.h>
     22
    2123#include <VBox/com/com.h>
     24#include <VBox/com/ErrorInfo.h>
    2225#include <VBox/com/string.h>
    2326#include <VBox/com/VirtualBox.h>
     
    3336#endif
    3437
    35 class Guest;
    36 class Progress;
    37 
    38 /** Structure representing the "value" side of a "key=value" pair. */
     38
     39/* Builds a context ID out of the session ID, process ID and an
     40 * increasing count. */
     41#define VBOX_GUESTCTRL_CONTEXTID_MAKE(uSession, uProcess, uCount) \
     42    (  (uint32_t)((uSession) &   0xff) << 24 \
     43     | (uint32_t)((uProcess) &   0xff) << 16 \
     44     | (uint32_t)((uCount)   & 0xffff)       \
     45    )
     46
     47
     48typedef std::vector <LONG> ProcessAffinity;
     49typedef std::vector <Utf8Str> ProcessArguments;
     50typedef std::map <Utf8Str, Utf8Str> ProcessEnvironmentMap;
     51
     52
     53/**
     54 * Generic class for a all guest control callbacks.
     55 */
     56class GuestCtrlCallback
     57{
     58public:
     59
     60    GuestCtrlCallback(void);
     61
     62    GuestCtrlCallback(eVBoxGuestCtrlCallbackType enmType);
     63
     64    virtual ~GuestCtrlCallback(void);
     65
     66    /** @todo Copy/comparison operator? */
     67
     68public:
     69
     70    int Init(eVBoxGuestCtrlCallbackType enmType);
     71
     72    void Destroy(void);
     73
     74    eVBoxGuestCtrlCallbackType Type(void);
     75
     76    int Wait(RTMSINTERVAL timeoutMS);
     77
     78protected:
     79
     80    /** The callback type. */
     81    eVBoxGuestCtrlCallbackType  mType;
     82    /** Callback flags. */
     83    uint32_t                    mFlags;
     84    /** Pointer to user-supplied data. */
     85    void                       *pvData;
     86    /** Size of user-supplied data. */
     87    size_t                      cbData;
     88    /** The event semaphore triggering the*/
     89    RTSEMEVENT                  mEventSem;
     90    /** Extended error information, if any. */
     91    ErrorInfo                   mErrorInfo;
     92};
     93typedef std::map <uint32_t, GuestCtrlCallback> GuestCtrlCallbacks;
     94
     95/**
     96 * Simple structure mantaining guest credentials.
     97 */
     98class GuestCredentials
     99{
     100public:
     101
     102
     103public:
     104
     105    Utf8Str                     mUser;
     106    Utf8Str                     mPassword;
     107    Utf8Str                     mDomain;
     108};
     109
     110/**
     111 * Structure for keeping all the relevant process
     112 * starting parameters around.
     113 */
     114struct GuestProcessInfo
     115{
     116    Utf8Str                     mCommand;
     117    ProcessArguments            mArguments;
     118    ProcessEnvironmentMap       mEnvironment;
     119    uint32_t                    mFlags;
     120    ULONG                       mTimeoutMS;
     121    ProcessPriority_T           mPriority;
     122    ProcessAffinity             mAffinity;
     123};
     124
     125/**
     126 * Class representing the "value" side of a "key=value" pair.
     127 */
    39128class GuestProcessStreamValue
    40129{
     
    144233    BYTE *m_pbBuffer;
    145234};
     235
     236class Guest;
     237class Progress;
    146238
    147239class GuestTask
  • trunk/src/VBox/Main/include/GuestImpl.h

    r42105 r42160  
    44
    55/*
    6  * Copyright (C) 2006-2011 Oracle Corporation
     6 * Copyright (C) 2006-2012 Oracle Corporation
    77 *
    88 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    205205    /** @name Public internal methods.
    206206     * @{ */
    207     int sessionClose(ComObjPtr<GuestSession> pSession);
     207    Console    *getConsole(void) { return mParent; }
     208    int         sessionClose(ComObjPtr<GuestSession> pSession);
     209    int         sessionCreate(const Utf8Str &strUser, const Utf8Str &aPassword, const Utf8Str &aDomain,
     210                              const Utf8Str &aSessionName, IGuestSession **aGuestSession);
     211    inline bool sessionExists(uint32_t uSessionID);
    208212    /** @}  */
    209213
     
    303307    typedef std::map< AdditionsFacilityType_T, ComObjPtr<AdditionsFacility> >::const_iterator FacilityMapIterConst;
    304308
    305     typedef std::list <ComObjPtr<GuestSession> > GuestSessions;
     309    /** Map for keeping the guest sessions. The primary key marks the guest session ID. */
     310    typedef std::map <uint32_t, ComObjPtr<GuestSession> > GuestSessions;
    306311
    307312    struct Data
     
    320325        Bstr                    mInterfaceVersion;
    321326        GuestSessions           mGuestSessions;
     327        uint32_t                mNextSessionID;
    322328    };
    323329
  • trunk/src/VBox/Main/include/GuestProcessImpl.h

    r42117 r42160  
    2121
    2222#include "VirtualBoxBase.h"
     23#include "GuestCtrlImplPrivate.h"
    2324
    24 #include <vector>
    25 
    26 typedef std::vector<Utf8Str> StringsArray;
    27 
     25class Console;
    2826class GuestSession;
    2927
     
    4745    DECLARE_EMPTY_CTOR_DTOR(GuestProcess)
    4846
    49     int     init(GuestSession *pSession,
    50                  const Utf8Str &aCommand, const StringsArray &aArguments, const StringsArray &aEnvironment,
    51                  ComSafeArrayIn(ProcessCreateFlag_T, aFlags), ULONG aTimeoutMS,
    52                  ProcessPriority_T aPriority, ComSafeArrayIn(LONG, aAffinity));
     47    int     init(Console *aConsole, GuestSession *aSession, uint32_t aProcessID, const GuestProcessInfo &aProcInfo);
    5348    void    uninit(void);
    5449    HRESULT FinalConstruct(void);
     
    7469    /** @name Public internal methods.
    7570     * @{ */
     71    int callbackAdd(const GuestCtrlCallback& theCallback, uint32_t *puContextID);
     72    bool callbackExists(uint32_t uContextID);
     73    bool isReady(void);
     74    int prepareExecuteEnv(const char *pszEnv, void **ppvList, uint32_t *pcbList, uint32_t *pcEnvVars);
     75    int readData(ULONG aHandle, ULONG aSize, ULONG aTimeoutMS, ComSafeArrayOut(BYTE, aData));
     76    int startProcess(void);
     77    static DECLCALLBACK(int) GuestProcess::startProcessThread(RTTHREAD Thread, void *pvUser);
     78    int terminateProcess(void);
     79    int waitFor(ComSafeArrayIn(ProcessWaitForFlag_T, aFlags), ULONG aTimeoutMS, ProcessWaitReason_T *aReason);
     80    int writeData(ULONG aHandle, ComSafeArrayIn(BYTE, aData), ULONG aTimeoutMS, ULONG *aWritten);
    7681    /** @}  */
    7782
    7883private:
    7984
    80     typedef std::map <Utf8Str, Utf8Str> MyStringMap;
    81 
    8285    struct Data
    8386    {
    84         GuestSession        *mParent;
    85         Bstr                 mName;
     87        /** Pointer to parent session. */
     88        GuestSession            *mParent;
     89        /** Pointer to the console object. Needed
     90         *  for HGCM (VMMDev) communication. */
     91        Console                 *mConsole;
     92        /** All related callbacks to this process. */
     93        GuestCtrlCallbacks       mCallbacks;
     94        /** The process start information. */
     95        GuestProcessInfo         mProcess;
     96        /** Exit code if process has been terminated. */
     97        LONG                     mExitCode;
     98        /** PID reported from the guest. */
     99        ULONG                    mPID;
     100        /** Internal, host-side process ID. */
     101        uint32_t                 mProcessID;
     102        /** The current process status. */
     103        ProcessStatus_T          mStatus;
     104        /** Flag indicating whether the process has been started. */
     105        bool                     mStarted;
     106        /** The next upcoming context ID. */
     107        uint32_t                 mNextContextID;
    86108    } mData;
    87109};
  • trunk/src/VBox/Main/include/GuestSessionImpl.h

    r42117 r42160  
    2222#include "VirtualBoxBase.h"
    2323
     24#include "GuestCtrlImplPrivate.h"
    2425#include "GuestProcessImpl.h"
    2526#include "GuestDirectoryImpl.h"
    2627#include "GuestFileImpl.h"
    2728#include "GuestFsObjInfoImpl.h"
    28 
    29 #include <map>
    30 #include <vector>
    31 
    32 typedef std::vector<Utf8Str> StringsArray;
    3329
    3430class Guest;
     
    5248    DECLARE_EMPTY_CTOR_DTOR(GuestSession)
    5349
    54     int     init(Guest *aGuest, Utf8Str aUser, Utf8Str aPassword, Utf8Str aDomain, Utf8Str aName);
     50    int     init(Guest *aGuest, uint32_t aSessionID, Utf8Str aUser, Utf8Str aPassword, Utf8Str aDomain, Utf8Str aName);
    5551    void    uninit(void);
    5652    HRESULT FinalConstruct(void);
     
    115111    /** @name Public internal methods.
    116112     * @{ */
    117     int directoryClose(ComObjPtr<GuestDirectory> pDirectory);
    118     int fileClose(ComObjPtr<GuestFile> pFile);
    119     int processClose(ComObjPtr<GuestProcess> pProcess);
    120     int processCreateExInteral(const Utf8Str &aCommand, const StringsArray &aArguments, const StringsArray &aEnvironment,
    121                                ComSafeArrayIn(ProcessCreateFlag_T, aFlags), ULONG aTimeoutMS,
    122                                ProcessPriority_T aPriority, ComSafeArrayIn(LONG, aAffinity),
    123                                IGuestProcess **aProcess);
     113    int                     directoryClose(ComObjPtr<GuestDirectory> pDirectory);
     114    int                     fileClose(ComObjPtr<GuestFile> pFile);
     115    const GuestCredentials &getCredentials(void);
     116    int                     processClose(ComObjPtr<GuestProcess> pProcess);
     117    int                     processCreateExInteral(GuestProcessInfo &aProcInfo, IGuestProcess **aProcess);
     118    inline bool             processExists(uint32_t uProcessID);
    124119    /** @}  */
    125120
     
    128123    typedef std::map <Utf8Str, Utf8Str> SessionEnvironment;
    129124
    130     typedef std::list <ComObjPtr<GuestDirectory> > SessionDirectories;
    131     typedef std::list <ComObjPtr<GuestFile> > SessionFiles;
    132     typedef std::list <ComObjPtr<GuestProcess> > SessionProcesses;
     125    typedef std::vector <ComObjPtr<GuestDirectory> > SessionDirectories;
     126    typedef std::vector <ComObjPtr<GuestFile> > SessionFiles;
     127    typedef std::map <uint32_t, ComObjPtr<GuestProcess> > SessionProcesses;
    133128
    134129    struct Data
     
    137132         *  or not. Internal session are not accessible by clients. */
    138133        bool                 fInternal;
    139         /** Pointer to the parent (IGuest). */
     134        /** Pointer to the parent (Guest). */
    140135        Guest               *mParent;
    141136        /** The session credentials. */
    142         Utf8Str              mUser;
    143         Utf8Str              mPassword;
    144         Utf8Str              mDomain;
     137        GuestCredentials     mCredentials;
    145138        /** The (optional) session name. */
    146139        Utf8Str              mName;
  • trunk/src/VBox/Main/src-client/GuestCtrlImpl.cpp

    r42105 r42160  
    26712671         itSessions != mData.mGuestSessions.end(); ++itSessions)
    26722672    {
    2673         if (pSession == (*itSessions))
    2674         {
    2675             mData.mGuestSessions.remove((*itSessions));
     2673        if (pSession == itSessions->second)
     2674        {
     2675            mData.mGuestSessions.erase(itSessions);
    26762676            return VINF_SUCCESS;
    26772677        }
     
    26792679
    26802680    return VERR_NOT_FOUND;
     2681}
     2682
     2683int Guest::sessionCreate(const Utf8Str &strUser, const Utf8Str &strPassword, const Utf8Str &strDomain,
     2684                         const Utf8Str &strSessionName, IGuestSession **aGuestSession)
     2685{
     2686    AssertPtrReturn(aGuestSession, VERR_INVALID_POINTER);
     2687
     2688    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
     2689
     2690    int rc = VERR_MAX_PROCS_REACHED;
     2691    ComObjPtr<GuestSession> pGuestSession;
     2692    try
     2693    {
     2694        /* Create a new session ID and assign it. */
     2695        uint32_t uNewSessionID = 0;
     2696        uint32_t uTries = 0;
     2697
     2698        for (;;)
     2699        {
     2700            /* Is the context ID already used?  Try next ID ... */
     2701            if (!sessionExists(uNewSessionID++))
     2702            {
     2703                /* Callback with context ID was not found. This means
     2704                 * we can use this context ID for our new callback we want
     2705                 * to add below. */
     2706                rc = VINF_SUCCESS;
     2707                break;
     2708            }
     2709
     2710            if (++uTries == UINT32_MAX)
     2711                break; /* Don't try too hard. */
     2712        }
     2713        if (RT_FAILURE(rc)) throw rc;
     2714
     2715        /* Create the session object. */
     2716        HRESULT hr = pGuestSession.createObject();
     2717        if (FAILED(hr)) throw VERR_COM_UNEXPECTED;
     2718
     2719        rc = pGuestSession->init(this, uNewSessionID,
     2720                                 strUser, strPassword, strDomain, strSessionName);
     2721        if (RT_FAILURE(rc)) throw VBOX_E_IPRT_ERROR;
     2722
     2723        mData.mGuestSessions[uNewSessionID] = pGuestSession;
     2724
     2725        /* Return guest session to the caller. */
     2726        hr = pGuestSession.queryInterfaceTo(aGuestSession);
     2727        if (FAILED(hr)) throw VERR_COM_OBJECT_NOT_FOUND;
     2728    }
     2729    catch (int rc2)
     2730    {
     2731        rc = rc2;
     2732    }
     2733
     2734    return rc;
     2735}
     2736
     2737inline bool Guest::sessionExists(uint32_t uSessionID)
     2738{
     2739    AssertReturn(uSessionID, false);
     2740
     2741    GuestSessions::const_iterator itSessions = mData.mGuestSessions.find(uSessionID);
     2742    return (itSessions == mData.mGuestSessions.end()) ? false : true;
    26812743}
    26822744
     
    26982760    if (FAILED(autoCaller.rc())) return autoCaller.rc();
    26992761
    2700     AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
    2701 
    2702     HRESULT hr;
    2703     ComObjPtr<GuestSession> pGuestSession;
    2704     try
    2705     {
    2706         /* Create the session object. */
    2707         hr = pGuestSession.createObject();
    2708         if (FAILED(hr)) throw hr;
    2709 
    2710         int rc = pGuestSession->init(this,
    2711                                      aUser, aPassword, aDomain, aSessionName);
    2712         if (RT_FAILURE(rc)) throw VBOX_E_IPRT_ERROR;
    2713 
    2714         mData.mGuestSessions.push_back(pGuestSession);
    2715 
    2716         /* Return guest session to the caller. */
    2717         hr = pGuestSession.queryInterfaceTo(aGuestSession);
    2718     }
    2719     catch (HRESULT aRC)
    2720     {
    2721         hr = aRC;
    2722     }
    2723 
    2724     return hr;
     2762
    27252763#endif /* VBOX_WITH_GUEST_CONTROL */
    27262764}
  • trunk/src/VBox/Main/src-client/GuestCtrlImplTasks.cpp

    r40685 r42160  
    4949}
    5050
    51 GuestTask::~GuestTask()
     51GuestTask::~GuestTask(void)
    5252{
    5353
    5454}
    5555
    56 int GuestTask::startThread()
     56int GuestTask::startThread(void)
    5757{
    5858    return RTThreadCreate(NULL, GuestTask::taskThread, this,
  • trunk/src/VBox/Main/src-client/GuestCtrlPrivate.cpp

    r42121 r42160  
    22/** @file
    33 *
    4  * IO helper for IGuest COM class implementations.
     4 * Internal helpers/structures for guest control functionality.
    55 */
    66
    77/*
    8  * Copyright (C) 2011 Oracle Corporation
     8 * Copyright (C) 2011-2012 Oracle Corporation
    99 *
    1010 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    3030 ******************************************************************************/
    3131
     32GuestCtrlCallback::GuestCtrlCallback(void)
     33    : mType(VBOXGUESTCTRLCALLBACKTYPE_UNKNOWN),
     34      pvData(NULL),
     35      cbData(0),
     36      mEventSem(NIL_RTSEMEVENT)
     37{
     38}
     39
     40GuestCtrlCallback::GuestCtrlCallback(eVBoxGuestCtrlCallbackType enmType)
     41    : mType(VBOXGUESTCTRLCALLBACKTYPE_UNKNOWN),
     42      pvData(NULL),
     43      cbData(0),
     44      mEventSem(NIL_RTSEMEVENT)
     45{
     46    int rc = Init(enmType);
     47    AssertRC(rc);
     48}
     49
     50GuestCtrlCallback::~GuestCtrlCallback(void)
     51{
     52    Destroy();
     53}
     54
     55int GuestCtrlCallback::Init(eVBoxGuestCtrlCallbackType enmType)
     56{
     57    AssertReturn(enmType > VBOXGUESTCTRLCALLBACKTYPE_UNKNOWN, VERR_INVALID_PARAMETER);
     58    Assert((pvData == NULL) && !cbData);
     59
     60    int rc = VINF_SUCCESS;
     61    switch (enmType)
     62    {
     63        case VBOXGUESTCTRLCALLBACKTYPE_EXEC_START:
     64        {
     65            pvData = (PCALLBACKDATAEXECSTATUS)RTMemAlloc(sizeof(CALLBACKDATAEXECSTATUS));
     66            AssertPtrReturn(pvData, VERR_NO_MEMORY);
     67            RT_BZERO(pvData, sizeof(CALLBACKDATAEXECSTATUS));
     68            cbData = sizeof(CALLBACKDATAEXECSTATUS);
     69            break;
     70        }
     71
     72        case VBOXGUESTCTRLCALLBACKTYPE_EXEC_OUTPUT:
     73        {
     74            pvData = (PCALLBACKDATAEXECOUT)RTMemAlloc(sizeof(CALLBACKDATAEXECOUT));
     75            AssertPtrReturn(pvData, VERR_NO_MEMORY);
     76            RT_BZERO(pvData, sizeof(CALLBACKDATAEXECOUT));
     77            cbData = sizeof(CALLBACKDATAEXECOUT);
     78            break;
     79        }
     80
     81        case VBOXGUESTCTRLCALLBACKTYPE_EXEC_INPUT_STATUS:
     82        {
     83            PCALLBACKDATAEXECINSTATUS pData = (PCALLBACKDATAEXECINSTATUS)RTMemAlloc(sizeof(CALLBACKDATAEXECINSTATUS));
     84            AssertPtrReturn(pData, VERR_NO_MEMORY);
     85            RT_BZERO(pData, sizeof(CALLBACKDATAEXECINSTATUS));
     86            cbData = sizeof(CALLBACKDATAEXECINSTATUS);
     87            break;
     88        }
     89
     90        default:
     91            AssertMsgFailed(("Unknown callback type specified (%d)\n", enmType));
     92            break;
     93    }
     94
     95    if (RT_SUCCESS(rc))
     96    {
     97        rc = RTSemEventCreate(&mEventSem);
     98        if (RT_SUCCESS(rc))
     99            mType  = enmType;
     100    }
     101
     102    return rc;
     103}
     104
     105void GuestCtrlCallback::Destroy(void)
     106{
     107    mType = VBOXGUESTCTRLCALLBACKTYPE_UNKNOWN;
     108    if (pvData)
     109    {
     110        RTMemFree(pvData);
     111        pvData = NULL;
     112    }
     113    cbData = 0;
     114    if (mEventSem != NIL_RTSEMEVENT)
     115        RTSemEventDestroy(mEventSem);
     116}
     117
     118eVBoxGuestCtrlCallbackType GuestCtrlCallback::Type(void)
     119{
     120    return mType;
     121}
     122
     123int GuestCtrlCallback::Wait(RTMSINTERVAL timeoutMS)
     124{
     125    Assert(mEventSem != NIL_RTSEMEVENT);
     126    return RTSemEventWait(mEventSem, timeoutMS);
     127}
     128
     129///////////////////////////////////////////////////////////////////////////////
     130
    32131/** @todo *NOT* thread safe yet! */
    33132/** @todo Add exception handling for STL stuff! */
    34133
    35 GuestProcessStreamBlock::GuestProcessStreamBlock()
     134GuestProcessStreamBlock::GuestProcessStreamBlock(void)
    36135{
    37136
     
    223322///////////////////////////////////////////////////////////////////////////////
    224323
    225 GuestProcessStream::GuestProcessStream()
     324GuestProcessStream::GuestProcessStream(void)
    226325    : m_cbAllocated(0),
    227326      m_cbSize(0),
     
    232331}
    233332
    234 GuestProcessStream::~GuestProcessStream()
     333GuestProcessStream::~GuestProcessStream(void)
    235334{
    236335    Destroy();
     
    311410 * Destroys the internal data buffer.
    312411 */
    313 void GuestProcessStream::Destroy()
     412void GuestProcessStream::Destroy(void)
    314413{
    315414    if (m_pbBuffer)
  • trunk/src/VBox/Main/src-client/GuestProcessImpl.cpp

    r42117 r42160  
    2222*******************************************************************************/
    2323#include "GuestProcessImpl.h"
     24#include "GuestSessionImpl.h"
     25#include "ConsoleImpl.h"
    2426
    2527#include "Global.h"
    2628#include "AutoCaller.h"
    2729#include "Logging.h"
     30#include "VMMDev.h"
     31
     32#include <iprt/asm.h>
     33#include <iprt/getopt.h>
     34#include <VBox/VMMDev.h>
     35#include <VBox/com/array.h>
     36
     37
     38struct GuestProcessTask
     39{
     40    GuestProcessTask(GuestProcess *pProcess)
     41        : mProcess(pProcess) { }
     42
     43    ~GuestProcessTask(void) { }
     44
     45    int rc() const { return mRC; }
     46    bool isOk() const { return RT_SUCCESS(rc()); }
     47
     48    const ComObjPtr<GuestProcess>    mProcess;
     49
     50private:
     51    int                              mRC;
     52};
     53
     54struct GuestProcessStartTask : public GuestProcessTask
     55{
     56    GuestProcessStartTask(GuestProcess *pProcess)
     57        : GuestProcessTask(pProcess) { }
     58};
    2859
    2960
     
    3667{
    3768    LogFlowThisFunc(("\n"));
     69
     70    mData.mExitCode = 0;
     71    mData.mNextContextID = 0;
     72    mData.mPID = 0;
     73    mData.mProcessID = 0;
     74    mData.mStatus = ProcessStatus_Undefined;
     75    mData.mStarted = false;
     76
    3877    return BaseFinalConstruct();
    3978}
     
    5089/////////////////////////////////////////////////////////////////////////////
    5190
    52 int GuestProcess::init(GuestSession *pSession,
    53                        const Utf8Str &aCommand, const StringsArray &aArguments, const StringsArray &aEnvironment,
    54                        ComSafeArrayIn(ProcessCreateFlag_T, aFlags), ULONG aTimeoutMS,
    55                        ProcessPriority_T aPriority, ComSafeArrayIn(LONG, aAffinity))
    56 {
     91int GuestProcess::init(Console *aConsole, GuestSession *aSession, uint32_t aProcessID, const GuestProcessInfo &aProcInfo)
     92{
     93    AssertPtrReturn(aSession, VERR_INVALID_POINTER);
     94
    5795    /* Enclose the state transition NotReady->InInit->Ready. */
    5896    AutoInitSpan autoInitSpan(this);
    5997    AssertReturn(autoInitSpan.isOk(), VERR_OBJECT_DESTROYED);
    6098
    61     int rc = VINF_SUCCESS;
    62 
    63     mData.mParent = pSession;
    64 
    65     /* Confirm a successful initialization when it's the case. */
     99    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
     100
     101    mData.mConsole = aConsole;
     102    mData.mParent = aSession;
     103    mData.mProcessID = aProcessID;
     104    mData.mStatus = ProcessStatus_Starting;
     105    /* Everything else will be set by the actual starting routine. */
     106
     107    /* Asynchronously start the process on the guest by kicking off a
     108     * worker thread. */
     109    std::auto_ptr<GuestProcessStartTask> pTask(new GuestProcessStartTask(this));
     110    AssertReturn(pTask->isOk(), pTask->rc());
     111
     112    int rc = RTThreadCreate(NULL, GuestProcess::startProcessThread,
     113                            (void *)pTask.get(), 0,
     114                            RTTHREADTYPE_MAIN_WORKER, 0,
     115                            "gctlPrcStart");
    66116    if (RT_SUCCESS(rc))
     117    {
     118        /* task is now owned by startProcessThread(), so release it. */
     119        pTask.release();
     120
     121        /* Confirm a successful initialization when it's the case. */
    67122        autoInitSpan.setSucceeded();
     123    }
    68124
    69125    return rc;
     
    97153    CheckComArgOutSafeArrayPointerValid(aArguments);
    98154
    99     ReturnComNotImplemented();
     155    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
     156
     157    com::SafeArray<BSTR> collection(mData.mProcess.mArguments.size());
     158    size_t s = 0;
     159    for (ProcessArguments::const_iterator it = mData.mProcess.mArguments.begin();
     160         it != mData.mProcess.mArguments.end();
     161         ++it, ++s)
     162    {
     163        collection[s] = Bstr((*it)).raw();
     164    }
     165
     166    collection.detachTo(ComSafeArrayOutArg(aArguments));
     167
     168    return S_OK;
    100169#endif /* VBOX_WITH_GUEST_CONTROL */
    101170}
     
    111180    CheckComArgOutSafeArrayPointerValid(aEnvironment);
    112181
    113     ReturnComNotImplemented();
     182    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
     183
     184    com::SafeArray<BSTR> collection(mData.mProcess.mEnvironment.size());
     185    size_t s = 0;
     186    for (ProcessEnvironmentMap::const_iterator it = mData.mProcess.mEnvironment.begin();
     187         it != mData.mProcess.mEnvironment.end();
     188         ++it, ++s)
     189    {
     190        collection[s] = Bstr(it->first + "=" + it->second).raw();
     191    }
     192
     193    collection.detachTo(ComSafeArrayOutArg(aEnvironment));
     194
     195    return S_OK;
    114196#endif /* VBOX_WITH_GUEST_CONTROL */
    115197}
     
    123205    if (FAILED(autoCaller.rc())) return autoCaller.rc();
    124206
    125     ReturnComNotImplemented();
     207    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
     208
     209    mData.mProcess.mCommand.cloneTo(aExecutablePath);
     210
     211    return S_OK;
    126212#endif /* VBOX_WITH_GUEST_CONTROL */
    127213}
     
    135221    if (FAILED(autoCaller.rc())) return autoCaller.rc();
    136222
    137     ReturnComNotImplemented();
     223    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
     224
     225    *aExitCode = mData.mExitCode;
     226
     227    return S_OK;
    138228#endif /* VBOX_WITH_GUEST_CONTROL */
    139229}
     
    147237    if (FAILED(autoCaller.rc())) return autoCaller.rc();
    148238
    149     ReturnComNotImplemented();
     239    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
     240
     241    *aPID = mData.mPID;
     242
     243    return S_OK;
    150244#endif /* VBOX_WITH_GUEST_CONTROL */
    151245}
     
    159253    if (FAILED(autoCaller.rc())) return autoCaller.rc();
    160254
    161     ReturnComNotImplemented();
    162 #endif /* VBOX_WITH_GUEST_CONTROL */
     255    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
     256
     257    *aStatus = mData.mStatus;
     258
     259    return S_OK;
     260#endif /* VBOX_WITH_GUEST_CONTROL */
     261}
     262
     263// private methods
     264/////////////////////////////////////////////////////////////////////////////
     265
     266/*
     267
     268    SYNC TO ASK:
     269    Everything which involves HGCM communication (start, read/write/status(?)/...)
     270    either can be called synchronously or asynchronously by running in a Main worker
     271    thread.
     272
     273    Rules:
     274        - Only one async operation per process a time can be around.
     275
     276*/
     277
     278int GuestProcess::callbackAdd(const GuestCtrlCallback& theCallback, uint32_t *puContextID)
     279{
     280    const ComObjPtr<GuestSession> pSession(mData.mParent);
     281    Assert(!pSession.isNull());
     282    ULONG uSessionID = 0;
     283    HRESULT hr = pSession->COMGETTER(Id)(&uSessionID);
     284    ComAssertComRC(hr);
     285
     286    /* Create a new context ID and assign it. */
     287    int rc = VERR_NOT_FOUND;
     288    uint32_t uNewContextID = 0;
     289    uint32_t uTries = 0;
     290    for (;;)
     291    {
     292        /* Create a new context ID ... */
     293        uNewContextID = VBOX_GUESTCTRL_CONTEXTID_MAKE(uSessionID,
     294                                                      mData.mProcessID, ASMAtomicIncU32(&mData.mNextContextID));
     295        if (uNewContextID == UINT32_MAX)
     296            ASMAtomicUoWriteU32(&mData.mNextContextID, 0);
     297        /* Is the context ID already used?  Try next ID ... */
     298        if (!callbackExists(uNewContextID))
     299        {
     300            /* Callback with context ID was not found. This means
     301             * we can use this context ID for our new callback we want
     302             * to add below. */
     303            rc = VINF_SUCCESS;
     304            break;
     305        }
     306
     307        if (++uTries == UINT32_MAX)
     308            break; /* Don't try too hard. */
     309    }
     310
     311    if (RT_SUCCESS(rc))
     312    {
     313        /* Add callback with new context ID to our callback map. */
     314        mData.mCallbacks[uNewContextID] = theCallback;
     315        Assert(mData.mCallbacks.size());
     316
     317        /* Report back new context ID. */
     318        if (puContextID)
     319            *puContextID = uNewContextID;
     320    }
     321
     322    return rc;
     323}
     324
     325bool GuestProcess::callbackExists(uint32_t uContextID)
     326{
     327    AssertReturn(uContextID, false);
     328
     329    GuestCtrlCallbacks::const_iterator it = mData.mCallbacks.find(uContextID);
     330    return (it == mData.mCallbacks.end()) ? false : true;
     331}
     332
     333bool GuestProcess::isReady(void)
     334{
     335    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
     336
     337    if (mData.mStatus == ProcessStatus_Started)
     338    {
     339        Assert(mData.mPID); /* PID must not be 0. */
     340        return true;
     341    }
     342
     343    return false;
     344}
     345
     346/**
     347 * Appends environment variables to the environment block.
     348 *
     349 * Each var=value pair is separated by the null character ('\\0').  The whole
     350 * block will be stored in one blob and disassembled on the guest side later to
     351 * fit into the HGCM param structure.
     352 *
     353 * @returns VBox status code.
     354 *
     355 * @param   pszEnvVar       The environment variable=value to append to the
     356 *                          environment block.
     357 * @param   ppvList         This is actually a pointer to a char pointer
     358 *                          variable which keeps track of the environment block
     359 *                          that we're constructing.
     360 * @param   pcbList         Pointer to the variable holding the current size of
     361 *                          the environment block.  (List is a misnomer, go
     362 *                          ahead a be confused.)
     363 * @param   pcEnvVars       Pointer to the variable holding count of variables
     364 *                          stored in the environment block.
     365 */
     366int GuestProcess::prepareExecuteEnv(const char *pszEnv, void **ppvList, uint32_t *pcbList, uint32_t *pcEnvVars)
     367{
     368    int rc = VINF_SUCCESS;
     369    uint32_t cchEnv = strlen(pszEnv); Assert(cchEnv >= 2);
     370    if (*ppvList)
     371    {
     372        uint32_t cbNewLen = *pcbList + cchEnv + 1; /* Include zero termination. */
     373        char *pvTmp = (char *)RTMemRealloc(*ppvList, cbNewLen);
     374        if (pvTmp == NULL)
     375            rc = VERR_NO_MEMORY;
     376        else
     377        {
     378            memcpy(pvTmp + *pcbList, pszEnv, cchEnv);
     379            pvTmp[cbNewLen - 1] = '\0'; /* Add zero termination. */
     380            *ppvList = (void **)pvTmp;
     381        }
     382    }
     383    else
     384    {
     385        char *pszTmp;
     386        if (RTStrAPrintf(&pszTmp, "%s", pszEnv) >= 0)
     387        {
     388            *ppvList = (void **)pszTmp;
     389            /* Reset counters. */
     390            *pcEnvVars = 0;
     391            *pcbList = 0;
     392        }
     393    }
     394    if (RT_SUCCESS(rc))
     395    {
     396        *pcbList += cchEnv + 1; /* Include zero termination. */
     397        *pcEnvVars += 1;        /* Increase env variable count. */
     398    }
     399    return rc;
     400}
     401
     402int GuestProcess::readData(ULONG aHandle, ULONG aSize, ULONG aTimeoutMS, ComSafeArrayOut(BYTE, aData))
     403{
     404    LogFlowFuncEnter();
     405
     406    LogFlowFuncLeave();
     407    return 0;
     408}
     409
     410int GuestProcess::startProcess(void)
     411{
     412    LogFlowFuncEnter();
     413
     414    AssertReturn(!mData.mStarted, VERR_ALREADY_EXISTS);
     415
     416    int rc;
     417    uint32_t uContextID;
     418
     419    {
     420        /* Wait until the caller function (if kicked off by a thread)
     421         * has returned and continue operation. */
     422        AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
     423
     424        /* Create callback and add it to the map. */
     425        GuestCtrlCallback callbackStart;
     426        rc = callbackStart.Init(VBOXGUESTCTRLCALLBACKTYPE_EXEC_START);
     427        if (RT_FAILURE(rc))
     428            return rc;
     429
     430        rc = callbackAdd(callbackStart, &uContextID);
     431        Assert(uContextID);
     432    }
     433
     434    if (RT_SUCCESS(rc))
     435    {
     436        ComObjPtr<GuestSession> pSession(mData.mParent);
     437        Assert(!pSession.isNull());
     438
     439        const GuestCredentials &sessionCreds = pSession->getCredentials();
     440
     441        /* Prepare arguments. */
     442        char *pszArgs = NULL;
     443        size_t cArgs = mData.mProcess.mArguments.size();
     444        if (cArgs)
     445        {
     446            char **papszArgv = (char**)RTMemAlloc(sizeof(char*) * (cArgs + 1));
     447            AssertReturn(papszArgv, VERR_NO_MEMORY);
     448            for (size_t i = 0; RT_SUCCESS(rc) && i < cArgs; i++)
     449                rc = RTStrDupEx(&papszArgv[i], mData.mProcess.mArguments[i].c_str());
     450            papszArgv[cArgs] = NULL;
     451
     452            if (RT_SUCCESS(rc))
     453                rc = RTGetOptArgvToString(&pszArgs, papszArgv, RTGETOPTARGV_CNV_QUOTE_MS_CRT);
     454        }
     455        uint32_t cbArgs = pszArgs ? strlen(pszArgs) + 1 : 0; /* Include terminating zero. */
     456
     457        /* Prepare environment. */
     458        void *pvEnv = NULL;
     459        size_t cEnv = mData.mProcess.mEnvironment.size();
     460        uint32_t cbEnv = 0;
     461        if (   RT_SUCCESS(rc)
     462            && cEnv)
     463        {
     464            uint32_t cEnvBuild = 0;
     465            ProcessEnvironmentMap::const_iterator itEnv = mData.mProcess.mEnvironment.begin();
     466            for (; itEnv != mData.mProcess.mEnvironment.end() && RT_SUCCESS(rc); itEnv++)
     467            {
     468                char *pszEnv;
     469                if (!RTStrAPrintf(&pszEnv, "%s=%s", itEnv->first, itEnv->second))
     470                    break;
     471                AssertPtr(pszEnv);
     472                rc = prepareExecuteEnv(pszEnv, &pvEnv, &cbEnv, &cEnvBuild);
     473                RTStrFree(pszEnv);
     474            }
     475            Assert(cEnv == cEnvBuild);
     476        }
     477
     478        if (RT_SUCCESS(rc))
     479        {
     480            /* Prepare HGCM call. */
     481            VBOXHGCMSVCPARM paParms[15];
     482            int i = 0;
     483            paParms[i++].setUInt32(uContextID);
     484            paParms[i++].setPointer((void*)mData.mProcess.mCommand.c_str(),
     485                                    (uint32_t)mData.mProcess.mCommand.length() + 1);
     486            paParms[i++].setUInt32(mData.mProcess.mFlags);
     487            paParms[i++].setUInt32(mData.mProcess.mArguments.size());
     488            paParms[i++].setPointer((void*)pszArgs, cbArgs);
     489            paParms[i++].setUInt32(mData.mProcess.mEnvironment.size());
     490            paParms[i++].setUInt32(cbEnv);
     491            paParms[i++].setPointer((void*)pvEnv, cbEnv);
     492            paParms[i++].setPointer((void*)sessionCreds.mUser.c_str(), (uint32_t)sessionCreds.mUser.length() + 1);
     493            paParms[i++].setPointer((void*)sessionCreds.mPassword.c_str(), (uint32_t)sessionCreds.mPassword.length() + 1);
     494
     495            /*
     496             * If the WaitForProcessStartOnly flag is set, we only want to define and wait for a timeout
     497             * until the process was started - the process itself then gets an infinite timeout for execution.
     498             * This is handy when we want to start a process inside a worker thread within a certain timeout
     499             * but let the started process perform lengthly operations then.
     500             */
     501            if (mData.mProcess.mFlags & ProcessCreateFlag_WaitForProcessStartOnly)
     502                paParms[i++].setUInt32(UINT32_MAX /* Infinite timeout */);
     503            else
     504                paParms[i++].setUInt32(mData.mProcess.mTimeoutMS);
     505
     506            const ComObjPtr<Console> pConsole(mData.mConsole);
     507            Assert(!pConsole.isNull());
     508
     509            VMMDev *pVMMDev = NULL;
     510            {
     511                /* Make sure mParent is valid, so set the read lock while using.
     512                 * Do not keep this lock while doing the actual call, because in the meanwhile
     513                 * another thread could request a write lock which would be a bad idea ... */
     514                AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
     515
     516                /* Forward the information to the VMM device. */
     517                pVMMDev = pConsole->getVMMDev();
     518            }
     519
     520            LogFlowFunc(("hgcmHostCall numParms=%d, CID=%RU32\n", i, uContextID));
     521            rc = pVMMDev->hgcmHostCall("VBoxGuestControlSvc", HOST_EXEC_CMD,
     522                                       i, paParms);
     523        }
     524
     525        if (pvEnv)
     526            RTMemFree(pvEnv);
     527        if (pszArgs)
     528            RTStrFree(pszArgs);
     529    }
     530
     531    LogFlowFuncLeave();
     532    return rc;
     533}
     534
     535DECLCALLBACK(int) GuestProcess::startProcessThread(RTTHREAD Thread, void *pvUser)
     536{
     537    LogFlowFuncEnter();
     538
     539    const ComObjPtr<GuestProcess> pProcess = static_cast<GuestProcess*>(pvUser);
     540    Assert(!pProcess.isNull());
     541
     542    int rc = pProcess->startProcess();
     543
     544    LogFlowFuncLeave();
     545    return rc;
     546}
     547
     548int GuestProcess::terminateProcess(void)
     549{
     550    LogFlowFuncEnter();
     551
     552    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
     553
     554    LogFlowFuncLeave();
     555    return 0;
     556}
     557
     558int GuestProcess::waitFor(ComSafeArrayIn(ProcessWaitForFlag_T, aFlags), ULONG aTimeoutMS, ProcessWaitReason_T *aReason)
     559{
     560    LogFlowFuncEnter();
     561
     562    LogFlowFuncLeave();
     563    return 0;
     564}
     565
     566int GuestProcess::writeData(ULONG aHandle, ComSafeArrayIn(BYTE, aData), ULONG aTimeoutMS, ULONG *aWritten)
     567{
     568    LogFlowFuncEnter();
     569
     570    LogFlowFuncLeave();
     571    return 0;
    163572}
    164573
     
    171580    ReturnComNotImplemented();
    172581#else
    173     AutoCaller autoCaller(this);
    174     if (FAILED(autoCaller.rc())) return autoCaller.rc();
    175 
    176     ReturnComNotImplemented();
     582
     583    AutoCaller autoCaller(this);
     584    if (FAILED(autoCaller.rc())) return autoCaller.rc();
     585
     586    int rc = readData(aHandle, aSize, aTimeoutMS, ComSafeArrayOutArg(aData));
     587    /** @todo Do setError() here. */
     588    return RT_SUCCESS(rc) ? S_OK : VBOX_E_IPRT_ERROR;
    177589#endif /* VBOX_WITH_GUEST_CONTROL */
    178590}
     
    186598    if (FAILED(autoCaller.rc())) return autoCaller.rc();
    187599
    188     ReturnComNotImplemented();
     600    int rc = terminateProcess();
     601    /** @todo Do setError() here. */
     602    return RT_SUCCESS(rc) ? S_OK : VBOX_E_IPRT_ERROR;
    189603#endif /* VBOX_WITH_GUEST_CONTROL */
    190604}
     
    198612    if (FAILED(autoCaller.rc())) return autoCaller.rc();
    199613
    200     ReturnComNotImplemented();
     614    int rc = waitFor(ComSafeArrayInArg(aFlags), aTimeoutMS, aReason);
     615    /** @todo Do setError() here. */
     616    return RT_SUCCESS(rc) ? S_OK : VBOX_E_IPRT_ERROR;
    201617#endif /* VBOX_WITH_GUEST_CONTROL */
    202618}
     
    210626    if (FAILED(autoCaller.rc())) return autoCaller.rc();
    211627
    212     ReturnComNotImplemented();
    213 #endif /* VBOX_WITH_GUEST_CONTROL */
    214 }
    215 
     628    int rc = writeData(aHandle, ComSafeArrayInArg(aData), aTimeoutMS, aWritten);
     629    /** @todo Do setError() here. */
     630    return RT_SUCCESS(rc) ? S_OK : VBOX_E_IPRT_ERROR;
     631#endif /* VBOX_WITH_GUEST_CONTROL */
     632}
     633
  • trunk/src/VBox/Main/src-client/GuestSessionImpl.cpp

    r42117 r42160  
    5353/////////////////////////////////////////////////////////////////////////////
    5454
    55 int GuestSession::init(Guest *aGuest,
     55int GuestSession::init(Guest *aGuest, uint32_t aSessionID,
    5656                       Utf8Str aUser, Utf8Str aPassword, Utf8Str aDomain, Utf8Str aName)
    5757{
     
    6363
    6464    mData.mParent = aGuest;
    65 
    66     mData.mUser = aUser;
    67     mData.mPassword = aPassword;
    68     mData.mDomain = aDomain;
     65    mData.mId = aSessionID;
     66
     67    mData.mCredentials.mUser = aUser;
     68    mData.mCredentials.mPassword = aPassword;
     69    mData.mCredentials.mDomain = aDomain;
    6970    mData.mName = aName;
    7071
     
    108109         itProcs != mData.mProcesses.end(); ++itProcs)
    109110    {
    110         (*itProcs)->uninit();
    111         (*itProcs).setNull();
     111        itProcs->second->uninit();
     112        itProcs->second.setNull();
    112113    }
    113114    mData.mProcesses.clear();
     
    132133    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
    133134
    134     mData.mUser.cloneTo(aUser);
     135    mData.mCredentials.mUser.cloneTo(aUser);
    135136
    136137    return S_OK;
     
    150151    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
    151152
    152     mData.mDomain.cloneTo(aDomain);
     153    mData.mCredentials.mDomain.cloneTo(aDomain);
    153154
    154155    return S_OK;
     
    228229         ++it, ++s)
    229230    {
    230         /** @todo */
     231        collection[s] = Bstr(it->first + "=" + it->second).raw();
    231232    }
    232233
     
    306307        if (pDirectory == (*itDirs))
    307308        {
    308             mData.mDirectories.remove((*itDirs));
     309            mData.mDirectories.erase(itDirs);
    309310            return VINF_SUCCESS;
    310311        }
     
    323324        if (pFile == (*itFiles))
    324325        {
    325             mData.mFiles.remove((*itFiles));
     326            mData.mFiles.erase(itFiles);
    326327            return VINF_SUCCESS;
    327328        }
     
    331332}
    332333
     334const GuestCredentials& GuestSession::getCredentials(void)
     335{
     336    return mData.mCredentials;
     337}
     338
    333339int GuestSession::processClose(ComObjPtr<GuestProcess> pProcess)
    334340{
     
    338344         itProcs != mData.mProcesses.end(); ++itProcs)
    339345    {
    340         if (pProcess == (*itProcs))
     346        if (pProcess == itProcs->second)
    341347        {
    342             mData.mProcesses.remove((*itProcs));
     348            mData.mProcesses.erase(itProcs);
    343349            return VINF_SUCCESS;
    344350        }
     
    348354}
    349355
    350 int GuestSession::processCreateExInteral(const Utf8Str &aCommand, const StringsArray &aArguments, const StringsArray &aEnvironment,
    351                                          ComSafeArrayIn(ProcessCreateFlag_T, aFlags), ULONG aTimeoutMS,
    352                                          ProcessPriority_T aPriority, ComSafeArrayIn(LONG, aAffinity),
    353                                          IGuestProcess **aProcess)
     356int GuestSession::processCreateExInteral(GuestProcessInfo &aProcInfo, IGuestProcess **aProcess)
    354357{
    355358    AssertPtrReturn(aProcess, VERR_INVALID_POINTER);
    356359
    357360    /* Validate flags. */
    358     com::SafeArray<ProcessCreateFlag_T> arrFlags(ComSafeArrayInArg(aFlags));
    359     for (size_t i = 0; i < arrFlags.size(); i++)
    360     {
    361         if (arrFlags[i] == ExecuteProcessFlag_None)
    362             continue;
    363 
    364         if (   !(arrFlags[i] & ExecuteProcessFlag_IgnoreOrphanedProcesses)
    365             && !(arrFlags[i] & ExecuteProcessFlag_WaitForProcessStartOnly)
    366             && !(arrFlags[i] & ExecuteProcessFlag_Hidden)
    367             && !(arrFlags[i] & ExecuteProcessFlag_NoProfile))
     361    if (aProcInfo.mFlags)
     362    {
     363        if (   !(aProcInfo.mFlags & ProcessCreateFlag_IgnoreOrphanedProcesses)
     364            && !(aProcInfo.mFlags & ProcessCreateFlag_WaitForProcessStartOnly)
     365            && !(aProcInfo.mFlags & ProcessCreateFlag_Hidden)
     366            && !(aProcInfo.mFlags & ProcessCreateFlag_NoProfile))
    368367        {
    369368            return VERR_INVALID_PARAMETER;
     
    373372    /* Adjust timeout. If set to 0, we define
    374373     * an infinite timeout. */
    375     if (aTimeoutMS == 0)
    376         aTimeoutMS = UINT32_MAX;
     374    if (aProcInfo.mTimeoutMS == 0)
     375        aProcInfo.mTimeoutMS = UINT32_MAX;
    377376
    378377    /** @tood Implement process priority + affinity. */
    379378
    380     int rc;
     379    int rc = VERR_MAX_THRDS_REACHED;
     380
     381    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
     382
     383    /* Create a new (host-based) process ID and assign it. */
     384    uint32_t uNewProcessID = 0;
     385    uint32_t uTries = 0;
     386
     387    for (;;)
     388    {
     389        /* Is the context ID already used?  Try next ID ... */
     390        if (!processExists(uNewProcessID++))
     391        {
     392            /* Callback with context ID was not found. This means
     393             * we can use this context ID for our new callback we want
     394             * to add below. */
     395            rc = VINF_SUCCESS;
     396            break;
     397        }
     398
     399        if (++uTries == UINT32_MAX)
     400            break; /* Don't try too hard. */
     401    }
     402    if (RT_FAILURE(rc)) throw rc;
     403
    381404    ComObjPtr<GuestProcess> pGuestProcess;
    382405    try
     
    386409        if (FAILED(hr)) throw VERR_COM_UNEXPECTED;
    387410
    388         rc = pGuestProcess->init(this,
    389                                  aCommand, aArguments, aEnvironment,
    390                                  ComSafeArrayInArg(aFlags), aTimeoutMS,
    391                                  aPriority, ComSafeArrayInArg(aAffinity));
     411        rc = pGuestProcess->init(mData.mParent->getConsole() /* Console */, this /* Session */,
     412                                 uNewProcessID, aProcInfo);
    392413        if (RT_FAILURE(rc)) throw rc;
    393414
    394         mData.mProcesses.push_back(pGuestProcess);
     415        mData.mProcesses[uNewProcessID] = pGuestProcess;
    395416
    396417        /* Return guest session to the caller. */
     
    404425
    405426    return rc;
    406 
    407 #if 0
    408     int rc = VINF_SUCCESS;
    409 
    410     char **papszArgv = NULL;
    411     try
    412     {
    413         /* Prepare arguments. */
    414         uint32_t uNumArgs = 0;
    415         if (aArguments)
    416         {
    417             com::SafeArray<IN_BSTR> args(ComSafeArrayInArg(aArguments));
    418             uNumArgs = args.size();
    419             papszArgv = (char**)RTMemAlloc(sizeof(char*) * (uNumArgs + 1));
    420             AssertReturn(papszArgv, VERR_NO_MEMORY);
    421             for (unsigned i = 0; RT_SUCCESS(rc) && i < uNumArgs; i++)
    422                 rc = RTUtf16ToUtf8(args[i], &papszArgv[i]);
    423             papszArgv[uNumArgs] = NULL;
    424 
    425             if (RT_FAILURE(rc))
    426                 return rc;
    427         }
    428 
    429         char *pszArgs = NULL;
    430         if (uNumArgs)
    431         {
    432             rc = RTGetOptArgvToString(&pszArgs, papszArgv, RTGETOPTARGV_CNV_QUOTE_MS_CRT);
    433             if (RT_FAILURE(rc)) throw rc;
    434         }
    435 
    436         /* Get number of arguments. */
    437         uint32_t cbArgs = pszArgs ? strlen(pszArgs) + 1 : 0; /* Include terminating zero. */
    438 
    439         /* Prepare environment. */
    440         void *pvEnv = NULL;
    441         uint32_t uNumEnv = 0;
    442         uint32_t cbEnv = 0;
    443         if (aEnvironment)
    444         {
    445             com::SafeArray<IN_BSTR> env(ComSafeArrayInArg(aEnvironment));
    446 
    447             for (unsigned i = 0; RT_SUCCESS(rc) && i < env.size(); i++)
    448                 rc = prepareExecuteEnv(Utf8Str(env[i]).c_str(), &pvEnv, &cbEnv, &uNumEnv);
    449         }
    450     }
    451     catch (int eRc)
    452     {
    453 
    454 
    455         rc = exRc;
    456     }
    457 
    458     for (unsigned i = 0; i < uNumArgs; i++)
    459         RTMemFree(papszArgv[i]);
    460             RTMemFree(papszArgv);
    461 #endif
    462 
    463     return rc;
     427}
     428
     429inline bool GuestSession::processExists(uint32_t uProcessID)
     430{
     431    AssertReturn(uProcessID, false);
     432
     433    SessionProcesses::const_iterator itProcesses = mData.mProcesses.find(uProcessID);
     434    return (itProcesses == mData.mProcesses.end()) ? false : true;
    464435}
    465436
     
    760731    ReturnComNotImplemented();
    761732#else
    762     AutoCaller autoCaller(this);
    763     if (FAILED(autoCaller.rc())) return autoCaller.rc();
    764 
    765     CheckComArgOutPointerValid(aProcess);
    766 
    767     com::SafeArray<LONG> affinity; /** @todo Process affinity, not used yet. */
    768 
    769     com::SafeArray<IN_BSTR> arguments(ComSafeArrayInArg(aArguments));
    770     StringsArray argumentsUtf8(arguments.size());
    771     for (size_t i = 0; i < arguments.size(); i++)
    772         argumentsUtf8[i] = Utf8Str(Bstr(arguments[i]));
    773 
    774     com::SafeArray<IN_BSTR> environment(ComSafeArrayInArg(aEnvironment));
    775     StringsArray environmentUtf8(environment.size());
    776     for (size_t i = 0; i < environment.size(); i++)
    777         environmentUtf8[i] = Utf8Str(Bstr(environment[i]));
    778 
    779     int rc = processCreateExInteral(Utf8Str(aCommand), argumentsUtf8, environmentUtf8,
    780                                     ComSafeArrayInArg(aFlags), aTimeoutMS,
    781                                     ProcessPriority_Default, ComSafeArrayAsInParam(affinity), aProcess);
    782     return RT_SUCCESS(rc) ? S_OK : VBOX_E_IPRT_ERROR;
     733
     734    com::SafeArray<LONG> affinity;
     735
     736    return ProcessCreateEx(aCommand, ComSafeArrayInArg(aArguments), ComSafeArrayInArg(aEnvironment),
     737                           ComSafeArrayInArg(aFlags), aTimeoutMS, ProcessPriority_Default, ComSafeArrayAsInParam(affinity), aProcess);
    783738#endif /* VBOX_WITH_GUEST_CONTROL */
    784739}
     
    797752    CheckComArgOutPointerValid(aProcess);
    798753
     754    GuestProcessInfo procInfo;
     755
     756    procInfo.mCommand = Utf8Str(aCommand);
     757
    799758    com::SafeArray<IN_BSTR> arguments(ComSafeArrayInArg(aArguments));
    800     StringsArray argumentsUtf8(arguments.size());
     759    procInfo.mArguments.reserve(arguments.size());
    801760    for (size_t i = 0; i < arguments.size(); i++)
    802         argumentsUtf8[i] = Utf8Str(Bstr(arguments[i]));
     761        procInfo.mArguments[i] = Utf8Str(Bstr(arguments[i]));
    803762
    804763    com::SafeArray<IN_BSTR> environment(ComSafeArrayInArg(aEnvironment));
    805     StringsArray environmentUtf8(environment.size());
    806764    for (size_t i = 0; i < environment.size(); i++)
    807         environmentUtf8[i] = Utf8Str(Bstr(environment[i]));
    808 
    809     int rc = processCreateExInteral(Utf8Str(aCommand), argumentsUtf8, environmentUtf8,
    810                                     ComSafeArrayInArg(aFlags), aTimeoutMS,
    811                                     aPriority, ComSafeArrayInArg(aAffinity), aProcess);
     765    {
     766        Utf8Str strEnv = Bstr(environment[i]);
     767        RTCList<RTCString> listPair = strEnv.split("=", RTCString::KeepEmptyParts);
     768        size_t p = 0;
     769        while(p < listPair.size())
     770        {
     771            Utf8Str strKey = listPair.at(p++);
     772            if (strKey.isEmpty()) /* Skip pairs with empty keys (e.g. "=FOO"). */
     773            {
     774                p++;
     775                continue;
     776            }
     777            Utf8Str strValue;
     778            if (p < listPair.size())
     779                strValue = listPair.at(p++);
     780            procInfo.mEnvironment[strKey] = strValue;
     781        }
     782    }
     783
     784    com::SafeArray<ProcessCreateFlag_T> flags(ComSafeArrayInArg(aFlags));
     785    for (size_t i = 0; i < flags.size(); i++)
     786        procInfo.mFlags |= flags[i];
     787
     788    procInfo.mTimeoutMS = aTimeoutMS;
     789
     790    com::SafeArray<LONG> affinity(ComSafeArrayInArg(aAffinity));
     791    procInfo.mAffinity.reserve(affinity.size());
     792    for (size_t i = 0; i < affinity.size(); i++)
     793        procInfo.mAffinity[i] = affinity[i]; /** @todo Really necessary? Later. */
     794
     795    procInfo.mPriority = aPriority;
     796
     797    int rc = processCreateExInteral(procInfo, aProcess);
    812798    return RT_SUCCESS(rc) ? S_OK : VBOX_E_IPRT_ERROR;
    813799#endif /* VBOX_WITH_GUEST_CONTROL */
  • trunk/src/VBox/Main/testcase/Makefile.kmk

    r41528 r42160  
    151151#
    152152tstGuestCtrlParseBuffer_TEMPLATE = VBOXMAINCLIENTEXE
     153tstGuestCtrlParseBuffer_DEFS    += VBOX_WITH_HGCM VBOX_WITH_GUEST_CONTROL
    153154tstGuestCtrlParseBuffer_SOURCES  = \
    154155        tstGuestCtrlParseBuffer.cpp \
    155         ../src-client/GuestCtrlIO.cpp
     156        ../src-client/GuestCtrlPrivate.cpp
    156157tstGuestCtrlParseBuffer_INCS     = ../include
    157158ifeq ($(KBUILD_TARGET),win) ## @todo just add this to the template.
注意: 瀏覽 TracChangeset 來幫助您使用更動檢視器

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette