VirtualBox

Changeset 42461 in vbox


Ignore:
Timestamp:
Jul 30, 2012 9:28:12 PM (12 years ago)
Author:
vboxsync
Message:

Guest Control 2.0: Update.

Location:
trunk
Files:
11 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/VBox/HostServices/GuestControlSvc.h

    r42160 r42461  
    4444/**
    4545 * Process status when executed in the guest.
    46  * Note: Has to match Main's ExecuteProcessStatus_*!
    4746 */
    4847enum eProcessStatus
     
    250249     * new data on stdout/stderr, process terminated etc.
    251250     */
    252     HOST_EXEC_GET_OUTPUT = 102
     251    HOST_EXEC_GET_OUTPUT = 102,
     252
     253    /*
     254     * Guest control 2.0 commands start in the 2xx number space.
     255     */
     256
     257    /**
     258     * Waits for a certain event to happen. This can be an input, output
     259     * or status event.
     260     */
     261    HOST_EXEC_WAIT_FOR = 210
    253262};
    254263
     
    278287    /*
    279288     * Process execution.
     289     * The 1xx commands are legacy guest control commands and
     290     * will be replaced by newer commands in the future.
    280291     */
    281292
     
    291302     * Guests sends an input status notification to the host.
    292303     */
    293     GUEST_EXEC_SEND_INPUT_STATUS = 102
     304    GUEST_EXEC_SEND_INPUT_STATUS = 102,
     305
     306    /*
     307     * Guest control 2.0 commands start in the 2xx number space.
     308     */
     309
     310    /**
     311     * Guest notifies the host about some I/O event. This can be
     312     * a stdout, stderr or a stdin event. The actual event only tells
     313     * how many data is available / can be sent without actually
     314     * transmitting the data.
     315     */
     316    GUEST_EXEC_IO_NOTIFY = 210,
    294317};
    295318
     
    332355    /** The command to execute on the guest. */
    333356    HGCMFunctionParameter cmd;
    334     /** Execution flags (see IGuest::ExecuteProcessFlag_*). */
     357    /** Execution flags (see IGuest::ProcessCreateFlag_*). */
    335358    HGCMFunctionParameter flags;
    336359    /** Number of arguments. */
     
    351374     *  overall lifetime of the process or how long it
    352375     *  can take to bring the process up and running -
    353      *  (depends on the IGuest::ExecuteProcessFlag_*). */
     376     *  (depends on the IGuest::ProcessCreateFlag_*). */
    354377    HGCMFunctionParameter timeout;
    355378
     
    434457} VBoxGuestCtrlHGCMMsgExecStatusIn;
    435458
     459/**
     460 * Reports back the currente I/O status of a guest process.
     461 */
     462typedef struct VBoxGuestCtrlHGCMMsgExecIONotify
     463{
     464    VBoxGuestHGCMCallInfo hdr;
     465    /** Context ID. */
     466    HGCMFunctionParameter context;
     467    /** Data written. */
     468    HGCMFunctionParameter written;
     469
     470} VBoxGuestCtrlHGCMMsgExecIONotify;
     471
    436472#pragma pack ()
    437473
  • trunk/src/VBox/Additions/common/VBoxService/VBoxServiceControlThread.cpp

    r41774 r42461  
    486486            }
    487487
    488             /* Reqport back actual data written (if any). */
     488            /* Report back actual data written (if any). */
    489489            pRequest->cbData = cbWritten;
    490490            break;
  • trunk/src/VBox/Main/idl/VirtualBox.xidl

    r42442 r42461  
    88848884  <enum
    88858885    name="ProcessWaitResult"
    8886     uuid="c593a234-21ee-4a67-85ef-ba0cc9b9b86a"
     8886    uuid="24a4d49f-a7c1-44b0-b01f-5686a316466b"
    88878887    >
    88888888    <desc>
     
    89158915    </const>   
    89168916    <const name="StdErr"                  value="8">
     8917      <desc>TODO</desc>
     8918    </const>
     8919    <const name="Any"                     value="9">
    89178920      <desc>TODO</desc>
    89188921    </const>   
  • trunk/src/VBox/Main/include/GuestCtrlImplPrivate.h

    r42411 r42461  
    127127    void Destroy(void);
    128128
    129     int FillData(const void *pData, size_t cbData);
     129    int FillData(const void *pvToWrite, size_t cbToWrite);
    130130
    131131    int Init(eVBoxGuestCtrlCallbackType enmType);
     
    133133    eVBoxGuestCtrlCallbackType GetCallbackType(void) { return mType; }
    134134
    135 protected:
    136 
    137     /** Pointer to user-supplied data. */
     135    const void* GetPayloadRaw(void) const { return pvPayload; }
     136
     137    size_t GetPayloadSize(void) { return cbPayload; }
     138
     139protected:
     140
     141    /** Pointer to actual callback data. */
    138142    void                       *pvData;
    139143    /** Size of user-supplied data. */
     
    143147    /** Callback flags. */
    144148    uint32_t                    uFlags;
     149    /** Payload which will be available on successful
     150     *  waiting (optional). */
     151    void                       *pvPayload;
     152    /** Size of the payload. */
     153    size_t                      cbPayload;
    145154};
    146155typedef std::map < uint32_t, GuestCtrlCallback* > GuestCtrlCallbacks;
  • trunk/src/VBox/Main/include/GuestImpl.h

    r42411 r42461  
    207207     * @{ */
    208208    int         dispatchToSession(uint32_t uContextID, uint32_t uFunction, void *pvData, size_t cbData);
     209    uint32_t    getAdditionsVersion(void) { return mData.mAdditionsVersionFull; }
    209210    Console    *getConsole(void) { return mParent; }
    210211    int         sessionClose(ComObjPtr<GuestSession> pSession);
  • trunk/src/VBox/Main/include/GuestProcessImpl.h

    r42436 r42461  
    7676    bool isReady(void);
    7777    ULONG getPID(void) { return mData.mPID; }
    78     int readData(ULONG uHandle, ULONG uSize, ULONG uTimeoutMS, BYTE *pbData, size_t cbData);
     78    int readData(ULONG uHandle, ULONG uSize, ULONG uTimeoutMS, BYTE *pbData, size_t cbData, size_t *pcbRead);
    7979    int startProcess(void);
    8080    int startProcessAsync(void);
     
    9292    int onGuestDisconnected(GuestCtrlCallback *pCallback, PCALLBACKDATACLIENTDISCONNECTED pData);
    9393    int onProcessInputStatus(GuestCtrlCallback *pCallback, PCALLBACKDATAEXECINSTATUS pData);
     94    int onProcessNotifyIO(GuestCtrlCallback *pCallback, PCALLBACKDATAEXECSTATUS pData);
    9495    int onProcessStatusChange(GuestCtrlCallback *pCallback, PCALLBACKDATAEXECSTATUS pData);
    9596    int onProcessOutput(GuestCtrlCallback *pCallback, PCALLBACKDATAEXECOUT pData);
  • trunk/src/VBox/Main/include/GuestSessionImpl.h

    r42441 r42461  
    128128    const GuestCredentials &getCredentials(void);
    129129    const GuestEnvironment &getEnvironment(void);
     130    uint32_t                getProtocolVersion(void) { return mData.mProtocolVersion; }
    130131    int                     processClose(ComObjPtr<GuestProcess> pProcess);
    131132    int                     processCreateExInteral(GuestProcessInfo &procInfo, ComObjPtr<GuestProcess> &pProgress);
    132133    inline bool             processExists(uint32_t uProcessID, ComObjPtr<GuestProcess> *pProcess);
    133134    inline int              processGetByPID(ULONG uPID, ComObjPtr<GuestProcess> *pProcess);
     135    int                     queryInfo(void);
    134136    /** @}  */
    135137
     
    138140    struct Data
    139141    {
     142        /** Guest control protocol version.
     143         *  Guest control prior to VBox 4.2 has version 1,
     144         *  guest control 2.0 has ...well, 2. */
     145        uint32_t             mProtocolVersion;
    140146        /** Flag indicating if this is an internal session
    141147         *  or not. Internal session are not accessible by clients. */
  • trunk/src/VBox/Main/src-client/GuestCtrlImpl.cpp

    r42436 r42461  
    28162816        if (FAILED(hr2))
    28172817            rc = VERR_COM_OBJECT_NOT_FOUND;
     2818
     2819        if (RT_SUCCESS(rc))
     2820            rc = pSession->queryInfo();
    28182821    }
    28192822
  • trunk/src/VBox/Main/src-client/GuestCtrlPrivate.cpp

    r42436 r42461  
    122122    : pvData(NULL),
    123123      cbData(0),
    124      mType(VBOXGUESTCTRLCALLBACKTYPE_UNKNOWN),
    125       uFlags(0)
     124      mType(VBOXGUESTCTRLCALLBACKTYPE_UNKNOWN),
     125      uFlags(0),
     126      pvPayload(NULL),
     127      cbPayload(0)
    126128{
    127129}
     
    131133      cbData(0),
    132134      mType(VBOXGUESTCTRLCALLBACKTYPE_UNKNOWN),
    133       uFlags(0)
     135      uFlags(0),
     136      pvPayload(NULL),
     137      cbPayload(0)
    134138{
    135139    int rc = Init(enmType);
     
    206210    }
    207211    cbData = 0;
    208 }
    209 
    210 int GuestCtrlCallback::FillData(const void *pData, size_t cbData)
    211 {
    212     if (!cbData)
     212
     213    if (pvPayload)
     214    {
     215        RTMemFree(pvPayload);
     216        pvPayload = NULL;
     217    }
     218    cbPayload = 0;
     219}
     220
     221int GuestCtrlCallback::FillData(const void *pvToWrite, size_t cbToWrite)
     222{
     223    if (!cbToWrite)
    213224        return VINF_SUCCESS;
    214     AssertPtr(pData);
    215 
    216     Assert(pvData == NULL); /* Can't reuse callbacks! */
    217     pvData = RTMemAlloc(cbData);
    218     if (!pvData)
     225    AssertPtr(pvToWrite);
     226
     227    Assert(pvPayload == NULL); /* Can't reuse callbacks! */
     228    pvPayload = RTMemAlloc(cbToWrite);
     229    if (!pvPayload)
    219230        return VERR_NO_MEMORY;
    220231
    221     memcpy(pvData, pData, cbData);
     232    memcpy(pvPayload, pvToWrite, cbToWrite);
     233    cbPayload = cbToWrite;
    222234
    223235    return VINF_SUCCESS;
  • trunk/src/VBox/Main/src-client/GuestProcessImpl.cpp

    r42439 r42461  
    8282
    8383    HRESULT hr = BaseFinalConstruct();
    84     LogFlowFuncLeaveRC(hr);
    8584    return hr;
    8685}
     
    308307// private methods
    309308/////////////////////////////////////////////////////////////////////////////
    310 
    311 /*
    312 
    313     SYNC TO ASK:
    314     Everything which involves HGCM communication (start, read/write/status(?)/...)
    315     either can be called synchronously or asynchronously by running in a Main worker
    316     thread.
    317 
    318     Rules:
    319         - Only one async operation per process a time can be around.
    320 
    321 */
    322309
    323310inline int GuestProcess::callbackAdd(GuestCtrlCallback *pCallback, ULONG *puContextID)
     
    387374    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
    388375
    389 #ifdef DEBUG
    390     LogFlowFunc(("Callback count=%RU32\n", VBOX_GUESTCTRL_CONTEXTID_GET_COUNT(uContextID)));
    391 #endif
    392 
    393376    int rc;
     377
     378    /* Get the optional callback associated to this context ID.
     379     * The callback may not be around anymore if just kept locally by the caller when
     380     * doing the actual HGCM sending stuff. */
     381    GuestCtrlCallback *pCallback = NULL;
    394382    GuestCtrlCallbacks::const_iterator it
    395383        = mData.mCallbacks.find(VBOX_GUESTCTRL_CONTEXTID_GET_COUNT(uContextID));
    396384    if (it != mData.mCallbacks.end())
    397385    {
    398         GuestCtrlCallback *pCallback = it->second;
     386        pCallback = it->second;
    399387        AssertPtr(pCallback);
    400 
    401         switch (uFunction)
    402         {
    403             case GUEST_DISCONNECTED:
    404             {
    405                 PCALLBACKDATACLIENTDISCONNECTED pCallbackData = reinterpret_cast<PCALLBACKDATACLIENTDISCONNECTED>(pvData);
    406                 AssertPtr(pCallbackData);
    407                 AssertReturn(sizeof(CALLBACKDATACLIENTDISCONNECTED) == cbData, VERR_INVALID_PARAMETER);
    408                 AssertReturn(CALLBACKDATAMAGIC_CLIENT_DISCONNECTED == pCallbackData->hdr.u32Magic, VERR_INVALID_PARAMETER);
    409 
    410                 rc = onGuestDisconnected(pCallback, pCallbackData); /* Affects all callbacks. */
    411                 break;
    412             }
    413 
    414             case GUEST_EXEC_SEND_STATUS:
    415             {
    416                 PCALLBACKDATAEXECSTATUS pCallbackData = reinterpret_cast<PCALLBACKDATAEXECSTATUS>(pvData);
    417                 AssertPtr(pCallbackData);
    418                 AssertReturn(sizeof(CALLBACKDATAEXECSTATUS) == cbData, VERR_INVALID_PARAMETER);
    419                 AssertReturn(CALLBACKDATAMAGIC_EXEC_STATUS == pCallbackData->hdr.u32Magic, VERR_INVALID_PARAMETER);
    420 
    421                 rc = onProcessStatusChange(pCallback, pCallbackData);
    422                 break;
    423             }
    424 
    425             case GUEST_EXEC_SEND_OUTPUT:
    426             {
    427                 PCALLBACKDATAEXECOUT pCallbackData = reinterpret_cast<PCALLBACKDATAEXECOUT>(pvData);
    428                 AssertPtr(pCallbackData);
    429                 AssertReturn(sizeof(CALLBACKDATAEXECOUT) == cbData, VERR_INVALID_PARAMETER);
    430                 AssertReturn(CALLBACKDATAMAGIC_EXEC_OUT == pCallbackData->hdr.u32Magic, VERR_INVALID_PARAMETER);
    431 
    432                 Assert(mData.mPID == pCallbackData->u32PID);
    433                 rc = onProcessOutput(pCallback, pCallbackData);
    434                 break;
    435             }
    436 
    437             case GUEST_EXEC_SEND_INPUT_STATUS:
    438             {
    439                 PCALLBACKDATAEXECINSTATUS pCallbackData = reinterpret_cast<PCALLBACKDATAEXECINSTATUS>(pvData);
    440                 AssertPtr(pCallbackData);
    441                 AssertReturn(sizeof(CALLBACKDATAEXECINSTATUS) == cbData, VERR_INVALID_PARAMETER);
    442                 AssertReturn(CALLBACKDATAMAGIC_EXEC_IN_STATUS == pCallbackData->hdr.u32Magic, VERR_INVALID_PARAMETER);
    443 
    444                 Assert(mData.mPID == pCallbackData->u32PID);
    445                 rc = onProcessInputStatus(pCallback, pCallbackData);
    446                 break;
    447             }
    448 
    449             default:
    450                 /* Silently ignore not implemented functions. */
    451                 rc = VERR_NOT_IMPLEMENTED;
    452                 break;
    453         }
    454     }
    455     else
    456         rc = VERR_NOT_FOUND;
     388#ifdef DEBUG
     389        LogFlowFunc(("pCallback=%p\n", pCallback));
     390#endif
     391    }
     392
     393    switch (uFunction)
     394    {
     395        case GUEST_DISCONNECTED:
     396        {
     397            PCALLBACKDATACLIENTDISCONNECTED pCallbackData = reinterpret_cast<PCALLBACKDATACLIENTDISCONNECTED>(pvData);
     398            AssertPtr(pCallbackData);
     399            AssertReturn(sizeof(CALLBACKDATACLIENTDISCONNECTED) == cbData, VERR_INVALID_PARAMETER);
     400            AssertReturn(CALLBACKDATAMAGIC_CLIENT_DISCONNECTED == pCallbackData->hdr.u32Magic, VERR_INVALID_PARAMETER);
     401
     402            rc = onGuestDisconnected(pCallback, pCallbackData); /* Affects all callbacks. */
     403            break;
     404        }
     405
     406        case GUEST_EXEC_SEND_STATUS:
     407        {
     408            PCALLBACKDATAEXECSTATUS pCallbackData = reinterpret_cast<PCALLBACKDATAEXECSTATUS>(pvData);
     409            AssertPtr(pCallbackData);
     410            AssertReturn(sizeof(CALLBACKDATAEXECSTATUS) == cbData, VERR_INVALID_PARAMETER);
     411            AssertReturn(CALLBACKDATAMAGIC_EXEC_STATUS == pCallbackData->hdr.u32Magic, VERR_INVALID_PARAMETER);
     412
     413            rc = onProcessStatusChange(pCallback, pCallbackData);
     414            break;
     415        }
     416
     417        case GUEST_EXEC_SEND_OUTPUT:
     418        {
     419            PCALLBACKDATAEXECOUT pCallbackData = reinterpret_cast<PCALLBACKDATAEXECOUT>(pvData);
     420            AssertPtr(pCallbackData);
     421            AssertReturn(sizeof(CALLBACKDATAEXECOUT) == cbData, VERR_INVALID_PARAMETER);
     422            AssertReturn(CALLBACKDATAMAGIC_EXEC_OUT == pCallbackData->hdr.u32Magic, VERR_INVALID_PARAMETER);
     423
     424            rc = onProcessOutput(pCallback, pCallbackData);
     425            break;
     426        }
     427
     428        case GUEST_EXEC_SEND_INPUT_STATUS:
     429        {
     430            PCALLBACKDATAEXECINSTATUS pCallbackData = reinterpret_cast<PCALLBACKDATAEXECINSTATUS>(pvData);
     431            AssertPtr(pCallbackData);
     432            AssertReturn(sizeof(CALLBACKDATAEXECINSTATUS) == cbData, VERR_INVALID_PARAMETER);
     433            AssertReturn(CALLBACKDATAMAGIC_EXEC_IN_STATUS == pCallbackData->hdr.u32Magic, VERR_INVALID_PARAMETER);
     434
     435            rc = onProcessInputStatus(pCallback, pCallbackData);
     436            break;
     437        }
     438
     439        default:
     440            /* Silently ignore not implemented functions. */
     441            rc = VERR_NOT_IMPLEMENTED;
     442            break;
     443    }
    457444
    458445#ifdef DEBUG
     
    473460    GuestCtrlCallbacks::iterator it =
    474461        mData.mCallbacks.find(VBOX_GUESTCTRL_CONTEXTID_GET_COUNT(uContextID));
    475     if (it == mData.mCallbacks.end())
     462    if (it != mData.mCallbacks.end())
    476463    {
    477464        delete it->second;
     
    537524int GuestProcess::onGuestDisconnected(GuestCtrlCallback *pCallback, PCALLBACKDATACLIENTDISCONNECTED pData)
    538525{
    539     AssertPtrReturn(pCallback, VERR_INVALID_POINTER);
     526    /* pCallback is optional. */
    540527    AssertPtrReturn(pData, VERR_INVALID_POINTER);
    541528
     
    545532
    546533    /* First, signal callback in every case. */
    547     pCallback->Signal();
     534    if (pCallback)
     535        pCallback->Signal();
    548536
    549537    /* Do we need to report a termination? */
     
    564552int GuestProcess::onProcessInputStatus(GuestCtrlCallback *pCallback, PCALLBACKDATAEXECINSTATUS pData)
    565553{
    566     AssertPtrReturn(pCallback, VERR_INVALID_POINTER);
     554    /* pCallback is optional. */
    567555    AssertPtrReturn(pData, VERR_INVALID_POINTER);
    568556
     
    575563
    576564    /* First, signal callback in every case. */
    577     pCallback->Signal();
     565    if (pCallback)
     566        pCallback->Signal();
    578567
    579568    /* Then do the WaitFor signalling stuff. */
     
    588577}
    589578
     579int GuestProcess::onProcessNotifyIO(GuestCtrlCallback *pCallback, PCALLBACKDATAEXECSTATUS pData)
     580{
     581    /* pCallback is optional. */
     582    AssertPtrReturn(pData, VERR_INVALID_POINTER);
     583
     584    return 0;
     585}
     586
    590587int GuestProcess::onProcessStatusChange(GuestCtrlCallback *pCallback, PCALLBACKDATAEXECSTATUS pData)
    591588{
    592     AssertPtrReturn(pCallback, VERR_INVALID_POINTER);
     589    /* pCallback is optional. */
    593590    AssertPtrReturn(pData, VERR_INVALID_POINTER);
    594591
     
    620617        case PROC_STS_TEN:
    621618        {
    622             fSignal = (uWaitFlags & ProcessWaitForFlag_Terminate);
     619            fSignal = TRUE; /* Signal in any case. */
    623620            waitRes = ProcessWaitResult_Status;
    624621
     
    630627        case PROC_STS_TES:
    631628        {
    632             fSignal = (uWaitFlags & ProcessWaitForFlag_Terminate);
     629            fSignal = TRUE; /* Signal in any case. */
    633630            waitRes = ProcessWaitResult_Status;
    634631
     
    640637        case PROC_STS_TEA:
    641638        {
    642             fSignal = (uWaitFlags & ProcessWaitForFlag_Terminate);
     639            fSignal = TRUE; /* Signal in any case. */
    643640            waitRes = ProcessWaitResult_Status;
    644641
     
    649646        case PROC_STS_TOK:
    650647        {
    651             fSignal = (uWaitFlags & ProcessWaitForFlag_Terminate);
     648            fSignal = TRUE; /* Signal in any case. */
    652649            waitRes = ProcessWaitResult_Timeout;
    653650
     
    658655        case PROC_STS_TOA:
    659656        {
    660             fSignal = (uWaitFlags & ProcessWaitForFlag_Terminate);
     657            fSignal = TRUE; /* Signal in any case. */
    661658            waitRes = ProcessWaitResult_Timeout;
    662659
     
    667664        case PROC_STS_DWN:
    668665        {
    669             fSignal = (uWaitFlags & ProcessWaitForFlag_Terminate);
     666            fSignal = TRUE; /* Signal in any case. */
    670667            waitRes = (mData.mProcess.mFlags & ProcessCreateFlag_IgnoreOrphanedProcesses)
    671668                    ? ProcessWaitResult_Terminate : ProcessWaitResult_Status;
     
    759756     * Now do the signalling stuff.
    760757     */
    761     rc = pCallback->Signal();
     758    if (pCallback)
     759        rc = pCallback->Signal();
    762760
    763761    if (fSignal)
     
    774772int GuestProcess::onProcessOutput(GuestCtrlCallback *pCallback, PCALLBACKDATAEXECOUT pData)
    775773{
    776     AssertPtrReturn(pCallback, VERR_INVALID_POINTER);
     774    /* pCallback is optional. */
    777775    AssertPtrReturn(pData, VERR_INVALID_POINTER);
    778776
     
    780778                 mData.mPID, pData->u32HandleId, pData->u32Flags, pData->pvData, pData->cbData, pCallback, pData));
    781779
    782     /* Copy data into callback. */
    783     int rc = pCallback->FillData(pData->pvData, pData->cbData);
    784 
    785     /* First, signal callback in every case. */
    786     int rc2 = pCallback->Signal();
    787     if (RT_SUCCESS(rc))
    788         rc = rc2;
     780    /* Copy data into callback (if any). */
     781    int rc = VINF_SUCCESS;
     782
     783    /* First, signal callback in every case (if available). */
     784    if (pCallback)
     785    {
     786        if (pData->pvData && pData->cbData)
     787            rc = pCallback->FillData(pData->pvData, pData->cbData);
     788
     789        int rc2 = pCallback->Signal();
     790        if (RT_SUCCESS(rc))
     791            rc = rc2;
     792    }
    789793
    790794    /* Then do the WaitFor signalling stuff. */
     
    811815    if (fSignal)
    812816    {
    813         rc2 = signalWaiters(  pData->u32HandleId == OUTPUT_HANDLE_ID_STDOUT
    814                             ? ProcessWaitResult_StdOut : ProcessWaitResult_StdErr);
     817        int rc2 = signalWaiters(  pData->u32HandleId == OUTPUT_HANDLE_ID_STDOUT
     818                                ? ProcessWaitResult_StdOut : ProcessWaitResult_StdErr);
    815819        if (RT_SUCCESS(rc))
    816820            rc = rc2;
    817821    }
    818     AssertRC(rc);
    819822
    820823    LogFlowFuncLeaveRC(rc);
     
    822825}
    823826
    824 int GuestProcess::readData(ULONG uHandle, ULONG uSize, ULONG uTimeoutMS, BYTE *pbData, size_t cbData)
    825 {
    826     LogFlowFunc(("uPID=%RU32, uHandle=%RU32, uSize=%RU32, uTimeoutMS=%RU32, pbData=%p, cbData=%z\n",
     827int GuestProcess::readData(ULONG uHandle, ULONG uSize, ULONG uTimeoutMS,
     828                           BYTE *pbData, size_t cbData, size_t *pcbRead)
     829{
     830    LogFlowFunc(("uPID=%RU32, uHandle=%RU32, uSize=%RU32, uTimeoutMS=%RU32, pbData=%p, cbData=%RU32\n",
    827831                 mData.mPID, uHandle, uSize, uTimeoutMS, pbData, cbData));
    828832    AssertReturn(uSize, VERR_INVALID_PARAMETER);
    829833    AssertPtrReturn(pbData, VERR_INVALID_POINTER);
    830834    AssertReturn(cbData >= uSize, VERR_INVALID_PARAMETER);
    831 
    832     LogFlowFuncLeave();
    833     return 0;
     835    /* pcbRead is optional. */
     836
     837    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
     838
     839    if (mData.mStatus != ProcessStatus_Started)
     840        return VERR_NOT_AVAILABLE;
     841
     842    ULONG uContextID = 0;
     843    GuestCtrlCallback *pCallbackRead = new GuestCtrlCallback();
     844    if (!pCallbackRead)
     845        return VERR_NO_MEMORY;
     846
     847    /* Create callback and add it to the map. */
     848    int rc = pCallbackRead->Init(VBOXGUESTCTRLCALLBACKTYPE_EXEC_OUTPUT);
     849    if (RT_SUCCESS(rc))
     850        rc = callbackAdd(pCallbackRead, &uContextID);
     851
     852    alock.release(); /* Drop the write lock again. */
     853
     854    if (RT_SUCCESS(rc))
     855    {
     856        VBOXHGCMSVCPARM paParms[5];
     857
     858        int i = 0;
     859        paParms[i++].setUInt32(uContextID);
     860        paParms[i++].setUInt32(mData.mPID);
     861        paParms[i++].setUInt32(uHandle);
     862        paParms[i++].setUInt32(0 /* Flags, none set yet. */);
     863
     864        rc = sendCommand(HOST_EXEC_GET_OUTPUT, i, paParms);
     865    }
     866
     867    if (RT_SUCCESS(rc))
     868    {
     869        /*
     870         * Let's wait for the process being started.
     871         * Note: Be sure not keeping a AutoRead/WriteLock here.
     872         */
     873        LogFlowFunc(("Waiting for callback (%RU32ms) ...\n", uTimeoutMS));
     874        rc = pCallbackRead->Wait(uTimeoutMS);
     875        if (RT_SUCCESS(rc)) /* Wait was successful, check for supplied information. */
     876        {
     877            rc = pCallbackRead->GetResultCode();
     878            LogFlowFunc(("Callback returned rc=%Rrc, cbData=%RU32\n", rc, pCallbackRead->GetPayloadSize()));
     879
     880            if (RT_SUCCESS(rc))
     881            {
     882                size_t cbDataCB = pCallbackRead->GetPayloadSize();
     883                if (cbDataCB)
     884                {
     885                    Assert(cbData >= cbDataCB);
     886                    memcpy(pbData, pCallbackRead->GetPayloadRaw(), cbDataCB);
     887                }
     888
     889                if (pcbRead)
     890                    *pcbRead = cbDataCB;
     891            }
     892        }
     893        else
     894            rc = VERR_TIMEOUT;
     895    }
     896
     897    alock.acquire();
     898
     899    AssertPtr(pCallbackRead);
     900    int rc2 = callbackRemove(uContextID);
     901    if (RT_SUCCESS(rc))
     902        rc = rc2;
     903
     904    LogFlowFuncLeaveRC(rc);
     905    return rc;
    834906}
    835907
     
    839911    LogFlowThisFuncEnter();
    840912
    841     Console *pConsole = mData.mConsole;
    842     AssertPtr(pConsole);
     913    ComObjPtr<Console> pConsole = mData.mConsole;
     914    Assert(!pConsole.isNull());
    843915
    844916    /* Forward the information to the VMM device. */
     
    850922    if (RT_FAILURE(rc))
    851923    {
     924        int rc2;
     925        if (rc == VERR_INVALID_VM_HANDLE)
     926            rc2 = setErrorInternal(rc, tr("VMM device is not available (is the VM running?)"));
     927        else if (rc == VERR_NOT_FOUND)
     928            rc2 = setErrorInternal(rc, tr("The guest execution service is not ready (yet)"));
     929        else if (rc == VERR_HGCM_SERVICE_NOT_FOUND)
     930            rc2 = setErrorInternal(rc, tr("The guest execution service is not available"));
     931        else
     932            rc2 = setErrorInternal(rc, Utf8StrFmt(tr("The HGCM call failed with error %Rrc"), rc));
     933        AssertRC(rc2);
    852934    }
    853935
     
    9831065
    9841066            rc = sendCommand(HOST_EXEC_CMD, i, paParms);
    985             if (RT_FAILURE(rc))
    986             {
    987                 int rc2;
    988                 if (rc == VERR_INVALID_VM_HANDLE)
    989                     rc2 = setErrorInternal(rc, tr("VMM device is not available (is the VM running?)"));
    990                 else if (rc == VERR_NOT_FOUND)
    991                     rc2 = setErrorInternal(rc, tr("The guest execution service is not ready (yet)"));
    992                 else if (rc == VERR_HGCM_SERVICE_NOT_FOUND)
    993                     rc2 = setErrorInternal(rc, tr("The guest execution service is not available"));
    994                 else
    995                     rc2 = setErrorInternal(rc, Utf8StrFmt(tr("The HGCM call failed with error %Rrc"), rc));
    996                 AssertRC(rc2);
    997             }
    9981067        }
    9991068
     
    10041073        uint32_t uTimeoutMS = mData.mProcess.mTimeoutMS;
    10051074
    1006         alock.release(); /* Drop the read lock again. */
     1075        alock.release(); /* Drop the write lock again. */
    10071076
    10081077        if (RT_SUCCESS(rc))
     
    10851154    LogFlowThisFuncEnter();
    10861155
     1156    if (mData.mParent->getProtocolVersion() < 2)
     1157        return VERR_NOT_SUPPORTED;
     1158
    10871159    LogFlowFuncLeave();
    10881160    return VERR_NOT_IMPLEMENTED;
     
    10951167    AssertReturn(fWaitFlags, VERR_INVALID_PARAMETER);
    10961168
    1097     AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
    1098 
    10991169    LogFlowFunc(("fWaitFlags=%x, uTimeoutMS=%RU32, mStatus=%RU32, mWaitCount=%RU32, mWaitEvent=%p\n",
    11001170                 fWaitFlags, uTimeoutMS, mData.mStatus, mData.mWaitCount, mData.mWaitEvent));
    11011171
    1102     ProcessStatus_T curStatus = mData.mStatus;
     1172    ProcessStatus_T curStatus;
     1173    {
     1174        AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
     1175        curStatus = mData.mStatus;
     1176    }
    11031177
    11041178    /* Did some error occur before? Then skip waiting and return. */
     
    11171191        || (fWaitFlags & ProcessWaitForFlag_StdErr))
    11181192    {
     1193        /* Filter out waits which are *not* supported using
     1194         * older guest control Guest Additions. */
     1195        AssertPtr(mData.mParent);
     1196        if (mData.mParent->getProtocolVersion() < 2)
     1197        {
     1198            /* We don't support waiting for stdin, out + err,
     1199             * just skip waiting then. */
     1200            if (   (fWaitFlags & ProcessWaitForFlag_StdIn)
     1201                || (fWaitFlags & ProcessWaitForFlag_StdOut)
     1202                || (fWaitFlags & ProcessWaitForFlag_StdErr))
     1203            {
     1204                /* Use _Any because we don't know what to tell the caller. */
     1205                waitRes.mResult = ProcessWaitResult_Any;
     1206            }
     1207        }
     1208
    11191209        switch (mData.mStatus)
    11201210        {
     
    11381228            case ProcessStatus_Undefined:
    11391229            case ProcessStatus_Starting:
     1230            case ProcessStatus_Started:
    11401231                /* Do the waiting below. */
    11411232                break;
     
    11811272    if (waitRes.mResult != ProcessWaitResult_None)
    11821273        return VINF_SUCCESS;
     1274
     1275    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
    11831276
    11841277    if (mData.mWaitCount > 0)
     
    13481441int GuestProcess::writeData(ULONG uHandle, const BYTE *pbData, size_t cbData, ULONG uTimeoutMS, ULONG *puWritten)
    13491442{
    1350     LogFlowFunc(("uPID=%RU32, uHandle=%RU32, pbData=%p, cbData=%z, uTimeoutMS=%RU32, puWritten=%p\n",
     1443    LogFlowFunc(("uPID=%RU32, uHandle=%RU32, pbData=%p, cbData=%RU32, uTimeoutMS=%RU32, puWritten=%p\n",
    13511444                 mData.mPID, uHandle, pbData, cbData, uTimeoutMS, puWritten));
    13521445    AssertPtrReturn(pbData, VERR_INVALID_POINTER);
     
    13661459    ReturnComNotImplemented();
    13671460#else
    1368     LogFlowThisFuncEnter();
    1369 
     1461    if (aSize < 0)
     1462        return setError(E_INVALIDARG, tr("The size argument (%lld) is negative"), aSize);
    13701463    if (aSize == 0)
    1371         return setError(E_INVALIDARG, tr("Invalid size to read specified"));
     1464        return setError(E_INVALIDARG, tr("The size (%lld) is zero"), aSize);
    13721465    CheckComArgOutSafeArrayPointerValid(aData);
    13731466
     
    13751468    if (FAILED(autoCaller.rc())) return autoCaller.rc();
    13761469
    1377     AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
    1378 
    1379     com::SafeArray<BYTE> data(aSize);
    1380     int rc = readData(aHandle, aSize, aTimeoutMS, data.raw(), aSize);
     1470    com::SafeArray<BYTE> data((size_t)aSize);
     1471    Assert(data.size() >= aSize);
     1472
     1473    size_t cbRead;
     1474    int rc = readData(aHandle, aSize, aTimeoutMS, data.raw(), aSize, &cbRead);
    13811475    if (RT_SUCCESS(rc))
     1476    {
     1477        if (data.size() != cbRead)
     1478            data.resize(cbRead);
    13821479        data.detachTo(ComSafeArrayOutArg(aData));
     1480    }
    13831481
    13841482    /** @todo Do setError() here. */
    13851483    HRESULT hr = RT_SUCCESS(rc) ? S_OK : VBOX_E_IPRT_ERROR;
    1386     LogFlowFuncLeaveRC(hr);
     1484    LogFlowFuncLeaveRC(rc);
    13871485
    13881486    return hr;
     
    14051503    /** @todo Do setError() here. */
    14061504    HRESULT hr = RT_SUCCESS(rc) ? S_OK : VBOX_E_IPRT_ERROR;
    1407     LogFlowFuncLeaveRC(hr);
     1505    LogFlowFuncLeaveRC(rc);
    14081506
    14091507    return hr;
     
    14711569        fWaitFor |= flags[i];
    14721570
    1473     HRESULT hr = WaitFor(fWaitFor, aTimeoutMS, aReason);
    1474 
    1475     LogFlowFuncLeaveRC(hr);
    1476     return hr;
     1571    return WaitFor(fWaitFor, aTimeoutMS, aReason);
    14771572#endif /* VBOX_WITH_GUEST_CONTROL */
    14781573}
     
    14961591    /** @todo Do setError() here. */
    14971592    HRESULT hr = RT_SUCCESS(rc) ? S_OK : VBOX_E_IPRT_ERROR;
    1498     LogFlowFuncLeaveRC(hr);
     1593    LogFlowFuncLeaveRC(rc);
    14991594
    15001595    return hr;
  • trunk/src/VBox/Main/src-client/GuestSessionImpl.cpp

    r42439 r42461  
    3131
    3232#include <VBox/com/array.h>
     33#include <VBox/version.h>
    3334
    3435
     
    562563}
    563564
     565/**
     566 * Queries/collects information prior to establishing a guest session.
     567 * This is necessary to know which guest control protocol version to use,
     568 * among other things (later).
     569 *
     570 * @return  IPRT status code.
     571 */
     572int GuestSession::queryInfo(void)
     573{
     574    /*
     575     * Try querying the guest control protocol version running on the guest.
     576     * This is done using the Guest Additions version
     577     */
     578    ComObjPtr<Guest> pGuest = mData.mParent;
     579    Assert(!pGuest.isNull());
     580
     581    uint32_t uVerAdditions = pGuest->getAdditionsVersion();
     582    mData.mProtocolVersion = (   VBOX_FULL_VERSION_GET_MAJOR(uVerAdditions) >= 4
     583                              && VBOX_FULL_VERSION_GET_MINOR(uVerAdditions) >= 2 )
     584                           ? 2  /* Guest control 2.0. */
     585                           : 1; /* Legacy guest control (VBox < 4.2). */
     586    /* Build revision is ignored. */
     587
     588    /* Tell the user but don't bitch too often. */
     589    static short s_gctrlLegacyWarning = 0;
     590    if (s_gctrlLegacyWarning++ < 3) /** @todo Find a bit nicer text. */
     591        LogRel((tr("Warning: Guest Additions are older (%ld.%ld) than host capabilities for guest control, please upgrade them. Using protocol version %ld now\n"),
     592                VBOX_FULL_VERSION_GET_MAJOR(uVerAdditions), VBOX_FULL_VERSION_GET_MINOR(uVerAdditions), mData.mProtocolVersion));
     593
     594    return VINF_SUCCESS;
     595}
     596
    564597// implementation of public methods
    565598/////////////////////////////////////////////////////////////////////////////
Note: See TracChangeset for help on using the changeset viewer.

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