VirtualBox

Changeset 28286 in vbox for trunk/src/VBox


Ignore:
Timestamp:
Apr 14, 2010 10:02:30 AM (15 years ago)
Author:
vboxsync
Message:

Guest Control: Update (introducing contexts for callbacks).

Location:
trunk/src/VBox
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Additions/common/VBoxGuestLib/VBoxGuestR3LibGuestCtrl.cpp

    r28233 r28286  
    147147 ** @todo Docs!
    148148 */
    149 VBGLR3DECL(int) VbglR3GuestCtrlExecGetHostCmd(uint32_t u32ClientId, uint32_t uNumParms,
    150                                               char    *pszCmd,      uint32_t cbCmd,
     149VBGLR3DECL(int) VbglR3GuestCtrlExecGetHostCmd(uint32_t  u32ClientId,    uint32_t  uNumParms,
     150                                              uint32_t *puContext,
     151                                              char     *pszCmd,         uint32_t  cbCmd,
    151152                                              uint32_t *puFlags,
    152                                               char *pszArgs,        uint32_t cbArgs,  uint32_t *puNumArgs,
    153                                               char *pszEnv,         uint32_t *pcbEnv, uint32_t *puNumEnvVars,
    154                                               char *pszStdIn,       uint32_t cbStdIn,
    155                                               char *pszStdOut,      uint32_t cbStdOut,
    156                                               char *pszStdErr,      uint32_t cbStdErr,
    157                                               char *pszUser,        uint32_t cbUser,
    158                                               char *pszPassword,    uint32_t cbPassword,
     153                                              char     *pszArgs,        uint32_t  cbArgs,   uint32_t *puNumArgs,
     154                                              char     *pszEnv,         uint32_t *pcbEnv,  uint32_t *puNumEnvVars,
     155                                              char     *pszStdIn,       uint32_t cbStdIn,
     156                                              char     *pszStdOut,      uint32_t cbStdOut,
     157                                              char     *pszStdErr,      uint32_t cbStdErr,
     158                                              char     *pszUser,        uint32_t cbUser,
     159                                              char     *pszPassword,    uint32_t cbPassword,
    159160                                              uint32_t *puTimeLimit)
    160161{
     162    AssertPtr(puContext);
    161163    AssertPtr(pszCmd);
    162164    AssertPtr(puFlags);
     
    181183    Msg.hdr.cParms = uNumParms;
    182184
     185    VbglHGCMParmUInt32Set(&Msg.context, 0); /** @todo Put this some header struct! */
    183186    VbglHGCMParmPtrSet(&Msg.cmd, pszCmd, cbCmd);
    184187    VbglHGCMParmUInt32Set(&Msg.flags, 0);
     
    205208        else
    206209        {
     210            Msg.context.GetUInt32(puContext);
    207211            Msg.flags.GetUInt32(puFlags);
    208212            Msg.num_args.GetUInt32(puNumArgs);
     
    225229 */
    226230VBGLR3DECL(int) VbglR3GuestCtrlExecReportStatus(uint32_t     u32ClientId,
     231                                                uint32_t     u32Context,
    227232                                                uint32_t     u32PID,
    228233                                                uint32_t     u32Status,
     
    236241    Msg.hdr.u32ClientID = u32ClientId;
    237242    Msg.hdr.u32Function = GUEST_EXEC_SEND_STATUS;
    238     Msg.hdr.cParms = 4;
    239 
     243    Msg.hdr.cParms = 5;
     244
     245    VbglHGCMParmUInt32Set(&Msg.context, u32Context);
    240246    VbglHGCMParmUInt32Set(&Msg.pid, u32PID);
    241247    VbglHGCMParmUInt32Set(&Msg.status, u32Status);
  • trunk/src/VBox/Additions/common/VBoxService/VBoxServiceControl.cpp

    r28218 r28286  
    9696static int VBoxServiceControlHandleCmdExec(uint32_t u32ClientId, uint32_t uNumParms)
    9797{
     98    uint32_t uContextID;
    9899    char szCmd[_1K];
    99100    uint32_t uFlags;
     
    110111    uint32_t uTimeLimitMS;
    111112
    112     int rc = VbglR3GuestCtrlExecGetHostCmd(u32ClientId, uNumParms,
     113    if (uNumParms != 14)
     114        return VERR_INVALID_PARAMETER;
     115
     116    int rc = VbglR3GuestCtrlExecGetHostCmd(u32ClientId,
     117                                           uNumParms,
     118                                           &uContextID,
    113119                                           /* Command */
    114120                                           szCmd,      sizeof(szCmd),
     
    134140    else
    135141    {     
    136         rc = VBoxServiceControlExecProcess(szCmd, uFlags, szArgs, uNumArgs,                                           
     142        rc = VBoxServiceControlExecProcess(uContextID, szCmd, uFlags, szArgs, uNumArgs,                                           
    137143                                           szEnv, cbEnv, uNumEnvVars,
    138144                                           szStdIn, szStdOut, szStdErr,
  • trunk/src/VBox/Additions/common/VBoxService/VBoxServiceControlExec.cpp

    r28244 r28286  
    235235
    236236
    237 static int VBoxServiceControlExecProcLoop(uint32_t uClientID, RTPROCESS hProcess, RTMSINTERVAL cMillies, RTPOLLSET hPollSet,
     237static int VBoxServiceControlExecProcLoop(PVBOXSERVICECTRLTHREADDATA pData,
     238                                          RTPROCESS hProcess, RTMSINTERVAL cMillies, RTPOLLSET hPollSet,
    238239                                          RTPIPE hStdInW, RTPIPE hStdOutR, RTPIPE hStdErrR)
    239240{
     
    256257    RTMSINTERVAL        cMsPollCur                  = 0;
    257258
     259    /* Assign PID to thread data. */
     260    pData->uPID = hProcess;
     261
    258262    /*
    259263     * Before entering the loop, tell the host that we've started the guest
    260264     * and that it's now OK to send input to the process.
    261265     */
    262     rc = VbglR3GuestCtrlExecReportStatus(uClientID, hProcess,
    263                                          PROC_STS_STARTED, 0 /* u32Flags */,
     266    AssertPtr(pData);
     267    rc = VbglR3GuestCtrlExecReportStatus(pData->uClientID, pData->uContextID,
     268                                         pData->uPID, PROC_STS_STARTED, 0 /* u32Flags */,
    264269                                         NULL /* pvData */, 0 /* cbData */);
    265270
     
    446451        }
    447452       
    448         VBoxServiceVerbose(3, "Control: Process ended: Status=%u, Flags=%u\n", uStatus, uFlags);
    449         rc = VbglR3GuestCtrlExecReportStatus(uClientID, hProcess,
    450                                              uStatus, uFlags,
     453        VBoxServiceVerbose(3, "Control: Process ended: PID=%u, Status=%u, Flags=%u\n",
     454                           pData->uPID, uStatus, uFlags);
     455        rc = VbglR3GuestCtrlExecReportStatus(pData->uClientID, pData->uContextID,
     456                                             pData->uPID, uStatus, uFlags,
    451457                                             NULL /* pvData */, 0 /* cbData */);
    452458    }
     
    509515
    510516/** Allocates and gives back a thread data struct which then can be used by the worker thread. */
    511 PVBOXSERVICECTRLTHREADDATA VBoxServiceControlExecAllocateThreadData(const char *pszCmd, uint32_t uFlags,
     517PVBOXSERVICECTRLTHREADDATA VBoxServiceControlExecAllocateThreadData(uint32_t u32ContextID,
     518                                                                    const char *pszCmd, uint32_t uFlags,
    512519                                                                    const char *pszArgs, uint32_t uNumArgs,                                           
    513520                                                                    const char *pszEnv, uint32_t cbEnv, uint32_t uNumEnvVars,
     
    519526        return NULL;
    520527
     528    /* ClientID will be assigned when thread is started! */
     529    pData->uContextID = u32ContextID;
    521530    pData->pszCmd = RTStrDup(pszCmd);
    522531    pData->uFlags = uFlags;
     
    601610     */
    602611    RTThreadUserSignal(RTThreadSelf());
    603     VBoxServiceVerbose(3, "Control: Thread of process \"%s\" started.\n", pData->pszCmd);
    604 
    605     uint32_t u32ClientID;
    606     int rc = VbglR3GuestCtrlConnect(&u32ClientID);
     612    VBoxServiceVerbose(3, "Control: Thread of process \"%s\" started\n", pData->pszCmd);
     613
     614    int rc = VbglR3GuestCtrlConnect(&pData->uClientID);
    607615    if (RT_FAILURE(rc))
    608616    {
     
    685693
    686694                                    /* Enter the process loop. */
    687                                     rc = VBoxServiceControlExecProcLoop(u32ClientID,
     695                                    rc = VBoxServiceControlExecProcLoop(pData,
    688696                                                                        hProcess, pData->uTimeLimitMS, hPollSet,
    689697                                                                        hStdInW, hStdOutR, hStdErrR);
     
    704712                                else /* Something went wrong; report error! */
    705713                                {
    706                                     int rc2 = VbglR3GuestCtrlExecReportStatus(u32ClientID, 0 /* PID */,
     714                                    int rc2 = VbglR3GuestCtrlExecReportStatus(pData->uClientID, pData->uContextID, pData->uPID,
    707715                                                                              PROC_STS_ERROR, rc,
    708716                                                                              NULL /* pvData */, 0 /* cbData */);
     
    726734    }
    727735
    728     VbglR3GuestCtrlDisconnect(u32ClientID);
     736    VbglR3GuestCtrlDisconnect(pData->uClientID);
    729737    VBoxServiceVerbose(3, "Control: Thread of process \"%s\" ended with rc=%Rrc\n", pData->pszCmd, rc);
    730738
     
    743751}
    744752
    745 int VBoxServiceControlExecProcess(const char *pszCmd, uint32_t uFlags,
     753int VBoxServiceControlExecProcess(uint32_t uContextID, const char *pszCmd, uint32_t uFlags,
    746754                                  const char *pszArgs, uint32_t uNumArgs,                                           
    747755                                  const char *pszEnv, uint32_t cbEnv, uint32_t uNumEnvVars,
     
    750758{
    751759    PVBOXSERVICECTRLTHREADDATA pThreadData =
    752         VBoxServiceControlExecAllocateThreadData(pszCmd, uFlags,
     760        VBoxServiceControlExecAllocateThreadData(uContextID,
     761                                                 pszCmd, uFlags,
    753762                                                 pszArgs, uNumArgs,
    754763                                                 pszEnv, cbEnv, uNumEnvVars,
  • trunk/src/VBox/Additions/common/VBoxService/VBoxServiceInternal.h

    r28251 r28286  
    129129typedef struct
    130130{
     131    uint32_t  uClientID;
     132    uint32_t  uContextID;
     133    uint32_t  uPID;
    131134    char     *pszCmd;
    132135    uint32_t  uFlags;
     
    213216
    214217#ifdef VBOX_WITH_GUEST_CONTROL
    215 extern int VBoxServiceControlExecProcess(const char *pszCmd, uint32_t uFlags,
     218extern int VBoxServiceControlExecProcess(uint32_t uContext, const char *pszCmd, uint32_t uFlags,
    216219                                         const char *pszArgs, uint32_t uNumArgs,                                           
    217220                                         const char *pszEnv, uint32_t cbEnv, uint32_t uNumEnvVars,
  • trunk/src/VBox/HostServices/GuestControl/service.cpp

    r28243 r28286  
    244244    int processHostMsg(VBOXHGCMCALLHANDLE callHandle, uint32_t cParms, VBOXHGCMSVCPARM paParms[]);
    245245    int notifyGuest(GuestCall *pCall, uint32_t eFunction, uint32_t cParms, VBOXHGCMSVCPARM paParms[]);
    246     int notifyHost(VBOXHGCMCALLHANDLE callHandle, uint32_t eFunction, uint32_t cParms, VBOXHGCMSVCPARM paParms[]);
     246    int notifyHost(uint32_t eFunction, uint32_t cParms, VBOXHGCMSVCPARM paParms[]);
    247247    int processCmd(uint32_t eFunction, uint32_t cParms, VBOXHGCMSVCPARM paParms[]);
    248248    void call(VBOXHGCMCALLHANDLE callHandle, uint32_t u32ClientID,
     
    487487}
    488488
    489 int Service::notifyHost(VBOXHGCMCALLHANDLE callHandle, uint32_t eFunction, uint32_t cParms, VBOXHGCMSVCPARM paParms[])
     489int Service::notifyHost(uint32_t eFunction, uint32_t cParms, VBOXHGCMSVCPARM paParms[])
    490490{
    491491    LogFlowFunc(("eFunction=%ld, cParms=%ld, paParms=%p\n",
     
    493493    int rc = VINF_SUCCESS;
    494494    if (   eFunction == GUEST_EXEC_SEND_STATUS
    495         && cParms    == 4)
     495        && cParms    == 5)
    496496    {
    497497        HOSTEXECCALLBACKDATA data;
    498         data.u32Magic = HOSTCALLBACKMAGIC;
    499         paParms[0].getUInt32(&data.pid);
    500         paParms[1].getUInt32(&data.status);
    501         paParms[2].getUInt32(&data.flags);
     498        data.hdr.u32Magic = HOSTEXECCALLBACKDATAMAGIC;
     499        paParms[0].getUInt32(&data.hdr.u32ContextID);
     500
     501        paParms[1].getUInt32(&data.u32PID);
     502        paParms[2].getUInt32(&data.u32Status);
     503        paParms[3].getUInt32(&data.u32Flags);
    502504        paParms[4].getPointer(&data.pvData, &data.cbData);
    503505
     
    576578            case GUEST_EXEC_SEND_STATUS:
    577579                LogFlowFunc(("SEND_STATUS\n"));
    578                 rc = notifyHost(callHandle, eFunction, cParms, paParms);
     580                rc = notifyHost(eFunction, cParms, paParms);
    579581                break;
    580582
  • trunk/src/VBox/Main/ConsoleImpl2.cpp

    r28138 r28286  
    3030#include "ConsoleImpl.h"
    3131#include "DisplayImpl.h"
     32#ifdef VBOX_WITH_GUEST_CONTROL
     33# include "GuestImpl.h"
     34#endif
    3235#include "VMMDev.h"
    3336
     
    37293732    }
    37303733    else
    3731         Log(("VBoxGuestControlSvc loaded\n"));
    3732 
    3733     return VINF_SUCCESS;
     3734    {
     3735        HGCMSVCEXTHANDLE hDummy;
     3736        rc = HGCMHostRegisterServiceExtension(&hDummy, "VBoxGuestControlSvc",
     3737                                              &Guest::doGuestCtrlNotification,
     3738                                              pConsole->getGuest());
     3739        if (RT_FAILURE(rc))
     3740            Log(("Cannot register VBoxGuestControlSvc extension!\n"));
     3741        else
     3742            Log(("VBoxGuestControlSvc loaded\n"));
     3743    }
     3744
     3745    return rc;
    37343746#else /* !VBOX_WITH_GUEST_CONTROL */
    37353747    return VERR_NOT_SUPPORTED;
  • trunk/src/VBox/Main/GuestImpl.cpp

    r28243 r28286  
    3434#include <VBox/VMMDev.h>
    3535#ifdef VBOX_WITH_GUEST_CONTROL
    36 # include <VBox/HostServices/GuestControlSvc.h>
    3736# include <VBox/com/array.h>
    38 # include <hgcm/HGCM.h>
    3937#endif
    4038#include <iprt/cpp/utils.h>
     
    9593    for (unsigned i = 0 ; i < GUESTSTATTYPE_MAX; i++)
    9694        mCurrentGuestStat[i] = 0;
     95
     96    /* Init the context ID counter at 1000. */
     97    mNextContextID = 1000;
    9798
    9899    return S_OK;
     
    438439
    439440/**
    440  * Static callback function for receiving updates on processes started on
    441  * the guest side.
     441 * Static callback function for receiving updates on guest control commands
     442 * from the guest. Acts as a dispatcher for the actual class instance.
    442443 *
    443444 * @returns VBox status code.
     
    446447 *
    447448 */
    448 DECLCALLBACK(int) Guest::doGuestCtrlExecNotification(void *pvExtension,
    449                                                      uint32_t u32Function,
    450                                                      void *pvParms,
    451                                                      uint32_t cbParms)
     449DECLCALLBACK(int) Guest::doGuestCtrlNotification(void    *pvExtension,
     450                                                 uint32_t u32Function,
     451                                                 void    *pvParms,
     452                                                 uint32_t cbParms)
    452453{
    453454    using namespace guestControl;
     
    457458     * changes to the object state.
    458459     */
    459     PHOSTEXECCALLBACKDATA pCBData = reinterpret_cast<PHOSTEXECCALLBACKDATA>(pvParms);
    460     AssertPtr(pCBData);
    461     AssertReturn(sizeof(HOSTEXECCALLBACKDATA) == cbParms, VERR_INVALID_PARAMETER);
    462     AssertReturn(HOSTCALLBACKMAGIC == pCBData->u32Magic, VERR_INVALID_PARAMETER);
    463460    LogFlowFunc(("pvExtension = %p, u32Function = %d, pvParms = %p, cbParms = %d\n",
    464461                 pvExtension, u32Function, pvParms, cbParms));
    465     PHOSTEXECCALLBACKDATA pExt = reinterpret_cast<HOSTEXECCALLBACKDATA *>(pvExtension);
     462    ComObjPtr<Guest> pGuest = reinterpret_cast<Guest *>(pvExtension);
    466463
    467464    int rc = VINF_SUCCESS;
     
    469466    {
    470467        LogFlowFunc(("GUEST_EXEC_SEND_STATUS\n"));
    471         pExt->pid = pCBData->pid;
    472         pExt->status = pCBData->status;
    473         pExt->flags = pCBData->flags;
    474         /** @todo Copy void* buffer! */
     468
     469        PHOSTEXECCALLBACKDATA pCBData = reinterpret_cast<PHOSTEXECCALLBACKDATA>(pvParms);
     470        AssertPtr(pCBData);
     471        AssertReturn(sizeof(HOSTEXECCALLBACKDATA) == cbParms, VERR_INVALID_PARAMETER);
     472        AssertReturn(HOSTEXECCALLBACKDATAMAGIC == pCBData->hdr.u32Magic, VERR_INVALID_PARAMETER);
     473
     474        rc = pGuest->notifyCtrlExec(u32Function, pCBData);
    475475    }
    476476    else
    477477        rc = VERR_NOT_SUPPORTED;
    478 
    479     ASMAtomicWriteBool(&pExt->called, true);
    480478    return rc;
     479}
     480
     481/* Notifier function for control execution stuff. */
     482int Guest::notifyCtrlExec(uint32_t              u32Function,
     483                          PHOSTEXECCALLBACKDATA pData)
     484{
     485    int rc = VINF_SUCCESS;
     486
     487  /*  bool bFound = false;
     488    for (int i=0; i<mList.size(); i++)
     489    {
     490    }
     491    if(pData->hdr.u32ContextID == it->hdr.u32ContextID)
     492    {
     493    }*/
     494    /*pExt->pid = pCBData->pid;
     495    pExt->status = pCBData->status;
     496    pExt->flags = pCBData->flags;*/
     497    /** @todo Copy void* buffer! */
     498
     499    return rc;
     500}
     501
     502void Guest::freeCtrlCallbackContextData(CallbackContext *pContext)
     503{
     504    AssertPtr(pContext);
     505    if (pContext->cbData)
     506    {
     507        RTMemFree(pContext->pvData);
     508        pContext->cbData = 0;
     509        pContext->pvData = NULL;
     510    }
     511}
     512
     513uint32_t Guest::addCtrlCallbackContext(void *pvData, uint32_t cbData)
     514{
     515    uint32_t uNewContext = ASMAtomicIncU32(&mNextContextID);
     516    /** @todo Add value clamping! */
     517
     518    CallbackContext context;
     519    context.mContextID = uNewContext;
     520    context.pvData = pvData;
     521    context.cbData = cbData;
     522
     523    mCallbackList.push_back(context);
     524    if (mCallbackList.size() > 256)
     525    {
     526        freeCtrlCallbackContextData(&mCallbackList.front());
     527        mCallbackList.pop_front();
     528    }
     529    return uNewContext;
    481530}
    482531#endif /* VBOX_WITH_GUEST_CONTROL */
     
    520569        if (FAILED(rc)) return rc;
    521570#endif
    522 
    523571        /*
    524          * Register the host notification callback
     572         * Prepare process execution.
    525573         */
    526         HGCMSVCEXTHANDLE hExt;
    527         HOSTEXECCALLBACKDATA callbackData;
    528         callbackData.called = false;
    529         int vrc = HGCMHostRegisterServiceExtension(&hExt, "VBoxGuestControlSvc",
    530                                                    &Guest::doGuestCtrlExecNotification,
    531                                                    &callbackData);
     574        int vrc = VINF_SUCCESS;
     575        Utf8Str Utf8Command(aCommand);
     576
     577        /* Prepare arguments. */       
     578        com::SafeArray<IN_BSTR> args(ComSafeArrayInArg(aArguments));
     579        uint32_t uNumArgs = args.size();
     580        char **papszArgv = NULL;
     581        if(uNumArgs > 0)
     582        {
     583            papszArgv = (char**)RTMemAlloc(sizeof(char*) * (uNumArgs + 1));
     584            AssertPtr(papszArgv);
     585            for (unsigned i = 0; RT_SUCCESS(vrc) && i < uNumArgs; i++)
     586                vrc = RTStrAPrintf(&papszArgv[i], "%s", Utf8Str(args[i]).raw());
     587            papszArgv[uNumArgs] = NULL;
     588        }
     589
    532590        if (RT_SUCCESS(vrc))
    533591        {
    534             /*
    535              * Prepare process execution.
    536              */
    537             Utf8Str Utf8Command(aCommand);
    538    
    539             /* Prepare arguments. */       
    540             com::SafeArray<IN_BSTR> args(ComSafeArrayInArg(aArguments));
    541             uint32_t uNumArgs = args.size();
    542             char **papszArgv = NULL;
    543             if(uNumArgs > 0)
    544             {
    545                 papszArgv = (char**)RTMemAlloc(sizeof(char*) * (uNumArgs + 1));
    546                 AssertPtr(papszArgv);
    547                 for (unsigned i = 0; RT_SUCCESS(vrc) && i < uNumArgs; i++)
    548                     vrc = RTStrAPrintf(&papszArgv[i], "%s", Utf8Str(args[i]).raw());
    549                 papszArgv[uNumArgs] = NULL;
    550             }
    551    
     592            char *pszArgs = NULL;
     593            if (uNumArgs > 0)
     594                vrc = RTGetOptArgvToString(&pszArgs, papszArgv, 0);         
    552595            if (RT_SUCCESS(vrc))
    553596            {
    554                 char *pszArgs = NULL;
    555                 if (uNumArgs > 0)
    556                     vrc = RTGetOptArgvToString(&pszArgs, papszArgv, 0);         
     597                uint32_t cbArgs = pszArgs ? strlen(pszArgs) + 1 : 0; /* Include terminating zero. */
     598
     599                /* Prepare environment. */
     600                com::SafeArray<IN_BSTR> env(ComSafeArrayInArg(aEnvironment));
     601   
     602                void *pvEnv = NULL;
     603                uint32_t uNumEnv = 0;
     604                uint32_t cbEnv = 0;
     605   
     606                for (unsigned i = 0; i < env.size(); i++)
     607                {
     608                    vrc = prepareExecuteEnv(Utf8Str(env[i]).raw(), &pvEnv, &cbEnv, &uNumEnv);
     609                    if (RT_FAILURE(vrc))
     610                        break;
     611                }
     612   
    557613                if (RT_SUCCESS(vrc))
    558614                {
    559                     uint32_t cbArgs = pszArgs ? strlen(pszArgs) + 1 : 0; /* Include terminating zero. */
     615                    Utf8Str Utf8StdIn(aStdIn);
     616                    Utf8Str Utf8StdOut(aStdOut);
     617                    Utf8Str Utf8StdErr(aStdErr);
     618                    Utf8Str Utf8UserName(aUserName);
     619                    Utf8Str Utf8Password(aPassword);
     620               
     621                    PHOSTEXECCALLBACKDATA pData = (HOSTEXECCALLBACKDATA*)RTMemAlloc(sizeof(HOSTEXECCALLBACKDATA));
     622                    AssertPtr(pData);
     623                    uint32_t uContextID = addCtrlCallbackContext(pData, sizeof(HOSTEXECCALLBACKDATA));
     624
     625                    VBOXHGCMSVCPARM paParms[15];
     626                    int i = 0;
     627                    paParms[i++].setUInt32(uContextID);
     628                    paParms[i++].setPointer((void*)Utf8Command.raw(), (uint32_t)strlen(Utf8Command.raw()) + 1);
     629                    paParms[i++].setUInt32(aFlags);
     630                    paParms[i++].setUInt32(uNumArgs);
     631                    paParms[i++].setPointer((void*)pszArgs, cbArgs);
     632                    paParms[i++].setUInt32(uNumEnv);
     633                    paParms[i++].setUInt32(cbEnv);
     634                    paParms[i++].setPointer((void*)pvEnv, cbEnv);
     635                    paParms[i++].setPointer((void*)Utf8StdIn.raw(), (uint32_t)strlen(Utf8StdIn.raw()) + 1);
     636                    paParms[i++].setPointer((void*)Utf8StdOut.raw(), (uint32_t)strlen(Utf8StdOut.raw()) + 1);
     637                    paParms[i++].setPointer((void*)Utf8StdErr.raw(), (uint32_t)strlen(Utf8StdErr.raw()) + 1);
     638                    paParms[i++].setPointer((void*)Utf8UserName.raw(), (uint32_t)strlen(Utf8UserName.raw()) + 1);
     639                    paParms[i++].setPointer((void*)Utf8Password.raw(), (uint32_t)strlen(Utf8Password.raw()) + 1);
     640                    paParms[i++].setUInt32(aTimeoutMS);
    560641   
    561                     /* Prepare environment. */
    562                     com::SafeArray<IN_BSTR> env(ComSafeArrayInArg(aEnvironment));
    563        
    564                     void *pvEnv = NULL;
    565                     uint32_t uNumEnv = 0;
    566                     uint32_t cbEnv = 0;
    567        
    568                     for (unsigned i = 0; i < env.size(); i++)
     642                    /* Forward the information to the VMM device. */
     643                    AssertPtr(mParent);
     644                    VMMDev *vmmDev = mParent->getVMMDev();
     645                    if (vmmDev)
    569646                    {
    570                         vrc = prepareExecuteEnv(Utf8Str(env[i]).raw(), &pvEnv, &cbEnv, &uNumEnv);
    571                         if (RT_FAILURE(vrc))
     647                        LogFlowFunc(("hgcmHostCall numParms=%d\n", i));
     648                        vrc = vmmDev->hgcmHostCall("VBoxGuestControlSvc", HOST_EXEC_CMD,
     649                                                   i, paParms);
     650                    }
     651                    RTMemFree(pvEnv);
     652                }
     653                RTStrFree(pszArgs);
     654            }
     655            if (RT_SUCCESS(vrc))
     656            {
     657                LogFlowFunc(("Waiting for HGCM callback (timeout=%ldms) ...\n", aTimeoutMS));
     658
     659                /*
     660                 * Wait for the HGCM low level callback until the process
     661                 * has been started (or something went wrong). This is necessary to
     662                 * get the PID.
     663                 */
     664#if 0
     665                uint64_t u64Started = RTTimeMilliTS();
     666                do
     667                {
     668                    unsigned cMsWait;
     669                    if (aTimeoutMS == RT_INDEFINITE_WAIT)
     670                        cMsWait = 1000;
     671                    else
     672                    {
     673                        uint64_t cMsElapsed = RTTimeMilliTS() - u64Started;
     674                        if (cMsElapsed >= aTimeoutMS)
     675                            break; /* timed out */
     676                        cMsWait = RT_MIN(1000, aTimeoutMS - (uint32_t)cMsElapsed);
     677                    }
     678                    RTThreadSleep(100);
     679                } while (!callbackData.called);
     680
     681                /* Did we get some status? */
     682                if (callbackData.called)
     683                {
     684                    switch (callbackData.status)
     685                    {
     686                        case PROC_STS_STARTED:
     687                            *aPID = callbackData.pid;
     688                            break;
     689
     690                        case PROC_STS_ERROR:
     691                            vrc = callbackData.flags; /* flags member contains IPRT error code. */
     692                            break;
     693
     694                        default:
     695                            vrc = VERR_INVALID_PARAMETER;
    572696                            break;
    573697                    }
    574        
    575                     if (RT_SUCCESS(vrc))
     698                }
     699
     700                if (RT_FAILURE(vrc))
     701                {
     702                    if (vrc == VERR_FILE_NOT_FOUND) /* This is the most likely error. */
    576703                    {
    577                         Utf8Str Utf8StdIn(aStdIn);
    578                         Utf8Str Utf8StdOut(aStdOut);
    579                         Utf8Str Utf8StdErr(aStdErr);
    580                         Utf8Str Utf8UserName(aUserName);
    581                         Utf8Str Utf8Password(aPassword);
    582                    
    583                         VBOXHGCMSVCPARM paParms[14];
    584                         int i = 0;
    585                         paParms[i++].setPointer((void*)Utf8Command.raw(), (uint32_t)strlen(Utf8Command.raw()) + 1);
    586                         paParms[i++].setUInt32(aFlags);
    587                         paParms[i++].setUInt32(uNumArgs);
    588                         paParms[i++].setPointer((void*)pszArgs, cbArgs);
    589                         paParms[i++].setUInt32(uNumEnv);
    590                         paParms[i++].setUInt32(cbEnv);
    591                         paParms[i++].setPointer((void*)pvEnv, cbEnv);
    592                         paParms[i++].setPointer((void*)Utf8StdIn.raw(), (uint32_t)strlen(Utf8StdIn.raw()) + 1);
    593                         paParms[i++].setPointer((void*)Utf8StdOut.raw(), (uint32_t)strlen(Utf8StdOut.raw()) + 1);
    594                         paParms[i++].setPointer((void*)Utf8StdErr.raw(), (uint32_t)strlen(Utf8StdErr.raw()) + 1);
    595                         paParms[i++].setPointer((void*)Utf8UserName.raw(), (uint32_t)strlen(Utf8UserName.raw()) + 1);
    596                         paParms[i++].setPointer((void*)Utf8Password.raw(), (uint32_t)strlen(Utf8Password.raw()) + 1);
    597                         paParms[i++].setUInt32(aTimeoutMS);
    598        
    599                         /* Forward the information to the VMM device. */
    600                         AssertPtr(mParent);
    601                         VMMDev *vmmDev = mParent->getVMMDev();
    602                         if (vmmDev)
    603                         {
    604                             LogFlowFunc(("hgcmHostCall numParms=%d\n", i));
    605                             vrc = vmmDev->hgcmHostCall("VBoxGuestControlSvc", HOST_EXEC_CMD,
    606                                                        i, paParms);
    607                         }
    608                         RTMemFree(pvEnv);
     704                        rc = setError(VBOX_E_IPRT_ERROR,
     705                                      tr("The file \"%s\" was not found on guest"), Utf8Command.raw());
    609706                    }
    610                     RTStrFree(pszArgs);
     707                    else
     708                    {
     709                        rc = setError(E_UNEXPECTED,
     710                                      tr("The service call failed with the error %Rrc"), vrc);
     711                    }
    611712                }
    612                 if (RT_SUCCESS(vrc))
    613                 {
    614                     LogFlowFunc(("Waiting for HGCM callback (timeout=%ldms) ...\n", aTimeoutMS));
    615 
    616                     /*
    617                      * Wait for the HGCM low level callback until the process
    618                      * has been started (or something went wrong). This is necessary to
    619                      * get the PID.
    620                      */
    621                     uint64_t u64Started = RTTimeMilliTS();
    622                     do
    623                     {
    624                         unsigned cMsWait;
    625                         if (aTimeoutMS == RT_INDEFINITE_WAIT)
    626                             cMsWait = 1000;
    627                         else
    628                         {
    629                             uint64_t cMsElapsed = RTTimeMilliTS() - u64Started;
    630                             if (cMsElapsed >= aTimeoutMS)
    631                                 break; /* timed out */
    632                             cMsWait = RT_MIN(1000, aTimeoutMS - (uint32_t)cMsElapsed);
    633                         }
    634                         RTThreadSleep(100);
    635                     } while (!callbackData.called);
    636 
    637                     /* Did we get some status? */
    638                     if (callbackData.called)
    639                     {
    640                         switch (callbackData.status)
    641                         {
    642                             case PROC_STS_STARTED:
    643                                 *aPID = callbackData.pid;
    644                                 break;
    645 
    646                             case PROC_STS_ERROR:
    647                                 vrc = callbackData.flags; /* flags member contains IPRT error code. */
    648                                 break;
    649 
    650                             default:
    651                                 vrc = VERR_INVALID_PARAMETER;
    652                                 break;
    653                         }
    654                     }
    655 
    656                     if (RT_FAILURE(vrc))
    657                     {
    658                         if (vrc == VERR_FILE_NOT_FOUND) /* This is the most likely error. */
    659                         {
    660                             rc = setError(VBOX_E_IPRT_ERROR,
    661                                           tr("The file \"%s\" was not found on guest"), Utf8Command.raw());
    662                         }
    663                         else
    664                         {
    665                             rc = setError(E_UNEXPECTED,
    666                                           tr("The service call failed with the error %Rrc"), vrc);
    667                         }
    668                     }
     713#endif
    669714#if 0
    670                     progress.queryInterfaceTo(aProgress);
     715                progress.queryInterfaceTo(aProgress);
    671716#endif
    672                 }
    673                 else
    674                 {
    675                     /* HGCM call went wrong. */
    676                     rc = setError(E_UNEXPECTED,
    677                                   tr("The service call failed with the error %Rrc"), vrc);
    678                 }
    679 
    680                 for (unsigned i = 0; i < uNumArgs; i++)
    681                     RTMemFree(papszArgv[i]);
    682                 RTMemFree(papszArgv);
    683717            }
    684             /* Unregister HGCM extension */
    685             HGCMHostUnregisterServiceExtension(hExt);
     718            else
     719            {
     720                /* HGCM call went wrong. */
     721                rc = setError(E_UNEXPECTED,
     722                              tr("The service call failed with error %Rrc"), vrc);
     723            }
     724
     725            for (unsigned i = 0; i < uNumArgs; i++)
     726                RTMemFree(papszArgv[i]);
     727            RTMemFree(papszArgv);
    686728        }
    687729    }
  • trunk/src/VBox/Main/include/GuestImpl.h

    r28233 r28286  
    2525#include "VirtualBoxBase.h"
    2626#include <VBox/ostypes.h>
     27
     28#ifdef VBOX_WITH_GUEST_CONTROL
     29# include <VBox/HostServices/GuestControlSvc.h>
     30# include <hgcm/HGCM.h>
     31using namespace guestControl;
     32#endif
    2733
    2834typedef enum
     
    104110    static const wchar_t *getComponentName() { return L"Guest"; }
    105111
     112# ifdef VBOX_WITH_GUEST_CONTROL
     113    /** Static callback for handling guest notifications. */
     114    static DECLCALLBACK(int) doGuestCtrlNotification(void *pvExtension, uint32_t u32Function, void *pvParms, uint32_t cbParms);
     115# endif
     116
    106117private:
    107118
    108119# ifdef VBOX_WITH_GUEST_CONTROL
     120
     121    struct CallbackContext
     122    {
     123        uint32_t  mContextID;
     124        void     *pvData;
     125        uint32_t  cbData;
     126    };
     127
    109128    int prepareExecuteArgs(const char *pszArgs, void **ppvList, uint32_t *pcbList, uint32_t *pcArgs);
    110129    int prepareExecuteEnv(const char *pszEnv, void **ppvList, uint32_t *pcbList, uint32_t *pcEnv);
    111     /** Static callback for handling guest notifications. */
    112     static DECLCALLBACK(int) doGuestCtrlExecNotification(void *pvExtension, uint32_t u32Function, void *pvParms, uint32_t cbParms);
     130    /** Handler for guest execution control notifications. */
     131    int notifyCtrlExec(uint32_t u32Function, PHOSTEXECCALLBACKDATA pData);
     132    void freeCtrlCallbackContextData(CallbackContext *pContext);
     133    uint32_t addCtrlCallbackContext(void *pvData, uint32_t cbData);
    113134# endif
    114135
     
    131152    Console *mParent;
    132153    Data mData;
    133     bool mSignalled;
     154
     155# ifdef VBOX_WITH_GUEST_CONTROL
     156    /** General extension callback for guest control. */
     157    HGCMSVCEXTHANDLE  mhExtCtrl;
     158       
     159    volatile uint32_t mNextContextID;
     160    typedef std::list< CallbackContext > CallbackList;
     161    CallbackList mCallbackList;
     162# endif
    134163};
    135164
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